From ca0d896b8d5a0ed65493b4104656b591f36a1a51 Mon Sep 17 00:00:00 2001 From: rvcas Date: Tue, 21 Mar 2023 23:17:51 -0400 Subject: [PATCH] feat: start using AirStack methods Co-authored-by: Kasey White --- crates/aiken-lang/src/gen_uplc.rs | 426 ++++++++-------------- crates/aiken-lang/src/gen_uplc/air.rs | 3 +- crates/aiken-lang/src/gen_uplc/builder.rs | 45 +-- crates/aiken-lang/src/gen_uplc/stack.rs | 165 +++++++-- 4 files changed, 313 insertions(+), 326 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 01963b80..a6854ec2 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -34,6 +34,8 @@ use builder::{ AssignmentProperties, ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey, }; +use self::stack::AirStack; + #[derive(Clone)] pub struct CodeGenerator<'a> { defined_functions: IndexMap, @@ -81,10 +83,9 @@ impl<'a> CodeGenerator<'a> { .. }: &TypedValidator, ) -> Program { - let mut ir_stack = vec![]; - let scope = vec![self.id_gen.next()]; + let mut ir_stack = AirStack::new(&mut self.id_gen); - self.build_ir(&fun.body, &mut ir_stack, scope); + self.build_ir(&fun.body, &mut ir_stack); self.define_ir(&mut ir_stack); @@ -132,10 +133,9 @@ impl<'a> CodeGenerator<'a> { } pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program { - let mut ir_stack = vec![]; - let scope = vec![self.id_gen.next()]; + let mut ir_stack = AirStack::new(&mut self.id_gen); - self.build_ir(test_body, &mut ir_stack, scope); + self.build_ir(test_body, &mut ir_stack); self.define_ir(&mut ir_stack); @@ -179,75 +179,52 @@ impl<'a> CodeGenerator<'a> { program } - pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut Vec, scope: Vec) { + pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut AirStack) { match body { - TypedExpr::Int { value, .. } => ir_stack.push(Air::Int { - scope, - value: value.to_string(), - }), - TypedExpr::String { value, .. } => ir_stack.push(Air::String { - scope, - value: value.to_string(), - }), - TypedExpr::ByteArray { bytes, .. } => ir_stack.push(Air::ByteArray { - scope, - bytes: bytes.to_vec(), - }), + TypedExpr::Int { value, .. } => ir_stack.integer(value.to_string()), + TypedExpr::String { value, .. } => ir_stack.string(value.to_string()), + TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()), TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => { + let stacks = Vec::new(); + for (index, expr) in expressions.iter().enumerate() { if index == 0 { - self.build_ir(expr, ir_stack, scope.clone()); + self.build_ir(expr, ir_stack); } else { - let mut branch_scope = scope.clone(); - branch_scope.push(self.id_gen.next()); - self.build_ir(expr, ir_stack, branch_scope); + let mut stack = ir_stack.in_new_scope(); + self.build_ir(expr, &mut stack); } } + + ir_stack.sequence(stacks); } TypedExpr::Var { constructor, name, .. } => match &constructor.variant { ValueConstructorVariant::ModuleConstant { literal, .. } => { - builder::constants_ir(literal, ir_stack, scope); + builder::constants_ir(literal, ir_stack); } ValueConstructorVariant::ModuleFn { builtin: Some(builtin), .. } => { - ir_stack.push(Air::Builtin { - scope, - func: *builtin, - tipo: constructor.tipo.clone(), - count: 0, - }); + ir_stack.builtin(*builtin, constructor.tipo.clone(), vec![]); } _ => { - ir_stack.push(Air::Var { - scope, - constructor: constructor.clone(), - name: name.clone(), - variant_name: String::new(), - }); + ir_stack.var(constructor.clone(), name, ""); } }, TypedExpr::Fn { args, body, .. } => { - let mut func_body = vec![]; - let mut func_scope = scope.clone(); - func_scope.push(self.id_gen.next()); - self.build_ir(body, &mut func_body, func_scope); - let mut arg_names = vec![]; - for arg in args { - let name = arg.arg_name.get_variable_name().unwrap_or("_").to_string(); + let mut body_stack = ir_stack.in_new_scope(); - arg_names.push(name); - } + self.build_ir(body, &mut body_stack); - ir_stack.push(Air::Fn { - scope, - params: arg_names, - }); + let mut params = args + .iter() + .map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string()) + .collect(); - ir_stack.append(&mut func_body); + ir_stack.anonymous_function(params, body_stack); } TypedExpr::List { elements, @@ -255,25 +232,24 @@ impl<'a> CodeGenerator<'a> { tipo, .. } => { - ir_stack.push(Air::List { - scope: scope.clone(), - count: elements.len(), - tipo: tipo.clone(), - tail: tail.is_some(), + let stacks = Vec::new(); + for element in elements { + let mut stack = ir_stack.in_new_scope(); + + self.build_ir(element, &mut stack); + + stacks.push(stack); + } + + let tail = tail.as_ref().map(|tail| { + let mut tail_stack = ir_stack.in_new_scope(); + + self.build_ir(tail, &mut tail_stack); + + tail_stack }); - for element in elements { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); - self.build_ir(element, ir_stack, scope.clone()) - } - - if let Some(tail) = tail { - let mut scope = scope; - scope.push(self.id_gen.next()); - - self.build_ir(tail, ir_stack, scope); - } + ir_stack.list(tipo.clone(), stacks, tail); } TypedExpr::Call { fun, args, tipo, .. @@ -293,30 +269,26 @@ impl<'a> CodeGenerator<'a> { .find(|(_, dt)| &dt.name == constr_name) .unwrap(); - ir_stack.push(Air::Record { - scope: scope.clone(), - constr_index, - tipo: constructor.tipo.clone(), - count: args.len(), - }); - - if let Some(fun_arg_types) = fun.tipo().arg_types() { - for (arg, func_type) in args.iter().zip(fun_arg_types) { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); - - if func_type.is_data() && !arg.value.tipo().is_data() { - ir_stack.push(Air::WrapData { - scope: scope.clone(), - tipo: arg.value.tipo(), - }) - } - - self.build_ir(&arg.value, ir_stack, scope); - } - } else { + let Some(fun_arg_types) = fun.tipo().arg_types() else { unreachable!() + }; + + let stacks = Vec::new(); + + for (arg, func_type) in args.iter().zip(fun_arg_types) { + let mut stack = ir_stack.in_new_scope(); + + if func_type.is_data() && !arg.value.tipo().is_data() { + stack.wrap_data(arg.value.tipo()); + } + + self.build_ir(&arg.value, &mut stack); + + stacks.push(stack); } + + ir_stack.record(constructor.tipo.clone(), constr_index, stacks); + return; } } @@ -324,31 +296,22 @@ impl<'a> CodeGenerator<'a> { builtin: Some(func), .. } => { - ir_stack.push(Air::Builtin { - scope: scope.clone(), - count: func.arity(), - func: *func, - tipo: tipo.clone(), - }); + let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()}; - if let Some(fun_arg_types) = fun.tipo().arg_types() { - for (arg, func_type) in args.iter().zip(fun_arg_types) { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); + let stacks = Vec::new(); - if func_type.is_data() && !arg.value.tipo().is_data() { - ir_stack.push(Air::WrapData { - scope: scope.clone(), - tipo: arg.value.tipo(), - }) - } + for (arg, func_type) in args.iter().zip(fun_arg_types) { + let mut stack = ir_stack.in_new_scope(); - self.build_ir(&arg.value, ir_stack, scope); + if func_type.is_data() && !arg.value.tipo().is_data() { + stack.wrap_data(arg.value.tipo()); } - } else { - unreachable!() + + self.build_ir(&arg.value, &mut stack); } + ir_stack.builtin(*func, tipo.clone(), stacks); + return; } _ => {} @@ -373,30 +336,22 @@ impl<'a> CodeGenerator<'a> { .find(|(_, dt)| &dt.name == constr_name) .unwrap(); - ir_stack.push(Air::Record { - scope: scope.clone(), - constr_index, - tipo: tipo.clone(), - count: args.len(), - }); + let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()}; - if let Some(fun_arg_types) = fun.tipo().arg_types() { - for (arg, func_type) in args.iter().zip(fun_arg_types) { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); + let mut stacks = Vec::new(); - if func_type.is_data() && !arg.value.tipo().is_data() { - ir_stack.push(Air::WrapData { - scope: scope.clone(), - tipo: arg.value.tipo(), - }) - } + for (arg, func_type) in args.iter().zip(fun_arg_types) { + let mut stack = ir_stack.in_new_scope(); - self.build_ir(&arg.value, ir_stack, scope); + if func_type.is_data() && !arg.value.tipo().is_data() { + stack.wrap_data(arg.value.tipo()); } - } else { - unreachable!() + + self.build_ir(&arg.value, &mut stack); } + + ir_stack.record(tipo.clone(), constr_index, stacks); + return; } } @@ -404,39 +359,25 @@ impl<'a> CodeGenerator<'a> { let type_info = self.module_types.get(module_name).unwrap(); let value = type_info.values.get(name).unwrap(); - match &value.variant { - ValueConstructorVariant::ModuleFn { builtin, .. } => { - if let Some(func) = builtin { - ir_stack.push(Air::Builtin { - scope: scope.clone(), - count: func.arity(), - func: *func, - tipo: tipo.clone(), - }); + let ValueConstructorVariant::ModuleFn { builtin, .. } = &value.variant else {unreachable!()}; - if let Some(fun_arg_types) = fun.tipo().arg_types() { - for (arg, func_type) in args.iter().zip(fun_arg_types) { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); + if let Some(func) = builtin { + let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()}; - if func_type.is_data() - && !arg.value.tipo().is_data() - { - ir_stack.push(Air::WrapData { - scope: scope.clone(), - tipo: arg.value.tipo(), - }) - } + let mut stacks = Vec::new(); + for (arg, func_type) in args.iter().zip(fun_arg_types) { + let mut stack = ir_stack.in_new_scope(); - self.build_ir(&arg.value, ir_stack, scope); - } - } else { - unreachable!() - } - return; + if func_type.is_data() && !arg.value.tipo().is_data() { + stack.wrap_data(arg.value.tipo()); } + + self.build_ir(&arg.value, &mut stack); } - _ => unreachable!(), + + ir_stack.builtin(*func, tipo.clone(), stacks); + + return; } } _ => {} @@ -444,48 +385,35 @@ impl<'a> CodeGenerator<'a> { _ => {} } - ir_stack.push(Air::Call { - scope: scope.clone(), - count: args.len(), - tipo: tipo.clone(), - }); - let mut scope_fun = scope.clone(); - scope_fun.push(self.id_gen.next()); - self.build_ir(fun, ir_stack, scope_fun); + let mut fun_stack = ir_stack.in_new_scope(); - if let Some(fun_arg_types) = fun.tipo().arg_types() { - for (arg, func_type) in args.iter().zip(fun_arg_types) { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); + self.build_ir(fun, &mut fun_stack); - if func_type.is_data() && !arg.value.tipo().is_data() { - ir_stack.push(Air::WrapData { - scope: scope.clone(), - tipo: arg.value.tipo(), - }) - } + let fun_arg_types = fun.tipo().arg_types().unwrap_or_default(); - self.build_ir(&arg.value, ir_stack, scope); + let mut stacks = Vec::new(); + for (arg, func_type) in args.iter().zip(fun_arg_types) { + let mut stack = ir_stack.in_new_scope(); + + if func_type.is_data() && !arg.value.tipo().is_data() { + stack.wrap_data(arg.value.tipo()); } + + self.build_ir(&arg.value, &mut stack); } + + ir_stack.call(tipo.clone(), fun_stack, stacks); } TypedExpr::BinOp { name, left, right, .. } => { - ir_stack.push(Air::BinOp { - scope: scope.clone(), - name: *name, - count: 2, - tipo: left.tipo(), - }); - let mut scope_left = scope.clone(); - scope_left.push(self.id_gen.next()); + let mut left_stack = ir_stack.in_new_scope(); + let mut right_stack = ir_stack.in_new_scope(); - let mut scope_right = scope; - scope_right.push(self.id_gen.next()); + self.build_ir(left, &mut left_stack); + self.build_ir(right, &mut right_stack); - self.build_ir(left, ir_stack, scope_left); - self.build_ir(right, ir_stack, scope_right); + ir_stack.binop(*name, left.tipo(), left_stack, right_stack); } TypedExpr::Assignment { value, @@ -494,30 +422,26 @@ impl<'a> CodeGenerator<'a> { tipo, .. } => { - let mut value_vec: Vec = vec![]; - let mut pattern_vec: Vec = vec![]; - - let mut value_scope = scope.clone(); - value_scope.push(self.id_gen.next()); + let mut value_stack = ir_stack.in_new_scope(); + let mut pattern_stack = ir_stack.in_new_scope(); let mut replaced_type = tipo.clone(); builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); - self.build_ir(value, &mut value_vec, value_scope); + self.build_ir(value, &mut value_stack); self.assignment_ir( pattern, - &mut pattern_vec, - &mut value_vec, + &mut pattern_stack, + value_stack, &replaced_type, AssignmentProperties { value_type: value.tipo(), kind: *kind, }, - scope, ); - ir_stack.append(&mut pattern_vec); + ir_stack.merge(pattern_stack); } TypedExpr::When { subject, clauses, .. @@ -1823,74 +1747,57 @@ impl<'a> CodeGenerator<'a> { fn assignment_ir( &mut self, pattern: &Pattern>, - pattern_vec: &mut Vec, - value_vec: &mut Vec, + pattern_stack: &mut AirStack, + value_stack: AirStack, tipo: &Type, assignment_properties: AssignmentProperties, - scope: Vec, ) { - if assignment_properties.value_type.is_data() && !tipo.is_data() && !pattern.is_discard() { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); + let value_stack = if assignment_properties.value_type.is_data() + && !tipo.is_data() + && !pattern.is_discard() + { + let mut wrap_stack = pattern_stack.in_new_scope(); + wrap_stack.un_wrap_data(tipo.clone().into()); + wrap_stack.merge(value_stack); + wrap_stack + } else if !assignment_properties.value_type.is_data() + && tipo.is_data() + && !pattern.is_discard() + { + let mut wrap_stack = pattern_stack.in_new_scope(); + wrap_stack.wrap_data(assignment_properties.value_type.clone()); + wrap_stack.merge(value_stack); + wrap_stack + } else { + value_stack + }; - value_vec.insert( - 0, - Air::UnWrapData { - scope: scope.clone(), - tipo: tipo.clone().into(), - }, - ); - } - if !assignment_properties.value_type.is_data() && tipo.is_data() && !pattern.is_discard() { - let mut scope = scope.clone(); - scope.push(self.id_gen.next()); - - value_vec.insert( - 0, - Air::WrapData { - scope: scope.clone(), - tipo: assignment_properties.value_type.clone(), - }, - ) - } match pattern { - Pattern::Int { .. } => unreachable!(), + Pattern::Int { .. } => todo!(), Pattern::Var { name, .. } => { - pattern_vec.push(Air::Let { - name: name.clone(), - scope: scope.clone(), - }); - - pattern_vec.append(value_vec); + let assert_value_stack = value_stack.in_new_scope(); + pattern_stack.let_assignment(name, value_stack); if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { - let mut assert_vec = vec![]; - let mut scope = scope; - - scope.push(self.id_gen.next()); + let mut assert_stack = pattern_stack.in_new_scope(); self.recursive_assert_pattern( pattern, - &mut assert_vec, - value_vec, + &mut assert_stack, + assert_value_stack, tipo, assignment_properties, - scope, ); - pattern_vec.append(&mut assert_vec); + + pattern_stack.merge(assert_stack); } } - Pattern::Assign { .. } => todo!("Assign not yet implemented yet"), + Pattern::Assign { .. } => todo!("Assign not yet implemented"), Pattern::Discard { .. } => { - pattern_vec.push(Air::Let { - name: "_".to_string(), - scope, - }); - - pattern_vec.append(value_vec); + pattern_stack.let_assignment("_", value_stack); } list @ Pattern::List { .. } => { if matches!(assignment_properties.kind, AssignmentKind::Expect) @@ -2261,18 +2168,17 @@ impl<'a> CodeGenerator<'a> { pub fn recursive_assert_pattern( &mut self, pattern: &Pattern>, - pattern_vec: &mut Vec, - value_vec: &mut Vec, + assert_stack: &mut AirStack, + value_stack: AirStack, tipo: &Type, assignment_properties: AssignmentProperties, - scope: Vec, ) { match pattern { Pattern::Int { .. } => unreachable!(), Pattern::Var { name, .. } => { - pattern_vec.append(value_vec); + assert_stack.merge(value_stack); - self.recursive_assert_tipo(tipo, pattern_vec, name, scope); + self.recursive_assert_tipo(tipo, assert_stack, name); } Pattern::Assign { .. } => todo!(), Pattern::Discard { .. } => unreachable!(), @@ -2530,13 +2436,7 @@ impl<'a> CodeGenerator<'a> { } } - fn recursive_assert_tipo( - &mut self, - tipo: &Type, - assert_vec: &mut Vec, - name: &str, - scope: Vec, - ) { + fn recursive_assert_tipo(&mut self, tipo: &Type, assert_vec: &mut AirStack, name: &str) { let mut tipo = tipo.clone().into(); builder::replace_opaque_type(&mut tipo, self.data_types.clone()); @@ -3675,19 +3575,13 @@ impl<'a> CodeGenerator<'a> { tipo: replaced_type, }; } - Air::BinOp { - tipo, - scope, - name, - count, - } => { + Air::BinOp { tipo, scope, name } => { let mut replaced_type = tipo.clone(); builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); ir_stack[index] = Air::BinOp { scope, name, - count, tipo: replaced_type, }; } @@ -3872,7 +3766,7 @@ impl<'a> CodeGenerator<'a> { }; } Air::Record { - constr_index, + tag: constr_index, tipo, count, scope, @@ -3885,7 +3779,7 @@ impl<'a> CodeGenerator<'a> { ir_stack[index] = Air::Record { scope, - constr_index, + tag: constr_index, tipo: replaced_type, count, }; @@ -4884,7 +4778,7 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } Air::Record { - constr_index, + tag: constr_index, tipo, count, .. diff --git a/crates/aiken-lang/src/gen_uplc/air.rs b/crates/aiken-lang/src/gen_uplc/air.rs index 64ec095e..6532f946 100644 --- a/crates/aiken-lang/src/gen_uplc/air.rs +++ b/crates/aiken-lang/src/gen_uplc/air.rs @@ -74,7 +74,6 @@ pub enum Air { BinOp { scope: Vec, name: BinOp, - count: usize, tipo: Arc, }, UnOp { @@ -156,7 +155,7 @@ pub enum Air { // Record Creation Record { scope: Vec, - constr_index: usize, + tag: usize, tipo: Arc, count: usize, }, diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index ea96a072..1a06be7a 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; +use super::{air::Air, stack::AirStack}; #[derive(Clone, Debug)] pub struct FuncComponents { @@ -713,25 +713,16 @@ pub fn check_when_pattern_needs( } } -pub fn constants_ir(literal: &Constant, ir_stack: &mut Vec, scope: Vec) { +pub fn constants_ir(literal: &Constant, ir_stack: &mut AirStack) { match literal { Constant::Int { value, .. } => { - ir_stack.push(Air::Int { - scope, - value: value.clone(), - }); + ir_stack.integer(value.clone()); } Constant::String { value, .. } => { - ir_stack.push(Air::String { - scope, - value: value.clone(), - }); + ir_stack.string(value.clone()); } Constant::ByteArray { bytes, .. } => { - ir_stack.push(Air::ByteArray { - scope, - bytes: bytes.clone(), - }); + ir_stack.byte_array(bytes.clone()); } }; } @@ -1110,22 +1101,12 @@ pub fn monomorphize( needs_variant = true; } } - Air::BinOp { - scope, - name, - count, - tipo, - } => { + Air::BinOp { scope, name, tipo } => { if tipo.is_generic() { let mut tipo = tipo.clone(); find_and_replace_generics(&mut tipo, &mono_types); - new_air[index] = Air::BinOp { - scope, - name, - tipo, - count, - }; + new_air[index] = Air::BinOp { scope, name, tipo }; needs_variant = true; } } @@ -1332,7 +1313,7 @@ pub fn monomorphize( } Air::Record { scope, - constr_index, + tag: constr_index, tipo, count, } => { @@ -1343,7 +1324,7 @@ pub fn monomorphize( new_air[index] = Air::Record { scope, tipo, - constr_index, + tag: constr_index, count, }; needs_variant = true; @@ -1719,7 +1700,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::Eq, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1729,7 +1709,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::NotEq, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1739,7 +1718,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::GtInt, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1749,7 +1727,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::GtEqInt, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1759,7 +1736,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::LtInt, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1769,7 +1745,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::LtEqInt, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1779,7 +1754,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::Or, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); @@ -1789,7 +1763,6 @@ pub fn handle_clause_guard( clause_guard_vec.push(Air::BinOp { scope: scope.clone(), name: BinOp::And, - count: 2, tipo: left.tipo(), }); handle_clause_guard(left, clause_guard_vec, scope.clone()); diff --git a/crates/aiken-lang/src/gen_uplc/stack.rs b/crates/aiken-lang/src/gen_uplc/stack.rs index b73975a1..02657f9d 100644 --- a/crates/aiken-lang/src/gen_uplc/stack.rs +++ b/crates/aiken-lang/src/gen_uplc/stack.rs @@ -1,4 +1,11 @@ -use crate::IdGenerator; +use std::sync::Arc; + +use uplc::builtins::DefaultFunction; + +use crate::{ + tipo::{Type, ValueConstructor}, + IdGenerator, +}; use super::air::Air; @@ -12,7 +19,7 @@ impl<'a> AirStack<'a> { pub fn new(id_gen: &'a mut IdGenerator) -> Self { AirStack { id_gen, - scope: vec![0], + scope: vec![id_gen.next()], air: vec![], } } @@ -25,44 +32,158 @@ impl<'a> AirStack<'a> { } } - pub fn merge(mut self, other: AirStack) -> Self { - self.air.extend(other.air.into_iter()); + pub fn in_new_scope(&mut self) -> Self { + let mut new_stack = AirStack::with_scope(&mut self.id_gen, self.scope.clone()); - self + new_stack.new_scope(); + + new_stack } - pub fn int(self, value: String) -> Self { - let mut air = self.air.clone(); + pub fn new_scope(&mut self) { + self.scope.push(self.id_gen.next()); + } - air.push(Air::Int { - scope: self.scope.clone(), - value, - }); + pub fn merge(&mut self, mut other: AirStack) { + self.air.append(&mut other.air); + } - AirStack { - id_gen: self.id_gen, - scope: self.scope, - air, + pub fn sequence(&mut self, stacks: Vec) { + for stack in stacks { + self.merge(stack) } } - pub fn string(mut self, value: String) -> Self { + pub fn integer(&mut self, value: String) { + self.air.push(Air::Int { + scope: self.scope.clone(), + value, + }); + } + + pub fn string(&mut self, value: String) { self.air.push(Air::String { scope: self.scope.clone(), value, }); - - self } - pub fn byte_array(mut self, bytes: Vec) -> Self { + pub fn byte_array(&mut self, bytes: Vec) { self.air.push(Air::ByteArray { scope: self.scope.clone(), bytes, }); - - self } - // pub fn sequence(mut self, expressions: AirEnv) -> Self {} + pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc, args: Vec) { + self.air.push(Air::Builtin { + scope: self.scope.clone(), + count: args.len(), + func, + tipo, + }); + + self.sequence(args); + } + + pub fn var( + &mut self, + constructor: ValueConstructor, + name: impl ToString, + variant_name: impl ToString, + ) { + self.air.push(Air::Var { + scope: self.scope.clone(), + constructor, + name: name.to_string(), + variant_name: variant_name.to_string(), + }); + } + + pub fn anonymous_function(&mut self, params: Vec, body: AirStack) { + self.air.push(Air::Fn { + scope: self.scope.clone(), + params, + }); + + self.merge(body); + } + + pub fn list(&mut self, tipo: Arc, elements: Vec, tail: Option) { + self.air.push(Air::List { + scope: self.scope.clone(), + count: elements.len(), + tipo, + tail: tail.is_some(), + }); + + self.sequence(elements); + + if let Some(tail) = tail { + self.merge(tail); + } + } + + pub fn record(&mut self, tipo: Arc, tag: usize, fields: Vec) { + self.air.push(Air::Record { + scope: self.scope.clone(), + tag, + tipo, + count: fields.len(), + }); + + self.sequence(fields); + } + + pub fn call(&mut self, tipo: Arc, fun: AirStack, args: Vec) { + self.air.push(Air::Call { + scope: self.scope.clone(), + count: args.len(), + tipo, + }); + + self.merge(fun); + + self.sequence(args); + } + + pub fn binop( + &mut self, + name: crate::ast::BinOp, + tipo: Arc, + left: AirStack, + right: AirStack, + ) { + self.air.push(Air::BinOp { + scope: self.scope.clone(), + name, + tipo, + }); + + self.merge(left); + self.merge(right); + } + + pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) { + self.air.push(Air::Let { + scope: self.scope.clone(), + name: name.to_string(), + }); + + self.merge(value); + } + + pub fn wrap_data(&mut self, tipo: Arc) { + self.air.push(Air::WrapData { + scope: self.scope.clone(), + tipo, + }) + } + + pub fn un_wrap_data(&mut self, tipo: Arc) { + self.air.push(Air::UnWrapData { + scope: self.scope.clone(), + tipo, + }) + } }