From 7ec3f2e8df595433caba4ff4b2824a1bb374d8d7 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 16 Aug 2024 15:26:52 +0200 Subject: [PATCH] DRY builtins types creation to ensure proper consistency. --- crates/aiken-lang/src/ast.rs | 280 +--- crates/aiken-lang/src/ast/well_known.rs | 339 +++++ crates/aiken-lang/src/builtins.rs | 1188 ++++++----------- crates/aiken-lang/src/expr.rs | 11 +- crates/aiken-lang/src/gen_uplc.rs | 166 ++- crates/aiken-lang/src/gen_uplc/builder.rs | 15 +- crates/aiken-lang/src/gen_uplc/tree.rs | 64 +- crates/aiken-lang/src/parser/annotation.rs | 6 +- crates/aiken-lang/src/parser/expr/pair.rs | 5 +- crates/aiken-lang/src/parser/pattern/pair.rs | 5 +- crates/aiken-lang/src/tipo.rs | 147 +- crates/aiken-lang/src/tipo/environment.rs | 25 +- crates/aiken-lang/src/tipo/exhaustive.rs | 7 +- crates/aiken-lang/src/tipo/expr.rs | 103 +- crates/aiken-lang/src/tipo/hydrator.rs | 12 +- crates/aiken-lang/src/tipo/infer.rs | 19 +- crates/aiken-lang/src/tipo/pattern.rs | 32 +- crates/aiken-lang/src/tipo/pipe.rs | 3 +- crates/aiken-lang/src/tipo/pretty.rs | 19 +- crates/aiken-project/src/blueprint/mod.rs | 8 +- crates/aiken-project/src/blueprint/schema.rs | 3 +- .../aiken-project/src/blueprint/validator.rs | 6 +- crates/aiken-project/src/test_framework.rs | 7 +- 23 files changed, 1170 insertions(+), 1300 deletions(-) create mode 100644 crates/aiken-lang/src/ast/well_known.rs diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index 2cfd76ad2..ee0e72bfd 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -1,8 +1,6 @@ +pub mod well_known; + use crate::{ - builtins::{ - self, g1_element, g2_element, SCRIPT_CONTEXT, SCRIPT_PURPOSE, SCRIPT_PURPOSE_MINT, - SCRIPT_PURPOSE_SPEND, SCRIPT_PURPOSE_WITHDRAW, - }, expr::{TypedExpr, UntypedExpr}, line_numbers::LineNumbers, parser::token::{Base, Token}, @@ -28,12 +26,12 @@ pub const ENV_MODULE: &str = "env"; pub const CONFIG_MODULE: &str = "config"; pub const DEFAULT_ENV_MODULE: &str = "default"; -pub const PURPOSE_SPEND: &str = "spend"; -pub const PURPOSE_MINT: &str = "mint"; -pub const PURPOSE_WITHDRAW: &str = "withdraw"; -pub const PURPOSE_PUBLISH: &str = "publish"; -pub const PURPOSE_VOTE: &str = "vote"; -pub const PURPOSE_PROPOSE: &str = "propose"; +pub const HANDLER_SPEND: &str = "spend"; +pub const HANDLER_MINT: &str = "mint"; +pub const HANDLER_WITHDRAW: &str = "withdraw"; +pub const HANDLER_PUBLISH: &str = "publish"; +pub const HANDLER_VOTE: &str = "vote"; +pub const HANDLER_PROPOSE: &str = "propose"; pub type TypedModule = Module; pub type UntypedModule = Module<(), UntypedDefinition>; @@ -281,23 +279,23 @@ impl TypedFunction { } pub fn has_valid_purpose_name(&self) -> bool { - self.name == PURPOSE_SPEND - || self.name == PURPOSE_PUBLISH - || self.name == PURPOSE_PROPOSE - || self.name == PURPOSE_MINT - || self.name == PURPOSE_WITHDRAW - || self.name == PURPOSE_VOTE + self.name == HANDLER_SPEND + || self.name == HANDLER_PUBLISH + || self.name == HANDLER_PROPOSE + || self.name == HANDLER_MINT + || self.name == HANDLER_WITHDRAW + || self.name == HANDLER_VOTE } pub fn validator_arity(&self) -> usize { - if self.name == PURPOSE_SPEND - || self.name == PURPOSE_PUBLISH - || self.name == PURPOSE_PROPOSE + if self.name == HANDLER_SPEND + || self.name == HANDLER_PUBLISH + || self.name == HANDLER_PROPOSE { 4 - } else if self.name == PURPOSE_MINT - || self.name == PURPOSE_WITHDRAW - || self.name == PURPOSE_VOTE + } else if self.name == HANDLER_MINT + || self.name == HANDLER_WITHDRAW + || self.name == HANDLER_VOTE { 3 } else { @@ -383,207 +381,24 @@ pub struct FunctionAccessKey { pub function_name: String, } +pub type UntypedDataType = DataType<()>; pub type TypedDataType = DataType>; impl TypedDataType { - pub fn data() -> Self { - DataType { - constructors: vec![], - doc: None, - location: Span::empty(), - name: "Data".to_string(), - opaque: false, - parameters: vec![], - public: true, - typed_parameters: vec![], - } - } - - pub fn bool() -> Self { - DataType { - constructors: vec![ - RecordConstructor { - location: Span::empty(), - name: "False".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: "True".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - ], - doc: None, - location: Span::empty(), - name: "Bool".to_string(), - opaque: false, - parameters: vec![], - public: true, - typed_parameters: vec![], - } - } - - pub fn script_purpose() -> Self { - DataType { - constructors: vec![ - RecordConstructor { - location: Span::empty(), - name: SCRIPT_PURPOSE_MINT.to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: SCRIPT_PURPOSE_SPEND.to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: SCRIPT_PURPOSE_WITHDRAW.to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - ], - doc: None, - location: Span::empty(), - name: SCRIPT_PURPOSE.to_string(), - opaque: false, - parameters: vec![], - public: true, - typed_parameters: vec![], - } - } - - pub fn script_context() -> Self { - DataType { - constructors: vec![RecordConstructor { - location: Span::empty(), - name: SCRIPT_CONTEXT.to_string(), - arguments: vec![], - doc: None, - sugar: false, - }], - doc: None, + pub fn known_enum(name: &str, constructors: &[&str]) -> Self { + Self { + name: name.to_string(), + constructors: RecordConstructor::known_enum(constructors), location: Span::empty(), - name: SCRIPT_CONTEXT.to_string(), opaque: false, - parameters: vec![], public: true, - typed_parameters: vec![], - } - } - - pub fn prng() -> Self { - DataType { - constructors: vec![ - RecordConstructor { - location: Span::empty(), - name: "Seeded".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: "Replayed".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - ], - doc: None, - location: Span::empty(), - name: "PRNG".to_string(), - opaque: false, parameters: vec![], - public: true, typed_parameters: vec![], - } - } - - pub fn ordering() -> Self { - DataType { - constructors: vec![ - RecordConstructor { - location: Span::empty(), - name: "Less".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: "Equal".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: "Greater".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - ], doc: None, - location: Span::empty(), - name: "Ordering".to_string(), - opaque: false, - parameters: vec![], - public: true, - typed_parameters: vec![], - } - } - - pub fn option(tipo: Rc) -> Self { - DataType { - constructors: vec![ - RecordConstructor { - location: Span::empty(), - name: "Some".to_string(), - arguments: vec![RecordConstructorArg { - label: None, - annotation: Annotation::Var { - location: Span::empty(), - name: "a".to_string(), - }, - location: Span::empty(), - tipo: tipo.clone(), - doc: None, - }], - doc: None, - sugar: false, - }, - RecordConstructor { - location: Span::empty(), - name: "None".to_string(), - arguments: vec![], - doc: None, - sugar: false, - }, - ], - doc: None, - location: Span::empty(), - name: "Option".to_string(), - opaque: false, - parameters: vec!["a".to_string()], - public: true, - typed_parameters: vec![tipo], } } } -pub type UntypedDataType = DataType<()>; - #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct DataType { pub constructors: Vec>, @@ -647,14 +462,14 @@ pub struct Validator { } impl TypedValidator { - pub fn available_purposes() -> Vec { + pub fn available_handler_names() -> Vec { vec![ - PURPOSE_SPEND.to_string(), - PURPOSE_MINT.to_string(), - PURPOSE_WITHDRAW.to_string(), - PURPOSE_PUBLISH.to_string(), - PURPOSE_VOTE.to_string(), - PURPOSE_PROPOSE.to_string(), + HANDLER_SPEND.to_string(), + HANDLER_MINT.to_string(), + HANDLER_WITHDRAW.to_string(), + HANDLER_PUBLISH.to_string(), + HANDLER_VOTE.to_string(), + HANDLER_PROPOSE.to_string(), ] } @@ -838,12 +653,12 @@ pub enum Constant { impl Constant { pub fn tipo(&self) -> Rc { match self { - Constant::Int { .. } => builtins::int(), - Constant::String { .. } => builtins::string(), - Constant::ByteArray { .. } => builtins::byte_array(), + Constant::Int { .. } => Type::int(), + Constant::String { .. } => Type::string(), + Constant::ByteArray { .. } => Type::byte_array(), Constant::CurvePoint { point, .. } => match point.as_ref() { - Curve::Bls12_381(Bls12_381Point::G1(_)) => builtins::g1_element(), - Curve::Bls12_381(Bls12_381Point::G2(_)) => builtins::g2_element(), + Curve::Bls12_381(Bls12_381Point::G1(_)) => Type::g1_element(), + Curve::Bls12_381(Bls12_381Point::G2(_)) => Type::g2_element(), }, } } @@ -896,6 +711,19 @@ impl RecordConstructor { pub fn put_doc(&mut self, new_doc: String) { self.doc = Some(new_doc); } + + pub fn known_enum(names: &[&str]) -> Vec> { + names + .iter() + .map(|name| RecordConstructor { + location: Span::empty(), + name: name.to_string(), + arguments: vec![], + doc: None, + sugar: false, + }) + .collect() + } } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -1601,8 +1429,8 @@ impl TypedPattern { // TODO: This function definition is weird, see where this is used and how. pub fn tipo(&self, value: &TypedExpr) -> Option> { match self { - Pattern::Int { .. } => Some(builtins::int()), - Pattern::ByteArray { .. } => Some(builtins::byte_array()), + Pattern::Int { .. } => Some(Type::int()), + Pattern::ByteArray { .. } => Some(Type::byte_array()), Pattern::Constructor { tipo, .. } => Some(tipo.clone()), Pattern::Var { .. } | Pattern::Assign { .. } | Pattern::Discard { .. } => { Some(value.tipo()) @@ -1800,8 +1628,8 @@ impl<'de> serde::Deserialize<'de> for Bls12_381Point { impl Bls12_381Point { pub fn tipo(&self) -> Rc { match self { - Bls12_381Point::G1(_) => g1_element(), - Bls12_381Point::G2(_) => g2_element(), + Bls12_381Point::G1(_) => Type::g1_element(), + Bls12_381Point::G2(_) => Type::g2_element(), } } } diff --git a/crates/aiken-lang/src/ast/well_known.rs b/crates/aiken-lang/src/ast/well_known.rs new file mode 100644 index 000000000..d97db55aa --- /dev/null +++ b/crates/aiken-lang/src/ast/well_known.rs @@ -0,0 +1,339 @@ +use crate::{ + ast::{Annotation, Span}, + tipo::{Type, TypeAliasAnnotation, TypeVar}, +}; +use std::{cell::RefCell, rc::Rc}; + +pub const BOOL: &str = "Bool"; +pub const BOOL_CONSTRUCTORS: &[&str] = &["False", "True"]; +pub const BYTE_ARRAY: &str = "ByteArray"; +pub const DATA: &str = "Data"; +pub const FUZZER: &str = "Fuzzer"; +pub const G1_ELEMENT: &str = "G1Element"; +pub const G2_ELEMENT: &str = "G2Element"; +pub const INT: &str = "Int"; +pub const LIST: &str = "List"; +pub const MILLER_LOOP_RESULT: &str = "MillerLoopResult"; +pub const OPTION: &str = "Option"; +pub const OPTION_CONSTRUCTORS: &[&str] = &["Some", "None"]; +pub const ORDERING: &str = "Ordering"; +pub const ORDERING_CONSTRUCTORS: &[&str] = &["Less", "Equal", "Greater"]; +pub const PAIR: &str = "Pair"; +pub const PAIRS: &str = "Pairs"; +pub const PRNG: &str = "PRNG"; +pub const PRNG_CONSTRUCTORS: &[&str] = &["Seeded", "Replayed"]; +pub const REDEEMER_WRAPPER: &str = "RedeemerWrapper"; +pub const STRING: &str = "String"; +pub const VOID: &str = "Void"; +pub const VOID_CONSTRUCTORS: &[&str] = &["Void"]; + +pub const SCRIPT_CONTEXT: &str = "__ScriptContext"; +pub const SCRIPT_CONTEXT_CONSTRUCTORS: &[&str] = &["__ScriptContext"]; +pub const SCRIPT_CONTEXT_TRANSACTION: &str = "__Transaction"; +pub const SCRIPT_CONTEXT_REDEEMER: &str = "__Redeemer"; +pub const SCRIPT_CONTEXT_PURPOSE: &str = "__ScriptPurpose"; + +pub const SCRIPT_PURPOSE: &str = "__ScriptPurpose"; +pub const SCRIPT_PURPOSE_MINT: &str = "__Mint"; +pub const SCRIPT_PURPOSE_SPEND: &str = "__Spend"; +pub const SCRIPT_PURPOSE_WITHDRAW: &str = "__Withdraw"; +pub const SCRIPT_PURPOSE_PUBLISH: &str = "__Publish"; +pub const SCRIPT_PURPOSE_VOTE: &str = "__Vote"; +pub const SCRIPT_PURPOSE_PROPOSE: &str = "__Propose"; +pub const SCRIPT_PURPOSE_CONSTRUCTORS: &[&str] = &[ + SCRIPT_PURPOSE_MINT, + SCRIPT_PURPOSE_SPEND, + SCRIPT_PURPOSE_WITHDRAW, + SCRIPT_PURPOSE_PUBLISH, + SCRIPT_PURPOSE_VOTE, + SCRIPT_PURPOSE_PROPOSE, +]; + +// ---------------------------------------------------------------------------- +// Types + +impl Type { + pub fn data() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + name: DATA.to_string(), + module: "".to_string(), + args: vec![], + alias: None, + }) + } + + pub fn int() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + name: INT.to_string(), + module: "".to_string(), + args: vec![], + alias: None, + }) + } + + pub fn bool() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: BOOL.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn byte_array() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: BYTE_ARRAY.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn g1_element() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + module: "".to_string(), + name: G1_ELEMENT.to_string(), + args: vec![], + alias: None, + }) + } + + pub fn g2_element() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + module: "".to_string(), + name: G2_ELEMENT.to_string(), + args: vec![], + alias: None, + }) + } + + pub fn miller_loop_result() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + module: "".to_string(), + name: MILLER_LOOP_RESULT.to_string(), + args: vec![], + alias: None, + }) + } + + pub fn tuple(elems: Vec>) -> Rc { + Rc::new(Type::Tuple { elems, alias: None }) + } + + pub fn pair(fst: Rc, snd: Rc) -> Rc { + Rc::new(Type::Pair { + fst, + snd, + alias: None, + }) + } + + pub fn script_purpose() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: SCRIPT_PURPOSE.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn script_context() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: SCRIPT_CONTEXT.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn prng() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: PRNG.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn fuzzer(a: Rc) -> Rc { + let prng_annotation = Annotation::Constructor { + location: Span::empty(), + module: None, + name: PRNG.to_string(), + arguments: vec![], + }; + + Rc::new(Type::Fn { + args: vec![Type::prng()], + ret: Type::option(Type::tuple(vec![Type::prng(), a])), + alias: Some( + TypeAliasAnnotation { + alias: FUZZER.to_string(), + parameters: vec!["a".to_string()], + annotation: Annotation::Fn { + location: Span::empty(), + arguments: vec![prng_annotation.clone()], + ret: Annotation::Constructor { + location: Span::empty(), + module: None, + name: OPTION.to_string(), + arguments: vec![Annotation::Tuple { + location: Span::empty(), + elems: vec![ + prng_annotation, + Annotation::Var { + location: Span::empty(), + name: "a".to_string(), + }, + ], + }], + } + .into(), + }, + } + .into(), + ), + }) + } + + pub fn map(k: Rc, v: Rc) -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + module: "".to_string(), + name: LIST.to_string(), + args: vec![Type::pair(k, v)], + alias: Some( + TypeAliasAnnotation { + alias: PAIRS.to_string(), + parameters: vec!["k".to_string(), "v".to_string()], + annotation: Annotation::Constructor { + location: Span::empty(), + module: None, + name: LIST.to_string(), + arguments: vec![Annotation::Pair { + location: Span::empty(), + fst: Box::new(Annotation::Var { + location: Span::empty(), + name: "k".to_string(), + }), + snd: Box::new(Annotation::Var { + location: Span::empty(), + name: "v".to_string(), + }), + }], + }, + } + .into(), + ), + }) + } + + pub fn list(t: Rc) -> Rc { + Rc::new(Type::App { + public: true, + // FIXME: We should probably have t.contains_opaque here? + contains_opaque: false, + name: LIST.to_string(), + module: "".to_string(), + args: vec![t], + alias: None, + }) + } + + pub fn string() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: STRING.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn void() -> Rc { + Rc::new(Type::App { + args: vec![], + public: true, + contains_opaque: false, + name: VOID.to_string(), + module: "".to_string(), + alias: None, + }) + } + + pub fn option(a: Rc) -> Rc { + Rc::new(Type::App { + public: true, + // FIXME: We should probably have t.contains_opaque here? + contains_opaque: false, + name: OPTION.to_string(), + module: "".to_string(), + args: vec![a], + alias: None, + }) + } + + pub fn ordering() -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + name: ORDERING.to_string(), + module: "".to_string(), + args: vec![], + alias: None, + }) + } + + pub fn function(args: Vec>, ret: Rc) -> Rc { + Rc::new(Type::Fn { + ret, + args, + alias: None, + }) + } + + pub fn generic_var(id: u64) -> Rc { + let tipo = Rc::new(RefCell::new(TypeVar::Generic { id })); + + Rc::new(Type::Var { tipo, alias: None }) + } + + pub fn unbound_var(id: u64) -> Rc { + let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id })); + + Rc::new(Type::Var { tipo, alias: None }) + } + + pub fn wrapped_redeemer(redeemer: Rc) -> Rc { + Rc::new(Type::App { + public: true, + contains_opaque: false, + module: "".to_string(), + name: REDEEMER_WRAPPER.to_string(), + args: vec![redeemer], + alias: None, + }) + } +} diff --git a/crates/aiken-lang/src/builtins.rs b/crates/aiken-lang/src/builtins.rs index 72a6854c3..8e47c4321 100644 --- a/crates/aiken-lang/src/builtins.rs +++ b/crates/aiken-lang/src/builtins.rs @@ -1,56 +1,25 @@ use crate::{ aiken_fn, ast::{ - Annotation, ArgName, CallArg, DataTypeKey, Function, FunctionAccessKey, ModuleKind, - OnTestFailure, Span, TypedArg, TypedDataType, TypedFunction, UnOp, + well_known, Annotation, ArgName, CallArg, DataType, DataTypeKey, Function, + FunctionAccessKey, ModuleKind, OnTestFailure, RecordConstructor, RecordConstructorArg, + Span, TypedArg, TypedDataType, TypedFunction, UnOp, }, expr::TypedExpr, tipo::{ - fields::FieldMap, Type, TypeAliasAnnotation, TypeConstructor, TypeInfo, TypeVar, - ValueConstructor, ValueConstructorVariant, + fields::FieldMap, Type, TypeConstructor, TypeInfo, ValueConstructor, + ValueConstructorVariant, }, IdGenerator, }; use indexmap::IndexMap; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{collections::HashMap, rc::Rc}; use strum::IntoEnumIterator; use uplc::builtins::DefaultFunction; pub const PRELUDE: &str = "aiken"; pub const BUILTIN: &str = "aiken/builtin"; -pub const BYTE_ARRAY: &str = "ByteArray"; -pub const BOOL: &str = "Bool"; -pub const INT: &str = "Int"; -pub const DATA: &str = "Data"; -pub const LIST: &str = "List"; -pub const PAIR: &str = "Pair"; -pub const PAIRS: &str = "Pairs"; -pub const VOID: &str = "Void"; -pub const G1_ELEMENT: &str = "G1Element"; -pub const G2_ELEMENT: &str = "G2Element"; -pub const MILLER_LOOP_RESULT: &str = "MillerLoopResult"; -pub const STRING: &str = "String"; -pub const OPTION: &str = "Option"; -pub const ORDERING: &str = "Ordering"; -pub const REDEEMER_WRAPPER: &str = "RedeemerWrapper"; -pub const PRNG: &str = "PRNG"; -pub const FUZZER: &str = "Fuzzer"; - -pub const SCRIPT_PURPOSE: &str = "__ScriptPurpose"; -pub const SCRIPT_PURPOSE_SPEND: &str = "__Spend"; -pub const SCRIPT_PURPOSE_MINT: &str = "__Mint"; -pub const SCRIPT_PURPOSE_WITHDRAW: &str = "__Withdraw"; -pub const SCRIPT_PURPOSE_PUBLISH: &str = "__Publish"; -pub const SCRIPT_PURPOSE_VOTE: &str = "__Vote"; -pub const SCRIPT_PURPOSE_PROPOSE: &str = "__Propose"; -pub const SCRIPT_PURPOSES_COUNT: u16 = 6; - -pub const SCRIPT_CONTEXT: &str = "__ScriptContext"; -pub const SCRIPT_CONTEXT_TRANSACTION: &str = "__Transaction"; -pub const SCRIPT_CONTEXT_REDEEMER: &str = "__Redeemer"; -pub const SCRIPT_CONTEXT_PURPOSE: &str = "__ScriptPurpose"; - /// Build a prelude that can be injected /// into a compiler pipeline pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { @@ -65,196 +34,201 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { annotations: HashMap::new(), }; - // Int + // Data prelude.types.insert( - INT.to_string(), - TypeConstructor { - parameters: vec![], - tipo: int(), - location: Span::empty(), - module: "".to_string(), - public: true, - }, + well_known::DATA.to_string(), + TypeConstructor::primitive(Type::data()), ); - // Data + // Int prelude.types.insert( - DATA.to_string(), - TypeConstructor { - parameters: vec![], - tipo: data(), - location: Span::empty(), - module: "".to_string(), - public: true, - }, + well_known::INT.to_string(), + TypeConstructor::primitive(Type::int()), ); // ByteArray prelude.types.insert( - BYTE_ARRAY.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: byte_array(), - module: "".to_string(), - public: true, - }, + well_known::BYTE_ARRAY.to_string(), + TypeConstructor::primitive(Type::byte_array()), ); // Bool + prelude.types.insert( + well_known::BOOL.to_string(), + TypeConstructor::primitive(Type::bool()), + ); prelude.types_constructors.insert( - BOOL.to_string(), - vec!["False".to_string(), "True".to_string()], + well_known::BOOL.to_string(), + ValueConstructor::known_enum( + &mut prelude.values, + Type::bool(), + well_known::BOOL_CONSTRUCTORS, + ), ); - prelude.values.insert( - "False".to_string(), - ValueConstructor::public( - bool(), - ValueConstructorVariant::Record { - module: "".into(), - name: "False".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 2, - }, - ), + // G1Element + prelude.types.insert( + well_known::G1_ELEMENT.to_string(), + TypeConstructor::primitive(Type::g1_element()), ); - prelude.values.insert( - "True".to_string(), - ValueConstructor::public( - bool(), - ValueConstructorVariant::Record { - module: "".into(), - name: "True".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 2, - }, - ), + // G2Element + prelude.types.insert( + well_known::G2_ELEMENT.to_string(), + TypeConstructor::primitive(Type::g2_element()), ); + // MillerLoopResult prelude.types.insert( - BOOL.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: bool(), - module: "".to_string(), - public: true, - }, + well_known::MILLER_LOOP_RESULT.to_string(), + TypeConstructor::primitive(Type::miller_loop_result()), ); - // G1Element + // Ordering prelude.types.insert( - G1_ELEMENT.to_string(), - TypeConstructor { - parameters: vec![], - tipo: g1_element(), - location: Span::empty(), - module: "".to_string(), - public: true, - }, + well_known::ORDERING.to_string(), + TypeConstructor::primitive(Type::ordering()), + ); + prelude.types_constructors.insert( + well_known::ORDERING.to_string(), + ValueConstructor::known_enum( + &mut prelude.values, + Type::ordering(), + well_known::ORDERING_CONSTRUCTORS, + ), ); - // G2Element + // String prelude.types.insert( - G2_ELEMENT.to_string(), - TypeConstructor { - parameters: vec![], - tipo: g2_element(), - location: Span::empty(), - module: "".to_string(), - public: true, - }, + well_known::STRING.to_string(), + TypeConstructor::primitive(Type::string()), ); - // MillerLoopResult + // Void prelude.types.insert( - MILLER_LOOP_RESULT.to_string(), - TypeConstructor { - parameters: vec![], - tipo: miller_loop_result(), - location: Span::empty(), - module: "".to_string(), - public: true, - }, + well_known::VOID.to_string(), + TypeConstructor::primitive(Type::void()), + ); + prelude.types_constructors.insert( + well_known::VOID.to_string(), + ValueConstructor::known_enum( + &mut prelude.values, + Type::void(), + well_known::VOID_CONSTRUCTORS, + ), ); - // Ordering + // List(a) + prelude.types.insert( + well_known::LIST.to_string(), + TypeConstructor::primitive(Type::list(Type::generic_var(id_gen.next()))), + ); + + // Pair(a, b) + prelude.types.insert( + well_known::PAIR.to_string(), + TypeConstructor::primitive(Type::pair( + Type::generic_var(id_gen.next()), + Type::generic_var(id_gen.next()), + )), + ); prelude.types_constructors.insert( - ORDERING.to_string(), - vec![ - "Less".to_string(), - "Equal".to_string(), - "Greater".to_string(), - ], + well_known::PAIR.to_string(), + vec![well_known::PAIR.to_string()], ); - prelude.values.insert( - "Less".to_string(), - ValueConstructor::public( - ordering(), - ValueConstructorVariant::Record { - module: "".into(), - name: "Less".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 3, - }, - ), + // Pairs = List> + prelude.types.insert( + well_known::PAIRS.to_string(), + TypeConstructor::primitive(Type::map( + Type::generic_var(id_gen.next()), + Type::generic_var(id_gen.next()), + )), ); - prelude.values.insert( - "Equal".to_string(), - ValueConstructor::public( - ordering(), - ValueConstructorVariant::Record { - module: "".into(), - name: "Equal".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 3, - }, + // Option(value) + let option_value = Type::generic_var(id_gen.next()); + prelude.types.insert( + well_known::OPTION.to_string(), + TypeConstructor::primitive(Type::option(option_value.clone())), + ); + let some_type = Type::function( + vec![option_value.clone()], + Type::option(option_value.clone()), + ); + let none_type = Type::option(option_value); + prelude.types_constructors.insert( + well_known::OPTION.to_string(), + ValueConstructor::known_adt( + &mut prelude.values, + &[ + (well_known::OPTION_CONSTRUCTORS[0], some_type), + (well_known::OPTION_CONSTRUCTORS[1], none_type), + ], ), ); - prelude.values.insert( - "Greater".to_string(), - ValueConstructor::public( - ordering(), - ValueConstructorVariant::Record { - module: "".into(), - name: "Greater".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 3, - }, - ), + // Cardano ScriptContext + prelude.types.insert( + well_known::SCRIPT_CONTEXT.to_string(), + TypeConstructor::primitive(Type::script_context()), + ); + prelude.types_constructors.insert( + well_known::SCRIPT_CONTEXT.to_string(), + vec![ + well_known::SCRIPT_CONTEXT_TRANSACTION.to_string(), + well_known::SCRIPT_CONTEXT_REDEEMER.to_string(), + well_known::SCRIPT_CONTEXT_PURPOSE.to_string(), + ], ); + // Cardano ScriptPurpose prelude.types.insert( - ORDERING.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: ordering(), - module: "".to_string(), - public: true, - }, + well_known::SCRIPT_PURPOSE.to_string(), + TypeConstructor::primitive(Type::script_purpose()), + ); + + prelude.types_constructors.insert( + well_known::SCRIPT_PURPOSE.to_string(), + ValueConstructor::known_adt( + &mut prelude.values, + &[ + ( + well_known::SCRIPT_PURPOSE_MINT, + Type::function(vec![Type::data()], Type::script_purpose()), + ), + ( + well_known::SCRIPT_PURPOSE_SPEND, + Type::function( + vec![Type::data(), Type::option(Type::data())], + Type::script_purpose(), + ), + ), + ( + well_known::SCRIPT_PURPOSE_WITHDRAW, + Type::function(vec![Type::data()], Type::script_purpose()), + ), + ( + well_known::SCRIPT_PURPOSE_PUBLISH, + Type::function(vec![Type::int(), Type::data()], Type::script_purpose()), + ), + ( + well_known::SCRIPT_PURPOSE_VOTE, + Type::function(vec![Type::data()], Type::script_purpose()), + ), + ( + well_known::SCRIPT_PURPOSE_PROPOSE, + Type::function(vec![Type::int(), Type::data()], Type::script_purpose()), + ), + ], + ), ); // not prelude.values.insert( "not".to_string(), ValueConstructor::public( - function(vec![bool()], bool()), + Type::function(vec![Type::bool()], Type::bool()), ValueConstructorVariant::ModuleFn { name: "not".to_string(), field_map: None, @@ -267,11 +241,11 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { ); // identity - let identity_var = generic_var(id_gen.next()); + let identity_var = Type::generic_var(id_gen.next()); prelude.values.insert( "identity".to_string(), ValueConstructor::public( - function(vec![identity_var.clone()], identity_var), + Type::function(vec![identity_var.clone()], identity_var), ValueConstructorVariant::ModuleFn { name: "identity".to_string(), field_map: None, @@ -284,20 +258,20 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { ); // enumerate - let enumerate_a = generic_var(id_gen.next()); - let enumerate_b = generic_var(id_gen.next()); + let enumerate_a = Type::generic_var(id_gen.next()); + let enumerate_b = Type::generic_var(id_gen.next()); prelude.values.insert( "enumerate".to_string(), ValueConstructor::public( - function( + Type::function( vec![ - list(enumerate_a.clone()), + Type::list(enumerate_a.clone()), enumerate_b.clone(), - function( + Type::function( vec![enumerate_a.clone(), enumerate_b.clone()], enumerate_b.clone(), ), - function( + Type::function( vec![enumerate_a.clone(), enumerate_b.clone()], enumerate_b.clone(), ), @@ -319,7 +293,10 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "encode_base16".to_string(), ValueConstructor::public( - function(vec![byte_array(), int(), byte_array()], byte_array()), + Type::function( + vec![Type::byte_array(), Type::int(), Type::byte_array()], + Type::byte_array(), + ), ValueConstructorVariant::ModuleFn { name: "encode_base16".to_string(), field_map: None, @@ -335,7 +312,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "from_int".to_string(), ValueConstructor::public( - function(vec![int(), byte_array()], byte_array()), + Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array()), ValueConstructorVariant::ModuleFn { name: "from_int".to_string(), field_map: None, @@ -351,7 +328,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "do_from_int".to_string(), ValueConstructor::public( - function(vec![int(), byte_array()], byte_array()), + Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array()), ValueConstructorVariant::ModuleFn { name: "do_from_int".to_string(), field_map: None, @@ -367,7 +344,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "diagnostic".to_string(), ValueConstructor::public( - function(vec![data(), byte_array()], byte_array()), + Type::function(vec![Type::data(), Type::byte_array()], Type::byte_array()), ValueConstructorVariant::ModuleFn { name: "diagnostic".to_string(), field_map: None, @@ -380,12 +357,12 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { ); // always - let always_a_var = generic_var(id_gen.next()); - let always_b_var = generic_var(id_gen.next()); + let always_a_var = Type::generic_var(id_gen.next()); + let always_b_var = Type::generic_var(id_gen.next()); prelude.values.insert( "always".to_string(), ValueConstructor::public( - function(vec![always_a_var.clone(), always_b_var], always_a_var), + Type::function(vec![always_a_var.clone(), always_b_var], always_a_var), ValueConstructorVariant::ModuleFn { name: "always".to_string(), field_map: None, @@ -398,20 +375,21 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { ); // flip - let flip_a_var = generic_var(id_gen.next()); - let flip_b_var = generic_var(id_gen.next()); - let flip_c_var = generic_var(id_gen.next()); + let flip_a_var = Type::generic_var(id_gen.next()); + let flip_b_var = Type::generic_var(id_gen.next()); + let flip_c_var = Type::generic_var(id_gen.next()); - let input_type = function( + let input_type = Type::function( vec![flip_a_var.clone(), flip_b_var.clone()], flip_c_var.clone(), ); - let return_type = function(vec![flip_b_var, flip_a_var], flip_c_var); + + let return_type = Type::function(vec![flip_b_var, flip_a_var], flip_c_var); prelude.values.insert( "flip".to_string(), ValueConstructor::public( - function(vec![input_type], return_type), + Type::function(vec![input_type], return_type), ValueConstructorVariant::ModuleFn { name: "flip".to_string(), field_map: None, @@ -423,129 +401,6 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { ), ); - // List(a) - let list_parameter = generic_var(id_gen.next()); - prelude.types.insert( - LIST.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![list_parameter.clone()], - tipo: list(list_parameter), - module: "".to_string(), - public: true, - }, - ); - - // Pair(a, b) - let fst_parameter = generic_var(id_gen.next()); - let snd_parameter = generic_var(id_gen.next()); - prelude.types.insert( - PAIR.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![fst_parameter.clone(), snd_parameter.clone()], - tipo: pair(fst_parameter.clone(), snd_parameter.clone()), - module: "".to_string(), - public: true, - }, - ); - - prelude - .types_constructors - .insert(PAIR.to_string(), vec![PAIR.to_string()]); - - // String - prelude.types.insert( - STRING.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: string(), - module: "".to_string(), - public: true, - }, - ); - - // Void - prelude - .types_constructors - .insert(VOID.to_string(), vec![VOID.to_string()]); - - prelude.values.insert( - VOID.to_string(), - ValueConstructor::public( - void(), - ValueConstructorVariant::Record { - module: "".into(), - name: VOID.to_string(), - arity: 0, - field_map: None::, - location: Span::empty(), - constructors_count: 1, - }, - ), - ); - - prelude.types.insert( - VOID.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: void(), - module: "".to_string(), - public: true, - }, - ); - - // Option(value) - let option_value = generic_var(id_gen.next()); - - prelude.types.insert( - OPTION.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![option_value.clone()], - tipo: option(option_value.clone()), - module: "".to_string(), - public: true, - }, - ); - - prelude.types_constructors.insert( - OPTION.to_string(), - vec!["Some".to_string(), "None".to_string()], - ); - - prelude.values.insert( - "Some".to_string(), - ValueConstructor::public( - function(vec![option_value.clone()], option(option_value.clone())), - ValueConstructorVariant::Record { - module: "".into(), - name: "Some".to_string(), - field_map: None::, - arity: 1, - location: Span::empty(), - constructors_count: 2, - }, - ), - ); - - prelude.values.insert( - "None".to_string(), - ValueConstructor::public( - option(option_value), - ValueConstructorVariant::Record { - module: "".into(), - name: "None".to_string(), - field_map: None::, - arity: 0, - location: Span::empty(), - constructors_count: 2, - }, - ), - ); - // PRNG // // pub type PRNG { @@ -553,18 +408,12 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { // Replayed { cursor: Int, choices: ByteArray } // } prelude.types.insert( - PRNG.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![], - tipo: prng(), - module: "".to_string(), - public: true, - }, + well_known::PRNG.to_string(), + TypeConstructor::primitive(Type::prng()), ); prelude.types_constructors.insert( - PRNG.to_string(), + well_known::PRNG.to_string(), vec!["Seeded".to_string(), "Replayed".to_string()], ); @@ -574,7 +423,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "Seeded".to_string(), ValueConstructor::public( - function(vec![byte_array(), byte_array()], prng()), + Type::function(vec![Type::byte_array(), Type::byte_array()], Type::prng()), ValueConstructorVariant::Record { module: "".into(), name: "Seeded".to_string(), @@ -596,7 +445,7 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { prelude.values.insert( "Replayed".to_string(), ValueConstructor::public( - function(vec![int(), byte_array()], prng()), + Type::function(vec![Type::int(), Type::byte_array()], Type::prng()), ValueConstructorVariant::Record { module: "".into(), name: "Replayed".to_string(), @@ -616,105 +465,18 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { // // pub type Fuzzer = // fn(PRNG) -> Option<(PRNG, a)> - let fuzzer_value = generic_var(id_gen.next()); + let fuzzer_value = Type::generic_var(id_gen.next()); prelude.types.insert( - FUZZER.to_string(), + well_known::FUZZER.to_string(), TypeConstructor { location: Span::empty(), parameters: vec![fuzzer_value.clone()], - tipo: fuzzer(fuzzer_value), + tipo: Type::fuzzer(fuzzer_value), module: "".to_string(), public: true, }, ); - // Map - // - // pub type Map = List> - let alist_key = generic_var(id_gen.next()); - let alist_value = generic_var(id_gen.next()); - prelude.types.insert( - PAIRS.to_string(), - TypeConstructor { - location: Span::empty(), - parameters: vec![alist_key.clone(), alist_value.clone()], - tipo: map(alist_key, alist_value), - module: "".to_string(), - public: true, - }, - ); - - // Cardano ScriptContext - prelude.types_constructors.insert( - SCRIPT_CONTEXT.to_string(), - vec![ - SCRIPT_CONTEXT_TRANSACTION.to_string(), - SCRIPT_CONTEXT_REDEEMER.to_string(), - SCRIPT_CONTEXT_PURPOSE.to_string(), - ], - ); - - prelude.types.insert( - SCRIPT_CONTEXT.to_string(), - TypeConstructor { - location: Span::empty(), - public: true, - module: "".to_string(), - parameters: vec![], - tipo: script_context(), - }, - ); - - // Cardano ScriptPurpose - prelude.types_constructors.insert( - SCRIPT_PURPOSE.to_string(), - vec![ - SCRIPT_PURPOSE_MINT.to_string(), - SCRIPT_PURPOSE_SPEND.to_string(), - ], - ); - - prelude.values.insert( - SCRIPT_PURPOSE_MINT.to_string(), - ValueConstructor::public( - function(vec![data()], script_purpose()), - ValueConstructorVariant::Record { - module: "".into(), - name: SCRIPT_PURPOSE_MINT.to_string(), - field_map: None::, - arity: 1, - location: Span::empty(), - constructors_count: SCRIPT_PURPOSES_COUNT, - }, - ), - ); - - prelude.values.insert( - SCRIPT_PURPOSE_SPEND.to_string(), - ValueConstructor::public( - function(vec![data(), option(data())], script_purpose()), - ValueConstructorVariant::Record { - module: "".into(), - name: SCRIPT_PURPOSE_SPEND.to_string(), - field_map: None::, - arity: 2, - location: Span::empty(), - constructors_count: SCRIPT_PURPOSES_COUNT, - }, - ), - ); - - prelude.types.insert( - SCRIPT_PURPOSE.to_string(), - TypeConstructor { - location: Span::empty(), - public: true, - module: "".to_string(), - parameters: vec![], - tipo: script_purpose(), - }, - ); - prelude } @@ -748,47 +510,52 @@ pub fn from_default_function(builtin: DefaultFunction, id_gen: &IdGenerator) -> | DefaultFunction::QuotientInteger | DefaultFunction::RemainderInteger | DefaultFunction::ModInteger => { - let tipo = function(vec![int(), int()], int()); - + let tipo = Type::function(vec![Type::int(), Type::int()], Type::int()); (tipo, 2) } DefaultFunction::EqualsInteger | DefaultFunction::LessThanInteger | DefaultFunction::LessThanEqualsInteger => { - let tipo = function(vec![int(), int()], bool()); + let tipo = Type::function(vec![Type::int(), Type::int()], Type::bool()); (tipo, 2) } DefaultFunction::AppendByteString => { - let tipo = function(vec![byte_array(), byte_array()], byte_array()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array()], + Type::byte_array(), + ); (tipo, 2) } DefaultFunction::ConsByteString => { - let tipo = function(vec![int(), byte_array()], byte_array()); + let tipo = Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array()); (tipo, 2) } DefaultFunction::SliceByteString => { - let tipo = function(vec![int(), int(), byte_array()], byte_array()); + let tipo = Type::function( + vec![Type::int(), Type::int(), Type::byte_array()], + Type::byte_array(), + ); (tipo, 3) } DefaultFunction::LengthOfByteString => { - let tipo = function(vec![byte_array()], int()); + let tipo = Type::function(vec![Type::byte_array()], Type::int()); (tipo, 1) } DefaultFunction::IndexByteString => { - let tipo = function(vec![byte_array(), int()], int()); + let tipo = Type::function(vec![Type::byte_array(), Type::int()], Type::int()); (tipo, 2) } DefaultFunction::EqualsByteString | DefaultFunction::LessThanByteString | DefaultFunction::LessThanEqualsByteString => { - let tipo = function(vec![byte_array(), byte_array()], bool()); + let tipo = Type::function(vec![Type::byte_array(), Type::byte_array()], Type::bool()); (tipo, 2) } @@ -797,141 +564,159 @@ pub fn from_default_function(builtin: DefaultFunction, id_gen: &IdGenerator) -> | DefaultFunction::Blake2b_224 | DefaultFunction::Blake2b_256 | DefaultFunction::Keccak_256 => { - let tipo = function(vec![byte_array()], byte_array()); + let tipo = Type::function(vec![Type::byte_array()], Type::byte_array()); (tipo, 1) } DefaultFunction::VerifyEd25519Signature => { - let tipo = function(vec![byte_array(), byte_array(), byte_array()], bool()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array(), Type::byte_array()], + Type::bool(), + ); (tipo, 3) } DefaultFunction::VerifyEcdsaSecp256k1Signature => { - let tipo = function(vec![byte_array(), byte_array(), byte_array()], bool()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array(), Type::byte_array()], + Type::bool(), + ); (tipo, 3) } DefaultFunction::VerifySchnorrSecp256k1Signature => { - let tipo = function(vec![byte_array(), byte_array(), byte_array()], bool()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array(), Type::byte_array()], + Type::bool(), + ); (tipo, 3) } DefaultFunction::AppendString => { - let tipo = function(vec![string(), string()], string()); + let tipo = Type::function(vec![Type::string(), Type::string()], Type::string()); (tipo, 2) } DefaultFunction::EqualsString => { - let tipo = function(vec![string(), string()], bool()); + let tipo = Type::function(vec![Type::string(), Type::string()], Type::bool()); (tipo, 2) } DefaultFunction::EncodeUtf8 => { - let tipo = function(vec![string()], byte_array()); + let tipo = Type::function(vec![Type::string()], Type::byte_array()); (tipo, 1) } DefaultFunction::DecodeUtf8 => { - let tipo = function(vec![byte_array()], string()); + let tipo = Type::function(vec![Type::byte_array()], Type::string()); (tipo, 1) } DefaultFunction::IfThenElse => { - let ret = generic_var(id_gen.next()); + let ret = Type::generic_var(id_gen.next()); - let tipo = function(vec![bool(), ret.clone(), ret.clone()], ret); + let tipo = Type::function(vec![Type::bool(), ret.clone(), ret.clone()], ret); (tipo, 3) } DefaultFunction::HeadList => { - let ret = generic_var(id_gen.next()); + let ret = Type::generic_var(id_gen.next()); - let tipo = function(vec![list(ret.clone())], ret); + let tipo = Type::function(vec![Type::list(ret.clone())], ret); (tipo, 1) } DefaultFunction::TailList => { - let ret = list(generic_var(id_gen.next())); + let ret = Type::list(Type::generic_var(id_gen.next())); - let tipo = function(vec![ret.clone()], ret); + let tipo = Type::function(vec![ret.clone()], ret); (tipo, 1) } DefaultFunction::NullList => { - let ret = list(generic_var(id_gen.next())); + let ret = Type::list(Type::generic_var(id_gen.next())); - let tipo = function(vec![ret], bool()); + let tipo = Type::function(vec![ret], Type::bool()); (tipo, 1) } DefaultFunction::ConstrData => { - let tipo = function(vec![int(), list(data())], data()); + let tipo = Type::function(vec![Type::int(), Type::list(Type::data())], Type::data()); (tipo, 2) } DefaultFunction::MapData => { - let tipo = function(vec![list(pair(data(), data()))], data()); + let tipo = Type::function( + vec![Type::list(Type::pair(Type::data(), Type::data()))], + Type::data(), + ); (tipo, 1) } DefaultFunction::ListData => { - let tipo = function(vec![list(data())], data()); + let tipo = Type::function(vec![Type::list(Type::data())], Type::data()); (tipo, 1) } DefaultFunction::IData => { - let tipo = function(vec![int()], data()); + let tipo = Type::function(vec![Type::int()], Type::data()); (tipo, 1) } DefaultFunction::BData => { - let tipo = function(vec![byte_array()], data()); + let tipo = Type::function(vec![Type::byte_array()], Type::data()); (tipo, 1) } DefaultFunction::UnConstrData => { - let tipo = function(vec![data()], pair(int(), list(data()))); + let tipo = Type::function( + vec![Type::data()], + Type::pair(Type::int(), Type::list(Type::data())), + ); (tipo, 1) } DefaultFunction::UnMapData => { - let tipo = function(vec![data()], list(pair(data(), data()))); + let tipo = Type::function( + vec![Type::data()], + Type::list(Type::pair(Type::data(), Type::data())), + ); (tipo, 1) } DefaultFunction::UnListData => { - let tipo = function(vec![data()], list(data())); + let tipo = Type::function(vec![Type::data()], Type::list(Type::data())); (tipo, 1) } DefaultFunction::UnIData => { - let tipo = function(vec![data()], int()); + let tipo = Type::function(vec![Type::data()], Type::int()); (tipo, 1) } DefaultFunction::UnBData => { - let tipo = function(vec![data()], byte_array()); + let tipo = Type::function(vec![Type::data()], Type::byte_array()); (tipo, 1) } DefaultFunction::EqualsData => { - let tipo = function(vec![data(), data()], bool()); + let tipo = Type::function(vec![Type::data(), Type::data()], Type::bool()); (tipo, 2) } DefaultFunction::SerialiseData => { - let tipo = function(vec![data()], byte_array()); + let tipo = Type::function(vec![Type::data()], Type::byte_array()); (tipo, 1) } DefaultFunction::ChooseData => { - let a = generic_var(id_gen.next()); - let tipo = function( + let a = Type::generic_var(id_gen.next()); + let tipo = Type::function( vec![ - data(), + Type::data(), a.clone(), a.clone(), a.clone(), @@ -943,146 +728,170 @@ pub fn from_default_function(builtin: DefaultFunction, id_gen: &IdGenerator) -> (tipo, 6) } DefaultFunction::MkPairData => { - let tipo = function(vec![data(), data()], pair(data(), data())); + let tipo = Type::function( + vec![Type::data(), Type::data()], + Type::pair(Type::data(), Type::data()), + ); (tipo, 2) } DefaultFunction::MkNilData => { - let tipo = function(vec![], list(data())); + let tipo = Type::function(vec![], Type::list(Type::data())); (tipo, 0) } DefaultFunction::MkNilPairData => { - let tipo = function(vec![], list(pair(data(), data()))); + let tipo = Type::function(vec![], Type::list(Type::pair(Type::data(), Type::data()))); (tipo, 0) } DefaultFunction::ChooseUnit => { - let a = generic_var(id_gen.next()); - let tipo = function(vec![data(), a.clone()], a); + let a = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![Type::data(), a.clone()], a); (tipo, 2) } DefaultFunction::Trace => { - let a = generic_var(id_gen.next()); - let tipo = function(vec![string(), a.clone()], a); + let a = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![Type::string(), a.clone()], a); (tipo, 2) } DefaultFunction::FstPair => { - let a = generic_var(id_gen.next()); - let b = generic_var(id_gen.next()); - let tipo = function(vec![pair(a.clone(), b)], a); + let a = Type::generic_var(id_gen.next()); + let b = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![Type::pair(a.clone(), b)], a); (tipo, 1) } DefaultFunction::SndPair => { - let a = generic_var(id_gen.next()); - let b = generic_var(id_gen.next()); - let tipo = function(vec![pair(a, b.clone())], b); + let a = Type::generic_var(id_gen.next()); + let b = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![Type::pair(a, b.clone())], b); (tipo, 1) } DefaultFunction::ChooseList => { - let a = generic_var(id_gen.next()); - let b = generic_var(id_gen.next()); - let tipo = function(vec![list(a), b.clone(), b.clone()], b); + let a = Type::generic_var(id_gen.next()); + let b = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![Type::list(a), b.clone(), b.clone()], b); (tipo, 3) } DefaultFunction::MkCons => { - let a = generic_var(id_gen.next()); - let tipo = function(vec![a.clone(), list(a.clone())], list(a)); + let a = Type::generic_var(id_gen.next()); + let tipo = Type::function(vec![a.clone(), Type::list(a.clone())], Type::list(a)); (tipo, 2) } DefaultFunction::Bls12_381_G1_Add => { - let tipo = function(vec![g1_element(), g1_element()], g1_element()); + let tipo = Type::function( + vec![Type::g1_element(), Type::g1_element()], + Type::g1_element(), + ); (tipo, 2) } DefaultFunction::Bls12_381_G1_Equal => { - let tipo = function(vec![g1_element(), g1_element()], bool()); + let tipo = Type::function(vec![Type::g1_element(), Type::g1_element()], Type::bool()); (tipo, 2) } DefaultFunction::Bls12_381_G1_Neg => { - let tipo = function(vec![g1_element()], g1_element()); + let tipo = Type::function(vec![Type::g1_element()], Type::g1_element()); (tipo, 1) } DefaultFunction::Bls12_381_G1_ScalarMul => { - let tipo = function(vec![int(), g1_element()], g1_element()); + let tipo = Type::function(vec![Type::int(), Type::g1_element()], Type::g1_element()); (tipo, 2) } DefaultFunction::Bls12_381_G1_Compress => { - let tipo = function(vec![g1_element()], byte_array()); + let tipo = Type::function(vec![Type::g1_element()], Type::byte_array()); (tipo, 1) } DefaultFunction::Bls12_381_G1_Uncompress => { - let tipo = function(vec![byte_array()], g1_element()); + let tipo = Type::function(vec![Type::byte_array()], Type::g1_element()); (tipo, 1) } DefaultFunction::Bls12_381_G1_HashToGroup => { - let tipo = function(vec![byte_array(), byte_array()], g1_element()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array()], + Type::g1_element(), + ); (tipo, 2) } DefaultFunction::Bls12_381_G2_Add => { - let tipo = function(vec![g2_element(), g2_element()], g2_element()); + let tipo = Type::function( + vec![Type::g2_element(), Type::g2_element()], + Type::g2_element(), + ); (tipo, 2) } DefaultFunction::Bls12_381_G2_Equal => { - let tipo = function(vec![g2_element(), g2_element()], bool()); + let tipo = Type::function(vec![Type::g2_element(), Type::g2_element()], Type::bool()); (tipo, 2) } DefaultFunction::Bls12_381_G2_Neg => { - let tipo = function(vec![g2_element()], g2_element()); + let tipo = Type::function(vec![Type::g2_element()], Type::g2_element()); (tipo, 1) } DefaultFunction::Bls12_381_G2_ScalarMul => { - let tipo = function(vec![int(), g2_element()], g2_element()); + let tipo = Type::function(vec![Type::int(), Type::g2_element()], Type::g2_element()); (tipo, 2) } DefaultFunction::Bls12_381_G2_Compress => { - let tipo = function(vec![g2_element()], byte_array()); + let tipo = Type::function(vec![Type::g2_element()], Type::byte_array()); (tipo, 1) } DefaultFunction::Bls12_381_G2_Uncompress => { - let tipo = function(vec![byte_array()], g2_element()); + let tipo = Type::function(vec![Type::byte_array()], Type::g2_element()); (tipo, 1) } DefaultFunction::Bls12_381_G2_HashToGroup => { - let tipo = function(vec![byte_array(), byte_array()], g2_element()); + let tipo = Type::function( + vec![Type::byte_array(), Type::byte_array()], + Type::g2_element(), + ); (tipo, 2) } DefaultFunction::Bls12_381_MillerLoop => { - let tipo = function(vec![g1_element(), g2_element()], miller_loop_result()); + let tipo = Type::function( + vec![Type::g1_element(), Type::g2_element()], + Type::miller_loop_result(), + ); (tipo, 2) } DefaultFunction::Bls12_381_MulMlResult => { - let tipo = function( - vec![miller_loop_result(), miller_loop_result()], - miller_loop_result(), + let tipo = Type::function( + vec![Type::miller_loop_result(), Type::miller_loop_result()], + Type::miller_loop_result(), ); (tipo, 2) } DefaultFunction::Bls12_381_FinalVerify => { - let tipo = function(vec![miller_loop_result(), miller_loop_result()], bool()); + let tipo = Type::function( + vec![Type::miller_loop_result(), Type::miller_loop_result()], + Type::bool(), + ); (tipo, 2) } DefaultFunction::IntegerToByteString => { - let tipo = function(vec![bool(), int(), int()], byte_array()); + let tipo = Type::function( + vec![Type::bool(), Type::int(), Type::int()], + Type::byte_array(), + ); (tipo, 3) } DefaultFunction::ByteStringToInteger => { - let tipo = function(vec![bool(), byte_array()], int()); + let tipo = Type::function(vec![Type::bool(), Type::byte_array()], Type::int()); (tipo, 2) } @@ -1127,7 +936,7 @@ pub fn prelude_functions( doc: None, location: Span::empty(), annotation: None, - tipo: bool(), + tipo: Type::bool(), }], on_test_failure: OnTestFailure::FailImmediately, doc: Some( @@ -1141,17 +950,17 @@ pub fn prelude_functions( name: "not".to_string(), public: true, return_annotation: None, - return_type: bool(), + return_type: Type::bool(), end_position: 0, body: TypedExpr::UnOp { location: Span::empty(), - tipo: bool(), + tipo: Type::bool(), op: UnOp::Not, value: Box::new(TypedExpr::Var { location: Span::empty(), constructor: ValueConstructor { public: true, - tipo: bool(), + tipo: Type::bool(), variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, @@ -1166,7 +975,7 @@ pub fn prelude_functions( // pub fn identity(a: a) -> a { // a // } - let a_var = generic_var(id_gen.next()); + let a_var = Type::generic_var(id_gen.next()); functions.insert( FunctionAccessKey { @@ -1219,8 +1028,8 @@ pub fn prelude_functions( // pub fn always(a: a, b _b: b) -> a { // a // } - let a_var = generic_var(id_gen.next()); - let b_var = generic_var(id_gen.next()); + let a_var = Type::generic_var(id_gen.next()); + let b_var = Type::generic_var(id_gen.next()); functions.insert( FunctionAccessKey { @@ -1294,12 +1103,12 @@ pub fn prelude_functions( // pub fn flip(f: fn(a, b) -> c) -> fn(b, a) -> c { // fn(b, a) { f(a, b) } // } - let a_var = generic_var(id_gen.next()); - let b_var = generic_var(id_gen.next()); - let c_var = generic_var(id_gen.next()); + let a_var = Type::generic_var(id_gen.next()); + let b_var = Type::generic_var(id_gen.next()); + let c_var = Type::generic_var(id_gen.next()); - let input_type = function(vec![a_var.clone(), b_var.clone()], c_var.clone()); - let return_type = function(vec![b_var.clone(), a_var.clone()], c_var.clone()); + let input_type = Type::function(vec![a_var.clone(), b_var.clone()], c_var.clone()); + let return_type = Type::function(vec![b_var.clone(), a_var.clone()], c_var.clone()); functions.insert( FunctionAccessKey { @@ -1659,7 +1468,7 @@ pub fn prelude_data_types(id_gen: &IdGenerator) -> IndexMap IndexMap IndexMap IndexMap IndexMap IndexMap IndexMap Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - name: INT.to_string(), - module: "".to_string(), - args: vec![], - alias: None, - }) -} +// ---------------------------------------------------------------------------- +// TypedDataTypes +// +// TODO: Rewrite in terms of ValueConstructor to avoid duplication and ensure +// consistency with prelude definitions. -pub fn data() -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - name: DATA.to_string(), - module: "".to_string(), - args: vec![], - alias: None, - }) -} - -pub fn byte_array() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: BYTE_ARRAY.to_string(), - module: "".to_string(), - alias: None, - }) -} - -pub fn g1_element() -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - module: "".to_string(), - name: G1_ELEMENT.to_string(), - args: vec![], - alias: None, - }) -} - -pub fn g2_element() -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - module: "".to_string(), - name: G2_ELEMENT.to_string(), - args: vec![], - alias: None, - }) -} - -pub fn miller_loop_result() -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - module: "".to_string(), - name: MILLER_LOOP_RESULT.to_string(), - args: vec![], - alias: None, - }) -} - -pub fn tuple(elems: Vec>) -> Rc { - Rc::new(Type::Tuple { elems, alias: None }) -} - -pub fn pair(fst: Rc, snd: Rc) -> Rc { - Rc::new(Type::Pair { - fst, - snd, - alias: None, - }) -} +impl TypedDataType { + pub fn data() -> Self { + DataType::known_enum(well_known::DATA, &[]) + } -pub fn bool() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: BOOL.to_string(), - module: "".to_string(), - alias: None, - }) -} + pub fn bool() -> Self { + DataType::known_enum(well_known::BOOL, well_known::BOOL_CONSTRUCTORS) + } -pub fn script_purpose() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: SCRIPT_PURPOSE.to_string(), - module: "".to_string(), - alias: None, - }) -} + pub fn script_purpose() -> Self { + DataType::known_enum( + well_known::SCRIPT_PURPOSE, + well_known::SCRIPT_PURPOSE_CONSTRUCTORS, + ) + } -pub fn script_context() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: SCRIPT_CONTEXT.to_string(), - module: "".to_string(), - alias: None, - }) -} + pub fn script_context() -> Self { + DataType::known_enum( + well_known::SCRIPT_CONTEXT, + well_known::SCRIPT_CONTEXT_CONSTRUCTORS, + ) + } -pub fn prng() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: PRNG.to_string(), - module: "".to_string(), - alias: None, - }) -} + pub fn prng() -> Self { + DataType::known_enum(well_known::PRNG, well_known::PRNG_CONSTRUCTORS) + } -pub fn fuzzer(a: Rc) -> Rc { - let prng_annotation = Annotation::Constructor { - location: Span::empty(), - module: None, - name: "PRNG".to_string(), - arguments: vec![], - }; + pub fn ordering() -> Self { + DataType::known_enum(well_known::ORDERING, well_known::ORDERING_CONSTRUCTORS) + } - Rc::new(Type::Fn { - args: vec![prng()], - ret: option(tuple(vec![prng(), a])), - alias: Some( - TypeAliasAnnotation { - alias: "Fuzzer".to_string(), - parameters: vec!["a".to_string()], - annotation: Annotation::Fn { + pub fn option(tipo: Rc) -> Self { + DataType { + constructors: vec![ + RecordConstructor { location: Span::empty(), - arguments: vec![prng_annotation.clone()], - ret: Annotation::Constructor { - location: Span::empty(), - module: None, - name: "Option".to_string(), - arguments: vec![Annotation::Tuple { + name: well_known::OPTION_CONSTRUCTORS[0].to_string(), + arguments: vec![RecordConstructorArg { + label: None, + annotation: Annotation::Var { location: Span::empty(), - elems: vec![ - prng_annotation, - Annotation::Var { - location: Span::empty(), - name: "a".to_string(), - }, - ], - }], - } - .into(), - }, - } - .into(), - ), - }) -} - -pub fn map(k: Rc, v: Rc) -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - module: "".to_string(), - name: LIST.to_string(), - args: vec![pair(k, v)], - alias: Some( - TypeAliasAnnotation { - alias: PAIRS.to_string(), - parameters: vec!["k".to_string(), "v".to_string()], - annotation: Annotation::Constructor { - location: Span::empty(), - module: None, - name: LIST.to_string(), - arguments: vec![Annotation::Pair { + name: "a".to_string(), + }, location: Span::empty(), - fst: Box::new(Annotation::Var { - location: Span::empty(), - name: "k".to_string(), - }), - snd: Box::new(Annotation::Var { - location: Span::empty(), - name: "v".to_string(), - }), + tipo: tipo.clone(), + doc: None, }], + doc: None, + sugar: false, }, - } - .into(), - ), - }) -} - -pub fn list(t: Rc) -> Rc { - Rc::new(Type::App { - public: true, - // FIXME: We should probably have t.contains_opaque here? - contains_opaque: false, - name: LIST.to_string(), - module: "".to_string(), - args: vec![t], - alias: None, - }) -} - -pub fn string() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: STRING.to_string(), - module: "".to_string(), - alias: None, - }) -} - -pub fn void() -> Rc { - Rc::new(Type::App { - args: vec![], - public: true, - contains_opaque: false, - name: VOID.to_string(), - module: "".to_string(), - alias: None, - }) -} - -pub fn option(a: Rc) -> Rc { - Rc::new(Type::App { - public: true, - // FIXME: We should probably have t.contains_opaque here? - contains_opaque: false, - name: OPTION.to_string(), - module: "".to_string(), - args: vec![a], - alias: None, - }) -} - -pub fn ordering() -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - name: ORDERING.to_string(), - module: "".to_string(), - args: vec![], - alias: None, - }) -} - -pub fn function(args: Vec>, ret: Rc) -> Rc { - Rc::new(Type::Fn { - ret, - args, - alias: None, - }) -} - -pub fn generic_var(id: u64) -> Rc { - let tipo = Rc::new(RefCell::new(TypeVar::Generic { id })); - - Rc::new(Type::Var { tipo, alias: None }) -} - -pub fn unbound_var(id: u64) -> Rc { - let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id })); - - Rc::new(Type::Var { tipo, alias: None }) -} - -pub fn wrapped_redeemer(redeemer: Rc) -> Rc { - Rc::new(Type::App { - public: true, - contains_opaque: false, - module: "".to_string(), - name: REDEEMER_WRAPPER.to_string(), - args: vec![redeemer], - alias: None, - }) + RecordConstructor { + location: Span::empty(), + name: well_known::OPTION_CONSTRUCTORS[1].to_string(), + arguments: vec![], + doc: None, + sugar: false, + }, + ], + doc: None, + location: Span::empty(), + name: well_known::OPTION.to_string(), + opaque: false, + parameters: vec!["a".to_string()], + public: true, + typed_parameters: vec![tipo], + } + } } diff --git a/crates/aiken-lang/src/expr.rs b/crates/aiken-lang/src/expr.rs index f6f1b9a94..dc30e48aa 100644 --- a/crates/aiken-lang/src/expr.rs +++ b/crates/aiken-lang/src/expr.rs @@ -1,4 +1,3 @@ -use crate::tipo::ValueConstructorVariant; pub(crate) use crate::{ ast::{ self, Annotation, ArgBy, ArgName, AssignmentPattern, BinOp, Bls12_381Point, @@ -8,7 +7,6 @@ pub(crate) use crate::{ TypedDataType, TypedIfBranch, TypedRecordUpdateArg, UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg, }, - builtins::void, parser::token::Base, tipo::{ check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo, @@ -224,9 +222,10 @@ impl TypedExpr { | Self::RecordAccess { tipo, .. } | Self::RecordUpdate { tipo, .. } | Self::CurvePoint { tipo, .. } => tipo.clone(), - Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => { - expressions.last().map(TypedExpr::tipo).unwrap_or_else(void) - } + Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => expressions + .last() + .map(TypedExpr::tipo) + .unwrap_or_else(Type::void), } } @@ -491,7 +490,7 @@ impl TypedExpr { module: String::new(), constructors_count: 1, }, - tipo: void(), + tipo: Type::void(), }, location, } diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 40116b767..c44e9ce60 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -13,14 +13,11 @@ use self::{ }; use crate::{ ast::{ - ArgName, AssignmentKind, BinOp, Bls12_381Point, CallArg, Curve, DataTypeKey, + well_known, ArgName, AssignmentKind, BinOp, Bls12_381Point, CallArg, Curve, DataTypeKey, FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg, TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, }, - builtins::{ - bool, byte_array, data, function, int, list, option, pair, script_context, script_purpose, - void, PRELUDE, SCRIPT_PURPOSE_MINT, SCRIPT_PURPOSE_SPEND, SCRIPT_PURPOSE_WITHDRAW, - }, + builtins::PRELUDE, expr::TypedExpr, gen_uplc::{ air::ExpectLevel, @@ -138,14 +135,14 @@ impl<'a> CodeGenerator<'a> { annotation: None, doc: None, is_validator_param: false, - tipo: data(), + tipo: Type::data(), }], body: TypedExpr::Sequence { location: Span::empty(), expressions: vec![ TypedExpr::Assignment { location: Span::empty(), - tipo: script_context(), + tipo: Type::script_context(), value: TypedExpr::Var { location: Span::empty(), constructor: ValueConstructor { @@ -153,7 +150,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: script_context(), + tipo: Type::script_context(), }, name: "__context__".to_string(), } @@ -194,13 +191,16 @@ impl<'a> CodeGenerator<'a> { field_map: None, }, spread_location: None, - tipo: function(vec![data(), data(), script_purpose()], data()), + tipo: Type::function( + vec![Type::data(), Type::data(), Type::script_purpose()], + Type::data(), + ), }, kind: AssignmentKind::let_(), }, TypedExpr::When { location: Span::empty(), - tipo: bool(), + tipo: Type::bool(), subject: TypedExpr::Var { location: Span::empty(), constructor: ValueConstructor { @@ -208,7 +208,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: script_purpose(), + tipo: Type::script_purpose(), }, name: "__purpose__".to_string(), } @@ -241,7 +241,7 @@ impl<'a> CodeGenerator<'a> { "spend" => TypedPattern::Constructor { is_record: false, location: Span::empty(), - name: SCRIPT_PURPOSE_SPEND.to_string(), + name: well_known::SCRIPT_PURPOSE_SPEND.to_string(), arguments: vec![ CallArg { label: None, @@ -262,20 +262,20 @@ impl<'a> CodeGenerator<'a> { ], module: None, constructor: PatternConstructor::Record { - name: SCRIPT_PURPOSE_SPEND.to_string(), + name: well_known::SCRIPT_PURPOSE_SPEND.to_string(), field_map: None, }, spread_location: None, - tipo: function( - vec![data(), option(data())], - script_purpose(), + tipo: Type::function( + vec![Type::data(), Type::option(Type::data())], + Type::script_purpose(), ), }, "mint" => TypedPattern::Constructor { is_record: false, location: Span::empty(), - name: SCRIPT_PURPOSE_MINT.to_string(), + name: well_known::SCRIPT_PURPOSE_MINT.to_string(), arguments: vec![CallArg { label: None, location: Span::empty(), @@ -286,17 +286,20 @@ impl<'a> CodeGenerator<'a> { }], module: None, constructor: PatternConstructor::Record { - name: SCRIPT_PURPOSE_MINT.to_string(), + name: well_known::SCRIPT_PURPOSE_MINT.to_string(), field_map: None, }, spread_location: None, - tipo: function(vec![byte_array()], script_purpose()), + tipo: Type::function( + vec![Type::byte_array()], + Type::script_purpose(), + ), }, "withdraw" => TypedPattern::Constructor { is_record: false, location: Span::empty(), - name: SCRIPT_PURPOSE_WITHDRAW.to_string(), + name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(), arguments: vec![CallArg { label: None, location: Span::empty(), @@ -307,11 +310,14 @@ impl<'a> CodeGenerator<'a> { }], module: None, constructor: PatternConstructor::Record { - name: SCRIPT_PURPOSE_WITHDRAW.to_string(), + name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(), field_map: None, }, spread_location: None, - tipo: function(vec![data()], script_purpose()), + tipo: Type::function( + vec![Type::data()], + Type::script_purpose(), + ), }, purpose => { @@ -332,7 +338,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: data(), + tipo: Type::data(), }, name: "__redeemer__".to_string(), } @@ -364,7 +370,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: option(data()), + tipo: Type::option(Type::data()), }, name: "__datum__".to_string(), } @@ -396,7 +402,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: data(), + tipo: Type::data(), }, name: "__purpose_arg__".to_string(), } @@ -421,7 +427,7 @@ impl<'a> CodeGenerator<'a> { variant: ValueConstructorVariant::LocalVariable { location: Span::empty(), }, - tipo: data(), + tipo: Type::data(), }, name: "__transaction__".to_string(), } @@ -504,7 +510,7 @@ impl<'a> CodeGenerator<'a> { name: "wrapper_validator".to_string(), public: true, return_annotation: None, - return_type: bool(), + return_type: Type::bool(), end_position: 0, on_test_failure: OnTestFailure::FailImmediately, }; @@ -619,7 +625,7 @@ impl<'a> CodeGenerator<'a> { self.special_functions.insert_new_function( msg_func_name.clone(), Term::Error.delayed_trace(Term::string(msg)).delay(), - void(), + Type::void(), ); Some(self.special_functions.use_function_tree(msg_func_name)) } @@ -1024,17 +1030,21 @@ impl<'a> CodeGenerator<'a> { let function_name = format!("__access_index_{}", *index); if self.code_gen_functions.get(&function_name).is_none() { - let mut body = AirTree::local_var("__fields", list(data())); + let mut body = AirTree::local_var("__fields", Type::list(Type::data())); for _ in 0..*index { body = AirTree::builtin( DefaultFunction::TailList, - list(data()), + Type::list(Type::data()), vec![body], ) } - body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]); + body = AirTree::builtin( + DefaultFunction::HeadList, + Type::data(), + vec![body], + ); self.code_gen_functions.insert( function_name.clone(), @@ -1048,7 +1058,7 @@ impl<'a> CodeGenerator<'a> { let list_of_fields = AirTree::call( self.special_functions .use_function_tree(CONSTR_FIELDS_EXPOSER.to_string()), - list(data()), + Type::list(Type::data()), vec![self.build(record, module_build_name, &[])], ); @@ -1163,17 +1173,21 @@ impl<'a> CodeGenerator<'a> { let function_name = format!("__access_index_{}", *index); if self.code_gen_functions.get(&function_name).is_none() { - let mut body = AirTree::local_var("__fields", list(data())); + let mut body = AirTree::local_var("__fields", Type::list(Type::data())); for _ in 0..*index { body = AirTree::builtin( DefaultFunction::TailList, - list(data()), + Type::list(Type::data()), vec![body], ) } - body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]); + body = AirTree::builtin( + DefaultFunction::HeadList, + Type::data(), + vec![body], + ); self.code_gen_functions.insert( function_name.clone(), @@ -1282,7 +1296,7 @@ impl<'a> CodeGenerator<'a> { let otherwise = match &props.otherwise { Some(x) => x.clone(), // (delay (error )) - None => AirTree::anon_func(vec![], AirTree::error(void(), false), true), + None => AirTree::anon_func(vec![], AirTree::error(Type::void(), false), true), }; match pattern { @@ -1298,10 +1312,10 @@ impl<'a> CodeGenerator<'a> { let expect = AirTree::binop( BinOp::Eq, - bool(), + Type::bool(), AirTree::int(expected_int), - AirTree::local_var(&name, int()), - int(), + AirTree::local_var(&name, Type::int()), + Type::int(), ); assign_casted_value( @@ -1320,10 +1334,10 @@ impl<'a> CodeGenerator<'a> { let expect = AirTree::binop( BinOp::Eq, - bool(), + Type::bool(), AirTree::byte_array(expected_bytes.clone()), - AirTree::local_var(&name, byte_array()), - byte_array(), + AirTree::local_var(&name, Type::byte_array()), + Type::byte_array(), ); assign_casted_value( @@ -1831,7 +1845,7 @@ impl<'a> CodeGenerator<'a> { AirTree::when( &subject_name, - void(), + Type::void(), tipo.clone(), AirTree::local_var(&constructor_name, tipo.clone()), AirTree::assert_constr_index( @@ -2000,11 +2014,14 @@ impl<'a> CodeGenerator<'a> { defined_data_types, location, AirTree::call( - AirTree::local_var(format!("__curried_expect_on_list_{}", depth), void()), - void(), + AirTree::local_var( + format!("__curried_expect_on_list_{}", depth), + Type::void(), + ), + Type::void(), vec![AirTree::builtin( DefaultFunction::TailList, - list(data()), + Type::list(Type::data()), vec![AirTree::local_var( format!("__list_{}", depth), tipo.clone(), @@ -2039,7 +2056,7 @@ impl<'a> CodeGenerator<'a> { &pair_name, AirTree::builtin( DefaultFunction::HeadList, - pair(data(), data()), + Type::pair(Type::data(), Type::data()), vec![AirTree::local_var( format!("__list_{}", depth), tipo.clone(), @@ -2083,7 +2100,7 @@ impl<'a> CodeGenerator<'a> { let func_call = AirTree::call( AirTree::var( ValueConstructor::public( - void(), + Type::void(), ValueConstructorVariant::ModuleFn { name: EXPECT_ON_LIST.to_string(), field_map: None, @@ -2096,7 +2113,7 @@ impl<'a> CodeGenerator<'a> { EXPECT_ON_LIST, "", ), - void(), + Type::void(), vec![AirTree::local_var(&map_name, tipo.clone()), unwrap_function], ); @@ -2176,7 +2193,7 @@ impl<'a> CodeGenerator<'a> { &item_name, AirTree::builtin( DefaultFunction::HeadList, - data(), + Type::data(), vec![AirTree::local_var( format!("__list_{}", depth), tipo.clone(), @@ -2185,7 +2202,7 @@ impl<'a> CodeGenerator<'a> { AirTree::soft_cast_assignment( &item_name, inner_list_type.clone(), - AirTree::local_var(&item_name, data()), + AirTree::local_var(&item_name, Type::data()), self.expect_type_assign( inner_list_type, AirTree::local_var(&item_name, inner_list_type.clone()), @@ -2194,12 +2211,12 @@ impl<'a> CodeGenerator<'a> { AirTree::call( AirTree::local_var( format!("__curried_expect_on_list_{}", depth), - void(), + Type::void(), ), - void(), + Type::void(), vec![AirTree::builtin( DefaultFunction::TailList, - list(data()), + Type::list(Type::data()), vec![AirTree::local_var( format!("__list_{}", depth), tipo.clone(), @@ -2243,7 +2260,7 @@ impl<'a> CodeGenerator<'a> { let func_call = AirTree::call( AirTree::var( ValueConstructor::public( - void(), + Type::void(), ValueConstructorVariant::ModuleFn { name: EXPECT_ON_LIST.to_string(), field_map: None, @@ -2256,7 +2273,7 @@ impl<'a> CodeGenerator<'a> { EXPECT_ON_LIST, "", ), - void(), + Type::void(), vec![ AirTree::local_var(&list_name, tipo.clone()), unwrap_function, @@ -2347,10 +2364,13 @@ impl<'a> CodeGenerator<'a> { let current_defined = defined_data_types.clone(); let mut diff_defined_types = vec![]; - let var_then = - AirTree::call(AirTree::local_var("then_delayed", void()), void(), vec![]); + let var_then = AirTree::call( + AirTree::local_var("then_delayed", Type::void()), + Type::void(), + vec![], + ); - let otherwise_delayed = AirTree::local_var("otherwise_delayed", void()); + let otherwise_delayed = AirTree::local_var("otherwise_delayed", Type::void()); let constr_clauses = data_type.constructors.iter().enumerate().rfold( otherwise_delayed.clone(), @@ -2431,13 +2451,13 @@ impl<'a> CodeGenerator<'a> { let when_expr = AirTree::when( format!("__subject_span_{}_{}", location.start, location.end), - void(), + Type::void(), tipo.clone(), AirTree::local_var( format!("__constr_var_span_{}_{}", location.start, location.end), tipo.clone(), ), - AirTree::call(constr_clauses, void(), vec![]), + AirTree::call(constr_clauses, Type::void(), vec![]), ); let func_body = AirTree::let_assignment( @@ -2490,7 +2510,7 @@ impl<'a> CodeGenerator<'a> { "", ); - AirTree::call(func_var, void(), args) + AirTree::call(func_var, Type::void(), args) } } } @@ -3014,7 +3034,7 @@ impl<'a> CodeGenerator<'a> { // Since check_last_item is false this will never get added to the final uplc anyway ExpectLevel::None, elems_then, - AirTree::error(void(), false), + AirTree::error(Type::void(), false), ) } else { assert!(defined_tails.len() >= elems.len()); @@ -3095,7 +3115,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()), false, next_then, - AirTree::error(void(), false), + AirTree::error(Type::void(), false), ) }; @@ -3226,7 +3246,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()), false, next_then, - AirTree::error(void(), false), + AirTree::error(Type::void(), false), ) }; @@ -3355,7 +3375,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(&props.clause_var_name, subject_tipo.clone()), false, tuple_name_assigns, - AirTree::error(void(), false), + AirTree::error(Type::void(), false), ), ) } else { @@ -3383,7 +3403,7 @@ impl<'a> CodeGenerator<'a> { AirTree::clause_guard( &props.original_subject_name, AirTree::int(value), - int(), + Type::int(), then, ) } @@ -3392,7 +3412,7 @@ impl<'a> CodeGenerator<'a> { AirTree::clause_guard( &props.original_subject_name, AirTree::byte_array(value.clone()), - byte_array(), + Type::byte_array(), then, ) } @@ -3517,14 +3537,14 @@ impl<'a> CodeGenerator<'a> { AirTree::clause_guard( &props.original_subject_name, AirTree::bool(constr_name == "True"), - bool(), + Type::bool(), then, ) } else if subject_tipo.is_void() { AirTree::clause_guard( &props.original_subject_name, AirTree::void(), - void(), + Type::void(), then, ) } else { @@ -3596,7 +3616,7 @@ impl<'a> CodeGenerator<'a> { arg_names.push(arg_name.clone()); - let param = AirTree::local_var(&arg_name, data()); + let param = AirTree::local_var(&arg_name, Type::data()); let actual_type = convert_opaque_type(&arg.tipo, &self.data_types, true); @@ -3621,7 +3641,7 @@ impl<'a> CodeGenerator<'a> { self.special_functions.insert_new_function( msg_func_name.clone(), Term::Error.delayed_trace(Term::string(msg)).delay(), - void(), + Type::void(), ); Some(self.special_functions.use_function_tree(msg_func_name)) @@ -3637,7 +3657,7 @@ impl<'a> CodeGenerator<'a> { inner_then, &actual_type, AssignmentProperties { - value_type: data(), + value_type: Type::data(), kind: AssignmentKind::expect(), remove_unused: false, full_check: true, diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 39697b9dd..d2f166ac9 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -7,7 +7,6 @@ use crate::{ Constant, DataTypeKey, FunctionAccessKey, Pattern, Span, TraceLevel, TypedArg, TypedAssignmentKind, TypedClause, TypedDataType, TypedPattern, }, - builtins::{data, function, int, list, void}, expr::TypedExpr, line_numbers::{LineColumn, LineNumbers}, tipo::{ @@ -212,7 +211,7 @@ impl CodeGenSpecialFuncs { Term::snd_pair() .apply(Term::unconstr_data().apply(Term::var("__constr_var"))) .lambda("__constr_var"), - function(vec![data()], list(data())), + Type::function(vec![Type::data()], Type::list(Type::data())), ), ); @@ -222,7 +221,7 @@ impl CodeGenSpecialFuncs { Term::fst_pair() .apply(Term::unconstr_data().apply(Term::var("__constr_var"))) .lambda("__constr_var"), - function(vec![data()], int()), + Type::function(vec![Type::data()], Type::int()), ), ); @@ -784,7 +783,7 @@ pub fn rearrange_list_clauses( tipo: tipo.clone(), text: Box::new(TypedExpr::String { location: Span::empty(), - tipo: crate::builtins::string(), + tipo: Type::string(), value: format!("Clause hole found for {index} elements."), }), then: Box::new(TypedExpr::ErrorTerm { @@ -1688,15 +1687,15 @@ pub fn cast_validator_args(term: Term, arguments: &[TypedArg]) -> Term AirTree { let otherwise = match trace { - TraceLevel::Silent | TraceLevel::Compact => AirTree::error(void(), true), + TraceLevel::Silent | TraceLevel::Compact => AirTree::error(Type::void(), true), TraceLevel::Verbose => AirTree::trace( AirTree::string("Validator returned false"), - void(), - AirTree::error(void(), true), + Type::void(), + AirTree::error(Type::void(), true), ), }; - AirTree::if_branch(void(), air_tree, AirTree::void(), otherwise) + AirTree::if_branch(Type::void(), air_tree, AirTree::void(), otherwise) } pub fn extract_constant(term: &Term) -> Option> { diff --git a/crates/aiken-lang/src/gen_uplc/tree.rs b/crates/aiken-lang/src/gen_uplc/tree.rs index 3fd792085..3e53c7508 100644 --- a/crates/aiken-lang/src/gen_uplc/tree.rs +++ b/crates/aiken-lang/src/gen_uplc/tree.rs @@ -1,7 +1,6 @@ use super::air::{Air, ExpectLevel}; use crate::{ ast::{BinOp, Curve, Span, UnOp}, - builtins::{bool, byte_array, data, int, list, string, void}, tipo::{Type, ValueConstructor, ValueConstructorVariant}, }; use indexmap::IndexSet; @@ -113,7 +112,7 @@ pub enum AirMsg { impl AirMsg { pub fn to_air_tree(&self) -> AirTree { match self { - AirMsg::LocalVar(name) => AirTree::local_var(name, string()), + AirMsg::LocalVar(name) => AirTree::local_var(name, Type::string()), AirMsg::Msg(msg) => AirTree::string(msg), } } @@ -862,8 +861,8 @@ impl AirTree { AirTree::var( ValueConstructor::public( Type::Fn { - args: vec![list(data())], - ret: data(), + args: vec![Type::list(Type::data())], + ret: Type::data(), alias: None, } .into(), @@ -879,7 +878,7 @@ impl AirTree { function_name, "", ), - data(), + Type::data(), vec![list_of_fields], ), tipo.clone(), @@ -984,7 +983,7 @@ impl AirTree { } else { DefaultFunction::SndPair }, - data(), + Type::data(), vec![tuple], ), tipo.clone(), @@ -1039,9 +1038,9 @@ impl AirTree { } pub fn expect_on_list2() -> AirTree { - let inner_expect_on_list = AirTree::local_var(INNER_EXPECT_ON_LIST, void()); + let inner_expect_on_list = AirTree::local_var(INNER_EXPECT_ON_LIST, Type::void()); - let list_var = AirTree::local_var("__list_to_check", list(data())); + let list_var = AirTree::local_var("__list_to_check", Type::list(Type::data())); AirTree::let_assignment( INNER_EXPECT_ON_LIST, @@ -1051,13 +1050,13 @@ impl AirTree { "__list_to_check".to_string(), ], AirTree::call( - AirTree::local_var("__check_with", void()), - void(), + AirTree::local_var("__check_with", Type::void()), + Type::void(), vec![ list_var.clone(), AirTree::call( inner_expect_on_list.clone(), - void(), + Type::void(), vec![inner_expect_on_list.clone()], ), ], @@ -1066,27 +1065,27 @@ impl AirTree { ), AirTree::call( inner_expect_on_list.clone(), - void(), + Type::void(), vec![inner_expect_on_list, list_var], ), ) } pub fn expect_on_list() -> AirTree { - let list_var = AirTree::local_var("__list_to_check", list(data())); + let list_var = AirTree::local_var("__list_to_check", Type::list(Type::data())); - let head_list = AirTree::builtin(DefaultFunction::HeadList, data(), vec![list_var]); + let head_list = AirTree::builtin(DefaultFunction::HeadList, Type::data(), vec![list_var]); let expect_on_head = AirTree::call( - AirTree::local_var("__check_with", void()), - void(), + AirTree::local_var("__check_with", Type::void()), + Type::void(), vec![head_list], ); let next_call = AirTree::call( AirTree::var( ValueConstructor::public( - void(), + Type::void(), ValueConstructorVariant::ModuleFn { name: EXPECT_ON_LIST.to_string(), field_map: None, @@ -1099,14 +1098,17 @@ impl AirTree { EXPECT_ON_LIST, "", ), - void(), + Type::void(), vec![ AirTree::builtin( DefaultFunction::TailList, - list(data()), - vec![AirTree::local_var("__list_to_check", list(data()))], + Type::list(Type::data()), + vec![AirTree::local_var( + "__list_to_check", + Type::list(Type::data()), + )], ), - AirTree::local_var("__check_with", void()), + AirTree::local_var("__check_with", Type::void()), ], ); @@ -1114,7 +1116,7 @@ impl AirTree { AirTree::list_clause( "__list_to_check", - void(), + Type::void(), AirTree::void(), assign, None, @@ -1675,10 +1677,10 @@ impl AirTree { pub fn return_type(&self) -> Rc { match self { - AirTree::Int { .. } => int(), - AirTree::String { .. } => string(), - AirTree::ByteArray { .. } => byte_array(), - AirTree::Bool { .. } => bool(), + AirTree::Int { .. } => Type::int(), + AirTree::String { .. } => Type::string(), + AirTree::ByteArray { .. } => Type::byte_array(), + AirTree::Bool { .. } => Type::bool(), AirTree::CurvePoint { point } => point.tipo(), AirTree::List { tipo, .. } | AirTree::Tuple { tipo, .. } @@ -1693,14 +1695,14 @@ impl AirTree { | AirTree::RecordUpdate { tipo, .. } | AirTree::ErrorTerm { tipo, .. } | AirTree::Trace { tipo, .. } => tipo.clone(), - AirTree::Void => void(), + AirTree::Void => Type::void(), AirTree::Var { constructor, .. } => constructor.tipo.clone(), AirTree::Fn { func_body, .. } => func_body.return_type(), AirTree::UnOp { op, .. } => match op { - UnOp::Not => bool(), - UnOp::Negate => int(), + UnOp::Not => Type::bool(), + UnOp::Negate => Type::int(), }, - AirTree::CastToData { .. } => data(), + AirTree::CastToData { .. } => Type::data(), AirTree::Clause { then, .. } | AirTree::ListClause { then, .. } | AirTree::WrapClause { then, .. } @@ -1725,7 +1727,7 @@ impl AirTree { | AirTree::FieldsEmpty { then, .. } | AirTree::ListEmpty { then, .. } | AirTree::NoOp { then } => then.return_type(), - AirTree::MultiValidator { .. } => void(), + AirTree::MultiValidator { .. } => Type::void(), } } diff --git a/crates/aiken-lang/src/parser/annotation.rs b/crates/aiken-lang/src/parser/annotation.rs index 148947e5d..b149a2949 100644 --- a/crates/aiken-lang/src/parser/annotation.rs +++ b/crates/aiken-lang/src/parser/annotation.rs @@ -1,7 +1,7 @@ use super::{error::ParseError, token::Token}; use crate::{ - ast, - builtins::{PAIR, PRELUDE}, + ast::{self, well_known}, + builtins::PRELUDE, }; use chumsky::prelude::*; @@ -19,7 +19,7 @@ pub fn parser() -> impl Parser { select! {Token::Name { name } if name == PRELUDE => name} .then_ignore(just(Token::Dot)) .or_not() - .then_ignore(select! {Token::UpName { name } if name == PAIR => name}) + .then_ignore(select! {Token::UpName { name } if name == well_known::PAIR => name}) .ignore_then( expression .clone() diff --git a/crates/aiken-lang/src/parser/expr/pair.rs b/crates/aiken-lang/src/parser/expr/pair.rs index 59359baa3..aad7a04b6 100644 --- a/crates/aiken-lang/src/parser/expr/pair.rs +++ b/crates/aiken-lang/src/parser/expr/pair.rs @@ -1,5 +1,6 @@ use crate::{ - builtins::{PAIR, PRELUDE}, + ast::well_known, + builtins::PRELUDE, expr::UntypedExpr, parser::{error::ParseError, token::Token}, }; @@ -11,7 +12,7 @@ pub fn parser( select! {Token::Name { name } if name == PRELUDE => name} .then_ignore(just(Token::Dot)) .or_not() - .then_ignore(select! {Token::UpName { name } if name == PAIR => name}) + .then_ignore(select! {Token::UpName { name } if name == well_known::PAIR => name}) .ignore_then( r.clone() .separated_by(just(Token::Comma)) diff --git a/crates/aiken-lang/src/parser/pattern/pair.rs b/crates/aiken-lang/src/parser/pattern/pair.rs index 58be7614b..d304d6d40 100644 --- a/crates/aiken-lang/src/parser/pattern/pair.rs +++ b/crates/aiken-lang/src/parser/pattern/pair.rs @@ -1,6 +1,5 @@ use crate::{ - ast::UntypedPattern, - builtins::PAIR, + ast::{well_known, UntypedPattern}, parser::{error::ParseError, token::Token}, }; use chumsky::prelude::*; @@ -8,7 +7,7 @@ use chumsky::prelude::*; pub fn parser( pattern: Recursive<'_, Token, UntypedPattern, ParseError>, ) -> impl Parser + '_ { - select! {Token::UpName { name } if name == PAIR => name} + select! {Token::UpName { name } if name == well_known::PAIR => name} .ignore_then(choice(( just(Token::LeftParen), just(Token::NewLineLeftParen), diff --git a/crates/aiken-lang/src/tipo.rs b/crates/aiken-lang/src/tipo.rs index 6507ac099..948ac4485 100644 --- a/crates/aiken-lang/src/tipo.rs +++ b/crates/aiken-lang/src/tipo.rs @@ -1,10 +1,9 @@ use self::{environment::Environment, pretty::Printer}; use crate::{ ast::{ - Annotation, Constant, DataType, DataTypeKey, DefinitionLocation, ModuleKind, Span, - TypedDataType, + well_known, Annotation, Constant, DataType, DataTypeKey, DefinitionLocation, ModuleKind, + Span, TypedDataType, }, - builtins::{G1_ELEMENT, G2_ELEMENT, MILLER_LOOP_RESULT}, tipo::fields::FieldMap, }; use indexmap::IndexMap; @@ -304,7 +303,7 @@ impl Type { pub fn is_int(&self) -> bool { match self { - Self::App { module, name, .. } if "Int" == name && module.is_empty() => true, + Self::App { module, name, .. } if well_known::INT == name && module.is_empty() => true, Self::Var { tipo, .. } => tipo.borrow().is_int(), _ => false, } @@ -312,7 +311,11 @@ impl Type { pub fn is_bytearray(&self) -> bool { match self { - Self::App { module, name, .. } if "ByteArray" == name && module.is_empty() => true, + Self::App { module, name, .. } + if well_known::BYTE_ARRAY == name && module.is_empty() => + { + true + } Self::Var { tipo, .. } => tipo.borrow().is_bytearray(), _ => false, } @@ -320,7 +323,7 @@ impl Type { pub fn is_bls381_12_g1(&self) -> bool { match self { - Self::App { module, name, .. } => G1_ELEMENT == name && module.is_empty(), + Self::App { module, name, .. } => well_known::G1_ELEMENT == name && module.is_empty(), Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g1(), _ => false, @@ -329,7 +332,7 @@ impl Type { pub fn is_bls381_12_g2(&self) -> bool { match self { - Self::App { module, name, .. } => G2_ELEMENT == name && module.is_empty(), + Self::App { module, name, .. } => well_known::G2_ELEMENT == name && module.is_empty(), Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g2(), _ => false, @@ -338,7 +341,9 @@ impl Type { pub fn is_ml_result(&self) -> bool { match self { - Self::App { module, name, .. } => MILLER_LOOP_RESULT == name && module.is_empty(), + Self::App { module, name, .. } => { + well_known::MILLER_LOOP_RESULT == name && module.is_empty() + } Self::Var { tipo, .. } => tipo.borrow().is_ml_result(), _ => false, @@ -422,31 +427,33 @@ impl Type { } pub fn is_generic(&self) -> bool { - match self { - Self::App { args, .. } => { - let mut is_a_generic = false; - for arg in args { - is_a_generic = is_a_generic || arg.is_generic(); - } - is_a_generic - } + !self.collect_generics().is_empty() + } - Self::Var { tipo, .. } => tipo.borrow().is_generic(), - Self::Tuple { elems, .. } => { - let mut is_a_generic = false; - for elem in elems { - is_a_generic = is_a_generic || elem.is_generic(); + pub fn collect_generics(&self) -> Vec> { + match self { + Self::App { args, .. } => args.iter().flat_map(|arg| arg.collect_generics()).collect(), + Self::Var { tipo, .. } => { + if tipo.borrow().is_generic() { + vec![self.clone().into()] + } else { + Vec::new() } - is_a_generic } - Self::Fn { args, ret, .. } => { - let mut is_a_generic = false; - for arg in args { - is_a_generic = is_a_generic || arg.is_generic(); - } - is_a_generic || ret.is_generic() + Self::Tuple { elems, .. } => elems + .iter() + .flat_map(|arg| arg.collect_generics()) + .collect(), + Self::Fn { args, ret, .. } => args + .iter() + .chain(std::iter::once(ret)) + .flat_map(|arg| arg.collect_generics()) + .collect(), + Self::Pair { fst, snd, .. } => { + let mut generics = fst.collect_generics(); + generics.extend(snd.collect_generics()); + generics } - Self::Pair { fst, snd, .. } => fst.is_generic() || snd.is_generic(), } } @@ -1068,7 +1075,7 @@ impl TypeVar { match self { TypeVar::Generic { .. } => true, TypeVar::Link { tipo } => tipo.is_generic(), - _ => false, + TypeVar::Unbound { .. } => false, } } @@ -1092,11 +1099,13 @@ impl TypeVar { Self::Link { tipo } => tipo.get_inner_types(), Self::Unbound { .. } => vec![], var => { - vec![Type::Var { - tipo: RefCell::new(var.clone()).into(), - alias: None, - } - .into()] + vec![ + Type::Var { + tipo: RefCell::new(var.clone()).into(), + alias: None, + } + .into(), + ] } } } @@ -1118,6 +1127,51 @@ impl ValueConstructor { } } + pub fn known_enum( + values: &mut HashMap, + tipo: Rc, + constructors: &[&str], + ) -> Vec { + for constructor in &constructors[..] { + values.insert( + constructor.to_string(), + ValueConstructor::public( + tipo.clone(), + ValueConstructorVariant::known_enum_variant(constructor, constructors.len(), 0), + ), + ); + } + + constructors + .into_iter() + .map(|constructor| constructor.to_string()) + .collect() + } + + pub fn known_adt( + values: &mut HashMap, + constructors: &[(&str, Rc)], + ) -> Vec { + for (constructor, tipo) in &constructors[..] { + values.insert( + constructor.to_string(), + ValueConstructor::public( + tipo.clone(), + ValueConstructorVariant::known_enum_variant( + constructor, + constructors.len(), + tipo.fn_arity().unwrap_or(0), + ), + ), + ); + } + + constructors + .into_iter() + .map(|(constructor, _)| constructor.to_string()) + .collect() + } + fn field_map(&self) -> Option<&FieldMap> { match &self.variant { ValueConstructorVariant::ModuleFn { field_map, .. } @@ -1248,6 +1302,17 @@ impl ValueConstructorVariant { pub fn is_local_variable(&self) -> bool { matches!(self, Self::LocalVariable { .. }) } + + pub fn known_enum_variant(name: &str, constructors_count: usize, arity: usize) -> Self { + ValueConstructorVariant::Record { + module: "".into(), + name: name.to_string(), + field_map: None::, + arity, + location: Span::empty(), + constructors_count: constructors_count as u16, + } + } } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] @@ -1271,6 +1336,18 @@ pub struct TypeConstructor { pub tipo: Rc, } +impl TypeConstructor { + pub fn primitive(tipo: Rc) -> Self { + TypeConstructor { + location: Span::empty(), + parameters: tipo.collect_generics(), + tipo, + module: "".to_string(), + public: true, + } + } +} + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AccessorsMap { pub public: bool, diff --git a/crates/aiken-lang/src/tipo/environment.rs b/crates/aiken-lang/src/tipo/environment.rs index a7ee6c236..2c8c70cd7 100644 --- a/crates/aiken-lang/src/tipo/environment.rs +++ b/crates/aiken-lang/src/tipo/environment.rs @@ -12,7 +12,6 @@ use crate::{ TypedPattern, UnqualifiedImport, UntypedArg, UntypedDefinition, UntypedFunction, Use, Validator, PIPE_VARIABLE, }, - builtins::{function, generic_var, pair, tuple, unbound_var}, tipo::{fields::FieldMap, TypeAliasAnnotation}, IdGenerator, }; @@ -183,7 +182,7 @@ impl<'a> Environment<'a> { if let Some((args, ret)) = new_value { *tipo.borrow_mut() = TypeVar::Link { - tipo: function(args.clone(), ret.clone()), + tipo: Type::function(args.clone(), ret.clone()), }; return Ok((args, Type::with_alias(ret, alias.clone()))); @@ -690,7 +689,7 @@ impl<'a> Environment<'a> { } Type::Fn { args, ret, alias } => Type::with_alias( - function( + Type::function( args.iter() .map(|t| self.instantiate(t.clone(), ids, hydrator)) .collect(), @@ -700,7 +699,7 @@ impl<'a> Environment<'a> { ), Type::Tuple { elems, alias } => Type::with_alias( - tuple( + Type::tuple( elems .iter() .map(|t| self.instantiate(t.clone(), ids, hydrator)) @@ -709,7 +708,7 @@ impl<'a> Environment<'a> { alias.clone(), ), Type::Pair { fst, snd, alias } => Type::with_alias( - pair( + Type::pair( self.instantiate(fst.clone(), ids, hydrator), self.instantiate(snd.clone(), ids, hydrator), ), @@ -795,13 +794,13 @@ impl<'a> Environment<'a> { /// Create a new generic type that can stand in for any type. pub fn new_generic_var(&mut self) -> Rc { - generic_var(self.next_uid()) + Type::generic_var(self.next_uid()) } /// Create a new unbound type that is a specific type, we just don't /// know which one yet. pub fn new_unbound_var(&mut self) -> Rc { - unbound_var(self.next_uid()) + Type::unbound_var(self.next_uid()) } pub fn next_uid(&mut self) -> u64 { @@ -1214,7 +1213,7 @@ impl<'a> Environment<'a> { let return_type = hydrator.type_from_option_annotation(return_annotation, self)?; - let tipo = function(arg_types, return_type); + let tipo = Type::function(arg_types, return_type); // Keep track of which types we create from annotations so we can know // which generic types not to instantiate later when performing @@ -1415,7 +1414,7 @@ impl<'a> Environment<'a> { // Insert constructor function into module scope let typ = match constructor.arguments.len() { 0 => typ.clone(), - _ => function(args_types, typ.clone()), + _ => Type::function(args_types, typ.clone()), }; let constructor_info = ValueConstructorVariant::Record { @@ -2013,7 +2012,7 @@ pub(crate) fn generalise(t: Rc, ctx_level: usize) -> Rc { match t.deref() { Type::Var { tipo, alias } => Type::with_alias( match tipo.borrow().deref() { - TypeVar::Unbound { id } => generic_var(*id), + TypeVar::Unbound { id } => Type::generic_var(*id), TypeVar::Link { tipo } => generalise(tipo.clone(), ctx_level), TypeVar::Generic { .. } => Rc::new(Type::Var { tipo: tipo.clone(), @@ -2047,7 +2046,7 @@ pub(crate) fn generalise(t: Rc, ctx_level: usize) -> Rc { } Type::Fn { args, ret, alias } => Type::with_alias( - function( + Type::function( args.iter() .map(|t| generalise(t.clone(), ctx_level)) .collect(), @@ -2057,7 +2056,7 @@ pub(crate) fn generalise(t: Rc, ctx_level: usize) -> Rc { ), Type::Tuple { elems, alias } => Type::with_alias( - tuple( + Type::tuple( elems .iter() .map(|t| generalise(t.clone(), ctx_level)) @@ -2066,7 +2065,7 @@ pub(crate) fn generalise(t: Rc, ctx_level: usize) -> Rc { alias.clone(), ), Type::Pair { fst, snd, alias } => Type::with_alias( - pair( + Type::pair( generalise(fst.clone(), ctx_level), generalise(snd.clone(), ctx_level), ), diff --git a/crates/aiken-lang/src/tipo/exhaustive.rs b/crates/aiken-lang/src/tipo/exhaustive.rs index 88df69fc0..71979425c 100644 --- a/crates/aiken-lang/src/tipo/exhaustive.rs +++ b/crates/aiken-lang/src/tipo/exhaustive.rs @@ -1,7 +1,6 @@ use crate::{ ast, - builtins::{self}, - tipo::{self, environment::Environment, error::Error}, + tipo::{self, environment::Environment, error::Error, Type}, }; use itertools::Itertools; use std::{collections::BTreeMap, iter, ops::Deref}; @@ -500,8 +499,8 @@ fn pretty_tail(tail: Pattern) -> String { } fn list_constructors() -> Vec { - let list_parameter = builtins::generic_var(0); - let list_type = builtins::list(list_parameter); + let list_parameter = Type::generic_var(0); + let list_type = Type::list(list_parameter); vec![ tipo::ValueConstructor { diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 1df80e83f..816d18887 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -17,10 +17,7 @@ use crate::{ UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedFunction, UntypedIfBranch, UntypedPattern, UntypedRecordUpdateArg, }, - builtins::{ - bool, byte_array, data, from_default_function, function, g1_element, g2_element, int, list, - pair, string, tuple, void, BUILTIN, - }, + builtins::{from_default_function, BUILTIN}, expr::{FnStyle, TypedExpr, UntypedExpr}, format, tipo::{fields::FieldMap, DefaultFunction, PatternConstructor, TypeVar}, @@ -163,7 +160,7 @@ pub(crate) fn infer_function( let args_types = arguments.iter().map(|a| a.tipo.clone()).collect(); - let tipo = function(args_types, return_type); + let tipo = Type::function(args_types, return_type); let safe_to_generalise = !expr_typer.ungeneralised_function_used; @@ -594,15 +591,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok(TypedExpr::ByteArray { location, bytes, - tipo: byte_array(), + tipo: Type::byte_array(), }) } fn infer_curve_point(&mut self, curve: Curve, location: Span) -> Result { let tipo = match curve { Curve::Bls12_381(point) => match point { - Bls12_381Point::G1(_) => g1_element(), - Bls12_381Point::G2(_) => g2_element(), + Bls12_381Point::G1(_) => Type::g1_element(), + Bls12_381Point::G2(_) => Type::g2_element(), }, }; @@ -631,7 +628,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { module: String::new(), constructors_count: 2, }, - tipo: bool(), + tipo: Type::bool(), }, }; @@ -648,14 +645,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> { module: String::new(), constructors_count: 2, }, - tipo: bool(), + tipo: Type::bool(), }, }; let text = match self.tracing.trace_level(false) { TraceLevel::Verbose => Some(TypedExpr::String { location, - tipo: string(), + tipo: Type::string(), value: format!( "{} ? False", format::Formatter::new() @@ -668,7 +665,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let typed_value = self.infer(value)?; - self.unify(bool(), typed_value.tipo(), typed_value.location(), false)?; + self.unify( + Type::bool(), + typed_value.tipo(), + typed_value.location(), + false, + )?; match text { None => Ok(typed_value), @@ -682,11 +684,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }], final_else: Box::new(TypedExpr::Trace { location, - tipo: bool(), + tipo: Type::bool(), text: Box::new(text), then: Box::new(var_false), }), - tipo: bool(), + tipo: Type::bool(), }), } } @@ -714,22 +716,22 @@ impl<'a, 'b> ExprTyper<'a, 'b> { return Ok(TypedExpr::BinOp { location, name, - tipo: bool(), + tipo: Type::bool(), left: Box::new(left), right: Box::new(right), }); } - BinOp::And => (bool(), bool()), - BinOp::Or => (bool(), bool()), - BinOp::LtInt => (int(), bool()), - BinOp::LtEqInt => (int(), bool()), - BinOp::GtEqInt => (int(), bool()), - BinOp::GtInt => (int(), bool()), - BinOp::AddInt => (int(), int()), - BinOp::SubInt => (int(), int()), - BinOp::MultInt => (int(), int()), - BinOp::DivInt => (int(), int()), - BinOp::ModInt => (int(), int()), + BinOp::And => (Type::bool(), Type::bool()), + BinOp::Or => (Type::bool(), Type::bool()), + BinOp::LtInt => (Type::int(), Type::bool()), + BinOp::LtEqInt => (Type::int(), Type::bool()), + BinOp::GtEqInt => (Type::int(), Type::bool()), + BinOp::GtInt => (Type::int(), Type::bool()), + BinOp::AddInt => (Type::int(), Type::int()), + BinOp::SubInt => (Type::int(), Type::int()), + BinOp::MultInt => (Type::int(), Type::int()), + BinOp::DivInt => (Type::int(), Type::int()), + BinOp::ModInt => (Type::int(), Type::int()), }; let left = self.infer(left)?; @@ -896,8 +898,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let value = self.infer(value)?; let tipo = match op { - UnOp::Not => bool(), - UnOp::Negate => int(), + UnOp::Not => Type::bool(), + UnOp::Negate => Type::int(), }; self.unify(tipo.clone(), value.tipo(), value.location(), false)?; @@ -1603,7 +1605,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let condition = self.infer(branch.condition.clone())?; self.unify( - bool(), + Type::bool(), condition.tipo(), condition.type_defining_location(), false, @@ -1647,7 +1649,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let args_types = args.iter().map(|a| a.tipo.clone()).collect(); - let tipo = function(args_types, return_type); + let tipo = Type::function(args_types, return_type); Ok(TypedExpr::Fn { location, @@ -1745,7 +1747,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { TypedExpr::UInt { location, value, - tipo: int(), + tipo: Type::int(), } } @@ -1772,7 +1774,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { ensure_serialisable(false, tipo.clone(), location)?; // Type check the ..tail, if there is one - let tipo = list(tipo); + let tipo = Type::list(tipo); let tail = match tail { Some(tail) => { @@ -1807,7 +1809,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let typed_expression = self.infer(expression)?; self.unify( - bool(), + Type::bool(), typed_expression.tipo(), typed_expression.location(), false, @@ -1831,7 +1833,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { .rev() .reduce(|acc, typed_expression| TypedExpr::BinOp { location, - tipo: bool(), + tipo: Type::bool(), name, left: typed_expression.into(), right: acc.into(), @@ -2151,7 +2153,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { TypedExpr::String { location, value, - tipo: string(), + tipo: Type::string(), } } @@ -2169,7 +2171,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok(TypedExpr::Pair { location, - tipo: pair(typed_fst.tipo(), typed_snd.tipo()), + tipo: Type::pair(typed_fst.tipo(), typed_snd.tipo()), fst: typed_fst.into(), snd: typed_snd.into(), }) @@ -2187,7 +2189,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { typed_elems.push(typed_elem); } - let tipo = tuple(typed_elems.iter().map(|e| e.tipo()).collect()); + let tipo = Type::tuple(typed_elems.iter().map(|e| e.tipo()).collect()); Ok(TypedExpr::Tuple { location, @@ -2255,9 +2257,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> { fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result { let typed_arg = self.infer(arg)?; - match self.unify(string(), typed_arg.tipo(), typed_arg.location(), false) { + match self.unify( + Type::string(), + typed_arg.tipo(), + typed_arg.location(), + false, + ) { Err(_) => { - self.unify(data(), typed_arg.tipo(), typed_arg.location(), true)?; + self.unify(Type::data(), typed_arg.tipo(), typed_arg.location(), true)?; Ok(diagnose_expr(typed_arg)) } Ok(()) => Ok(typed_arg), @@ -2291,7 +2298,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { TraceLevel::Silent => Ok(then), TraceLevel::Compact => { let text = self.infer(label)?; - self.unify(string(), text.tipo(), text.location(), false)?; + self.unify(Type::string(), text.tipo(), text.location(), false)?; Ok(TypedExpr::Trace { location, tipo, @@ -2307,7 +2314,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } else { let delimiter = |ix| TypedExpr::String { location: Span::empty(), - tipo: string(), + tipo: Type::string(), value: if ix == 0 { ": " } else { ", " }.to_string(), }; typed_arguments @@ -2594,7 +2601,7 @@ fn assert_assignment(expr: TypedExpr) -> Result { if expr.tipo().is_void() { return Ok(TypedExpr::Assignment { location: expr.location(), - tipo: void(), + tipo: Type::void(), value: expr.clone().into(), pattern: Pattern::Constructor { is_record: false, @@ -2607,7 +2614,7 @@ fn assert_assignment(expr: TypedExpr) -> Result { arguments: vec![], module: None, spread_location: None, - tipo: void(), + tipo: Type::void(), }, kind: AssignmentKind::let_(), }); @@ -2713,7 +2720,7 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr { name: "diagnostic".to_string(), constructor: ValueConstructor { public: true, - tipo: function(vec![data(), byte_array()], byte_array()), + tipo: Type::function(vec![Type::data(), Type::byte_array()], Type::byte_array()), variant: ValueConstructorVariant::ModuleFn { name: "diagnostic".to_string(), field_map: None, @@ -2728,13 +2735,13 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr { let location = expr.location(); TypedExpr::Call { - tipo: string(), + tipo: Type::string(), fun: Box::new(decode_utf8.clone()), args: vec![CallArg { label: None, location: expr.location(), value: TypedExpr::Call { - tipo: byte_array(), + tipo: Type::byte_array(), fun: Box::new(diagnostic.clone()), args: vec![ CallArg { @@ -2746,7 +2753,7 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr { label: None, location, value: TypedExpr::ByteArray { - tipo: byte_array(), + tipo: Type::byte_array(), bytes: vec![], location, }, @@ -2785,7 +2792,7 @@ fn append_string_expr(left: TypedExpr, right: TypedExpr) -> TypedExpr { TypedExpr::Call { location: Span::empty(), - tipo: string(), + tipo: Type::string(), fun: Box::new(append_string.clone()), args: vec![ CallArg { diff --git a/crates/aiken-lang/src/tipo/hydrator.rs b/crates/aiken-lang/src/tipo/hydrator.rs index 9b66a3010..8d5d2bc45 100644 --- a/crates/aiken-lang/src/tipo/hydrator.rs +++ b/crates/aiken-lang/src/tipo/hydrator.rs @@ -3,11 +3,7 @@ use super::{ error::{Error, Warning}, Type, TypeConstructor, }; -use crate::{ - ast::Annotation, - builtins::{function, pair, tuple}, - tipo::Span, -}; +use crate::{ast::Annotation, tipo::Span}; use std::{collections::HashMap, rc::Rc}; /// The Hydrator takes an AST representing a type (i.e. a type annotation @@ -201,7 +197,7 @@ impl Hydrator { let ret = self.do_type_from_annotation(ret, environment, unbounds)?; - Ok(function(args, ret)) + Ok(Type::function(args, ret)) } Annotation::Var { name, location, .. } => match self.created_type_variables.get(name) { @@ -244,13 +240,13 @@ impl Hydrator { typed_elems.push(typed_elem) } - Ok(tuple(typed_elems)) + Ok(Type::tuple(typed_elems)) } Annotation::Pair { fst, snd, .. } => { let fst = self.do_type_from_annotation(fst, environment, unbounds)?; let snd = self.do_type_from_annotation(snd, environment, unbounds)?; - Ok(pair(fst, snd)) + Ok(Type::pair(fst, snd)) } }?; diff --git a/crates/aiken-lang/src/tipo/infer.rs b/crates/aiken-lang/src/tipo/infer.rs index 1aa0abbf1..e49520457 100644 --- a/crates/aiken-lang/src/tipo/infer.rs +++ b/crates/aiken-lang/src/tipo/infer.rs @@ -11,7 +11,6 @@ use crate::{ RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition, TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator, }, - builtins::{self, fuzzer, generic_var}, tipo::{expr::infer_function, Span, Type, TypeVar}, IdGenerator, }; @@ -214,7 +213,7 @@ fn infer_definition( location: typed_fun .location .map(|start, _end| (start, start + typed_fun.name.len())), - available_purposes: TypedValidator::available_purposes(), + available_purposes: TypedValidator::available_handler_names(), }); } @@ -228,7 +227,7 @@ fn infer_definition( for arg in typed_fun.arguments.iter_mut() { if arg.tipo.is_unbound() { - arg.tipo = builtins::data(); + arg.tipo = Type::data(); } } @@ -263,7 +262,7 @@ fn infer_definition( .drain(0..params_length) .map(|mut arg| { if arg.tipo.is_unbound() { - arg.tipo = builtins::data(); + arg.tipo = Type::data(); } arg @@ -280,7 +279,7 @@ fn infer_definition( for arg in typed_fallback.arguments.iter_mut() { if arg.tipo.is_unbound() { - arg.tipo = builtins::data(); + arg.tipo = Type::data(); } } @@ -383,14 +382,14 @@ fn infer_definition( let is_bool = environment.unify( typed_f.return_type.clone(), - builtins::bool(), + Type::bool(), typed_f.location, false, ); let is_void = environment.unify( typed_f.return_type.clone(), - builtins::void(), + Type::void(), typed_f.location, false, ); @@ -642,10 +641,10 @@ fn infer_fuzzer( ) -> Result<(Annotation, Rc), Error> { let could_not_unify = || Error::CouldNotUnify { location: *location, - expected: fuzzer( + expected: Type::fuzzer( expected_inner_type .clone() - .unwrap_or_else(|| generic_var(0)), + .unwrap_or_else(|| Type::generic_var(0)), ), given: tipo.clone(), situation: None, @@ -681,7 +680,7 @@ fn infer_fuzzer( // `unify` now that we have figured out the type carried by the fuzzer. environment.unify( tipo.clone(), - fuzzer(wrapped.clone()), + Type::fuzzer(wrapped.clone()), *location, false, )?; diff --git a/crates/aiken-lang/src/tipo/pattern.rs b/crates/aiken-lang/src/tipo/pattern.rs index 4a3064a6c..c27e050eb 100644 --- a/crates/aiken-lang/src/tipo/pattern.rs +++ b/crates/aiken-lang/src/tipo/pattern.rs @@ -6,10 +6,7 @@ use super::{ hydrator::Hydrator, PatternConstructor, Type, ValueConstructorVariant, }; -use crate::{ - ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern}, - builtins::{byte_array, int, list, pair, tuple}, -}; +use crate::ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern}; use itertools::Itertools; use std::{ collections::{HashMap, HashSet}, @@ -190,7 +187,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { value, base, } => { - self.environment.unify(tipo, int(), location, false)?; + self.environment.unify(tipo, Type::int(), location, false)?; Ok(Pattern::Int { location, @@ -205,7 +202,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { preferred_format, } => { self.environment - .unify(tipo, byte_array(), location, false)?; + .unify(tipo, Type::byte_array(), location, false)?; Ok(Pattern::ByteArray { location, @@ -231,7 +228,12 @@ impl<'a, 'b> PatternTyper<'a, 'b> { .try_collect()?; let tail = match tail { - Some(tail) => Some(Box::new(self.unify(*tail, list(tipo), None, false)?)), + Some(tail) => Some(Box::new(self.unify( + *tail, + Type::list(tipo), + None, + false, + )?)), None => None, }; @@ -243,7 +245,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { } None => Err(Error::CouldNotUnify { - given: list(self.environment.new_unbound_var()), + given: Type::list(self.environment.new_unbound_var()), expected: tipo.clone(), situation: None, location, @@ -267,7 +269,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { let t_snd = self.environment.new_unbound_var(); self.environment.unify( - pair(t_fst.clone(), t_snd.clone()), + Type::pair(t_fst.clone(), t_snd.clone()), tipo, location, false, @@ -280,7 +282,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { } _ => Err(Error::CouldNotUnify { - given: pair( + given: Type::pair( self.environment.new_unbound_var(), self.environment.new_unbound_var(), ), @@ -322,8 +324,12 @@ impl<'a, 'b> PatternTyper<'a, 'b> { .map(|_| self.environment.new_unbound_var()) .collect(); - self.environment - .unify(tuple(elems_types.clone()), tipo, location, false)?; + self.environment.unify( + Type::tuple(elems_types.clone()), + tipo, + location, + false, + )?; let mut patterns = vec![]; @@ -345,7 +351,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { .collect(); Err(Error::CouldNotUnify { - given: tuple(elems_types), + given: Type::tuple(elems_types), expected: tipo, situation: None, location, diff --git a/crates/aiken-lang/src/tipo/pipe.rs b/crates/aiken-lang/src/tipo/pipe.rs index dc2e21b1f..15692010d 100644 --- a/crates/aiken-lang/src/tipo/pipe.rs +++ b/crates/aiken-lang/src/tipo/pipe.rs @@ -5,7 +5,6 @@ use super::{ }; use crate::{ ast::{AssignmentKind, CallArg, Pattern, Span, PIPE_VARIABLE}, - builtins::function, expr::{TypedExpr, UntypedExpr}, }; use std::{ops::Deref, rc::Rc}; @@ -257,7 +256,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> { .environment .unify( func.tipo(), - function(vec![self.argument_type.clone()], return_type.clone()), + Type::function(vec![self.argument_type.clone()], return_type.clone()), func.location(), if let Type::Fn { args, .. } = func.tipo().deref() { if let Some(typ) = args.first() { diff --git a/crates/aiken-lang/src/tipo/pretty.rs b/crates/aiken-lang/src/tipo/pretty.rs index ea89924de..a38b899f6 100644 --- a/crates/aiken-lang/src/tipo/pretty.rs +++ b/crates/aiken-lang/src/tipo/pretty.rs @@ -296,10 +296,7 @@ fn resolve_alias( #[cfg(test)] mod tests { use super::*; - use crate::{ - builtins::{function, int}, - tipo::Span, - }; + use crate::tipo::{Span, Type}; use pretty_assertions::assert_eq; use std::cell::RefCell; @@ -490,7 +487,7 @@ mod tests { "?", ); assert_string!( - function( + Type::function( vec![Rc::new(Type::Var { tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 78 })), alias: None, @@ -503,7 +500,7 @@ mod tests { "fn(?) -> ?", ); assert_string!( - function( + Type::function( vec![Rc::new(Type::Var { tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 78 })), alias: None, @@ -692,10 +689,16 @@ mod tests { #[test] fn function_test() { - assert_eq!(pretty_print(function(vec![], int())), "fn() -> Int"); + assert_eq!( + pretty_print(Type::function(vec![], Type::int())), + "fn() -> Int" + ); assert_eq!( - pretty_print(function(vec![int(), int(), int()], int())), + pretty_print(Type::function( + vec![Type::int(), Type::int(), Type::int()], + Type::int() + )), "fn(Int, Int, Int) -> Int" ); } diff --git a/crates/aiken-project/src/blueprint/mod.rs b/crates/aiken-project/src/blueprint/mod.rs index 86369656c..7417bcc26 100644 --- a/crates/aiken-project/src/blueprint/mod.rs +++ b/crates/aiken-project/src/blueprint/mod.rs @@ -153,7 +153,7 @@ impl From<&Config> for Preamble { #[cfg(test)] mod tests { use super::*; - use aiken_lang::builtins; + use aiken_lang::tipo::Type; use schema::{Data, Declaration, Items, Schema}; use serde_json::{self, json}; use std::collections::HashMap; @@ -225,17 +225,17 @@ mod tests { fn serialize_with_definitions() { let mut definitions = Definitions::new(); definitions - .register::<_, Error>(&builtins::int(), &HashMap::new(), |_| { + .register::<_, Error>(&Type::int(), &HashMap::new(), |_| { Ok(Schema::Data(Data::Integer).into()) }) .unwrap(); definitions .register::<_, Error>( - &builtins::list(builtins::byte_array()), + &Type::list(Type::byte_array()), &HashMap::new(), |definitions| { let ref_bytes = definitions.register::<_, Error>( - &builtins::byte_array(), + &Type::byte_array(), &HashMap::new(), |_| Ok(Schema::Data(Data::Bytes).into()), )?; diff --git a/crates/aiken-project/src/blueprint/schema.rs b/crates/aiken-project/src/blueprint/schema.rs index be7620171..88f391ce4 100644 --- a/crates/aiken-project/src/blueprint/schema.rs +++ b/crates/aiken-project/src/blueprint/schema.rs @@ -4,7 +4,6 @@ use crate::{ }; use aiken_lang::{ ast::{Definition, TypedDataType, TypedDefinition}, - builtins::wrapped_redeemer, tipo::{pretty, Type, TypeVar}, }; use owo_colors::{OwoColorize, Stream::Stdout}; @@ -142,7 +141,7 @@ impl Annotated { ) -> Reference { definitions .register( - &wrapped_redeemer(type_info), + &Type::wrapped_redeemer(type_info), &HashMap::new(), |_| { Ok::<_, Error>(Annotated { diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index dd202b94a..8b936ac26 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -272,7 +272,7 @@ mod tests { use aiken_lang::{ self, ast::{TraceLevel, Tracing}, - builtins, + tipo::Type, }; use std::collections::HashMap; use uplc::ast as uplc_ast; @@ -336,7 +336,7 @@ mod tests { // "dataType": "integer" // } definitions - .register::<_, Error>(&builtins::int(), &HashMap::new(), |_| { + .register::<_, Error>(&Type::int(), &HashMap::new(), |_| { Ok(Schema::Data(Data::Integer).into()) }) .unwrap(); @@ -347,7 +347,7 @@ mod tests { // "dataType": "bytes" // } definitions - .register::<_, Error>(&builtins::byte_array(), &HashMap::new(), |_| { + .register::<_, Error>(&Type::byte_array(), &HashMap::new(), |_| { Ok(Schema::Data(Data::Bytes).into()) }) .unwrap(); diff --git a/crates/aiken-project/src/test_framework.rs b/crates/aiken-project/src/test_framework.rs index cac3d445f..884a3595c 100644 --- a/crates/aiken-project/src/test_framework.rs +++ b/crates/aiken-project/src/test_framework.rs @@ -1,7 +1,6 @@ use aiken_lang::ast::OnTestFailure; pub(crate) use aiken_lang::{ ast::{BinOp, DataTypeKey, IfBranch, Span, TypedArg, TypedDataType, TypedTest}, - builtins::bool, expr::{TypedExpr, UntypedExpr}, format::Formatter, gen_uplc::CodeGenerator, @@ -1056,7 +1055,7 @@ impl TryFrom for Assertion { left, right, .. - } if tipo == bool() => { + } if tipo == Type::bool() => { // 'and' and 'or' are left-associative operators. match (*right).clone().try_into() { Ok(Assertion { @@ -1094,7 +1093,7 @@ impl TryFrom for Assertion { let then_is_true = match body { TypedExpr::Var { name, constructor, .. - } => name == "True" && constructor.tipo == bool(), + } => name == "True" && constructor.tipo == Type::bool(), _ => false, }; @@ -1102,7 +1101,7 @@ impl TryFrom for Assertion { TypedExpr::Trace { then, .. } => match *then { TypedExpr::Var { name, constructor, .. - } => name == "False" && constructor.tipo == bool(), + } => name == "False" && constructor.tipo == Type::bool(), _ => false, }, _ => false,