From 709ee914ed34e612457b3ae499560f7c4d29ed95 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 23 Mar 2023 21:14:20 -0400 Subject: [PATCH] feat: another round of functions using AirStack Co-authored-by: Kasey White --- crates/aiken-lang/src/gen_uplc.rs | 157 +++++++++------------- crates/aiken-lang/src/gen_uplc/builder.rs | 26 ++-- crates/aiken-lang/src/gen_uplc/scope.rs | 2 +- crates/aiken-lang/src/gen_uplc/stack.rs | 4 + 4 files changed, 85 insertions(+), 104 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 06a0296c..9d15eb51 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use uplc::{ ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, - builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST}, + builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER}, builtins::DefaultFunction, machine::cost_model::ExBudget, optimize::aiken_optimize_and_intern, @@ -86,7 +86,9 @@ impl<'a> CodeGenerator<'a> { ) -> Program { let mut ir_stack = AirStack::new(&mut self.id_gen); - self.build_ir(&fun.body, &mut ir_stack); + self.build(&fun.body, &mut ir_stack); + + let mut ir_stack = ir_stack.complete(); self.define_ir(&mut ir_stack); @@ -102,11 +104,11 @@ impl<'a> CodeGenerator<'a> { if let Some(other) = other_fun { self.reset(); - let mut other_ir_stack = vec![]; + let mut other_ir_stack = AirStack::new(&mut self.id_gen); - let scope = vec![self.id_gen.next()]; + self.build(&other.body, &mut other_ir_stack); - self.build_ir(&other.body, &mut other_ir_stack, scope); + let mut other_ir_stack = other_ir_stack.complete(); self.define_ir(&mut other_ir_stack); @@ -136,7 +138,9 @@ impl<'a> CodeGenerator<'a> { pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program { let mut ir_stack = AirStack::new(&mut self.id_gen); - self.build_ir(test_body, &mut ir_stack); + self.build(test_body, &mut ir_stack); + + let mut ir_stack = ir_stack.complete(); self.define_ir(&mut ir_stack); @@ -180,7 +184,7 @@ impl<'a> CodeGenerator<'a> { program } - pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut AirStack) { + pub(crate) fn build(&mut self, body: &TypedExpr, ir_stack: &mut AirStack) { match body { TypedExpr::Int { value, .. } => ir_stack.integer(value.to_string()), TypedExpr::String { value, .. } => ir_stack.string(value.to_string()), @@ -190,10 +194,10 @@ impl<'a> CodeGenerator<'a> { for (index, expr) in expressions.iter().enumerate() { if index == 0 { - self.build_ir(expr, ir_stack); + self.build(expr, ir_stack); } else { let mut stack = ir_stack.empty_with_scope(); - self.build_ir(expr, &mut stack); + self.build(expr, &mut stack); stacks.push(stack); } } @@ -219,7 +223,7 @@ impl<'a> CodeGenerator<'a> { TypedExpr::Fn { args, body, .. } => { let mut body_stack = ir_stack.empty_with_scope(); - self.build_ir(body, &mut body_stack); + self.build(body, &mut body_stack); let mut params = args .iter() @@ -238,7 +242,7 @@ impl<'a> CodeGenerator<'a> { for element in elements { let mut stack = ir_stack.empty_with_scope(); - self.build_ir(element, &mut stack); + self.build(element, &mut stack); stacks.push(stack); } @@ -246,7 +250,7 @@ impl<'a> CodeGenerator<'a> { let tail = tail.as_ref().map(|tail| { let mut tail_stack = ir_stack.empty_with_scope(); - self.build_ir(tail, &mut tail_stack); + self.build(tail, &mut tail_stack); tail_stack }); @@ -284,7 +288,7 @@ impl<'a> CodeGenerator<'a> { stack.wrap_data(arg.value.tipo()); } - self.build_ir(&arg.value, &mut stack); + self.build(&arg.value, &mut stack); stacks.push(stack); } @@ -309,7 +313,7 @@ impl<'a> CodeGenerator<'a> { stack.wrap_data(arg.value.tipo()); } - self.build_ir(&arg.value, &mut stack); + self.build(&arg.value, &mut stack); } ir_stack.builtin(*func, tipo.clone(), stacks); @@ -349,7 +353,7 @@ impl<'a> CodeGenerator<'a> { stack.wrap_data(arg.value.tipo()); } - self.build_ir(&arg.value, &mut stack); + self.build(&arg.value, &mut stack); } ir_stack.record(tipo.clone(), constr_index, stacks); @@ -374,7 +378,7 @@ impl<'a> CodeGenerator<'a> { stack.wrap_data(arg.value.tipo()); } - self.build_ir(&arg.value, &mut stack); + self.build(&arg.value, &mut stack); } ir_stack.builtin(*func, tipo.clone(), stacks); @@ -389,7 +393,7 @@ impl<'a> CodeGenerator<'a> { let mut fun_stack = ir_stack.empty_with_scope(); - self.build_ir(fun, &mut fun_stack); + self.build(fun, &mut fun_stack); let fun_arg_types = fun.tipo().arg_types().unwrap_or_default(); @@ -401,7 +405,7 @@ impl<'a> CodeGenerator<'a> { stack.wrap_data(arg.value.tipo()); } - self.build_ir(&arg.value, &mut stack); + self.build(&arg.value, &mut stack); } ir_stack.call(tipo.clone(), fun_stack, stacks); @@ -412,8 +416,8 @@ impl<'a> CodeGenerator<'a> { let mut left_stack = ir_stack.empty_with_scope(); let mut right_stack = ir_stack.empty_with_scope(); - self.build_ir(left, &mut left_stack); - self.build_ir(right, &mut right_stack); + self.build(left, &mut left_stack); + self.build(right, &mut right_stack); ir_stack.binop(*name, left.tipo(), left_stack, right_stack); } @@ -430,7 +434,7 @@ impl<'a> CodeGenerator<'a> { let mut replaced_type = tipo.clone(); builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); - self.build_ir(value, &mut value_stack); + self.build(value, &mut value_stack); self.assignment( pattern, @@ -457,9 +461,9 @@ impl<'a> CodeGenerator<'a> { let mut pattern_vec: Vec = vec![]; let mut subject_vec: Vec = vec![]; - self.build_ir(&clauses[0].then, &mut value_vec); + self.build(&clauses[0].then, &mut value_vec); - self.build_ir(subject, &mut subject_vec); + self.build(subject, &mut subject_vec); self.assignment( &clauses[0].pattern, @@ -512,7 +516,7 @@ impl<'a> CodeGenerator<'a> { let mut final_clause_vec = vec![]; - self.build_ir(&last_clause.then, &mut final_clause_vec); + self.build(&last_clause.then, &mut final_clause_vec); *clause_properties.is_final_clause() = true; @@ -533,7 +537,7 @@ impl<'a> CodeGenerator<'a> { let mut subject_scope = scope.clone(); subject_scope.push(self.id_gen.next()); - self.build_ir(subject, ir_stack, subject_scope.clone()); + self.build(subject, ir_stack); let mut scope = scope; scope.push(self.id_gen.next()); @@ -565,7 +569,7 @@ impl<'a> CodeGenerator<'a> { let mut scope = scope; scope.push(self.id_gen.next()); - self.build_ir(subject, ir_stack, scope); + self.build(subject, ir_stack); } ir_stack.append(&mut pattern_vec); @@ -582,16 +586,16 @@ impl<'a> CodeGenerator<'a> { let mut condition_stack = ir_stack.empty_with_scope(); let mut branch_body_stack = ir_stack.empty_with_scope(); - self.build_ir(&branch.condition, &mut condition_stack); + self.build(&branch.condition, &mut condition_stack); - self.build_ir(&branch.body, &mut branch_body_stack); + self.build(&branch.body, &mut branch_body_stack); ir_stack.if_branch(tipo.clone(), condition_stack, branch_body_stack); } let mut else_stack = ir_stack.empty_with_scope(); - self.build_ir(final_else, &mut else_stack); + self.build(final_else, &mut else_stack); ir_stack.merge_child(else_stack); } @@ -603,7 +607,7 @@ impl<'a> CodeGenerator<'a> { } => { let mut record_access_stack = ir_stack.empty_with_scope(); - self.build_ir(record, &mut record_access_stack); + self.build(record, &mut record_access_stack); ir_stack.record_access(tipo.clone(), *index, record_access_stack); } @@ -651,12 +655,12 @@ impl<'a> CodeGenerator<'a> { let mut update_stack = ir_stack.empty_with_scope(); - self.build_ir(spread, &mut update_stack); + self.build(spread, &mut update_stack); for arg in args { let mut arg_stack = update_stack.empty_with_scope(); - self.build_ir(&arg.value, &mut arg_stack); + self.build(&arg.value, &mut arg_stack); update_stack.merge(arg_stack); @@ -672,7 +676,7 @@ impl<'a> CodeGenerator<'a> { TypedExpr::UnOp { value, op, .. } => { let mut value_stack = ir_stack.empty_with_scope(); - self.build_ir(value, &mut value_stack); + self.build(value, &mut value_stack); ir_stack.unop(*op, value_stack); } @@ -681,7 +685,7 @@ impl<'a> CodeGenerator<'a> { for elem in elems { let mut elem_stack = ir_stack.empty_with_scope(); - self.build_ir(elem, &mut elem_stack); + self.build(elem, &mut elem_stack); stacks.push(elem_stack); } @@ -694,8 +698,8 @@ impl<'a> CodeGenerator<'a> { let mut text_stack = ir_stack.empty_with_scope(); let mut then_stack = ir_stack.empty_with_scope(); - self.build_ir(text, &mut text_stack); - self.build_ir(then, &mut then_stack); + self.build(text, &mut text_stack); + self.build(then, &mut then_stack); ir_stack.trace(tipo.clone()); ir_stack.merge_child(text_stack); @@ -705,7 +709,7 @@ impl<'a> CodeGenerator<'a> { TypedExpr::TupleIndex { index, tuple, .. } => { let mut tuple_stack = ir_stack.empty_with_scope(); - self.build_ir(tuple, &mut tuple_stack); + self.build(tuple, &mut tuple_stack); ir_stack.tuple_index(tuple.tipo(), *index, tuple_stack); } @@ -722,7 +726,6 @@ impl<'a> CodeGenerator<'a> { clause_properties: &mut ClauseProperties, clauses: &[TypedClause], subject_type: &Arc, - scope: Vec, ) { for (index, clause) in clauses.iter().enumerate() { // scope per clause is different @@ -739,7 +742,7 @@ impl<'a> CodeGenerator<'a> { let mut clause_scope = scope.clone(); clause_scope.push(self.id_gen.next()); - self.build_ir(&clause.then, &mut clause_then_vec, clause_scope); + self.build(&clause.then, &mut clause_then_vec); if let Some(clause_guard) = &clause.guard { let mut clause_guard_vec = vec![]; @@ -2514,89 +2517,57 @@ impl<'a> CodeGenerator<'a> { let id = self.id_gen.next(); let constr_name = format!("{constr_name}_{id}"); + let mut local_var_stack = nested_pattern_stack.empty_with_scope(); + + local_var_stack.local_var(tipo.clone(), constr_name); + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { self.expect_pattern( a, - nested_pattern, - &mut vec![Air::Var { - scope: scope.to_owned(), - constructor: ValueConstructor::public( - tipo.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: constr_name.clone(), - variant_name: String::new(), - }], + nested_pattern_stack, + local_var_stack, tipo, assignment_properties.clone(), ); } else { self.pattern_ir( a, - nested_pattern, - &mut vec![Air::Var { - scope: scope.to_owned(), - constructor: ValueConstructor::public( - tipo.clone(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: constr_name.clone(), - variant_name: String::new(), - }], + nested_pattern_stack, + local_var_stack, tipo, assignment_properties.clone(), ); } - (false, constr_name) + Some(constr_name) } a @ Pattern::Tuple { .. } => { let id = self.id_gen.next(); let tuple_name = format!("__tuple_name_{id}"); + let mut local_var_stack = nested_pattern_stack.empty_with_scope(); + + local_var_stack.local_var(tipo.clone().into(), tuple_name); + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { self.expect_pattern( a, - nested_pattern, - &mut vec![Air::Var { - scope: scope.to_owned(), - constructor: ValueConstructor::public( - tipo.clone().into(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: tuple_name.clone(), - variant_name: String::new(), - }], + nested_pattern_stack, + local_var_stack, tipo, assignment_properties.clone(), ); } else { self.pattern_ir( a, - nested_pattern, - &mut vec![Air::Var { - scope: scope.to_owned(), - constructor: ValueConstructor::public( - tipo.clone().into(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: tuple_name.clone(), - variant_name: String::new(), - }], + nested_pattern_stack, + local_var_stack, tipo, assignment_properties.clone(), ); @@ -2676,7 +2647,7 @@ impl<'a> CodeGenerator<'a> { if !function_component.args.is_empty() { // deal with function dependencies - builder::handle_func_dependencies_ir( + builder::handle_func_dependencies( &mut dep_ir, function_component, &function_definitions, @@ -2692,7 +2663,7 @@ impl<'a> CodeGenerator<'a> { let mut defined_functions = IndexMap::new(); // deal with function dependencies in zero arg functions - builder::handle_func_dependencies_ir( + builder::handle_func_dependencies( &mut dep_ir, function_component, &function_definitions, @@ -2721,7 +2692,7 @@ impl<'a> CodeGenerator<'a> { let funt_comp = function_definitions.get(&func.0).unwrap(); let func_scope = func_index_map.get(&func.0).unwrap(); - builder::handle_func_dependencies_ir( + builder::handle_func_dependencies( &mut dep_ir, funt_comp, &function_definitions, @@ -2939,7 +2910,7 @@ impl<'a> CodeGenerator<'a> { let mut func_ir = vec![]; - self.build_ir(&function.body, &mut func_ir, scope.to_vec()); + self.build(&function.body, &mut func_ir); let param_types = constructor.tipo.arg_types().unwrap(); @@ -3055,7 +3026,7 @@ impl<'a> CodeGenerator<'a> { mono_types = map.into_iter().collect(); let mut func_ir = vec![]; - self.build_ir(&function.body, &mut func_ir, scope.to_vec()); + self.build(&function.body, &mut func_ir); let (variant_name, _) = builder::monomorphize(func_ir, mono_types, &tipo); diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 8d0c0a58..fbd7014f 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -22,7 +22,7 @@ use crate::{ tipo::{PatternConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant}, }; -use super::{air::Air, stack::AirStack}; +use super::{air::Air, scope::Scope, stack::AirStack}; #[derive(Clone, Debug)] pub struct FuncComponents { @@ -1427,13 +1427,13 @@ pub fn monomorphize( (new_name, new_air) } -pub fn handle_func_dependencies_ir( +pub fn handle_func_dependencies( dependencies_ir: &mut Vec, function_component: &FuncComponents, func_components: &IndexMap, defined_functions: &mut IndexMap, - func_index_map: &IndexMap>, - func_scope: &[u64], + func_index_map: &IndexMap, + func_scope: &Scope, to_be_defined: &mut IndexMap, ) { let mut function_component = function_component.clone(); @@ -1444,10 +1444,13 @@ pub fn handle_func_dependencies_ir( // deal with function dependencies by sorting order in which we pop them. while let Some(dependency) = function_component.dependencies.pop() { let depend_comp = func_components.get(&dependency).unwrap(); + if dependency_map.contains_key(&dependency) { dependency_map.shift_remove(&dependency); } + dependency_map.insert(dependency, ()); + function_component .dependencies .extend(depend_comp.dependencies.clone().into_iter()); @@ -1457,15 +1460,17 @@ pub fn handle_func_dependencies_ir( dependency_vec.reverse(); while let Some(dependency) = dependency_vec.pop() { - if defined_functions.contains_key(&dependency) || func_components.get(&dependency).is_none() - { + let func_component_dep = func_components.get(&dependency); + + if defined_functions.contains_key(&dependency) { continue; } - let depend_comp = func_components.get(&dependency).unwrap(); + let Some(depend_comp) = func_component_dep else {continue}; + let dep_scope = func_index_map.get(&dependency).unwrap(); - if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec() + if dep_scope.common_ancestor(func_scope) == *func_scope || function_component.args.is_empty() { let mut recursion_ir = vec![]; @@ -1485,7 +1490,8 @@ pub fn handle_func_dependencies_ir( temp_ir.append(dependencies_ir); *dependencies_ir = temp_ir; - if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec() { + + if dep_scope.common_ancestor(func_scope) == *func_scope { defined_functions.insert(dependency, ()); } } else if depend_comp.args.is_empty() { @@ -1759,7 +1765,7 @@ pub fn handle_clause_guard( }); } ClauseGuard::Constant(constant) => { - constants_ir(constant, clause_guard_vec, scope); + constants_ir(constant, clause_guard_vec); } } } diff --git a/crates/aiken-lang/src/gen_uplc/scope.rs b/crates/aiken-lang/src/gen_uplc/scope.rs index 4f09291b..eba320c9 100644 --- a/crates/aiken-lang/src/gen_uplc/scope.rs +++ b/crates/aiken-lang/src/gen_uplc/scope.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Eq, PartialEq)] pub struct Scope(Vec); impl Scope { diff --git a/crates/aiken-lang/src/gen_uplc/stack.rs b/crates/aiken-lang/src/gen_uplc/stack.rs index 361857c7..4046fb36 100644 --- a/crates/aiken-lang/src/gen_uplc/stack.rs +++ b/crates/aiken-lang/src/gen_uplc/stack.rs @@ -67,6 +67,10 @@ impl<'a> AirStack<'a> { } } + pub fn complete(self) -> Vec { + self.air + } + pub fn sequence(&mut self, stacks: Vec) { for stack in stacks { self.merge(stack)