DRY builtins types creation to ensure proper consistency.

This commit is contained in:
KtorZ 2024-08-16 15:26:52 +02:00
parent 5b61a75088
commit 7ec3f2e8df
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
23 changed files with 1182 additions and 1312 deletions

View File

@ -1,8 +1,6 @@
pub mod well_known;
use crate::{ use crate::{
builtins::{
self, g1_element, g2_element, SCRIPT_CONTEXT, SCRIPT_PURPOSE, SCRIPT_PURPOSE_MINT,
SCRIPT_PURPOSE_SPEND, SCRIPT_PURPOSE_WITHDRAW,
},
expr::{TypedExpr, UntypedExpr}, expr::{TypedExpr, UntypedExpr},
line_numbers::LineNumbers, line_numbers::LineNumbers,
parser::token::{Base, Token}, parser::token::{Base, Token},
@ -28,12 +26,12 @@ pub const ENV_MODULE: &str = "env";
pub const CONFIG_MODULE: &str = "config"; pub const CONFIG_MODULE: &str = "config";
pub const DEFAULT_ENV_MODULE: &str = "default"; pub const DEFAULT_ENV_MODULE: &str = "default";
pub const PURPOSE_SPEND: &str = "spend"; pub const HANDLER_SPEND: &str = "spend";
pub const PURPOSE_MINT: &str = "mint"; pub const HANDLER_MINT: &str = "mint";
pub const PURPOSE_WITHDRAW: &str = "withdraw"; pub const HANDLER_WITHDRAW: &str = "withdraw";
pub const PURPOSE_PUBLISH: &str = "publish"; pub const HANDLER_PUBLISH: &str = "publish";
pub const PURPOSE_VOTE: &str = "vote"; pub const HANDLER_VOTE: &str = "vote";
pub const PURPOSE_PROPOSE: &str = "propose"; pub const HANDLER_PROPOSE: &str = "propose";
pub type TypedModule = Module<TypeInfo, TypedDefinition>; pub type TypedModule = Module<TypeInfo, TypedDefinition>;
pub type UntypedModule = Module<(), UntypedDefinition>; pub type UntypedModule = Module<(), UntypedDefinition>;
@ -281,23 +279,23 @@ impl TypedFunction {
} }
pub fn has_valid_purpose_name(&self) -> bool { pub fn has_valid_purpose_name(&self) -> bool {
self.name == PURPOSE_SPEND self.name == HANDLER_SPEND
|| self.name == PURPOSE_PUBLISH || self.name == HANDLER_PUBLISH
|| self.name == PURPOSE_PROPOSE || self.name == HANDLER_PROPOSE
|| self.name == PURPOSE_MINT || self.name == HANDLER_MINT
|| self.name == PURPOSE_WITHDRAW || self.name == HANDLER_WITHDRAW
|| self.name == PURPOSE_VOTE || self.name == HANDLER_VOTE
} }
pub fn validator_arity(&self) -> usize { pub fn validator_arity(&self) -> usize {
if self.name == PURPOSE_SPEND if self.name == HANDLER_SPEND
|| self.name == PURPOSE_PUBLISH || self.name == HANDLER_PUBLISH
|| self.name == PURPOSE_PROPOSE || self.name == HANDLER_PROPOSE
{ {
4 4
} else if self.name == PURPOSE_MINT } else if self.name == HANDLER_MINT
|| self.name == PURPOSE_WITHDRAW || self.name == HANDLER_WITHDRAW
|| self.name == PURPOSE_VOTE || self.name == HANDLER_VOTE
{ {
3 3
} else { } else {
@ -383,207 +381,24 @@ pub struct FunctionAccessKey {
pub function_name: String, pub function_name: String,
} }
pub type UntypedDataType = DataType<()>;
pub type TypedDataType = DataType<Rc<Type>>; pub type TypedDataType = DataType<Rc<Type>>;
impl TypedDataType { impl TypedDataType {
pub fn data() -> Self { pub fn known_enum(name: &str, constructors: &[&str]) -> Self {
DataType { Self {
constructors: vec![], name: name.to_string(),
doc: None, constructors: RecordConstructor::known_enum(constructors),
location: Span::empty(), location: Span::empty(),
name: "Data".to_string(),
opaque: false, opaque: false,
public: true,
parameters: vec![], parameters: vec![],
public: true,
typed_parameters: vec![], typed_parameters: vec![],
}
}
pub fn bool() -> Self {
DataType {
constructors: vec![
RecordConstructor {
location: Span::empty(),
name: "False".to_string(),
arguments: vec![],
doc: None, 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,
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<Type>) -> 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)] #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct DataType<T> { pub struct DataType<T> {
pub constructors: Vec<RecordConstructor<T>>, pub constructors: Vec<RecordConstructor<T>>,
@ -647,14 +462,14 @@ pub struct Validator<T, Arg, Expr> {
} }
impl TypedValidator { impl TypedValidator {
pub fn available_purposes() -> Vec<String> { pub fn available_handler_names() -> Vec<String> {
vec![ vec![
PURPOSE_SPEND.to_string(), HANDLER_SPEND.to_string(),
PURPOSE_MINT.to_string(), HANDLER_MINT.to_string(),
PURPOSE_WITHDRAW.to_string(), HANDLER_WITHDRAW.to_string(),
PURPOSE_PUBLISH.to_string(), HANDLER_PUBLISH.to_string(),
PURPOSE_VOTE.to_string(), HANDLER_VOTE.to_string(),
PURPOSE_PROPOSE.to_string(), HANDLER_PROPOSE.to_string(),
] ]
} }
@ -838,12 +653,12 @@ pub enum Constant {
impl Constant { impl Constant {
pub fn tipo(&self) -> Rc<Type> { pub fn tipo(&self) -> Rc<Type> {
match self { match self {
Constant::Int { .. } => builtins::int(), Constant::Int { .. } => Type::int(),
Constant::String { .. } => builtins::string(), Constant::String { .. } => Type::string(),
Constant::ByteArray { .. } => builtins::byte_array(), Constant::ByteArray { .. } => Type::byte_array(),
Constant::CurvePoint { point, .. } => match point.as_ref() { Constant::CurvePoint { point, .. } => match point.as_ref() {
Curve::Bls12_381(Bls12_381Point::G1(_)) => builtins::g1_element(), Curve::Bls12_381(Bls12_381Point::G1(_)) => Type::g1_element(),
Curve::Bls12_381(Bls12_381Point::G2(_)) => builtins::g2_element(), Curve::Bls12_381(Bls12_381Point::G2(_)) => Type::g2_element(),
}, },
} }
} }
@ -896,6 +711,19 @@ impl<A> RecordConstructor<A> {
pub fn put_doc(&mut self, new_doc: String) { pub fn put_doc(&mut self, new_doc: String) {
self.doc = Some(new_doc); self.doc = Some(new_doc);
} }
pub fn known_enum(names: &[&str]) -> Vec<RecordConstructor<A>> {
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)] #[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. // TODO: This function definition is weird, see where this is used and how.
pub fn tipo(&self, value: &TypedExpr) -> Option<Rc<Type>> { pub fn tipo(&self, value: &TypedExpr) -> Option<Rc<Type>> {
match self { match self {
Pattern::Int { .. } => Some(builtins::int()), Pattern::Int { .. } => Some(Type::int()),
Pattern::ByteArray { .. } => Some(builtins::byte_array()), Pattern::ByteArray { .. } => Some(Type::byte_array()),
Pattern::Constructor { tipo, .. } => Some(tipo.clone()), Pattern::Constructor { tipo, .. } => Some(tipo.clone()),
Pattern::Var { .. } | Pattern::Assign { .. } | Pattern::Discard { .. } => { Pattern::Var { .. } | Pattern::Assign { .. } | Pattern::Discard { .. } => {
Some(value.tipo()) Some(value.tipo())
@ -1800,8 +1628,8 @@ impl<'de> serde::Deserialize<'de> for Bls12_381Point {
impl Bls12_381Point { impl Bls12_381Point {
pub fn tipo(&self) -> Rc<Type> { pub fn tipo(&self) -> Rc<Type> {
match self { match self {
Bls12_381Point::G1(_) => g1_element(), Bls12_381Point::G1(_) => Type::g1_element(),
Bls12_381Point::G2(_) => g2_element(), Bls12_381Point::G2(_) => Type::g2_element(),
} }
} }
} }

View File

@ -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<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: DATA.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn int() -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
name: INT.to_string(),
module: "".to_string(),
args: vec![],
alias: None,
})
}
pub fn bool() -> Rc<Self> {
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<Type> {
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<Type> {
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<Type> {
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<Type> {
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<Type>>) -> Rc<Type> {
Rc::new(Type::Tuple { elems, alias: None })
}
pub fn pair(fst: Rc<Type>, snd: Rc<Type>) -> Rc<Type> {
Rc::new(Type::Pair {
fst,
snd,
alias: None,
})
}
pub fn script_purpose() -> Rc<Type> {
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<Type> {
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<Type> {
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<Type>) -> Rc<Type> {
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<Type>, v: Rc<Type>) -> Rc<Type> {
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<Type>) -> Rc<Type> {
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<Type> {
Rc::new(Type::App {
args: vec![],
public: true,
contains_opaque: false,
name: STRING.to_string(),
module: "".to_string(),
alias: None,
})
}
pub fn void() -> Rc<Type> {
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<Type>) -> Rc<Type> {
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<Type> {
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<Rc<Type>>, ret: Rc<Type>) -> Rc<Type> {
Rc::new(Type::Fn {
ret,
args,
alias: None,
})
}
pub fn generic_var(id: u64) -> Rc<Type> {
let tipo = Rc::new(RefCell::new(TypeVar::Generic { id }));
Rc::new(Type::Var { tipo, alias: None })
}
pub fn unbound_var(id: u64) -> Rc<Type> {
let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id }));
Rc::new(Type::Var { tipo, alias: None })
}
pub fn wrapped_redeemer(redeemer: Rc<Type>) -> Rc<Type> {
Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: REDEEMER_WRAPPER.to_string(),
args: vec![redeemer],
alias: None,
})
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
use crate::tipo::ValueConstructorVariant;
pub(crate) use crate::{ pub(crate) use crate::{
ast::{ ast::{
self, Annotation, ArgBy, ArgName, AssignmentPattern, BinOp, Bls12_381Point, self, Annotation, ArgBy, ArgName, AssignmentPattern, BinOp, Bls12_381Point,
@ -8,7 +7,6 @@ pub(crate) use crate::{
TypedDataType, TypedIfBranch, TypedRecordUpdateArg, UnOp, UntypedArg, TypedDataType, TypedIfBranch, TypedRecordUpdateArg, UnOp, UntypedArg,
UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg, UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg,
}, },
builtins::void,
parser::token::Base, parser::token::Base,
tipo::{ tipo::{
check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo, check_replaceable_opaque_type, convert_opaque_type, lookup_data_type_by_tipo,
@ -224,9 +222,10 @@ impl TypedExpr {
| Self::RecordAccess { tipo, .. } | Self::RecordAccess { tipo, .. }
| Self::RecordUpdate { tipo, .. } | Self::RecordUpdate { tipo, .. }
| Self::CurvePoint { tipo, .. } => tipo.clone(), | Self::CurvePoint { tipo, .. } => tipo.clone(),
Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => { Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => expressions
expressions.last().map(TypedExpr::tipo).unwrap_or_else(void) .last()
} .map(TypedExpr::tipo)
.unwrap_or_else(Type::void),
} }
} }
@ -491,7 +490,7 @@ impl TypedExpr {
module: String::new(), module: String::new(),
constructors_count: 1, constructors_count: 1,
}, },
tipo: void(), tipo: Type::void(),
}, },
location, location,
} }

View File

@ -13,14 +13,11 @@ use self::{
}; };
use crate::{ use crate::{
ast::{ 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, FunctionAccessKey, OnTestFailure, Pattern, Span, TraceLevel, Tracing, TypedArg,
TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp,
}, },
builtins::{ builtins::PRELUDE,
bool, byte_array, data, function, int, list, option, pair, script_context, script_purpose,
void, PRELUDE, SCRIPT_PURPOSE_MINT, SCRIPT_PURPOSE_SPEND, SCRIPT_PURPOSE_WITHDRAW,
},
expr::TypedExpr, expr::TypedExpr,
gen_uplc::{ gen_uplc::{
air::ExpectLevel, air::ExpectLevel,
@ -138,14 +135,14 @@ impl<'a> CodeGenerator<'a> {
annotation: None, annotation: None,
doc: None, doc: None,
is_validator_param: false, is_validator_param: false,
tipo: data(), tipo: Type::data(),
}], }],
body: TypedExpr::Sequence { body: TypedExpr::Sequence {
location: Span::empty(), location: Span::empty(),
expressions: vec![ expressions: vec![
TypedExpr::Assignment { TypedExpr::Assignment {
location: Span::empty(), location: Span::empty(),
tipo: script_context(), tipo: Type::script_context(),
value: TypedExpr::Var { value: TypedExpr::Var {
location: Span::empty(), location: Span::empty(),
constructor: ValueConstructor { constructor: ValueConstructor {
@ -153,7 +150,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: script_context(), tipo: Type::script_context(),
}, },
name: "__context__".to_string(), name: "__context__".to_string(),
} }
@ -194,13 +191,16 @@ impl<'a> CodeGenerator<'a> {
field_map: None, field_map: None,
}, },
spread_location: 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_(), kind: AssignmentKind::let_(),
}, },
TypedExpr::When { TypedExpr::When {
location: Span::empty(), location: Span::empty(),
tipo: bool(), tipo: Type::bool(),
subject: TypedExpr::Var { subject: TypedExpr::Var {
location: Span::empty(), location: Span::empty(),
constructor: ValueConstructor { constructor: ValueConstructor {
@ -208,7 +208,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: script_purpose(), tipo: Type::script_purpose(),
}, },
name: "__purpose__".to_string(), name: "__purpose__".to_string(),
} }
@ -241,7 +241,7 @@ impl<'a> CodeGenerator<'a> {
"spend" => TypedPattern::Constructor { "spend" => TypedPattern::Constructor {
is_record: false, is_record: false,
location: Span::empty(), location: Span::empty(),
name: SCRIPT_PURPOSE_SPEND.to_string(), name: well_known::SCRIPT_PURPOSE_SPEND.to_string(),
arguments: vec![ arguments: vec![
CallArg { CallArg {
label: None, label: None,
@ -262,20 +262,20 @@ impl<'a> CodeGenerator<'a> {
], ],
module: None, module: None,
constructor: PatternConstructor::Record { constructor: PatternConstructor::Record {
name: SCRIPT_PURPOSE_SPEND.to_string(), name: well_known::SCRIPT_PURPOSE_SPEND.to_string(),
field_map: None, field_map: None,
}, },
spread_location: None, spread_location: None,
tipo: function( tipo: Type::function(
vec![data(), option(data())], vec![Type::data(), Type::option(Type::data())],
script_purpose(), Type::script_purpose(),
), ),
}, },
"mint" => TypedPattern::Constructor { "mint" => TypedPattern::Constructor {
is_record: false, is_record: false,
location: Span::empty(), location: Span::empty(),
name: SCRIPT_PURPOSE_MINT.to_string(), name: well_known::SCRIPT_PURPOSE_MINT.to_string(),
arguments: vec![CallArg { arguments: vec![CallArg {
label: None, label: None,
location: Span::empty(), location: Span::empty(),
@ -286,17 +286,20 @@ impl<'a> CodeGenerator<'a> {
}], }],
module: None, module: None,
constructor: PatternConstructor::Record { constructor: PatternConstructor::Record {
name: SCRIPT_PURPOSE_MINT.to_string(), name: well_known::SCRIPT_PURPOSE_MINT.to_string(),
field_map: None, field_map: None,
}, },
spread_location: None, spread_location: None,
tipo: function(vec![byte_array()], script_purpose()), tipo: Type::function(
vec![Type::byte_array()],
Type::script_purpose(),
),
}, },
"withdraw" => TypedPattern::Constructor { "withdraw" => TypedPattern::Constructor {
is_record: false, is_record: false,
location: Span::empty(), location: Span::empty(),
name: SCRIPT_PURPOSE_WITHDRAW.to_string(), name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(),
arguments: vec![CallArg { arguments: vec![CallArg {
label: None, label: None,
location: Span::empty(), location: Span::empty(),
@ -307,11 +310,14 @@ impl<'a> CodeGenerator<'a> {
}], }],
module: None, module: None,
constructor: PatternConstructor::Record { constructor: PatternConstructor::Record {
name: SCRIPT_PURPOSE_WITHDRAW.to_string(), name: well_known::SCRIPT_PURPOSE_WITHDRAW.to_string(),
field_map: None, field_map: None,
}, },
spread_location: None, spread_location: None,
tipo: function(vec![data()], script_purpose()), tipo: Type::function(
vec![Type::data()],
Type::script_purpose(),
),
}, },
purpose => { purpose => {
@ -332,7 +338,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: data(), tipo: Type::data(),
}, },
name: "__redeemer__".to_string(), name: "__redeemer__".to_string(),
} }
@ -364,7 +370,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: option(data()), tipo: Type::option(Type::data()),
}, },
name: "__datum__".to_string(), name: "__datum__".to_string(),
} }
@ -396,7 +402,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: data(), tipo: Type::data(),
}, },
name: "__purpose_arg__".to_string(), name: "__purpose_arg__".to_string(),
} }
@ -421,7 +427,7 @@ impl<'a> CodeGenerator<'a> {
variant: ValueConstructorVariant::LocalVariable { variant: ValueConstructorVariant::LocalVariable {
location: Span::empty(), location: Span::empty(),
}, },
tipo: data(), tipo: Type::data(),
}, },
name: "__transaction__".to_string(), name: "__transaction__".to_string(),
} }
@ -504,7 +510,7 @@ impl<'a> CodeGenerator<'a> {
name: "wrapper_validator".to_string(), name: "wrapper_validator".to_string(),
public: true, public: true,
return_annotation: None, return_annotation: None,
return_type: bool(), return_type: Type::bool(),
end_position: 0, end_position: 0,
on_test_failure: OnTestFailure::FailImmediately, on_test_failure: OnTestFailure::FailImmediately,
}; };
@ -619,7 +625,7 @@ impl<'a> CodeGenerator<'a> {
self.special_functions.insert_new_function( self.special_functions.insert_new_function(
msg_func_name.clone(), msg_func_name.clone(),
Term::Error.delayed_trace(Term::string(msg)).delay(), Term::Error.delayed_trace(Term::string(msg)).delay(),
void(), Type::void(),
); );
Some(self.special_functions.use_function_tree(msg_func_name)) 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); let function_name = format!("__access_index_{}", *index);
if self.code_gen_functions.get(&function_name).is_none() { 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 { for _ in 0..*index {
body = AirTree::builtin( body = AirTree::builtin(
DefaultFunction::TailList, DefaultFunction::TailList,
list(data()), Type::list(Type::data()),
vec![body], vec![body],
) )
} }
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]); body = AirTree::builtin(
DefaultFunction::HeadList,
Type::data(),
vec![body],
);
self.code_gen_functions.insert( self.code_gen_functions.insert(
function_name.clone(), function_name.clone(),
@ -1048,7 +1058,7 @@ impl<'a> CodeGenerator<'a> {
let list_of_fields = AirTree::call( let list_of_fields = AirTree::call(
self.special_functions self.special_functions
.use_function_tree(CONSTR_FIELDS_EXPOSER.to_string()), .use_function_tree(CONSTR_FIELDS_EXPOSER.to_string()),
list(data()), Type::list(Type::data()),
vec![self.build(record, module_build_name, &[])], vec![self.build(record, module_build_name, &[])],
); );
@ -1163,17 +1173,21 @@ impl<'a> CodeGenerator<'a> {
let function_name = format!("__access_index_{}", *index); let function_name = format!("__access_index_{}", *index);
if self.code_gen_functions.get(&function_name).is_none() { 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 { for _ in 0..*index {
body = AirTree::builtin( body = AirTree::builtin(
DefaultFunction::TailList, DefaultFunction::TailList,
list(data()), Type::list(Type::data()),
vec![body], vec![body],
) )
} }
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]); body = AirTree::builtin(
DefaultFunction::HeadList,
Type::data(),
vec![body],
);
self.code_gen_functions.insert( self.code_gen_functions.insert(
function_name.clone(), function_name.clone(),
@ -1282,7 +1296,7 @@ impl<'a> CodeGenerator<'a> {
let otherwise = match &props.otherwise { let otherwise = match &props.otherwise {
Some(x) => x.clone(), Some(x) => x.clone(),
// (delay (error )) // (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 { match pattern {
@ -1298,10 +1312,10 @@ impl<'a> CodeGenerator<'a> {
let expect = AirTree::binop( let expect = AirTree::binop(
BinOp::Eq, BinOp::Eq,
bool(), Type::bool(),
AirTree::int(expected_int), AirTree::int(expected_int),
AirTree::local_var(&name, int()), AirTree::local_var(&name, Type::int()),
int(), Type::int(),
); );
assign_casted_value( assign_casted_value(
@ -1320,10 +1334,10 @@ impl<'a> CodeGenerator<'a> {
let expect = AirTree::binop( let expect = AirTree::binop(
BinOp::Eq, BinOp::Eq,
bool(), Type::bool(),
AirTree::byte_array(expected_bytes.clone()), AirTree::byte_array(expected_bytes.clone()),
AirTree::local_var(&name, byte_array()), AirTree::local_var(&name, Type::byte_array()),
byte_array(), Type::byte_array(),
); );
assign_casted_value( assign_casted_value(
@ -1831,7 +1845,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::when( AirTree::when(
&subject_name, &subject_name,
void(), Type::void(),
tipo.clone(), tipo.clone(),
AirTree::local_var(&constructor_name, tipo.clone()), AirTree::local_var(&constructor_name, tipo.clone()),
AirTree::assert_constr_index( AirTree::assert_constr_index(
@ -2000,11 +2014,14 @@ impl<'a> CodeGenerator<'a> {
defined_data_types, defined_data_types,
location, location,
AirTree::call( AirTree::call(
AirTree::local_var(format!("__curried_expect_on_list_{}", depth), void()), AirTree::local_var(
void(), format!("__curried_expect_on_list_{}", depth),
Type::void(),
),
Type::void(),
vec![AirTree::builtin( vec![AirTree::builtin(
DefaultFunction::TailList, DefaultFunction::TailList,
list(data()), Type::list(Type::data()),
vec![AirTree::local_var( vec![AirTree::local_var(
format!("__list_{}", depth), format!("__list_{}", depth),
tipo.clone(), tipo.clone(),
@ -2039,7 +2056,7 @@ impl<'a> CodeGenerator<'a> {
&pair_name, &pair_name,
AirTree::builtin( AirTree::builtin(
DefaultFunction::HeadList, DefaultFunction::HeadList,
pair(data(), data()), Type::pair(Type::data(), Type::data()),
vec![AirTree::local_var( vec![AirTree::local_var(
format!("__list_{}", depth), format!("__list_{}", depth),
tipo.clone(), tipo.clone(),
@ -2083,7 +2100,7 @@ impl<'a> CodeGenerator<'a> {
let func_call = AirTree::call( let func_call = AirTree::call(
AirTree::var( AirTree::var(
ValueConstructor::public( ValueConstructor::public(
void(), Type::void(),
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
name: EXPECT_ON_LIST.to_string(), name: EXPECT_ON_LIST.to_string(),
field_map: None, field_map: None,
@ -2096,7 +2113,7 @@ impl<'a> CodeGenerator<'a> {
EXPECT_ON_LIST, EXPECT_ON_LIST,
"", "",
), ),
void(), Type::void(),
vec![AirTree::local_var(&map_name, tipo.clone()), unwrap_function], vec![AirTree::local_var(&map_name, tipo.clone()), unwrap_function],
); );
@ -2176,7 +2193,7 @@ impl<'a> CodeGenerator<'a> {
&item_name, &item_name,
AirTree::builtin( AirTree::builtin(
DefaultFunction::HeadList, DefaultFunction::HeadList,
data(), Type::data(),
vec![AirTree::local_var( vec![AirTree::local_var(
format!("__list_{}", depth), format!("__list_{}", depth),
tipo.clone(), tipo.clone(),
@ -2185,7 +2202,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::soft_cast_assignment( AirTree::soft_cast_assignment(
&item_name, &item_name,
inner_list_type.clone(), inner_list_type.clone(),
AirTree::local_var(&item_name, data()), AirTree::local_var(&item_name, Type::data()),
self.expect_type_assign( self.expect_type_assign(
inner_list_type, inner_list_type,
AirTree::local_var(&item_name, inner_list_type.clone()), AirTree::local_var(&item_name, inner_list_type.clone()),
@ -2194,12 +2211,12 @@ impl<'a> CodeGenerator<'a> {
AirTree::call( AirTree::call(
AirTree::local_var( AirTree::local_var(
format!("__curried_expect_on_list_{}", depth), format!("__curried_expect_on_list_{}", depth),
void(), Type::void(),
), ),
void(), Type::void(),
vec![AirTree::builtin( vec![AirTree::builtin(
DefaultFunction::TailList, DefaultFunction::TailList,
list(data()), Type::list(Type::data()),
vec![AirTree::local_var( vec![AirTree::local_var(
format!("__list_{}", depth), format!("__list_{}", depth),
tipo.clone(), tipo.clone(),
@ -2243,7 +2260,7 @@ impl<'a> CodeGenerator<'a> {
let func_call = AirTree::call( let func_call = AirTree::call(
AirTree::var( AirTree::var(
ValueConstructor::public( ValueConstructor::public(
void(), Type::void(),
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
name: EXPECT_ON_LIST.to_string(), name: EXPECT_ON_LIST.to_string(),
field_map: None, field_map: None,
@ -2256,7 +2273,7 @@ impl<'a> CodeGenerator<'a> {
EXPECT_ON_LIST, EXPECT_ON_LIST,
"", "",
), ),
void(), Type::void(),
vec![ vec![
AirTree::local_var(&list_name, tipo.clone()), AirTree::local_var(&list_name, tipo.clone()),
unwrap_function, unwrap_function,
@ -2347,10 +2364,13 @@ impl<'a> CodeGenerator<'a> {
let current_defined = defined_data_types.clone(); let current_defined = defined_data_types.clone();
let mut diff_defined_types = vec![]; let mut diff_defined_types = vec![];
let var_then = let var_then = AirTree::call(
AirTree::call(AirTree::local_var("then_delayed", void()), void(), vec![]); 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( let constr_clauses = data_type.constructors.iter().enumerate().rfold(
otherwise_delayed.clone(), otherwise_delayed.clone(),
@ -2431,13 +2451,13 @@ impl<'a> CodeGenerator<'a> {
let when_expr = AirTree::when( let when_expr = AirTree::when(
format!("__subject_span_{}_{}", location.start, location.end), format!("__subject_span_{}_{}", location.start, location.end),
void(), Type::void(),
tipo.clone(), tipo.clone(),
AirTree::local_var( AirTree::local_var(
format!("__constr_var_span_{}_{}", location.start, location.end), format!("__constr_var_span_{}_{}", location.start, location.end),
tipo.clone(), tipo.clone(),
), ),
AirTree::call(constr_clauses, void(), vec![]), AirTree::call(constr_clauses, Type::void(), vec![]),
); );
let func_body = AirTree::let_assignment( 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 // Since check_last_item is false this will never get added to the final uplc anyway
ExpectLevel::None, ExpectLevel::None,
elems_then, elems_then,
AirTree::error(void(), false), AirTree::error(Type::void(), false),
) )
} else { } else {
assert!(defined_tails.len() >= elems.len()); 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()), AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
false, false,
next_then, 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()), AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
false, false,
next_then, 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()), AirTree::local_var(&props.clause_var_name, subject_tipo.clone()),
false, false,
tuple_name_assigns, tuple_name_assigns,
AirTree::error(void(), false), AirTree::error(Type::void(), false),
), ),
) )
} else { } else {
@ -3383,7 +3403,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::clause_guard( AirTree::clause_guard(
&props.original_subject_name, &props.original_subject_name,
AirTree::int(value), AirTree::int(value),
int(), Type::int(),
then, then,
) )
} }
@ -3392,7 +3412,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::clause_guard( AirTree::clause_guard(
&props.original_subject_name, &props.original_subject_name,
AirTree::byte_array(value.clone()), AirTree::byte_array(value.clone()),
byte_array(), Type::byte_array(),
then, then,
) )
} }
@ -3517,14 +3537,14 @@ impl<'a> CodeGenerator<'a> {
AirTree::clause_guard( AirTree::clause_guard(
&props.original_subject_name, &props.original_subject_name,
AirTree::bool(constr_name == "True"), AirTree::bool(constr_name == "True"),
bool(), Type::bool(),
then, then,
) )
} else if subject_tipo.is_void() { } else if subject_tipo.is_void() {
AirTree::clause_guard( AirTree::clause_guard(
&props.original_subject_name, &props.original_subject_name,
AirTree::void(), AirTree::void(),
void(), Type::void(),
then, then,
) )
} else { } else {
@ -3596,7 +3616,7 @@ impl<'a> CodeGenerator<'a> {
arg_names.push(arg_name.clone()); 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); 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( self.special_functions.insert_new_function(
msg_func_name.clone(), msg_func_name.clone(),
Term::Error.delayed_trace(Term::string(msg)).delay(), Term::Error.delayed_trace(Term::string(msg)).delay(),
void(), Type::void(),
); );
Some(self.special_functions.use_function_tree(msg_func_name)) Some(self.special_functions.use_function_tree(msg_func_name))
@ -3637,7 +3657,7 @@ impl<'a> CodeGenerator<'a> {
inner_then, inner_then,
&actual_type, &actual_type,
AssignmentProperties { AssignmentProperties {
value_type: data(), value_type: Type::data(),
kind: AssignmentKind::expect(), kind: AssignmentKind::expect(),
remove_unused: false, remove_unused: false,
full_check: true, full_check: true,

View File

@ -7,7 +7,6 @@ use crate::{
Constant, DataTypeKey, FunctionAccessKey, Pattern, Span, TraceLevel, TypedArg, Constant, DataTypeKey, FunctionAccessKey, Pattern, Span, TraceLevel, TypedArg,
TypedAssignmentKind, TypedClause, TypedDataType, TypedPattern, TypedAssignmentKind, TypedClause, TypedDataType, TypedPattern,
}, },
builtins::{data, function, int, list, void},
expr::TypedExpr, expr::TypedExpr,
line_numbers::{LineColumn, LineNumbers}, line_numbers::{LineColumn, LineNumbers},
tipo::{ tipo::{
@ -212,7 +211,7 @@ impl CodeGenSpecialFuncs {
Term::snd_pair() Term::snd_pair()
.apply(Term::unconstr_data().apply(Term::var("__constr_var"))) .apply(Term::unconstr_data().apply(Term::var("__constr_var")))
.lambda("__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() Term::fst_pair()
.apply(Term::unconstr_data().apply(Term::var("__constr_var"))) .apply(Term::unconstr_data().apply(Term::var("__constr_var")))
.lambda("__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(), tipo: tipo.clone(),
text: Box::new(TypedExpr::String { text: Box::new(TypedExpr::String {
location: Span::empty(), location: Span::empty(),
tipo: crate::builtins::string(), tipo: Type::string(),
value: format!("Clause hole found for {index} elements."), value: format!("Clause hole found for {index} elements."),
}), }),
then: Box::new(TypedExpr::ErrorTerm { then: Box::new(TypedExpr::ErrorTerm {
@ -1688,15 +1687,15 @@ pub fn cast_validator_args(term: Term<Name>, arguments: &[TypedArg]) -> Term<Nam
pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree { pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree {
let otherwise = match trace { 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( TraceLevel::Verbose => AirTree::trace(
AirTree::string("Validator returned false"), AirTree::string("Validator returned false"),
void(), Type::void(),
AirTree::error(void(), true), 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<Name>) -> Option<Rc<UplcConstant>> { pub fn extract_constant(term: &Term<Name>) -> Option<Rc<UplcConstant>> {

View File

@ -1,7 +1,6 @@
use super::air::{Air, ExpectLevel}; use super::air::{Air, ExpectLevel};
use crate::{ use crate::{
ast::{BinOp, Curve, Span, UnOp}, ast::{BinOp, Curve, Span, UnOp},
builtins::{bool, byte_array, data, int, list, string, void},
tipo::{Type, ValueConstructor, ValueConstructorVariant}, tipo::{Type, ValueConstructor, ValueConstructorVariant},
}; };
use indexmap::IndexSet; use indexmap::IndexSet;
@ -113,7 +112,7 @@ pub enum AirMsg {
impl AirMsg { impl AirMsg {
pub fn to_air_tree(&self) -> AirTree { pub fn to_air_tree(&self) -> AirTree {
match self { 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), AirMsg::Msg(msg) => AirTree::string(msg),
} }
} }
@ -862,8 +861,8 @@ impl AirTree {
AirTree::var( AirTree::var(
ValueConstructor::public( ValueConstructor::public(
Type::Fn { Type::Fn {
args: vec![list(data())], args: vec![Type::list(Type::data())],
ret: data(), ret: Type::data(),
alias: None, alias: None,
} }
.into(), .into(),
@ -879,7 +878,7 @@ impl AirTree {
function_name, function_name,
"", "",
), ),
data(), Type::data(),
vec![list_of_fields], vec![list_of_fields],
), ),
tipo.clone(), tipo.clone(),
@ -984,7 +983,7 @@ impl AirTree {
} else { } else {
DefaultFunction::SndPair DefaultFunction::SndPair
}, },
data(), Type::data(),
vec![tuple], vec![tuple],
), ),
tipo.clone(), tipo.clone(),
@ -1039,9 +1038,9 @@ impl AirTree {
} }
pub fn expect_on_list2() -> 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( AirTree::let_assignment(
INNER_EXPECT_ON_LIST, INNER_EXPECT_ON_LIST,
@ -1051,13 +1050,13 @@ impl AirTree {
"__list_to_check".to_string(), "__list_to_check".to_string(),
], ],
AirTree::call( AirTree::call(
AirTree::local_var("__check_with", void()), AirTree::local_var("__check_with", Type::void()),
void(), Type::void(),
vec![ vec![
list_var.clone(), list_var.clone(),
AirTree::call( AirTree::call(
inner_expect_on_list.clone(), inner_expect_on_list.clone(),
void(), Type::void(),
vec![inner_expect_on_list.clone()], vec![inner_expect_on_list.clone()],
), ),
], ],
@ -1066,27 +1065,27 @@ impl AirTree {
), ),
AirTree::call( AirTree::call(
inner_expect_on_list.clone(), inner_expect_on_list.clone(),
void(), Type::void(),
vec![inner_expect_on_list, list_var], vec![inner_expect_on_list, list_var],
), ),
) )
} }
pub fn expect_on_list() -> AirTree { 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( let expect_on_head = AirTree::call(
AirTree::local_var("__check_with", void()), AirTree::local_var("__check_with", Type::void()),
void(), Type::void(),
vec![head_list], vec![head_list],
); );
let next_call = AirTree::call( let next_call = AirTree::call(
AirTree::var( AirTree::var(
ValueConstructor::public( ValueConstructor::public(
void(), Type::void(),
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
name: EXPECT_ON_LIST.to_string(), name: EXPECT_ON_LIST.to_string(),
field_map: None, field_map: None,
@ -1099,14 +1098,17 @@ impl AirTree {
EXPECT_ON_LIST, EXPECT_ON_LIST,
"", "",
), ),
void(), Type::void(),
vec![ vec![
AirTree::builtin( AirTree::builtin(
DefaultFunction::TailList, DefaultFunction::TailList,
list(data()), Type::list(Type::data()),
vec![AirTree::local_var("__list_to_check", list(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( AirTree::list_clause(
"__list_to_check", "__list_to_check",
void(), Type::void(),
AirTree::void(), AirTree::void(),
assign, assign,
None, None,
@ -1675,10 +1677,10 @@ impl AirTree {
pub fn return_type(&self) -> Rc<Type> { pub fn return_type(&self) -> Rc<Type> {
match self { match self {
AirTree::Int { .. } => int(), AirTree::Int { .. } => Type::int(),
AirTree::String { .. } => string(), AirTree::String { .. } => Type::string(),
AirTree::ByteArray { .. } => byte_array(), AirTree::ByteArray { .. } => Type::byte_array(),
AirTree::Bool { .. } => bool(), AirTree::Bool { .. } => Type::bool(),
AirTree::CurvePoint { point } => point.tipo(), AirTree::CurvePoint { point } => point.tipo(),
AirTree::List { tipo, .. } AirTree::List { tipo, .. }
| AirTree::Tuple { tipo, .. } | AirTree::Tuple { tipo, .. }
@ -1693,14 +1695,14 @@ impl AirTree {
| AirTree::RecordUpdate { tipo, .. } | AirTree::RecordUpdate { tipo, .. }
| AirTree::ErrorTerm { tipo, .. } | AirTree::ErrorTerm { tipo, .. }
| AirTree::Trace { tipo, .. } => tipo.clone(), | AirTree::Trace { tipo, .. } => tipo.clone(),
AirTree::Void => void(), AirTree::Void => Type::void(),
AirTree::Var { constructor, .. } => constructor.tipo.clone(), AirTree::Var { constructor, .. } => constructor.tipo.clone(),
AirTree::Fn { func_body, .. } => func_body.return_type(), AirTree::Fn { func_body, .. } => func_body.return_type(),
AirTree::UnOp { op, .. } => match op { AirTree::UnOp { op, .. } => match op {
UnOp::Not => bool(), UnOp::Not => Type::bool(),
UnOp::Negate => int(), UnOp::Negate => Type::int(),
}, },
AirTree::CastToData { .. } => data(), AirTree::CastToData { .. } => Type::data(),
AirTree::Clause { then, .. } AirTree::Clause { then, .. }
| AirTree::ListClause { then, .. } | AirTree::ListClause { then, .. }
| AirTree::WrapClause { then, .. } | AirTree::WrapClause { then, .. }
@ -1725,7 +1727,7 @@ impl AirTree {
| AirTree::FieldsEmpty { then, .. } | AirTree::FieldsEmpty { then, .. }
| AirTree::ListEmpty { then, .. } | AirTree::ListEmpty { then, .. }
| AirTree::NoOp { then } => then.return_type(), | AirTree::NoOp { then } => then.return_type(),
AirTree::MultiValidator { .. } => void(), AirTree::MultiValidator { .. } => Type::void(),
} }
} }

View File

@ -1,7 +1,7 @@
use super::{error::ParseError, token::Token}; use super::{error::ParseError, token::Token};
use crate::{ use crate::{
ast, ast::{self, well_known},
builtins::{PAIR, PRELUDE}, builtins::PRELUDE,
}; };
use chumsky::prelude::*; use chumsky::prelude::*;
@ -19,7 +19,7 @@ pub fn parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
select! {Token::Name { name } if name == PRELUDE => name} select! {Token::Name { name } if name == PRELUDE => name}
.then_ignore(just(Token::Dot)) .then_ignore(just(Token::Dot))
.or_not() .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( .ignore_then(
expression expression
.clone() .clone()

View File

@ -1,5 +1,6 @@
use crate::{ use crate::{
builtins::{PAIR, PRELUDE}, ast::well_known,
builtins::PRELUDE,
expr::UntypedExpr, expr::UntypedExpr,
parser::{error::ParseError, token::Token}, parser::{error::ParseError, token::Token},
}; };
@ -11,7 +12,7 @@ pub fn parser(
select! {Token::Name { name } if name == PRELUDE => name} select! {Token::Name { name } if name == PRELUDE => name}
.then_ignore(just(Token::Dot)) .then_ignore(just(Token::Dot))
.or_not() .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( .ignore_then(
r.clone() r.clone()
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
ast::UntypedPattern, ast::{well_known, UntypedPattern},
builtins::PAIR,
parser::{error::ParseError, token::Token}, parser::{error::ParseError, token::Token},
}; };
use chumsky::prelude::*; use chumsky::prelude::*;
@ -8,7 +7,7 @@ use chumsky::prelude::*;
pub fn parser( pub fn parser(
pattern: Recursive<'_, Token, UntypedPattern, ParseError>, pattern: Recursive<'_, Token, UntypedPattern, ParseError>,
) -> impl Parser<Token, UntypedPattern, Error = ParseError> + '_ { ) -> impl Parser<Token, UntypedPattern, Error = ParseError> + '_ {
select! {Token::UpName { name } if name == PAIR => name} select! {Token::UpName { name } if name == well_known::PAIR => name}
.ignore_then(choice(( .ignore_then(choice((
just(Token::LeftParen), just(Token::LeftParen),
just(Token::NewLineLeftParen), just(Token::NewLineLeftParen),

View File

@ -1,10 +1,9 @@
use self::{environment::Environment, pretty::Printer}; use self::{environment::Environment, pretty::Printer};
use crate::{ use crate::{
ast::{ ast::{
Annotation, Constant, DataType, DataTypeKey, DefinitionLocation, ModuleKind, Span, well_known, Annotation, Constant, DataType, DataTypeKey, DefinitionLocation, ModuleKind,
TypedDataType, Span, TypedDataType,
}, },
builtins::{G1_ELEMENT, G2_ELEMENT, MILLER_LOOP_RESULT},
tipo::fields::FieldMap, tipo::fields::FieldMap,
}; };
use indexmap::IndexMap; use indexmap::IndexMap;
@ -304,7 +303,7 @@ impl Type {
pub fn is_int(&self) -> bool { pub fn is_int(&self) -> bool {
match self { 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(), Self::Var { tipo, .. } => tipo.borrow().is_int(),
_ => false, _ => false,
} }
@ -312,7 +311,11 @@ impl Type {
pub fn is_bytearray(&self) -> bool { pub fn is_bytearray(&self) -> bool {
match self { 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(), Self::Var { tipo, .. } => tipo.borrow().is_bytearray(),
_ => false, _ => false,
} }
@ -320,7 +323,7 @@ impl Type {
pub fn is_bls381_12_g1(&self) -> bool { pub fn is_bls381_12_g1(&self) -> bool {
match self { 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(), Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g1(),
_ => false, _ => false,
@ -329,7 +332,7 @@ impl Type {
pub fn is_bls381_12_g2(&self) -> bool { pub fn is_bls381_12_g2(&self) -> bool {
match self { 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(), Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g2(),
_ => false, _ => false,
@ -338,7 +341,9 @@ impl Type {
pub fn is_ml_result(&self) -> bool { pub fn is_ml_result(&self) -> bool {
match self { 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(), Self::Var { tipo, .. } => tipo.borrow().is_ml_result(),
_ => false, _ => false,
@ -422,31 +427,33 @@ impl Type {
} }
pub fn is_generic(&self) -> bool { pub fn is_generic(&self) -> bool {
match self { !self.collect_generics().is_empty()
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::Var { tipo, .. } => tipo.borrow().is_generic(), pub fn collect_generics(&self) -> Vec<Rc<Type>> {
Self::Tuple { elems, .. } => { match self {
let mut is_a_generic = false; Self::App { args, .. } => args.iter().flat_map(|arg| arg.collect_generics()).collect(),
for elem in elems { Self::Var { tipo, .. } => {
is_a_generic = is_a_generic || elem.is_generic(); if tipo.borrow().is_generic() {
vec![self.clone().into()]
} else {
Vec::new()
} }
is_a_generic
} }
Self::Fn { args, ret, .. } => { Self::Tuple { elems, .. } => elems
let mut is_a_generic = false; .iter()
for arg in args { .flat_map(|arg| arg.collect_generics())
is_a_generic = is_a_generic || arg.is_generic(); .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
} }
is_a_generic || ret.is_generic()
}
Self::Pair { fst, snd, .. } => fst.is_generic() || snd.is_generic(),
} }
} }
@ -1068,7 +1075,7 @@ impl TypeVar {
match self { match self {
TypeVar::Generic { .. } => true, TypeVar::Generic { .. } => true,
TypeVar::Link { tipo } => tipo.is_generic(), TypeVar::Link { tipo } => tipo.is_generic(),
_ => false, TypeVar::Unbound { .. } => false,
} }
} }
@ -1092,11 +1099,13 @@ impl TypeVar {
Self::Link { tipo } => tipo.get_inner_types(), Self::Link { tipo } => tipo.get_inner_types(),
Self::Unbound { .. } => vec![], Self::Unbound { .. } => vec![],
var => { var => {
vec![Type::Var { vec![
Type::Var {
tipo: RefCell::new(var.clone()).into(), tipo: RefCell::new(var.clone()).into(),
alias: None, alias: None,
} }
.into()] .into(),
]
} }
} }
} }
@ -1118,6 +1127,51 @@ impl ValueConstructor {
} }
} }
pub fn known_enum(
values: &mut HashMap<String, Self>,
tipo: Rc<Type>,
constructors: &[&str],
) -> Vec<String> {
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<String, Self>,
constructors: &[(&str, Rc<Type>)],
) -> Vec<String> {
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> { fn field_map(&self) -> Option<&FieldMap> {
match &self.variant { match &self.variant {
ValueConstructorVariant::ModuleFn { field_map, .. } ValueConstructorVariant::ModuleFn { field_map, .. }
@ -1248,6 +1302,17 @@ impl ValueConstructorVariant {
pub fn is_local_variable(&self) -> bool { pub fn is_local_variable(&self) -> bool {
matches!(self, Self::LocalVariable { .. }) 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::<FieldMap>,
arity,
location: Span::empty(),
constructors_count: constructors_count as u16,
}
}
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@ -1271,6 +1336,18 @@ pub struct TypeConstructor {
pub tipo: Rc<Type>, pub tipo: Rc<Type>,
} }
impl TypeConstructor {
pub fn primitive(tipo: Rc<Type>) -> Self {
TypeConstructor {
location: Span::empty(),
parameters: tipo.collect_generics(),
tipo,
module: "".to_string(),
public: true,
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AccessorsMap { pub struct AccessorsMap {
pub public: bool, pub public: bool,

View File

@ -12,7 +12,6 @@ use crate::{
TypedPattern, UnqualifiedImport, UntypedArg, UntypedDefinition, UntypedFunction, Use, TypedPattern, UnqualifiedImport, UntypedArg, UntypedDefinition, UntypedFunction, Use,
Validator, PIPE_VARIABLE, Validator, PIPE_VARIABLE,
}, },
builtins::{function, generic_var, pair, tuple, unbound_var},
tipo::{fields::FieldMap, TypeAliasAnnotation}, tipo::{fields::FieldMap, TypeAliasAnnotation},
IdGenerator, IdGenerator,
}; };
@ -183,7 +182,7 @@ impl<'a> Environment<'a> {
if let Some((args, ret)) = new_value { if let Some((args, ret)) = new_value {
*tipo.borrow_mut() = TypeVar::Link { *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()))); 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( Type::Fn { args, ret, alias } => Type::with_alias(
function( Type::function(
args.iter() args.iter()
.map(|t| self.instantiate(t.clone(), ids, hydrator)) .map(|t| self.instantiate(t.clone(), ids, hydrator))
.collect(), .collect(),
@ -700,7 +699,7 @@ impl<'a> Environment<'a> {
), ),
Type::Tuple { elems, alias } => Type::with_alias( Type::Tuple { elems, alias } => Type::with_alias(
tuple( Type::tuple(
elems elems
.iter() .iter()
.map(|t| self.instantiate(t.clone(), ids, hydrator)) .map(|t| self.instantiate(t.clone(), ids, hydrator))
@ -709,7 +708,7 @@ impl<'a> Environment<'a> {
alias.clone(), alias.clone(),
), ),
Type::Pair { fst, snd, alias } => Type::with_alias( Type::Pair { fst, snd, alias } => Type::with_alias(
pair( Type::pair(
self.instantiate(fst.clone(), ids, hydrator), self.instantiate(fst.clone(), ids, hydrator),
self.instantiate(snd.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. /// Create a new generic type that can stand in for any type.
pub fn new_generic_var(&mut self) -> Rc<Type> { pub fn new_generic_var(&mut self) -> Rc<Type> {
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 /// Create a new unbound type that is a specific type, we just don't
/// know which one yet. /// know which one yet.
pub fn new_unbound_var(&mut self) -> Rc<Type> { pub fn new_unbound_var(&mut self) -> Rc<Type> {
unbound_var(self.next_uid()) Type::unbound_var(self.next_uid())
} }
pub fn next_uid(&mut self) -> u64 { 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 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 // Keep track of which types we create from annotations so we can know
// which generic types not to instantiate later when performing // which generic types not to instantiate later when performing
@ -1415,7 +1414,7 @@ impl<'a> Environment<'a> {
// Insert constructor function into module scope // Insert constructor function into module scope
let typ = match constructor.arguments.len() { let typ = match constructor.arguments.len() {
0 => typ.clone(), 0 => typ.clone(),
_ => function(args_types, typ.clone()), _ => Type::function(args_types, typ.clone()),
}; };
let constructor_info = ValueConstructorVariant::Record { let constructor_info = ValueConstructorVariant::Record {
@ -2013,7 +2012,7 @@ pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
match t.deref() { match t.deref() {
Type::Var { tipo, alias } => Type::with_alias( Type::Var { tipo, alias } => Type::with_alias(
match tipo.borrow().deref() { 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::Link { tipo } => generalise(tipo.clone(), ctx_level),
TypeVar::Generic { .. } => Rc::new(Type::Var { TypeVar::Generic { .. } => Rc::new(Type::Var {
tipo: tipo.clone(), tipo: tipo.clone(),
@ -2047,7 +2046,7 @@ pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
} }
Type::Fn { args, ret, alias } => Type::with_alias( Type::Fn { args, ret, alias } => Type::with_alias(
function( Type::function(
args.iter() args.iter()
.map(|t| generalise(t.clone(), ctx_level)) .map(|t| generalise(t.clone(), ctx_level))
.collect(), .collect(),
@ -2057,7 +2056,7 @@ pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
), ),
Type::Tuple { elems, alias } => Type::with_alias( Type::Tuple { elems, alias } => Type::with_alias(
tuple( Type::tuple(
elems elems
.iter() .iter()
.map(|t| generalise(t.clone(), ctx_level)) .map(|t| generalise(t.clone(), ctx_level))
@ -2066,7 +2065,7 @@ pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
alias.clone(), alias.clone(),
), ),
Type::Pair { fst, snd, alias } => Type::with_alias( Type::Pair { fst, snd, alias } => Type::with_alias(
pair( Type::pair(
generalise(fst.clone(), ctx_level), generalise(fst.clone(), ctx_level),
generalise(snd.clone(), ctx_level), generalise(snd.clone(), ctx_level),
), ),

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
ast, ast,
builtins::{self}, tipo::{self, environment::Environment, error::Error, Type},
tipo::{self, environment::Environment, error::Error},
}; };
use itertools::Itertools; use itertools::Itertools;
use std::{collections::BTreeMap, iter, ops::Deref}; use std::{collections::BTreeMap, iter, ops::Deref};
@ -500,8 +499,8 @@ fn pretty_tail(tail: Pattern) -> String {
} }
fn list_constructors() -> Vec<tipo::ValueConstructor> { fn list_constructors() -> Vec<tipo::ValueConstructor> {
let list_parameter = builtins::generic_var(0); let list_parameter = Type::generic_var(0);
let list_type = builtins::list(list_parameter); let list_type = Type::list(list_parameter);
vec![ vec![
tipo::ValueConstructor { tipo::ValueConstructor {

View File

@ -17,10 +17,7 @@ use crate::{
UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedFunction, UntypedIfBranch, UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedFunction, UntypedIfBranch,
UntypedPattern, UntypedRecordUpdateArg, UntypedPattern, UntypedRecordUpdateArg,
}, },
builtins::{ builtins::{from_default_function, BUILTIN},
bool, byte_array, data, from_default_function, function, g1_element, g2_element, int, list,
pair, string, tuple, void, BUILTIN,
},
expr::{FnStyle, TypedExpr, UntypedExpr}, expr::{FnStyle, TypedExpr, UntypedExpr},
format, format,
tipo::{fields::FieldMap, DefaultFunction, PatternConstructor, TypeVar}, 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 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; let safe_to_generalise = !expr_typer.ungeneralised_function_used;
@ -594,15 +591,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
Ok(TypedExpr::ByteArray { Ok(TypedExpr::ByteArray {
location, location,
bytes, bytes,
tipo: byte_array(), tipo: Type::byte_array(),
}) })
} }
fn infer_curve_point(&mut self, curve: Curve, location: Span) -> Result<TypedExpr, Error> { fn infer_curve_point(&mut self, curve: Curve, location: Span) -> Result<TypedExpr, Error> {
let tipo = match curve { let tipo = match curve {
Curve::Bls12_381(point) => match point { Curve::Bls12_381(point) => match point {
Bls12_381Point::G1(_) => g1_element(), Bls12_381Point::G1(_) => Type::g1_element(),
Bls12_381Point::G2(_) => g2_element(), Bls12_381Point::G2(_) => Type::g2_element(),
}, },
}; };
@ -631,7 +628,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
module: String::new(), module: String::new(),
constructors_count: 2, constructors_count: 2,
}, },
tipo: bool(), tipo: Type::bool(),
}, },
}; };
@ -648,14 +645,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
module: String::new(), module: String::new(),
constructors_count: 2, constructors_count: 2,
}, },
tipo: bool(), tipo: Type::bool(),
}, },
}; };
let text = match self.tracing.trace_level(false) { let text = match self.tracing.trace_level(false) {
TraceLevel::Verbose => Some(TypedExpr::String { TraceLevel::Verbose => Some(TypedExpr::String {
location, location,
tipo: string(), tipo: Type::string(),
value: format!( value: format!(
"{} ? False", "{} ? False",
format::Formatter::new() format::Formatter::new()
@ -668,7 +665,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let typed_value = self.infer(value)?; 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 { match text {
None => Ok(typed_value), None => Ok(typed_value),
@ -682,11 +684,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
}], }],
final_else: Box::new(TypedExpr::Trace { final_else: Box::new(TypedExpr::Trace {
location, location,
tipo: bool(), tipo: Type::bool(),
text: Box::new(text), text: Box::new(text),
then: Box::new(var_false), then: Box::new(var_false),
}), }),
tipo: bool(), tipo: Type::bool(),
}), }),
} }
} }
@ -714,22 +716,22 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
return Ok(TypedExpr::BinOp { return Ok(TypedExpr::BinOp {
location, location,
name, name,
tipo: bool(), tipo: Type::bool(),
left: Box::new(left), left: Box::new(left),
right: Box::new(right), right: Box::new(right),
}); });
} }
BinOp::And => (bool(), bool()), BinOp::And => (Type::bool(), Type::bool()),
BinOp::Or => (bool(), bool()), BinOp::Or => (Type::bool(), Type::bool()),
BinOp::LtInt => (int(), bool()), BinOp::LtInt => (Type::int(), Type::bool()),
BinOp::LtEqInt => (int(), bool()), BinOp::LtEqInt => (Type::int(), Type::bool()),
BinOp::GtEqInt => (int(), bool()), BinOp::GtEqInt => (Type::int(), Type::bool()),
BinOp::GtInt => (int(), bool()), BinOp::GtInt => (Type::int(), Type::bool()),
BinOp::AddInt => (int(), int()), BinOp::AddInt => (Type::int(), Type::int()),
BinOp::SubInt => (int(), int()), BinOp::SubInt => (Type::int(), Type::int()),
BinOp::MultInt => (int(), int()), BinOp::MultInt => (Type::int(), Type::int()),
BinOp::DivInt => (int(), int()), BinOp::DivInt => (Type::int(), Type::int()),
BinOp::ModInt => (int(), int()), BinOp::ModInt => (Type::int(), Type::int()),
}; };
let left = self.infer(left)?; let left = self.infer(left)?;
@ -896,8 +898,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let value = self.infer(value)?; let value = self.infer(value)?;
let tipo = match op { let tipo = match op {
UnOp::Not => bool(), UnOp::Not => Type::bool(),
UnOp::Negate => int(), UnOp::Negate => Type::int(),
}; };
self.unify(tipo.clone(), value.tipo(), value.location(), false)?; 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())?; let condition = self.infer(branch.condition.clone())?;
self.unify( self.unify(
bool(), Type::bool(),
condition.tipo(), condition.tipo(),
condition.type_defining_location(), condition.type_defining_location(),
false, false,
@ -1647,7 +1649,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let args_types = args.iter().map(|a| a.tipo.clone()).collect(); 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 { Ok(TypedExpr::Fn {
location, location,
@ -1745,7 +1747,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
TypedExpr::UInt { TypedExpr::UInt {
location, location,
value, value,
tipo: int(), tipo: Type::int(),
} }
} }
@ -1772,7 +1774,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
ensure_serialisable(false, tipo.clone(), location)?; ensure_serialisable(false, tipo.clone(), location)?;
// Type check the ..tail, if there is one // Type check the ..tail, if there is one
let tipo = list(tipo); let tipo = Type::list(tipo);
let tail = match tail { let tail = match tail {
Some(tail) => { Some(tail) => {
@ -1807,7 +1809,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let typed_expression = self.infer(expression)?; let typed_expression = self.infer(expression)?;
self.unify( self.unify(
bool(), Type::bool(),
typed_expression.tipo(), typed_expression.tipo(),
typed_expression.location(), typed_expression.location(),
false, false,
@ -1831,7 +1833,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
.rev() .rev()
.reduce(|acc, typed_expression| TypedExpr::BinOp { .reduce(|acc, typed_expression| TypedExpr::BinOp {
location, location,
tipo: bool(), tipo: Type::bool(),
name, name,
left: typed_expression.into(), left: typed_expression.into(),
right: acc.into(), right: acc.into(),
@ -2151,7 +2153,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
TypedExpr::String { TypedExpr::String {
location, location,
value, value,
tipo: string(), tipo: Type::string(),
} }
} }
@ -2169,7 +2171,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
Ok(TypedExpr::Pair { Ok(TypedExpr::Pair {
location, location,
tipo: pair(typed_fst.tipo(), typed_snd.tipo()), tipo: Type::pair(typed_fst.tipo(), typed_snd.tipo()),
fst: typed_fst.into(), fst: typed_fst.into(),
snd: typed_snd.into(), snd: typed_snd.into(),
}) })
@ -2187,7 +2189,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
typed_elems.push(typed_elem); 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 { Ok(TypedExpr::Tuple {
location, location,
@ -2255,9 +2257,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result<TypedExpr, Error> { fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result<TypedExpr, Error> {
let typed_arg = self.infer(arg)?; 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(_) => { 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(diagnose_expr(typed_arg))
} }
Ok(()) => Ok(typed_arg), Ok(()) => Ok(typed_arg),
@ -2291,7 +2298,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
TraceLevel::Silent => Ok(then), TraceLevel::Silent => Ok(then),
TraceLevel::Compact => { TraceLevel::Compact => {
let text = self.infer(label)?; 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 { Ok(TypedExpr::Trace {
location, location,
tipo, tipo,
@ -2307,7 +2314,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
} else { } else {
let delimiter = |ix| TypedExpr::String { let delimiter = |ix| TypedExpr::String {
location: Span::empty(), location: Span::empty(),
tipo: string(), tipo: Type::string(),
value: if ix == 0 { ": " } else { ", " }.to_string(), value: if ix == 0 { ": " } else { ", " }.to_string(),
}; };
typed_arguments typed_arguments
@ -2594,7 +2601,7 @@ fn assert_assignment(expr: TypedExpr) -> Result<TypedExpr, Error> {
if expr.tipo().is_void() { if expr.tipo().is_void() {
return Ok(TypedExpr::Assignment { return Ok(TypedExpr::Assignment {
location: expr.location(), location: expr.location(),
tipo: void(), tipo: Type::void(),
value: expr.clone().into(), value: expr.clone().into(),
pattern: Pattern::Constructor { pattern: Pattern::Constructor {
is_record: false, is_record: false,
@ -2607,7 +2614,7 @@ fn assert_assignment(expr: TypedExpr) -> Result<TypedExpr, Error> {
arguments: vec![], arguments: vec![],
module: None, module: None,
spread_location: None, spread_location: None,
tipo: void(), tipo: Type::void(),
}, },
kind: AssignmentKind::let_(), kind: AssignmentKind::let_(),
}); });
@ -2713,7 +2720,7 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr {
name: "diagnostic".to_string(), name: "diagnostic".to_string(),
constructor: ValueConstructor { constructor: ValueConstructor {
public: true, 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 { variant: ValueConstructorVariant::ModuleFn {
name: "diagnostic".to_string(), name: "diagnostic".to_string(),
field_map: None, field_map: None,
@ -2728,13 +2735,13 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr {
let location = expr.location(); let location = expr.location();
TypedExpr::Call { TypedExpr::Call {
tipo: string(), tipo: Type::string(),
fun: Box::new(decode_utf8.clone()), fun: Box::new(decode_utf8.clone()),
args: vec![CallArg { args: vec![CallArg {
label: None, label: None,
location: expr.location(), location: expr.location(),
value: TypedExpr::Call { value: TypedExpr::Call {
tipo: byte_array(), tipo: Type::byte_array(),
fun: Box::new(diagnostic.clone()), fun: Box::new(diagnostic.clone()),
args: vec![ args: vec![
CallArg { CallArg {
@ -2746,7 +2753,7 @@ fn diagnose_expr(expr: TypedExpr) -> TypedExpr {
label: None, label: None,
location, location,
value: TypedExpr::ByteArray { value: TypedExpr::ByteArray {
tipo: byte_array(), tipo: Type::byte_array(),
bytes: vec![], bytes: vec![],
location, location,
}, },
@ -2785,7 +2792,7 @@ fn append_string_expr(left: TypedExpr, right: TypedExpr) -> TypedExpr {
TypedExpr::Call { TypedExpr::Call {
location: Span::empty(), location: Span::empty(),
tipo: string(), tipo: Type::string(),
fun: Box::new(append_string.clone()), fun: Box::new(append_string.clone()),
args: vec![ args: vec![
CallArg { CallArg {

View File

@ -3,11 +3,7 @@ use super::{
error::{Error, Warning}, error::{Error, Warning},
Type, TypeConstructor, Type, TypeConstructor,
}; };
use crate::{ use crate::{ast::Annotation, tipo::Span};
ast::Annotation,
builtins::{function, pair, tuple},
tipo::Span,
};
use std::{collections::HashMap, rc::Rc}; use std::{collections::HashMap, rc::Rc};
/// The Hydrator takes an AST representing a type (i.e. a type annotation /// 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)?; 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) { Annotation::Var { name, location, .. } => match self.created_type_variables.get(name) {
@ -244,13 +240,13 @@ impl Hydrator {
typed_elems.push(typed_elem) typed_elems.push(typed_elem)
} }
Ok(tuple(typed_elems)) Ok(Type::tuple(typed_elems))
} }
Annotation::Pair { fst, snd, .. } => { Annotation::Pair { fst, snd, .. } => {
let fst = self.do_type_from_annotation(fst, environment, unbounds)?; let fst = self.do_type_from_annotation(fst, environment, unbounds)?;
let snd = self.do_type_from_annotation(snd, environment, unbounds)?; let snd = self.do_type_from_annotation(snd, environment, unbounds)?;
Ok(pair(fst, snd)) Ok(Type::pair(fst, snd))
} }
}?; }?;

View File

@ -11,7 +11,6 @@ use crate::{
RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition, RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition,
TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator, TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, Use, Validator,
}, },
builtins::{self, fuzzer, generic_var},
tipo::{expr::infer_function, Span, Type, TypeVar}, tipo::{expr::infer_function, Span, Type, TypeVar},
IdGenerator, IdGenerator,
}; };
@ -214,7 +213,7 @@ fn infer_definition(
location: typed_fun location: typed_fun
.location .location
.map(|start, _end| (start, start + typed_fun.name.len())), .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() { for arg in typed_fun.arguments.iter_mut() {
if arg.tipo.is_unbound() { if arg.tipo.is_unbound() {
arg.tipo = builtins::data(); arg.tipo = Type::data();
} }
} }
@ -263,7 +262,7 @@ fn infer_definition(
.drain(0..params_length) .drain(0..params_length)
.map(|mut arg| { .map(|mut arg| {
if arg.tipo.is_unbound() { if arg.tipo.is_unbound() {
arg.tipo = builtins::data(); arg.tipo = Type::data();
} }
arg arg
@ -280,7 +279,7 @@ fn infer_definition(
for arg in typed_fallback.arguments.iter_mut() { for arg in typed_fallback.arguments.iter_mut() {
if arg.tipo.is_unbound() { 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( let is_bool = environment.unify(
typed_f.return_type.clone(), typed_f.return_type.clone(),
builtins::bool(), Type::bool(),
typed_f.location, typed_f.location,
false, false,
); );
let is_void = environment.unify( let is_void = environment.unify(
typed_f.return_type.clone(), typed_f.return_type.clone(),
builtins::void(), Type::void(),
typed_f.location, typed_f.location,
false, false,
); );
@ -642,10 +641,10 @@ fn infer_fuzzer(
) -> Result<(Annotation, Rc<Type>), Error> { ) -> Result<(Annotation, Rc<Type>), Error> {
let could_not_unify = || Error::CouldNotUnify { let could_not_unify = || Error::CouldNotUnify {
location: *location, location: *location,
expected: fuzzer( expected: Type::fuzzer(
expected_inner_type expected_inner_type
.clone() .clone()
.unwrap_or_else(|| generic_var(0)), .unwrap_or_else(|| Type::generic_var(0)),
), ),
given: tipo.clone(), given: tipo.clone(),
situation: None, situation: None,
@ -681,7 +680,7 @@ fn infer_fuzzer(
// `unify` now that we have figured out the type carried by the fuzzer. // `unify` now that we have figured out the type carried by the fuzzer.
environment.unify( environment.unify(
tipo.clone(), tipo.clone(),
fuzzer(wrapped.clone()), Type::fuzzer(wrapped.clone()),
*location, *location,
false, false,
)?; )?;

View File

@ -6,10 +6,7 @@ use super::{
hydrator::Hydrator, hydrator::Hydrator,
PatternConstructor, Type, ValueConstructorVariant, PatternConstructor, Type, ValueConstructorVariant,
}; };
use crate::{ use crate::ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern};
ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern},
builtins::{byte_array, int, list, pair, tuple},
};
use itertools::Itertools; use itertools::Itertools;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -190,7 +187,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
value, value,
base, base,
} => { } => {
self.environment.unify(tipo, int(), location, false)?; self.environment.unify(tipo, Type::int(), location, false)?;
Ok(Pattern::Int { Ok(Pattern::Int {
location, location,
@ -205,7 +202,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
preferred_format, preferred_format,
} => { } => {
self.environment self.environment
.unify(tipo, byte_array(), location, false)?; .unify(tipo, Type::byte_array(), location, false)?;
Ok(Pattern::ByteArray { Ok(Pattern::ByteArray {
location, location,
@ -231,7 +228,12 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
.try_collect()?; .try_collect()?;
let tail = match tail { 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, None => None,
}; };
@ -243,7 +245,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
} }
None => Err(Error::CouldNotUnify { None => Err(Error::CouldNotUnify {
given: list(self.environment.new_unbound_var()), given: Type::list(self.environment.new_unbound_var()),
expected: tipo.clone(), expected: tipo.clone(),
situation: None, situation: None,
location, location,
@ -267,7 +269,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
let t_snd = self.environment.new_unbound_var(); let t_snd = self.environment.new_unbound_var();
self.environment.unify( self.environment.unify(
pair(t_fst.clone(), t_snd.clone()), Type::pair(t_fst.clone(), t_snd.clone()),
tipo, tipo,
location, location,
false, false,
@ -280,7 +282,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
} }
_ => Err(Error::CouldNotUnify { _ => Err(Error::CouldNotUnify {
given: pair( given: Type::pair(
self.environment.new_unbound_var(), self.environment.new_unbound_var(),
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()) .map(|_| self.environment.new_unbound_var())
.collect(); .collect();
self.environment self.environment.unify(
.unify(tuple(elems_types.clone()), tipo, location, false)?; Type::tuple(elems_types.clone()),
tipo,
location,
false,
)?;
let mut patterns = vec![]; let mut patterns = vec![];
@ -345,7 +351,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
.collect(); .collect();
Err(Error::CouldNotUnify { Err(Error::CouldNotUnify {
given: tuple(elems_types), given: Type::tuple(elems_types),
expected: tipo, expected: tipo,
situation: None, situation: None,
location, location,

View File

@ -5,7 +5,6 @@ use super::{
}; };
use crate::{ use crate::{
ast::{AssignmentKind, CallArg, Pattern, Span, PIPE_VARIABLE}, ast::{AssignmentKind, CallArg, Pattern, Span, PIPE_VARIABLE},
builtins::function,
expr::{TypedExpr, UntypedExpr}, expr::{TypedExpr, UntypedExpr},
}; };
use std::{ops::Deref, rc::Rc}; use std::{ops::Deref, rc::Rc};
@ -257,7 +256,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> {
.environment .environment
.unify( .unify(
func.tipo(), func.tipo(),
function(vec![self.argument_type.clone()], return_type.clone()), Type::function(vec![self.argument_type.clone()], return_type.clone()),
func.location(), func.location(),
if let Type::Fn { args, .. } = func.tipo().deref() { if let Type::Fn { args, .. } = func.tipo().deref() {
if let Some(typ) = args.first() { if let Some(typ) = args.first() {

View File

@ -296,10 +296,7 @@ fn resolve_alias(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::tipo::{Span, Type};
builtins::{function, int},
tipo::Span,
};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use std::cell::RefCell; use std::cell::RefCell;
@ -490,7 +487,7 @@ mod tests {
"?", "?",
); );
assert_string!( assert_string!(
function( Type::function(
vec![Rc::new(Type::Var { vec![Rc::new(Type::Var {
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 78 })), tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 78 })),
alias: None, alias: None,
@ -503,7 +500,7 @@ mod tests {
"fn(?) -> ?", "fn(?) -> ?",
); );
assert_string!( assert_string!(
function( Type::function(
vec![Rc::new(Type::Var { vec![Rc::new(Type::Var {
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 78 })), tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 78 })),
alias: None, alias: None,
@ -692,10 +689,16 @@ mod tests {
#[test] #[test]
fn function_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!( 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" "fn(Int, Int, Int) -> Int"
); );
} }

View File

@ -153,7 +153,7 @@ impl From<&Config> for Preamble {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use aiken_lang::builtins; use aiken_lang::tipo::Type;
use schema::{Data, Declaration, Items, Schema}; use schema::{Data, Declaration, Items, Schema};
use serde_json::{self, json}; use serde_json::{self, json};
use std::collections::HashMap; use std::collections::HashMap;
@ -225,17 +225,17 @@ mod tests {
fn serialize_with_definitions() { fn serialize_with_definitions() {
let mut definitions = Definitions::new(); let mut definitions = Definitions::new();
definitions definitions
.register::<_, Error>(&builtins::int(), &HashMap::new(), |_| { .register::<_, Error>(&Type::int(), &HashMap::new(), |_| {
Ok(Schema::Data(Data::Integer).into()) Ok(Schema::Data(Data::Integer).into())
}) })
.unwrap(); .unwrap();
definitions definitions
.register::<_, Error>( .register::<_, Error>(
&builtins::list(builtins::byte_array()), &Type::list(Type::byte_array()),
&HashMap::new(), &HashMap::new(),
|definitions| { |definitions| {
let ref_bytes = definitions.register::<_, Error>( let ref_bytes = definitions.register::<_, Error>(
&builtins::byte_array(), &Type::byte_array(),
&HashMap::new(), &HashMap::new(),
|_| Ok(Schema::Data(Data::Bytes).into()), |_| Ok(Schema::Data(Data::Bytes).into()),
)?; )?;

View File

@ -4,7 +4,6 @@ use crate::{
}; };
use aiken_lang::{ use aiken_lang::{
ast::{Definition, TypedDataType, TypedDefinition}, ast::{Definition, TypedDataType, TypedDefinition},
builtins::wrapped_redeemer,
tipo::{pretty, Type, TypeVar}, tipo::{pretty, Type, TypeVar},
}; };
use owo_colors::{OwoColorize, Stream::Stdout}; use owo_colors::{OwoColorize, Stream::Stdout};
@ -142,7 +141,7 @@ impl Annotated<Schema> {
) -> Reference { ) -> Reference {
definitions definitions
.register( .register(
&wrapped_redeemer(type_info), &Type::wrapped_redeemer(type_info),
&HashMap::new(), &HashMap::new(),
|_| { |_| {
Ok::<_, Error>(Annotated { Ok::<_, Error>(Annotated {

View File

@ -272,7 +272,7 @@ mod tests {
use aiken_lang::{ use aiken_lang::{
self, self,
ast::{TraceLevel, Tracing}, ast::{TraceLevel, Tracing},
builtins, tipo::Type,
}; };
use std::collections::HashMap; use std::collections::HashMap;
use uplc::ast as uplc_ast; use uplc::ast as uplc_ast;
@ -336,7 +336,7 @@ mod tests {
// "dataType": "integer" // "dataType": "integer"
// } // }
definitions definitions
.register::<_, Error>(&builtins::int(), &HashMap::new(), |_| { .register::<_, Error>(&Type::int(), &HashMap::new(), |_| {
Ok(Schema::Data(Data::Integer).into()) Ok(Schema::Data(Data::Integer).into())
}) })
.unwrap(); .unwrap();
@ -347,7 +347,7 @@ mod tests {
// "dataType": "bytes" // "dataType": "bytes"
// } // }
definitions definitions
.register::<_, Error>(&builtins::byte_array(), &HashMap::new(), |_| { .register::<_, Error>(&Type::byte_array(), &HashMap::new(), |_| {
Ok(Schema::Data(Data::Bytes).into()) Ok(Schema::Data(Data::Bytes).into())
}) })
.unwrap(); .unwrap();

View File

@ -1,7 +1,6 @@
use aiken_lang::ast::OnTestFailure; use aiken_lang::ast::OnTestFailure;
pub(crate) use aiken_lang::{ pub(crate) use aiken_lang::{
ast::{BinOp, DataTypeKey, IfBranch, Span, TypedArg, TypedDataType, TypedTest}, ast::{BinOp, DataTypeKey, IfBranch, Span, TypedArg, TypedDataType, TypedTest},
builtins::bool,
expr::{TypedExpr, UntypedExpr}, expr::{TypedExpr, UntypedExpr},
format::Formatter, format::Formatter,
gen_uplc::CodeGenerator, gen_uplc::CodeGenerator,
@ -1056,7 +1055,7 @@ impl TryFrom<TypedExpr> for Assertion<TypedExpr> {
left, left,
right, right,
.. ..
} if tipo == bool() => { } if tipo == Type::bool() => {
// 'and' and 'or' are left-associative operators. // 'and' and 'or' are left-associative operators.
match (*right).clone().try_into() { match (*right).clone().try_into() {
Ok(Assertion { Ok(Assertion {
@ -1094,7 +1093,7 @@ impl TryFrom<TypedExpr> for Assertion<TypedExpr> {
let then_is_true = match body { let then_is_true = match body {
TypedExpr::Var { TypedExpr::Var {
name, constructor, .. name, constructor, ..
} => name == "True" && constructor.tipo == bool(), } => name == "True" && constructor.tipo == Type::bool(),
_ => false, _ => false,
}; };
@ -1102,7 +1101,7 @@ impl TryFrom<TypedExpr> for Assertion<TypedExpr> {
TypedExpr::Trace { then, .. } => match *then { TypedExpr::Trace { then, .. } => match *then {
TypedExpr::Var { TypedExpr::Var {
name, constructor, .. name, constructor, ..
} => name == "False" && constructor.tipo == bool(), } => name == "False" && constructor.tipo == Type::bool(),
_ => false, _ => false,
}, },
_ => false, _ => false,