DRY builtins types creation to ensure proper consistency.
This commit is contained in:
parent
5b61a75088
commit
7ec3f2e8df
|
@ -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<TypeInfo, TypedDefinition>;
|
||||
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<Rc<Type>>;
|
||||
|
||||
impl TypedDataType {
|
||||
pub fn data() -> Self {
|
||||
DataType {
|
||||
constructors: vec![],
|
||||
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: "Data".to_string(),
|
||||
opaque: false,
|
||||
public: true,
|
||||
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,
|
||||
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)]
|
||||
pub struct DataType<T> {
|
||||
pub constructors: Vec<RecordConstructor<T>>,
|
||||
|
@ -647,14 +462,14 @@ pub struct Validator<T, Arg, Expr> {
|
|||
}
|
||||
|
||||
impl TypedValidator {
|
||||
pub fn available_purposes() -> Vec<String> {
|
||||
pub fn available_handler_names() -> Vec<String> {
|
||||
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<Type> {
|
||||
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<A> RecordConstructor<A> {
|
|||
pub fn put_doc(&mut self, new_doc: String) {
|
||||
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)]
|
||||
|
@ -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<Rc<Type>> {
|
||||
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<Type> {
|
||||
match self {
|
||||
Bls12_381Point::G1(_) => g1_element(),
|
||||
Bls12_381Point::G2(_) => g2_element(),
|
||||
Bls12_381Point::G1(_) => Type::g1_element(),
|
||||
Bls12_381Point::G2(_) => Type::g2_element(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Name>, arguments: &[TypedArg]) -> Term<Nam
|
|||
|
||||
pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> 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<Name>) -> Option<Rc<UplcConstant>> {
|
||||
|
|
|
@ -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<Type> {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Token, ast::Annotation, Error = ParseError> {
|
|||
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()
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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<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((
|
||||
just(Token::LeftParen),
|
||||
just(Token::NewLineLeftParen),
|
||||
|
|
|
@ -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<Rc<Type>> {
|
||||
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();
|
||||
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
|
||||
}
|
||||
is_a_generic || ret.is_generic()
|
||||
}
|
||||
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 {
|
||||
vec![
|
||||
Type::Var {
|
||||
tipo: RefCell::new(var.clone()).into(),
|
||||
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> {
|
||||
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::<FieldMap>,
|
||||
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<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)]
|
||||
pub struct AccessorsMap {
|
||||
pub public: bool,
|
||||
|
|
|
@ -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<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
|
||||
/// know which one yet.
|
||||
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 {
|
||||
|
@ -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<Type>, ctx_level: usize) -> Rc<Type> {
|
|||
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<Type>, ctx_level: usize) -> Rc<Type> {
|
|||
}
|
||||
|
||||
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<Type>, ctx_level: usize) -> Rc<Type> {
|
|||
),
|
||||
|
||||
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<Type>, ctx_level: usize) -> Rc<Type> {
|
|||
alias.clone(),
|
||||
),
|
||||
Type::Pair { fst, snd, alias } => Type::with_alias(
|
||||
pair(
|
||||
Type::pair(
|
||||
generalise(fst.clone(), ctx_level),
|
||||
generalise(snd.clone(), ctx_level),
|
||||
),
|
||||
|
|
|
@ -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<tipo::ValueConstructor> {
|
||||
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 {
|
||||
|
|
|
@ -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<TypedExpr, Error> {
|
||||
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<TypedExpr, Error> {
|
||||
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<TypedExpr, Error> {
|
|||
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<TypedExpr, Error> {
|
|||
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 {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}?;
|
||||
|
||||
|
|
|
@ -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<Type>), 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,
|
||||
)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
)?;
|
||||
|
|
|
@ -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<Schema> {
|
|||
) -> Reference {
|
||||
definitions
|
||||
.register(
|
||||
&wrapped_redeemer(type_info),
|
||||
&Type::wrapped_redeemer(type_info),
|
||||
&HashMap::new(),
|
||||
|_| {
|
||||
Ok::<_, Error>(Annotated {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<TypedExpr> for Assertion<TypedExpr> {
|
|||
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<TypedExpr> for Assertion<TypedExpr> {
|
|||
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<TypedExpr> for Assertion<TypedExpr> {
|
|||
TypedExpr::Trace { then, .. } => match *then {
|
||||
TypedExpr::Var {
|
||||
name, constructor, ..
|
||||
} => name == "False" && constructor.tipo == bool(),
|
||||
} => name == "False" && constructor.tipo == Type::bool(),
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
|
|
Loading…
Reference in New Issue