feat: wrap up adding uplc builtins for now

This commit is contained in:
rvcas 2022-10-25 14:52:29 -04:00 committed by Lucas
parent d5d2ba9cd7
commit 819256df99
12 changed files with 222 additions and 110 deletions

View File

@ -6,6 +6,7 @@
**aiken**: Fancy errors using [miette](https://github.com/zkat/miette) **aiken**: Fancy errors using [miette](https://github.com/zkat/miette)
**aiken**: Typechecking **aiken**: Typechecking
**aiken**: Inject `aiken/builtin` module with some functions from `DefaultFunction` in UPLC directly exposed
**aiken-lang**: add `infer` method to `UntypedModule` which returns a `TypedModule` **aiken-lang**: add `infer` method to `UntypedModule` which returns a `TypedModule`
### Changed ### Changed

28
Cargo.lock generated
View File

@ -80,6 +80,7 @@ dependencies = [
"itertools", "itertools",
"miette", "miette",
"pretty_assertions", "pretty_assertions",
"strum",
"thiserror", "thiserror",
"uplc", "uplc",
"vec1", "vec1",
@ -928,6 +929,12 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustversion"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]] [[package]]
name = "rusty-fork" name = "rusty-fork"
version = "0.3.0" version = "0.3.0"
@ -1010,6 +1017,25 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]] [[package]]
name = "supports-color" name = "supports-color"
version = "1.3.0" version = "1.3.0"
@ -1192,6 +1218,8 @@ dependencies = [
"proptest", "proptest",
"serde", "serde",
"serde_json", "serde_json",
"strum",
"strum_macros",
"thiserror", "thiserror",
] ]

View File

