diff --git a/crates/lang/src/builtins.rs b/crates/lang/src/builtins.rs index b3f7e095a..37b911aac 100644 --- a/crates/lang/src/builtins.rs +++ b/crates/lang/src/builtins.rs @@ -7,7 +7,7 @@ use uplc::builtins::DefaultFunction; use crate::{ ast::{ModuleKind, Span}, tipo::{ - self, fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor, + fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor, ValueConstructorVariant, }, IdGenerator, diff --git a/crates/lang/src/ir.rs b/crates/lang/src/ir.rs index ec2ae4129..447282fcf 100644 --- a/crates/lang/src/ir.rs +++ b/crates/lang/src/ir.rs @@ -3,11 +3,8 @@ use std::sync::Arc; use uplc::builtins::DefaultFunction; use crate::{ - ast::{ - Annotation, Arg, AssignmentKind, BinOp, CallArg, Clause, IfBranch, Pattern, Span, - TypedRecordUpdateArg, - }, - tipo::{ModuleValueConstructor, PatternConstructor, Type, ValueConstructor}, + ast::{AssignmentKind, BinOp, TypedRecordUpdateArg}, + tipo::{Type, ValueConstructor}, }; // [] @@ -79,7 +76,6 @@ pub enum IR { DefineFunc { func_name: String, module_name: String, - count: usize, }, DefineConst { @@ -131,9 +127,8 @@ pub enum IR { }, RecordAccess { - label: String, index: u64, - count: usize, + tipo: Arc, }, FieldsExpose { diff --git a/crates/lang/src/uplc_two.rs b/crates/lang/src/uplc_two.rs index ee623099f..e002ef9c2 100644 --- a/crates/lang/src/uplc_two.rs +++ b/crates/lang/src/uplc_two.rs @@ -1,8 +1,10 @@ use std::{collections::HashMap, ops::Deref, sync::Arc}; -use indexmap::IndexMap; use uplc::{ - ast::{Constant, Name, Program, Term, Type as UplcType}, + ast::{ + builder::{self, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD}, + Constant, Name, Program, Term, + }, builtins::DefaultFunction, parser::interner::Interner, BigInt, PlutusData, @@ -18,12 +20,7 @@ use crate::{ }; pub struct CodeGenerator<'a> { - // uplc_function_holder: Vec<(String, Term)>, - // uplc_function_holder_lookup: IndexMap, - // uplc_data_holder_lookup: IndexMap, - // uplc_data_constr_lookup: IndexMap, - // uplc_data_usage_holder_lookup: IndexMap, - function_recurse_lookup: IndexMap, + defined_functions: HashMap, functions: &'a HashMap, TypedExpr>>, // type_aliases: &'a HashMap<(String, String), &'a TypeAlias>>, data_types: &'a HashMap>>, @@ -31,6 +28,7 @@ pub struct CodeGenerator<'a> { // constants: &'a HashMap<(String, String), &'a ModuleConstant, String>>, module_types: &'a HashMap, id_gen: IdGenerator, + needs_field_access: bool, } impl<'a> CodeGenerator<'a> { @@ -43,12 +41,7 @@ impl<'a> CodeGenerator<'a> { module_types: &'a HashMap, ) -> Self { CodeGenerator { - // uplc_function_holder: Vec::new(), - // uplc_function_holder_lookup: IndexMap::new(), - // uplc_data_holder_lookup: IndexMap::new(), - // uplc_data_constr_lookup: IndexMap::new(), - // uplc_data_usage_holder_lookup: IndexMap::new(), - function_recurse_lookup: IndexMap::new(), + defined_functions: HashMap::new(), functions, // type_aliases, data_types, @@ -56,6 +49,7 @@ impl<'a> CodeGenerator<'a> { // constants, module_types, id_gen: IdGenerator::new(), + needs_field_access: false, } } @@ -68,59 +62,14 @@ impl<'a> CodeGenerator<'a> { let mut term = self.uplc_code_gen(&mut ir_stack); - // Apply constr exposer to top level. - term = Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: "constr_fields_exposer".to_string(), - unique: 0.into(), - }, - body: term.into(), - } - .into(), - argument: Term::Lambda { - parameter_name: Name { - text: "constr_var".to_string(), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Force( - Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(), - ) - .into(), - argument: Term::Apply { - function: Term::Builtin(DefaultFunction::UnConstrData).into(), - argument: Term::Var(Name { - text: "constr_var".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - } - .into(), - } - .into(), - }; + if self.needs_field_access { + term = builder::constr_get_field(term); - term = self.add_arg_getter(term); + term = builder::constr_fields_exposer(term); + } - term = Term::Force( - Term::Apply { - function: Term::Apply { - function: Term::Apply { - function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into()) - .into(), - argument: term.into(), - } - .into(), - argument: Term::Delay(Term::Constant(Constant::Unit).into()).into(), - } - .into(), - argument: Term::Delay(Term::Error.into()).into(), - } - .into(), - ); + // Wrap the validator body if ifThenElse term unit error + term = builder::final_wrapper(term); for arg in arguments.iter().rev() { term = Term::Lambda { @@ -174,8 +123,6 @@ impl<'a> CodeGenerator<'a> { constructor: constructor.clone(), name: name.clone(), }); - - // Add constructor information here? } TypedExpr::Fn { .. } => todo!(), TypedExpr::List { @@ -193,9 +140,11 @@ impl<'a> CodeGenerator<'a> { tipo: tipo.clone(), tail: tail.is_some(), }); + for element in elements { self.build_ir(element, ir_stack) } + if let Some(tail) = tail { ir_stack.push(IR::Tail { count: 1 }); self.build_ir(tail, ir_stack); @@ -212,16 +161,12 @@ impl<'a> CodeGenerator<'a> { } } TypedExpr::BinOp { - name, - left, - right, - tipo, - .. + name, left, right, .. } => { ir_stack.push(IR::BinOp { name: *name, count: 2, - tipo: tipo.clone(), + tipo: left.tipo(), }); self.build_ir(left, ir_stack); self.build_ir(right, ir_stack); @@ -246,10 +191,7 @@ impl<'a> CodeGenerator<'a> { } TypedExpr::Try { .. } => todo!(), TypedExpr::When { - subjects, - clauses, - tipo, - .. + subjects, clauses, .. } => { // assuming one subject at the moment ir_stack.push(IR::When { @@ -274,19 +216,28 @@ impl<'a> CodeGenerator<'a> { }; } TypedExpr::If { .. } => todo!(), - TypedExpr::RecordAccess { .. } => todo!(), - TypedExpr::ModuleSelect { + TypedExpr::RecordAccess { + record, + index, tipo, + .. + } => { + self.needs_field_access = true; + + ir_stack.push(IR::RecordAccess { + index: *index, + tipo: tipo.clone(), + }); + + self.build_ir(record, ir_stack); + } + TypedExpr::ModuleSelect { constructor, module_name, .. } => match constructor { tipo::ModuleValueConstructor::Record { .. } => todo!(), - tipo::ModuleValueConstructor::Fn { - location, - module, - name, - } => { + tipo::ModuleValueConstructor::Fn { name, .. } => { let func = self.functions.get(&FunctionAccessKey { module_name: module_name.clone(), function_name: name.clone(), @@ -315,7 +266,7 @@ impl<'a> CodeGenerator<'a> { } } - fn define_ir(&self, value_vec: &Vec, _define_vec: &mut Vec) { + fn define_ir(&self, value_vec: &Vec, _define_vec: &mut [IR]) { // get value item for value in value_vec { match dbg!(value) { @@ -390,7 +341,6 @@ impl<'a> CodeGenerator<'a> { Pattern::Discard { .. } => todo!(), Pattern::List { elements, tail, .. } => { let mut elements_vec = vec![]; - let mut var_vec = vec![]; let mut names = vec![]; for element in elements { @@ -399,8 +349,7 @@ impl<'a> CodeGenerator<'a> { names.push(name.clone()); } a @ Pattern::List { .. } => { - self.pattern_ir(a, &mut elements_vec, &mut vec![]); - + let mut var_vec = vec![]; let item_name = format!("list_item_id_{}", self.id_gen.next()); names.push(item_name.clone()); var_vec.push(IR::Var { @@ -418,7 +367,7 @@ impl<'a> CodeGenerator<'a> { ), name: item_name, }); - var_vec.append(&mut elements_vec); + self.pattern_ir(a, &mut elements_vec, &mut var_vec); } _ => todo!(), } @@ -438,8 +387,7 @@ impl<'a> CodeGenerator<'a> { }); pattern_vec.append(values); - - pattern_vec.append(&mut var_vec); + pattern_vec.append(&mut elements_vec); } Pattern::Constructor { .. } => todo!(), } @@ -488,7 +436,13 @@ impl<'a> CodeGenerator<'a> { module_name: module.to_string(), defined_type: name.to_string(), }, - Type::Fn { .. } => todo!(), + Type::Fn { ret, .. } => match ret.deref() { + Type::App { module, name, .. } => DataTypeKey { + module_name: module.to_string(), + defined_type: name.to_string(), + }, + _ => unreachable!(), + }, Type::Var { .. } => todo!(), }; @@ -538,20 +492,14 @@ impl<'a> CodeGenerator<'a> { } } - println!("TIPO IS {tipo:#?}"); - let list_type = match tipo.deref() { Type::App { args, .. } => &args[0], _ => unreachable!(), }; - println!("ARGS IS {:#?}", args); - println!("GET UPLC TYPE IS {:#?}", list_type.get_uplc_type()); - if constants.len() == args.len() && !tail { let list = Term::Constant(Constant::ProtoList(list_type.get_uplc_type(), constants)); - println!("LIST TERM IS {:#?}", list); arg_stack.push(list); } else { @@ -579,7 +527,7 @@ impl<'a> CodeGenerator<'a> { } IR::Tail { .. } => todo!(), - IR::ListAccessor { mut names, tail } => { + IR::ListAccessor { names, tail } => { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); @@ -589,31 +537,6 @@ impl<'a> CodeGenerator<'a> { id_list.push(self.id_gen.next()); } - // if tail { - // let last = names.pop().unwrap(); - // let id = id_list[names.len() - 1]; - // term = Term::Apply { - // function: Term::Lambda { - // parameter_name: Name { - // text: last, - // unique: 0.into(), - // }, - // body: term.into(), - // } - // .into(), - // argument: Term::Apply { - // function: Term::Force(Term::Builtin(DefaultFunction::TailList).into()) - // .into(), - // argument: Term::Var(Name { - // text: format!("tail_item_{}_{}", names.len() - 1, id), - // unique: 0.into(), - // }) - // .into(), - // } - // .into(), - // }; - // } - let current_index = 0; let (first_name, names) = names.split_first().unwrap(); @@ -624,9 +547,14 @@ impl<'a> CodeGenerator<'a> { unique: 0.into(), }, body: Term::Apply { - function: self - .list_access_to_uplc(names, &id_list, tail, current_index, term) - .into(), + function: list_access_to_uplc( + names, + &id_list, + tail, + current_index, + term, + ) + .into(), argument: Term::Apply { function: Term::Force( Term::Builtin(DefaultFunction::TailList).into(), @@ -647,17 +575,6 @@ impl<'a> CodeGenerator<'a> { .into(), }; - for (index, name) in names.iter().enumerate().rev() { - // let var_argument = if index == 0 { - // value.clone() - // } else { - // Term::Var(Name { - // text: format!("tail_item_{}", index - 1), - // unique: 0.into(), - // }) - // }; - } - arg_stack.push(term); } IR::Call { count } => { @@ -836,7 +753,11 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } - IR::DefineFunc { .. } => todo!(), + IR::DefineFunc { func_name, .. } => { + let body = arg_stack.pop().unwrap(); + + todo!() + } IR::DefineConst { .. } => todo!(), IR::DefineConstrFields { .. } => todo!(), IR::DefineConstrFieldAccess { .. } => todo!(), @@ -846,200 +767,97 @@ impl<'a> CodeGenerator<'a> { IR::If { .. } => todo!(), IR::Constr { .. } => todo!(), IR::Fields { .. } => todo!(), - IR::RecordAccess { .. } => todo!(), + IR::RecordAccess { index, tipo } => { + let constr = arg_stack.pop().unwrap(); + + let mut term = Term::Apply { + function: Term::Apply { + function: Term::Var(Name { + text: CONSTR_GET_FIELD.to_string(), + unique: 0.into(), + }) + .into(), + argument: Term::Apply { + function: Term::Var(Name { + text: CONSTR_FIELDS_EXPOSER.to_string(), + unique: 0.into(), + }) + .into(), + argument: constr.into(), + } + .into(), + } + .into(), + argument: Term::Constant(Constant::Integer(index.into())).into(), + }; + + if tipo.is_int() { + term = Term::Apply { + function: Term::Builtin(DefaultFunction::UnIData).into(), + argument: term.into(), + }; + } else if tipo.is_bytearray() { + term = Term::Apply { + function: Term::Builtin(DefaultFunction::UnBData).into(), + argument: term.into(), + }; + } else if tipo.is_list() { + term = Term::Apply { + function: Term::Builtin(DefaultFunction::UnListData).into(), + argument: term.into(), + }; + } + + arg_stack.push(term); + } IR::FieldsExpose { .. } => todo!(), IR::Todo { .. } => todo!(), IR::RecordUpdate { .. } => todo!(), IR::Negate { .. } => todo!(), } } +} - fn add_arg_getter(&self, term: Term) -> Term { - // Apply constr arg getter to top level. - Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: "constr_field_get_arg".to_string(), - unique: 0.into(), - }, - body: term.into(), - } - .into(), - argument: Term::Lambda { - parameter_name: Name { - text: "constr_list".to_string(), - unique: 0.into(), - }, - body: Term::Lambda { +fn list_access_to_uplc( + names: &[String], + id_list: &[u64], + tail: bool, + current_index: usize, + term: Term, +) -> Term { + let (first, names) = names.split_first().unwrap(); + + if names.len() == 1 && tail { + Term::Lambda { + parameter_name: Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Lambda { parameter_name: Name { - text: "arg_number".to_string(), + text: first.clone(), unique: 0.into(), }, body: Term::Apply { function: Term::Lambda { parameter_name: Name { - text: "recurse".to_string(), + text: names[0].clone(), unique: 0.into(), }, - body: Term::Apply { - function: Term::Apply { - function: Term::Apply { - function: Term::Var(Name { - text: "recurse".to_string(), - unique: 0.into(), - }) - .into(), - argument: Term::Var(Name { - text: "recurse".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - - // Start recursive with index 0 of list - argument: Term::Constant(Constant::Integer(0.into())).into(), - } - .into(), - argument: Term::Var(Name { - text: "constr_list".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), + body: term.into(), } .into(), - - argument: Term::Lambda { - parameter_name: Name { - text: "self_recursor".to_string(), - unique: 0.into(), - }, - body: Term::Lambda { - parameter_name: Name { - text: "current_arg_number".to_string(), - unique: 0.into(), - }, - body: Term::Lambda { - parameter_name: Name { - text: "list_of_constr_args".to_string(), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Apply { - function: Term::Apply { - function: Term::Apply { - function: Term::Force( - Term::Builtin(DefaultFunction::IfThenElse) - .into(), - ) - .into(), - argument: Term::Apply { - function: Term::Apply { - function: Term::Builtin( - DefaultFunction::EqualsInteger, - ) - .into(), - argument: Term::Var(Name { - text: "arg_number".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - argument: Term::Var(Name { - text: "current_arg_number".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - } - .into(), - argument: Term::Force( - Term::Builtin(DefaultFunction::HeadList).into(), - ) - .into(), - } - .into(), - argument: Term::Lambda { - parameter_name: Name { - text: "current_list_of_constr_args".to_string(), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Apply { - function: Term::Apply { - function: Term::Var(Name { - text: "self_recursor".to_string(), - unique: 0.into(), - }) - .into(), - argument: Term::Var(Name { - text: "self_recursor".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - - argument: Term::Apply { - function: Term::Apply { - function: Term::Builtin( - DefaultFunction::AddInteger, - ) - .into(), - argument: Term::Var(Name { - text: "current_arg_number" - .to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - argument: Term::Constant( - Constant::Integer(1.into()), - ) - .into(), - } - .into(), - } - .into(), - - argument: Term::Apply { - function: Term::Force( - Term::Builtin( - DefaultFunction::TailList, - ) - .into(), - ) - .into(), - - argument: Term::Var(Name { - text: "current_list_of_constr_args" - .to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - } - .into(), - } - .into(), - } - .into(), - argument: Term::Var(Name { - text: "list_of_constr_args".to_string(), - unique: 0.into(), - }) - .into(), - } - .into(), - } + argument: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::TailList).into()) .into(), - } + argument: Term::Var(Name { + text: format!( + "tail_index_{}_{}", + current_index, id_list[current_index] + ), + unique: 0.into(), + }) .into(), } .into(), @@ -1047,162 +865,94 @@ impl<'a> CodeGenerator<'a> { .into(), } .into(), + argument: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(), + argument: Term::Var(Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }) + .into(), + } + .into(), } .into(), } - } - - fn list_access_to_uplc( - &self, - names: &[String], - id_list: &[u64], - tail: bool, - current_index: usize, - term: Term, - ) -> Term { - let (first, names) = names.split_first().unwrap(); - - if names.len() == 1 && tail { - let term = Term::Lambda { - parameter_name: Name { - text: format!("tail_index_{}_{}", current_index, id_list[current_index]), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: first.clone(), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: names[0].clone(), - unique: 0.into(), - }, - body: term.into(), - } - .into(), - argument: Term::Apply { - function: Term::Force( - Term::Builtin(DefaultFunction::TailList).into(), - ) - .into(), - argument: Term::Var(Name { - text: format!( - "tail_index_{}_{}", - current_index, id_list[current_index] - ), - unique: 0.into(), - }) - .into(), - } - .into(), - } - .into(), - } - .into(), - argument: Term::Apply { - function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()) - .into(), - argument: Term::Var(Name { - text: format!( - "tail_index_{}_{}", - current_index, id_list[current_index] - ), - unique: 0.into(), - }) - .into(), - } - .into(), + } else if names.is_empty() { + Term::Lambda { + parameter_name: Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: first.clone(), + unique: 0.into(), + }, + body: term.into(), } .into(), - }; - term - } else if names.len() == 0 { - let term = Term::Lambda { - parameter_name: Name { - text: format!("tail_index_{}_{}", current_index, id_list[current_index]), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: first.clone(), - unique: 0.into(), - }, - body: term.into(), - } - .into(), - argument: Term::Apply { - function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()) - .into(), - argument: Term::Var(Name { - text: format!( - "tail_index_{}_{}", - current_index, id_list[current_index] - ), - unique: 0.into(), - }) - .into(), - } + argument: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(), + argument: Term::Var(Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }) .into(), } .into(), - }; - term - } else { - let term = Term::Lambda { - parameter_name: Name { - text: format!("tail_index_{}_{}", current_index, id_list[current_index]), - unique: 0.into(), - }, - body: Term::Apply { - function: Term::Lambda { - parameter_name: Name { - text: first.clone(), - unique: 0.into(), - }, - body: Term::Apply { - function: self - .list_access_to_uplc(names, id_list, tail, current_index + 1, term) - .into(), - argument: Term::Apply { - function: Term::Force( - Term::Builtin(DefaultFunction::TailList).into(), - ) - .into(), - argument: Term::Var(Name { - text: format!( - "tail_index_{}_{}", - current_index, id_list[current_index] - ), - unique: 0.into(), - }) + } + .into(), + } + } else { + Term::Lambda { + parameter_name: Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: first.clone(), + unique: 0.into(), + }, + body: Term::Apply { + function: list_access_to_uplc( + names, + id_list, + tail, + current_index + 1, + term, + ) + .into(), + argument: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::TailList).into()) .into(), - } + argument: Term::Var(Name { + text: format!( + "tail_index_{}_{}", + current_index, id_list[current_index] + ), + unique: 0.into(), + }) .into(), } .into(), } .into(), - argument: Term::Apply { - function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()) - .into(), - argument: Term::Var(Name { - text: format!( - "tail_index_{}_{}", - current_index, id_list[current_index] - ), - unique: 0.into(), - }) - .into(), - } + } + .into(), + argument: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(), + argument: Term::Var(Name { + text: format!("tail_index_{}_{}", current_index, id_list[current_index]), + unique: 0.into(), + }) .into(), } .into(), - }; - term + } + .into(), } } } diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index e02e202d4..cd35ee3b3 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -12,6 +12,8 @@ use crate::{ }, }; +pub mod builder; + /// This represents a program in Untyped Plutus Core. /// A program contains a version tuple and a term. /// It is generic because Term requires a generic type. diff --git a/crates/uplc/src/ast/builder.rs b/crates/uplc/src/ast/builder.rs new file mode 100644 index 000000000..b6d13f65a --- /dev/null +++ b/crates/uplc/src/ast/builder.rs @@ -0,0 +1,255 @@ +use crate::builtins::DefaultFunction; + +use super::{Constant, Name, Term}; + +pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer"; +pub const CONSTR_GET_FIELD: &str = "__constr_get_field"; + +pub fn final_wrapper(term: Term) -> Term { + Term::Force( + Term::Apply { + function: Term::Apply { + function: Term::Apply { + function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into()).into(), + argument: term.into(), + } + .into(), + argument: Term::Delay(Term::Constant(Constant::Unit).into()).into(), + } + .into(), + argument: Term::Delay(Term::Error.into()).into(), + } + .into(), + ) +} + +pub fn constr_fields_exposer(term: Term) -> Term { + Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: CONSTR_FIELDS_EXPOSER.to_string(), + unique: 0.into(), + }, + body: term.into(), + } + .into(), + argument: Term::Lambda { + parameter_name: Name { + text: "__constr_var".to_string(), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Force( + Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(), + ) + .into(), + argument: Term::Apply { + function: Term::Builtin(DefaultFunction::UnConstrData).into(), + argument: Term::Var(Name { + text: "__constr_var".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + .into(), + } + .into(), + } +} + +pub fn constr_get_field(term: Term) -> Term { + Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: CONSTR_GET_FIELD.to_string(), + unique: 0.into(), + }, + body: term.into(), + } + .into(), + argument: Term::Lambda { + parameter_name: Name { + text: "__constr_list".to_string(), + unique: 0.into(), + }, + body: Term::Lambda { + parameter_name: Name { + text: "__arg_number".to_string(), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Lambda { + parameter_name: Name { + text: "__recurse".to_string(), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Apply { + function: Term::Apply { + function: Term::Var(Name { + text: "__recurse".to_string(), + unique: 0.into(), + }) + .into(), + argument: Term::Var(Name { + text: "__recurse".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + + // Start recursive with index 0 of list + argument: Term::Constant(Constant::Integer(0.into())).into(), + } + .into(), + argument: Term::Var(Name { + text: "__constr_list".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + .into(), + + argument: Term::Lambda { + parameter_name: Name { + text: "__self_recursor".to_string(), + unique: 0.into(), + }, + body: Term::Lambda { + parameter_name: Name { + text: "__current_arg_number".to_string(), + unique: 0.into(), + }, + body: Term::Lambda { + parameter_name: Name { + text: "__list_of_constr_args".to_string(), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Apply { + function: Term::Apply { + function: Term::Apply { + function: Term::Force( + Term::Builtin(DefaultFunction::IfThenElse) + .into(), + ) + .into(), + argument: Term::Apply { + function: Term::Apply { + function: Term::Builtin( + DefaultFunction::EqualsInteger, + ) + .into(), + argument: Term::Var(Name { + text: "__arg_number".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + argument: Term::Var(Name { + text: "__current_arg_number".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + .into(), + argument: Term::Force( + Term::Builtin(DefaultFunction::HeadList).into(), + ) + .into(), + } + .into(), + argument: Term::Lambda { + parameter_name: Name { + text: "__current_list_of_constr_args".to_string(), + unique: 0.into(), + }, + body: Term::Apply { + function: Term::Apply { + function: Term::Apply { + function: Term::Var(Name { + text: "__self_recursor".to_string(), + unique: 0.into(), + }) + .into(), + argument: Term::Var(Name { + text: "__self_recursor".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + + argument: Term::Apply { + function: Term::Apply { + function: Term::Builtin( + DefaultFunction::AddInteger, + ) + .into(), + argument: Term::Var(Name { + text: "__current_arg_number" + .to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + argument: Term::Constant( + Constant::Integer(1.into()), + ) + .into(), + } + .into(), + } + .into(), + + argument: Term::Apply { + function: Term::Force( + Term::Builtin(DefaultFunction::TailList) + .into(), + ) + .into(), + + argument: Term::Var(Name { + text: "__current_list_of_constr_args" + .to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + .into(), + } + .into(), + } + .into(), + argument: Term::Var(Name { + text: "__list_of_constr_args".to_string(), + unique: 0.into(), + }) + .into(), + } + .into(), + } + .into(), + } + .into(), + } + .into(), + } + .into(), + } + .into(), + } + .into(), + } +} diff --git a/examples/sample/validators/swap.ak b/examples/sample/validators/swap.ak index ba7f87414..077933fa4 100644 --- a/examples/sample/validators/swap.ak +++ b/examples/sample/validators/swap.ak @@ -38,14 +38,13 @@ pub fn incrementor(counter: Int, target: Int) -> Int { } pub type Datum { - Buy - Sell + thing: Int, + stuff: Int, } pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool { - let x = [[[2, 9], [7]], [[4]], [[6]]] - - let [[[a, g], d], b, ..] = x - - True + when datum.thing is { + 0 -> True + _ -> False + } }