diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 10430bd8..003f3e9e 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -3,7 +3,9 @@ use std::{rc::Rc, sync::Arc}; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use uplc::{ - ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, + ast::{ + Constant as UplcConstant, DeBruijn, Name, NamedDeBruijn, Program, Term, Type as UplcType, + }, builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER}, builtins::DefaultFunction, machine::cost_model::ExBudget, @@ -37,6 +39,13 @@ use builder::{ use self::{builder::replace_opaque_type, scope::Scope, stack::AirStack}; +#[derive(Clone, Debug)] +pub struct CodeGenFunction { + air: Vec, + dependencies: Vec, + recursive: bool, +} + #[derive(Clone)] pub struct CodeGenerator<'a> { defined_functions: IndexMap, @@ -45,8 +54,9 @@ pub struct CodeGenerator<'a> { module_types: IndexMap<&'a String, &'a TypeInfo>, id_gen: Rc, needs_field_access: bool, - used_data_assert_on_list: bool, + code_gen_functions: IndexMap, zero_arg_functions: IndexMap>, + uplc_to_function: IndexMap, FunctionAccessKey>, } impl<'a> CodeGenerator<'a> { @@ -60,19 +70,21 @@ impl<'a> CodeGenerator<'a> { functions, data_types, module_types, - id_gen: IdGenerator::new().into(), needs_field_access: false, - used_data_assert_on_list: false, + id_gen: IdGenerator::new().into(), + code_gen_functions: IndexMap::new(), zero_arg_functions: IndexMap::new(), + uplc_to_function: IndexMap::new(), } } pub fn reset(&mut self) { - self.needs_field_access = false; - self.used_data_assert_on_list = false; + self.code_gen_functions = IndexMap::new(); self.zero_arg_functions = IndexMap::new(); self.id_gen = IdGenerator::new().into(); + self.needs_field_access = false; self.defined_functions = IndexMap::new(); + self.uplc_to_function = IndexMap::new(); } pub fn generate( @@ -157,11 +169,13 @@ impl<'a> CodeGenerator<'a> { } fn finalize(&mut self, term: Term, wrap_as_validator: bool) -> Program { - let mut term = if wrap_as_validator || self.used_data_assert_on_list { - term.assert_on_list() - } else { - term - }; + // let mut term = if self.used_data_assert_on_list { + // term.assert_on_list() + // } else { + // term + // }; + + let mut term = term; if self.needs_field_access { term = term @@ -197,14 +211,10 @@ impl<'a> CodeGenerator<'a> { TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => { let mut stacks = Vec::new(); - for (index, expr) in expressions.iter().enumerate() { - if index == 0 { - self.build(expr, ir_stack); - } else { - let mut stack = ir_stack.empty_with_scope(); - self.build(expr, &mut stack); - stacks.push(stack); - } + for expr in expressions.iter() { + let mut stack = ir_stack.empty_with_scope(); + self.build(expr, &mut stack); + stacks.push(stack); } ir_stack.sequence(stacks); @@ -1638,6 +1648,8 @@ impl<'a> CodeGenerator<'a> { { let mut expect_stack = pattern_stack.empty_with_scope(); + println!("GETTING 2 HERE"); + self.expect_pattern( pattern, &mut expect_stack, @@ -2225,7 +2237,7 @@ impl<'a> CodeGenerator<'a> { || tipo.is_data() { } else if tipo.is_map() { - self.used_data_assert_on_list = true; + // self.used_data_assert_on_list = true; let new_id = self.id_gen.next(); let id_pair = (self.id_gen.next(), self.id_gen.next()); let inner_list_type = &tipo.get_inner_types()[0]; @@ -2266,7 +2278,7 @@ impl<'a> CodeGenerator<'a> { expect_stack.void(); } else if tipo.is_list() { - self.used_data_assert_on_list = true; + // self.used_data_assert_on_list = true; let new_id = self.id_gen.next(); let inner_list_type = &tipo.get_inner_types()[0]; @@ -4813,8 +4825,9 @@ impl<'a> CodeGenerator<'a> { param_stack.local_var(data(), arg.arg_name.get_variable_name().unwrap_or("_")); let mut actual_type = arg.tipo.clone(); - + println!("GETTING HERE"); replace_opaque_type(&mut actual_type, self.data_types.clone()); + println!("ALSO HERE. TYPE IS {:#?}", actual_type); self.assignment( &Pattern::Var { @@ -4834,6 +4847,8 @@ impl<'a> CodeGenerator<'a> { arg.arg_name.get_variable_name().unwrap_or("_").to_string(), ); + println!("CONTINUING HERE"); + let mut air_vec = air_stack.complete(); term = term diff --git a/crates/aiken-lang/src/gen_uplc/stack.rs b/crates/aiken-lang/src/gen_uplc/stack.rs index 0cbd05ba..f8cbf6b7 100644 --- a/crates/aiken-lang/src/gen_uplc/stack.rs +++ b/crates/aiken-lang/src/gen_uplc/stack.rs @@ -5,7 +5,7 @@ use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; use crate::{ ast::Span, - builtins::void, + builtins::{data, list, void}, tipo::{Type, ValueConstructor, ValueConstructorVariant}, IdGenerator, }; @@ -706,13 +706,73 @@ impl AirStack { self.merge_child(value_stack); } + + pub fn assert_on_list(&mut self) { + let mut head_stack = self.empty_with_scope(); + let mut tail_stack = self.empty_with_scope(); + let mut check_with_stack = self.empty_with_scope(); + let mut expect_stack = self.empty_with_scope(); + let mut var_stack = self.empty_with_scope(); + let mut void_stack = self.empty_with_scope(); + let mut fun_stack = self.empty_with_scope(); + let mut arg_stack1 = self.empty_with_scope(); + let mut arg_stack2 = self.empty_with_scope(); + + self.air.push(Air::DefineFunc { + scope: self.scope.clone(), + func_name: EXPECT_ON_LIST.to_string(), + module_name: "".to_string(), + params: vec!["__list_to_check".to_string(), "__check_with".to_string()], + recursive: true, + variant_name: "".to_string(), + }); + + var_stack.local_var(list(data()), "__list_to_check"); + + head_stack.builtin(DefaultFunction::HeadList, data(), vec![var_stack]); + + fun_stack.local_var(void(), "__check_with".to_string()); + + check_with_stack.call(void(), fun_stack, vec![head_stack]); + + void_stack.void(); + void_stack.void(); + + self.list_clause( + void(), + "__list_to_check".to_string(), + None, + false, + void_stack, + ); + + self.choose_unit(check_with_stack); + + expect_stack.local_var(void(), EXPECT_ON_LIST.to_string()); + + arg_stack1.local_var(list(data()), "__list_to_check".to_string()); + + arg_stack2.local_var(void(), "__check_with".to_string()); + + tail_stack.builtin(DefaultFunction::TailList, list(data()), vec![arg_stack1]); + + self.call(void(), expect_stack, vec![tail_stack, arg_stack2]) + } } #[cfg(test)] mod test { use std::rc::Rc; - use crate::{gen_uplc::air::Air, IdGenerator}; + use uplc::builtins::DefaultFunction; + + use crate::{ + ast::Span, + builtins::{data, list, void}, + gen_uplc::air::Air, + tipo::{ValueConstructor, ValueConstructorVariant}, + IdGenerator, + }; use super::AirStack; @@ -812,4 +872,135 @@ mod test { ], ) } + + #[test] + fn assert_on_list_matches_air() { + let id_gen: Rc = IdGenerator::new().into(); + + let scope = vec![id_gen.next()]; + + let mut stack1 = AirStack { + id_gen, + scope: scope.into(), + air: vec![], + }; + + stack1.assert_on_list(); + + println!("{:#?}", stack1); + + let air_vec = vec![ + Air::DefineFunc { + scope: vec![0].into(), + func_name: "__expect_on_list".to_string(), + module_name: "".to_string(), + params: vec!["__list_to_check".to_string(), "__check_with".to_string()], + recursive: true, + variant_name: "".to_string(), + }, + Air::ListClause { + scope: vec![0, 7].into(), + tipo: void(), + tail_name: "__list_to_check".to_string(), + next_tail_name: None, + complex_clause: false, + }, + Air::Void { + scope: vec![0, 7, 5].into(), + }, + Air::Void { + scope: vec![0, 7, 5, 6].into(), + }, + Air::Builtin { + scope: vec![0, 7, 8].into(), + count: 2, + func: DefaultFunction::ChooseUnit, + tipo: void(), + }, + Air::Call { + scope: vec![0, 7, 8, 4].into(), + count: 1, + tipo: void(), + }, + Air::Var { + scope: vec![0, 7, 8, 4, 3].into(), + constructor: ValueConstructor { + public: true, + variant: ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + tipo: void(), + }, + name: "__check_with".to_string(), + variant_name: "".to_string(), + }, + Air::Builtin { + scope: vec![0, 7, 8, 4, 2].into(), + count: 1, + func: DefaultFunction::HeadList, + tipo: data(), + }, + Air::Var { + scope: vec![0, 7, 8, 4, 2, 1].into(), + constructor: ValueConstructor { + public: true, + variant: ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + tipo: list(data()), + }, + name: "__list_to_check".to_string(), + variant_name: "".to_string(), + }, + Air::Call { + scope: vec![0, 7, 8, 13].into(), + count: 2, + tipo: void(), + }, + Air::Var { + scope: vec![0, 7, 8, 13, 9].into(), + constructor: ValueConstructor { + public: true, + variant: ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + tipo: void(), + }, + name: "__expect_on_list".to_string(), + variant_name: "".to_string(), + }, + Air::Builtin { + scope: vec![0, 7, 8, 13, 12].into(), + count: 1, + func: DefaultFunction::TailList, + tipo: list(data()), + }, + Air::Var { + scope: vec![0, 7, 8, 13, 12, 10].into(), + constructor: ValueConstructor { + public: true, + variant: ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + tipo: list(data()), + }, + name: "__list_to_check".to_string(), + variant_name: "".to_string(), + }, + Air::Var { + scope: vec![0, 7, 8, 13, 11].into(), + constructor: ValueConstructor { + public: true, + variant: ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + tipo: void(), + }, + name: "__check_with".to_string(), + variant_name: "".to_string(), + }, + ]; + + assert_eq!(stack1.air, air_vec) + } } diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index 1b46ff91..0ec00265 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -507,8 +507,8 @@ mod test { "$ref": "#/definitions/test_module~1Input" } }, - "compiledCode": "583b0100003232323232323222253330064a22930b180080091129998030010a4c26600a6002600e0046660060066010004002ae695cdaab9f5742ae89", - "hash": "e37db487fbd58c45d059bcbf5cd6b1604d3bec16cf888f1395a4ebc4", + "compiledCode": "5902aa01000032323232323232323232323232322322322533300c4a22930b1980599299980599b874800000454ccc040c024008526153300d49011d4578706563746564206e6f206669656c647320666f7220436f6e73747200161533300b3370e90010008a99980818048010a4c2a6601a92011d4578706563746564206e6f206669656c647320666f7220436f6e73747200161533300b3370e90020008a99980818048010a4c2a6601a92011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300d4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e7400163009001001330093253330093370e90000008991919191919299980a180b00109980819299980819b87480000044c8c94ccc05cc06400852615330144901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602e002601c00c2a660249212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e0053301033009003232498dd7000a4c2a660229201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c602800260280046eb0c048004c048008c040004c01c00854cc02d2412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e74001630070010013001001222533300d00214984cc024c004c038008ccc00c00cc03c008004cc0040052000222233330073370e00200601a4666600a00a66e000112002300f0010020022300737540024600a6ea80055cd2b9b5738aae7555cf2ab9f5742ae89", + "hash": "f5268862002ca36eaf7ad18cb01daf0393f6c78715272ca3fd88143a", "definitions": { "ByteArray": { "dataType": "bytes" @@ -619,8 +619,8 @@ mod test { "$ref": "#/definitions/Tuple$Int_Int_Int" } }, - "compiledCode": "585301000032323232323232232232253330084a22930b1bac0013232337606012004601200260120026eb0004c0040048894ccc0180085261330053001300700233300300330080020015734ae6d55cfaba157441", - "hash": "500b9b576c11ad73dee3b9d5202496a7df78e8de4097c57f0acfcc3a", + "compiledCode": "58cd01000032323232323232323232232232253330084a22930b1919191919192999808980980108030a99807249334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602200260220046eb4c03c004c03c008dd698068009bac001323232003375c60140046eb4c020004c8c8cdd81806001180600098060009bac0013001001222533300900214984cc014c004c028008ccc00c00cc02c0080055cd2b9b5738aae7555cf2ab9f5742ae881", + "hash": "992c2391be3d472eda9de2da280f68338bff2eddb45dc75ab3e36046", "definitions": { "ByteArray": { "dataType": "bytes"