@ -37,7 +37,7 @@ impl Project {
let mut module_types = HashMap::new(); let mut module_types = HashMap::new();
module_types.insert("aiken".to_string(), builtins::prelude(&id_gen)); module_types.insert("aiken".to_string(), builtins::prelude(&id_gen));
module_types.insert("aiken/builtin".to_string(), builtins::plutus()); module_types.insert("aiken/builtin".to_string(), builtins::plutus(&id_gen));
Project { Project {
config, config,

View File

@ -15,6 +15,7 @@ chumsky = "0.8.0"
internment = "0.7.0" internment = "0.7.0"
itertools = "0.10.5" itertools = "0.10.5"
miette = "5.2.0" miette = "5.2.0"
strum = "0.24.1"
thiserror = "1.0.37" thiserror = "1.0.37"
uplc = { path = '../uplc', version = "0.0.21" } uplc = { path = '../uplc', version = "0.0.21" }
vec1 = "1.8.0" vec1 = "1.8.0"

View File

@ -1,5 +1,7 @@
use std::{cell::RefCell, collections::HashMap, sync::Arc}; use std::{cell::RefCell, collections::HashMap, sync::Arc};
use strum::IntoEnumIterator;
use uplc::builtins::DefaultFunction; use uplc::builtins::DefaultFunction;
use crate::{ use crate::{
@ -212,7 +214,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo {
prelude prelude
} }
pub fn plutus() -> TypeInfo { pub fn plutus(id_gen: &IdGenerator) -> TypeInfo {
let mut plutus = TypeInfo { let mut plutus = TypeInfo {
name: "aiken/builtin".to_string(), name: "aiken/builtin".to_string(),
package: "".to_string(), package: "".to_string(),
@ -223,101 +225,174 @@ pub fn plutus() -> TypeInfo {
accessors: HashMap::new(), accessors: HashMap::new(),
}; };
plutus.values.insert( for builtin in DefaultFunction::iter() {
DefaultFunction::AddInteger.to_string(), if let Some(value) = from_default_function(builtin, id_gen) {
DefaultFunction::AddInteger.into(), plutus.values.insert(
); builtin.to_string().replace("ByteString", "ByteArray"),
value,
plutus.values.insert( );
DefaultFunction::SubtractInteger.to_string(), }
DefaultFunction::SubtractInteger.into(), }
);
plutus.values.insert(
DefaultFunction::MultiplyInteger.to_string(),
DefaultFunction::MultiplyInteger.into(),
);
plutus.values.insert(
DefaultFunction::DivideInteger.to_string(),
DefaultFunction::DivideInteger.into(),
);
plutus plutus
} }
impl From<DefaultFunction> for ValueConstructor { pub fn from_default_function(
fn from(builtin: DefaultFunction) -> Self { builtin: DefaultFunction,
let (tipo, arity) = match builtin { id_gen: &IdGenerator,
DefaultFunction::AddInteger ) -> Option<ValueConstructor> {
| DefaultFunction::SubtractInteger let info = match builtin {
| DefaultFunction::MultiplyInteger DefaultFunction::AddInteger
| DefaultFunction::DivideInteger | DefaultFunction::SubtractInteger
| DefaultFunction::QuotientInteger | DefaultFunction::MultiplyInteger
| DefaultFunction::RemainderInteger | DefaultFunction::DivideInteger
| DefaultFunction::ModInteger => { | DefaultFunction::QuotientInteger
let tipo = function(vec![int(), int()], int()); | DefaultFunction::RemainderInteger
| DefaultFunction::ModInteger => {
let tipo = function(vec![int(), int()], int());
(tipo, 2) Some((tipo, 2))
} }
DefaultFunction::EqualsInteger DefaultFunction::EqualsInteger
| DefaultFunction::LessThanInteger | DefaultFunction::LessThanInteger
| DefaultFunction::LessThanEqualsInteger => { | DefaultFunction::LessThanEqualsInteger => {
let tipo = function(vec![int(), int()], bool()); let tipo = function(vec![int(), int()], bool());
(tipo, 2) Some((tipo, 2))
} }
DefaultFunction::AppendByteString => todo!(), DefaultFunction::AppendByteString => {
DefaultFunction::ConsByteString => todo!(), let tipo = function(vec![byte_array(), byte_array()], byte_array());
DefaultFunction::SliceByteString => todo!(),
DefaultFunction::LengthOfByteString => todo!(),
DefaultFunction::IndexByteString => todo!(),
DefaultFunction::EqualsByteString => todo!(),
DefaultFunction::LessThanByteString => todo!(),
DefaultFunction::LessThanEqualsByteString => todo!(),
DefaultFunction::Sha2_256 => todo!(),
DefaultFunction::Sha3_256 => todo!(),
DefaultFunction::Blake2b_256 => todo!(),
DefaultFunction::VerifyEd25519Signature => todo!(),
DefaultFunction::VerifyEcdsaSecp256k1Signature => todo!(),
DefaultFunction::VerifySchnorrSecp256k1Signature => todo!(),
DefaultFunction::AppendString => todo!(),
DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(),
DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(),
DefaultFunction::SndPair => todo!(),
DefaultFunction::ChooseList => todo!(),
DefaultFunction::MkCons => todo!(),
DefaultFunction::HeadList => todo!(),
DefaultFunction::TailList => todo!(),
DefaultFunction::NullList => todo!(),
DefaultFunction::ChooseData => todo!(),
DefaultFunction::ConstrData => todo!(),
DefaultFunction::MapData => todo!(),
DefaultFunction::ListData => todo!(),
DefaultFunction::IData => todo!(),
DefaultFunction::BData => todo!(),
DefaultFunction::UnConstrData => todo!(),
DefaultFunction::UnMapData => todo!(),
DefaultFunction::UnListData => todo!(),
DefaultFunction::UnIData => todo!(),
DefaultFunction::UnBData => todo!(),
DefaultFunction::EqualsData => todo!(),
DefaultFunction::SerialiseData => todo!(),
DefaultFunction::MkPairData => todo!(),
DefaultFunction::MkNilData => todo!(),
DefaultFunction::MkNilPairData => todo!(),
};
Some((tipo, 2))
}
DefaultFunction::ConsByteString => {
let tipo = function(vec![int(), byte_array()], byte_array());
Some((tipo, 2))
}
DefaultFunction::SliceByteString => {
let tipo = function(vec![int(), int(), byte_array()], byte_array());
Some((tipo, 3))
}
DefaultFunction::LengthOfByteString => {
let tipo = function(vec![byte_array()], int());
Some((tipo, 1))
}
DefaultFunction::IndexByteString => {
let tipo = function(vec![byte_array(), int()], int());
Some((tipo, 2))
}
DefaultFunction::EqualsByteString
| DefaultFunction::LessThanByteString
| DefaultFunction::LessThanEqualsByteString => {
let tipo = function(vec![byte_array(), byte_array()], bool());
Some((tipo, 2))
}
DefaultFunction::Sha2_256 | DefaultFunction::Sha3_256 | DefaultFunction::Blake2b_256 => {
let tipo = function(vec![byte_array()], byte_array());
Some((tipo, 1))
}
DefaultFunction::VerifyEd25519Signature => {
let tipo = function(vec![byte_array(), byte_array(), byte_array()], bool());
Some((tipo, 3))
}
DefaultFunction::VerifyEcdsaSecp256k1Signature => None,
DefaultFunction::VerifySchnorrSecp256k1Signature => None,
DefaultFunction::AppendString => {
let tipo = function(vec![string(), string()], string());
Some((tipo, 2))
}
DefaultFunction::EqualsString => {
let tipo = function(vec![string(), string()], bool());
Some((tipo, 2))
}
DefaultFunction::EncodeUtf8 => {
let tipo = function(vec![string()], byte_array());
Some((tipo, 1))
}
DefaultFunction::DecodeUtf8 => {
let tipo = function(vec![byte_array()], string());
Some((tipo, 1))
}
DefaultFunction::IfThenElse => None,
DefaultFunction::ChooseUnit => None,
DefaultFunction::Trace => {
let ret = generic_var(id_gen.next());
let tipo = function(vec![string(), ret.clone()], ret);
Some((tipo, 2))
}
DefaultFunction::FstPair => None,
DefaultFunction::SndPair => None,
DefaultFunction::ChooseList => None,
DefaultFunction::MkCons => None,
DefaultFunction::HeadList => {
let ret = generic_var(id_gen.next());
let tipo = function(vec![list(ret.clone())], ret);
Some((tipo, 1))
}
DefaultFunction::TailList => {
let ret = list(generic_var(id_gen.next()));
let tipo = function(vec![ret.clone()], ret);
Some((tipo, 1))
}
DefaultFunction::NullList => {
let ret = list(generic_var(id_gen.next()));
let tipo = function(vec![ret], bool());
Some((tipo, 1))
}
DefaultFunction::ChooseData => None,
DefaultFunction::ConstrData => None,
DefaultFunction::MapData => None,
DefaultFunction::ListData => None,
DefaultFunction::IData => None,
DefaultFunction::BData => None,
DefaultFunction::UnConstrData => None,
DefaultFunction::UnMapData => None,
DefaultFunction::UnListData => None,
DefaultFunction::UnIData => None,
DefaultFunction::UnBData => None,
DefaultFunction::EqualsData => {
let arg = generic_var(id_gen.next());
let tipo = function(vec![arg.clone(), arg], bool());
Some((tipo, 1))
}
DefaultFunction::SerialiseData => {
let tipo = function(vec![generic_var(id_gen.next())], byte_array());
Some((tipo, 1))
}
DefaultFunction::MkPairData => None,
DefaultFunction::MkNilData => None,
DefaultFunction::MkNilPairData => None,
};
info.map(|(tipo, arity)| {
ValueConstructor::public( ValueConstructor::public(
tipo, tipo,
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
name: builtin.to_string(), name: builtin.to_string().replace("ByteString", "ByteArray"),
field_map: None, field_map: None,
module: "".to_string(), module: "".to_string(),
arity, arity,
@ -325,7 +400,7 @@ impl From<DefaultFunction> for ValueConstructor {
builtin: Some(builtin), builtin: Some(builtin),
}, },
) )
} })
} }
pub fn int() -> Arc<Type> { pub fn int() -> Arc<Type> {

View File

@ -27,6 +27,8 @@ thiserror = "1.0.31"
anyhow = "1.0.57" anyhow = "1.0.57"
serde = { version = "1.0.144", features = ["derive"] } serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.85" serde_json = "1.0.85"
strum = "0.24.1"
strum_macros = "0.24.3"
[dev-dependencies] [dev-dependencies]
hex = "0.4.3" hex = "0.4.3"

View File

@ -1,11 +1,13 @@
use std::{fmt::Display, str::FromStr}; use std::{fmt::Display, str::FromStr};
use strum_macros::EnumIter;
use flat_rs::de; use flat_rs::de;
/// All the possible builtin functions in Untyped Plutus Core. /// All the possible builtin functions in Untyped Plutus Core.
#[repr(u8)] #[repr(u8)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Copy, EnumIter)]
pub enum DefaultFunction { pub enum DefaultFunction {
// Integer functions // Integer functions
AddInteger = 0, AddInteger = 0,

View File

@ -0,0 +1,8 @@
pub type ScriptContext(purpose) {
tx_info: TxInfo,
script_purpose: purpose
}
pub type TxInfo {
idk: Int
}

View File

@ -0,0 +1,7 @@
use sample/context
pub type Mint {
currency_symbol: ByteArray
}
pub type ScriptContext = context.ScriptContext(Mint)

View File

@ -0,0 +1,7 @@
use sample/context
pub type Spend {
idk: Int
}
pub type ScriptContext = context.ScriptContext(Spend)

View File

@ -1,13 +0,0 @@
use aiken/builtin.{addInteger}
pub type ScriptContext {
idk: Int
}
pub fn append(a: ByteArray, b: ByteArray) -> ByteArray {
todo
}
pub fn add(a, b) {
addInteger(a, b)
}

View File

@ -1,5 +1,5 @@
use sample use sample/mint
use sample/syntax.{append} use sample/spend
pub type Datum { pub type Datum {
something: String, something: String,
@ -10,13 +10,7 @@ pub type Redeemer {
Sell Sell
} }
pub fn validate(datum: Datum, rdmr: Redeemer, ctx: sample.ScriptContext) -> Bool { pub fn spend(datum: Datum, rdmr: Redeemer, ctx: spend.ScriptContext) -> Bool {
let thing = if True {
3
} else {
"thing"
}
when rdmr is { when rdmr is {
Buy -> True Buy -> True
Sell -> datum.something == "Aiken" Sell -> datum.something == "Aiken"