diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 40721be1..abf131b6 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -39,7 +39,11 @@ use builder::{ AssignmentProperties, ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey, }; -use self::{builder::replace_opaque_type, scope::Scope, stack::AirStack}; +use self::{ + builder::{replace_opaque_type, SpecificClause}, + scope::Scope, + stack::AirStack, +}; #[derive(Clone, Debug)] pub enum CodeGenFunction { @@ -571,7 +575,7 @@ impl<'a> CodeGenerator<'a> { self.build(&last_clause.then, &mut final_clause_stack); - *clause_properties.is_final_clause() = true; + clause_properties.final_clause = true; self.when_pattern( last_pattern, @@ -587,7 +591,7 @@ impl<'a> CodeGenerator<'a> { finally_stack.merge(final_pattern_stack); } - if *clause_properties.needs_constr_var() { + if clause_properties.needs_constr_var { let mut subject_stack = ir_stack.empty_with_scope(); self.build(subject, &mut subject_stack); @@ -813,7 +817,7 @@ impl<'a> CodeGenerator<'a> { let mut clause_then_stack = ir_stack.empty_with_scope(); // reset complex clause setting per clause back to default - *clause_properties.is_complex_clause() = false; + clause_properties.complex_clause = false; self.build(&clause.then, &mut clause_then_stack); @@ -821,7 +825,7 @@ impl<'a> CodeGenerator<'a> { let mut clause_guard_stack = ir_stack.empty_with_scope(); let mut clause_guard_condition = ir_stack.empty_with_scope(); - *clause_properties.is_complex_clause() = true; + clause_properties.complex_clause = true; let clause_guard_name = format!("__clause_guard_{}", self.id_gen.next()); @@ -856,8 +860,9 @@ impl<'a> CodeGenerator<'a> { ); match clause_properties { - ClauseProperties::ConstrClause { + ClauseProperties { original_subject_name, + specific_clause: SpecificClause::ConstrClause, .. } => { let subject_name = original_subject_name.clone(); @@ -873,7 +878,7 @@ impl<'a> CodeGenerator<'a> { ir_stack.clause( subject_type.clone(), subject_name, - *clause_properties.is_complex_clause(), + clause_properties.complex_clause, clause_pattern_stack, ); } else { @@ -886,7 +891,7 @@ impl<'a> CodeGenerator<'a> { ir_stack.clause( subject_type.clone(), subject_name, - *clause_properties.is_complex_clause(), + clause_properties.complex_clause, condition_stack, ); } @@ -894,15 +899,15 @@ impl<'a> CodeGenerator<'a> { ir_stack.clause( subject_type.clone(), subject_name, - *clause_properties.is_complex_clause(), + clause_properties.complex_clause, clause_pattern_stack, ); } } } - ClauseProperties::ListClause { + ClauseProperties { original_subject_name, - current_index, + specific_clause: SpecificClause::ListClause { current_index, .. }, .. } => { let original_subject_name = original_subject_name.clone(); @@ -958,7 +963,7 @@ impl<'a> CodeGenerator<'a> { subject_type.clone(), subject_name, next_tail, - *clause_properties.is_complex_clause(), + clause_properties.complex_clause, clause_pattern_stack, ); } @@ -966,12 +971,15 @@ impl<'a> CodeGenerator<'a> { ir_stack.wrap_clause(clause_pattern_stack); } } - ClauseProperties::TupleClause { + ClauseProperties { original_subject_name, - defined_tuple_indices, + specific_clause: + SpecificClause::TupleClause { + defined_tuple_indices, + }, .. } => { - let ClauseProperties::TupleClause { defined_tuple_indices: prev_defined_tuple_indices, .. } = prev_clause_properties + let ClauseProperties { specific_clause: SpecificClause::TupleClause { defined_tuple_indices: prev_defined_tuple_indices}, ..} = prev_clause_properties else { unreachable!() }; @@ -988,8 +996,7 @@ impl<'a> CodeGenerator<'a> { subject_name, indices_to_define, prev_defined_tuple_indices, - *clause_properties.is_complex_clause() - || (!*clause_properties.is_final_clause()), + clause_properties.complex_clause || (!clause_properties.final_clause), clause_pattern_stack, ); } @@ -1019,19 +1026,16 @@ impl<'a> CodeGenerator<'a> { var_stack.local_var( tipo.clone().into(), match clause_properties { - ClauseProperties::ConstrClause { + ClauseProperties { clause_var_name, needs_constr_var, + specific_clause: SpecificClause::ConstrClause, .. } => { *needs_constr_var = true; clause_var_name } - ClauseProperties::ListClause { - original_subject_name, - .. - } => original_subject_name, - ClauseProperties::TupleClause { + ClauseProperties { original_subject_name, .. } => original_subject_name, @@ -1048,19 +1052,16 @@ impl<'a> CodeGenerator<'a> { new_stack.local_var( tipo.clone().into(), match clause_properties { - ClauseProperties::ConstrClause { + ClauseProperties { clause_var_name, needs_constr_var, + specific_clause: SpecificClause::ConstrClause, .. } => { *needs_constr_var = true; clause_var_name } - ClauseProperties::ListClause { - original_subject_name, - .. - } => original_subject_name, - ClauseProperties::TupleClause { + ClauseProperties { original_subject_name, .. } => original_subject_name, @@ -1088,7 +1089,7 @@ impl<'a> CodeGenerator<'a> { builder::check_when_pattern_needs(tail, clause_properties); } - *clause_properties.needs_constr_var() = false; + clause_properties.needs_constr_var = false; let mut void_stack = pattern_stack.empty_with_scope(); @@ -1104,7 +1105,7 @@ impl<'a> CodeGenerator<'a> { .. } => { let mut temp_clause_properties = clause_properties.clone(); - *temp_clause_properties.needs_constr_var() = false; + temp_clause_properties.needs_constr_var = false; if tipo.is_bool() { pattern_stack.bool(constr_name == "True"); @@ -1126,20 +1127,18 @@ impl<'a> CodeGenerator<'a> { let mut new_stack = pattern_stack.empty_with_scope(); - new_stack.local_var( - tipo.clone().into(), - temp_clause_properties.clause_var_name(), - ); + new_stack + .local_var(tipo.clone().into(), temp_clause_properties.clause_var_name); // if only one constructor, no need to check - if data_type.constructors.len() > 1 || *clause_properties.is_final_clause() { + if data_type.constructors.len() > 1 || clause_properties.final_clause { // push constructor Index let mut tag_stack = pattern_stack.empty_with_scope(); tag_stack.integer(index.to_string()); pattern_stack.merge_child(tag_stack); } - if *temp_clause_properties.needs_constr_var() { + if temp_clause_properties.needs_constr_var { self.expose_elements( pattern, pattern_stack, @@ -1163,18 +1162,18 @@ impl<'a> CodeGenerator<'a> { pattern_stack.merge_child(value_stack); // unify clause properties - *clause_properties.is_complex_clause() = *clause_properties.is_complex_clause() - || *temp_clause_properties.is_complex_clause(); + clause_properties.complex_clause = + clause_properties.complex_clause || temp_clause_properties.complex_clause; - *clause_properties.needs_constr_var() = *clause_properties.needs_constr_var() - || *temp_clause_properties.needs_constr_var(); + clause_properties.needs_constr_var = + clause_properties.needs_constr_var || temp_clause_properties.needs_constr_var; } Pattern::Tuple { elems, .. } => { for elem in elems { builder::check_when_pattern_needs(elem, clause_properties); } - *clause_properties.needs_constr_var() = false; + clause_properties.needs_constr_var = false; let temp = pattern_stack.empty_with_scope(); @@ -1185,8 +1184,8 @@ impl<'a> CodeGenerator<'a> { } // final clause can not be complex - if *(clause_properties.is_final_clause()) { - *clause_properties.is_complex_clause() = false; + if clause_properties.final_clause { + clause_properties.complex_clause = false; } } @@ -1217,7 +1216,7 @@ impl<'a> CodeGenerator<'a> { element, &mut nested_pattern, items_type, - *clause_properties.is_final_clause(), + clause_properties.final_clause, ); names.push(name.unwrap_or_else(|| "_".to_string())) @@ -1244,7 +1243,7 @@ impl<'a> CodeGenerator<'a> { .map(|(index, name)| { if index == 0 { ( - clause_properties.original_subject_name().clone(), + clause_properties.original_subject_name.clone(), name.clone(), ) } else { @@ -1254,7 +1253,7 @@ impl<'a> CodeGenerator<'a> { .collect_vec(); let tail_var = if elements.len() == 1 || elements.is_empty() { - clause_properties.original_subject_name().clone() + clause_properties.original_subject_name.clone() } else { format!("__tail_{}", elements.len() - 2) }; @@ -1331,7 +1330,7 @@ impl<'a> CodeGenerator<'a> { } .into(), ), - *clause_properties.is_final_clause(), + clause_properties.final_clause, ); var_name.map_or( @@ -1374,7 +1373,7 @@ impl<'a> CodeGenerator<'a> { &item.value, &mut nested_pattern, type_map.get(&index).unwrap(), - *clause_properties.is_final_clause(), + clause_properties.final_clause, ); var_name.map_or(("_".to_string(), index), |var_name| (var_name, index)) @@ -1411,7 +1410,7 @@ impl<'a> CodeGenerator<'a> { element, &mut nested_pattern, &items_type[index], - *clause_properties.is_final_clause(), + clause_properties.final_clause, ); name.map(|name| (name, index)) @@ -1419,8 +1418,11 @@ impl<'a> CodeGenerator<'a> { .collect_vec(); let mut defined_indices = match clause_properties.clone() { - ClauseProperties::TupleClause { - defined_tuple_indices, + ClauseProperties { + specific_clause: + SpecificClause::TupleClause { + defined_tuple_indices, + }, .. } => defined_tuple_indices, _ => unreachable!(), @@ -1455,8 +1457,11 @@ impl<'a> CodeGenerator<'a> { } match clause_properties { - ClauseProperties::TupleClause { - defined_tuple_indices, + ClauseProperties { + specific_clause: + SpecificClause::TupleClause { + defined_tuple_indices, + }, .. } => { *defined_tuple_indices = defined_indices; @@ -1509,12 +1514,15 @@ impl<'a> CodeGenerator<'a> { format!("{}_{}", new_tail_name, index - 1) }; - let mut clause_properties = ClauseProperties::ListClause { + let mut clause_properties = ClauseProperties { clause_var_name: item_name.clone(), needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: item_name.clone(), - current_index: index as i64, + specific_clause: SpecificClause::ListClause { + current_index: index as i64, + defined_tails: vec![], + }, final_clause, }; @@ -1606,12 +1614,13 @@ impl<'a> CodeGenerator<'a> { let mut when_stack = pattern_stack.empty_with_scope(); - let mut clause_properties = ClauseProperties::ConstrClause { + let mut clause_properties = ClauseProperties { clause_var_name: constr_var_name.clone(), needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: constr_var_name.clone(), final_clause, + specific_clause: SpecificClause::ConstrClause, }; self.when_pattern( @@ -1652,12 +1661,14 @@ impl<'a> CodeGenerator<'a> { a @ Pattern::Tuple { .. } => { let item_name = format!("__tuple_item_id_{}", self.id_gen.next()); - let mut clause_properties = ClauseProperties::TupleClause { + let mut clause_properties = ClauseProperties { clause_var_name: item_name.clone(), needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: item_name.clone(), - defined_tuple_indices: IndexSet::new(), + specific_clause: SpecificClause::TupleClause { + defined_tuple_indices: IndexSet::new(), + }, final_clause, }; @@ -1672,8 +1683,12 @@ impl<'a> CodeGenerator<'a> { ); let defined_indices = match clause_properties.clone() { - ClauseProperties::TupleClause { - defined_tuple_indices, + ClauseProperties { + specific_clause: + SpecificClause::TupleClause { + defined_tuple_indices, + .. + }, .. } => defined_tuple_indices, _ => unreachable!(), @@ -1681,7 +1696,7 @@ impl<'a> CodeGenerator<'a> { pattern_stack.tuple_clause( pattern_type.clone().into(), - clause_properties.original_subject_name(), + clause_properties.original_subject_name, defined_indices, IndexSet::new(), false, diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 4fc90dab..c9256fd9 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -65,128 +65,60 @@ pub struct AssignmentProperties { } #[derive(Clone, Debug)] -pub enum ClauseProperties { - ConstrClause { - clause_var_name: String, - needs_constr_var: bool, - is_complex_clause: bool, - original_subject_name: String, - final_clause: bool, - }, + +pub struct ClauseProperties { + pub clause_var_name: String, + pub complex_clause: bool, + pub needs_constr_var: bool, + pub original_subject_name: String, + pub final_clause: bool, + pub specific_clause: SpecificClause, +} +#[derive(Clone, Debug)] +pub enum SpecificClause { + ConstrClause, ListClause { - clause_var_name: String, - needs_constr_var: bool, - is_complex_clause: bool, - original_subject_name: String, current_index: i64, - final_clause: bool, + defined_tails: Vec, }, TupleClause { - clause_var_name: String, - needs_constr_var: bool, - is_complex_clause: bool, - original_subject_name: String, defined_tuple_indices: IndexSet<(usize, String)>, - final_clause: bool, }, } impl ClauseProperties { pub fn init(t: &Arc, constr_var: String, subject_name: String) -> Self { if t.is_list() { - ClauseProperties::ListClause { + ClauseProperties { clause_var_name: constr_var, - needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: subject_name, - current_index: -1, final_clause: false, + needs_constr_var: false, + specific_clause: SpecificClause::ConstrClause, } } else if t.is_tuple() { - ClauseProperties::TupleClause { + ClauseProperties { clause_var_name: constr_var, - needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: subject_name, - defined_tuple_indices: IndexSet::new(), + needs_constr_var: false, final_clause: false, + specific_clause: SpecificClause::TupleClause { + defined_tuple_indices: IndexSet::new(), + }, } } else { - ClauseProperties::ConstrClause { + ClauseProperties { clause_var_name: constr_var, - needs_constr_var: false, - is_complex_clause: false, + complex_clause: false, original_subject_name: subject_name, + needs_constr_var: false, final_clause: false, + specific_clause: SpecificClause::ConstrClause, } } } - - pub fn is_complex_clause(&mut self) -> &mut bool { - match self { - ClauseProperties::ConstrClause { - is_complex_clause, .. - } - | ClauseProperties::ListClause { - is_complex_clause, .. - } - | ClauseProperties::TupleClause { - is_complex_clause, .. - } => is_complex_clause, - } - } - pub fn needs_constr_var(&mut self) -> &mut bool { - match self { - ClauseProperties::ConstrClause { - needs_constr_var, .. - } - | ClauseProperties::ListClause { - needs_constr_var, .. - } - | ClauseProperties::TupleClause { - needs_constr_var, .. - } => needs_constr_var, - } - } - - pub fn is_final_clause(&mut self) -> &mut bool { - match self { - ClauseProperties::ConstrClause { final_clause, .. } - | ClauseProperties::ListClause { final_clause, .. } - | ClauseProperties::TupleClause { final_clause, .. } => final_clause, - } - } - - pub fn clause_var_name(&mut self) -> &mut String { - match self { - ClauseProperties::ConstrClause { - clause_var_name, .. - } - | ClauseProperties::ListClause { - clause_var_name, .. - } - | ClauseProperties::TupleClause { - clause_var_name, .. - } => clause_var_name, - } - } - - pub fn original_subject_name(&mut self) -> &mut String { - match self { - ClauseProperties::ConstrClause { - original_subject_name, - .. - } - | ClauseProperties::ListClause { - original_subject_name, - .. - } - | ClauseProperties::TupleClause { - original_subject_name, - .. - } => original_subject_name, - } - } } pub fn convert_type_to_data(term: Term, field_type: &Arc) -> Term { @@ -706,12 +638,12 @@ pub fn check_when_pattern_needs( ) { match pattern { Pattern::Var { .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; } Pattern::List { elements, tail, .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; - *clause_properties.is_complex_clause() = true; + clause_properties.complex_clause = true; for element in elements { check_when_pattern_needs(element, clause_properties); @@ -721,33 +653,33 @@ pub fn check_when_pattern_needs( } } Pattern::Tuple { elems, .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; - *clause_properties.is_complex_clause() = true; + clause_properties.complex_clause = true; for element in elems { check_when_pattern_needs(element, clause_properties); } } Pattern::Int { .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; - *clause_properties.is_complex_clause() = true; + clause_properties.complex_clause = true; } Pattern::Constructor { arguments, .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; - *clause_properties.is_complex_clause() = true; + clause_properties.complex_clause = true; for argument in arguments { check_when_pattern_needs(&argument.value, clause_properties); } } Pattern::Discard { .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; } Pattern::Assign { pattern, .. } => { - *clause_properties.needs_constr_var() = true; + clause_properties.needs_constr_var = true; check_when_pattern_needs(pattern, clause_properties) } diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index aaf599ff..185ccea1 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -22,6 +22,7 @@ use crate::{ air::Air, builder::{ self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey, + SpecificClause, }, }, tipo::{ @@ -270,7 +271,7 @@ impl<'a> CodeGenerator<'a> { value_type: value.tipo(), kind: *kind, remove_unused: kind.is_let(), - full_check: false, + full_check: !tipo.is_data() && value.tipo().is_data() && kind.is_expect(), }, ) } @@ -516,7 +517,7 @@ impl<'a> CodeGenerator<'a> { } } Pattern::Var { name, .. } => { - if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() { + if props.full_check { let mut index_map = IndexMap::new(); // let tipo = builder::convert_opaque_type(); let assignment = AirTree::let_assignment(name, value); @@ -525,12 +526,8 @@ impl<'a> CodeGenerator<'a> { if tipo.is_primitive() { AirTree::let_assignment(name, AirTree::hoist_over(assignment, val)) } else { - let expect = self.expect_type( - &tipo, - val.clone(), - &mut index_map, - pattern.location(), - ); + let expect = + self.expect_type(tipo, val.clone(), &mut index_map, pattern.location()); let assign = AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect)); AirTree::let_assignment(name, AirTree::hoist_over(assign, val)) @@ -547,7 +544,8 @@ impl<'a> CodeGenerator<'a> { AirTree::UnhoistedSequence(vec![assign, inner_pattern]) } Pattern::Discard { name, .. } => { - if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() { + if props.full_check { + let name = &format!("__discard_expect_{}", name); let mut index_map = IndexMap::new(); // let tipo = builder::convert_opaque_type(); let assignment = AirTree::let_assignment(name, value); @@ -584,10 +582,7 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => name.to_string(), Pattern::Assign { name, .. } => name.to_string(), Pattern::Discard { name, .. } => { - if props.kind.is_expect() - && props.value_type.is_data() - && !tipo.is_data() - { + if props.full_check { format!("__discard_{}", name) } else { "_".to_string() @@ -613,7 +608,7 @@ impl<'a> CodeGenerator<'a> { value_type: list_elem_type.clone(), kind: props.kind, remove_unused: true, - full_check: false, + full_check: props.full_check, }, ), ) @@ -651,10 +646,10 @@ impl<'a> CodeGenerator<'a> { val, tipo, AssignmentProperties { - value_type: props.value_type.clone(), + value_type: tipo.clone(), kind: props.kind, remove_unused: true, - full_check: false, + full_check: props.full_check, }, ), )); @@ -694,9 +689,7 @@ impl<'a> CodeGenerator<'a> { let data_type = build::lookup_data_type_by_tipo(&self.data_types, tipo) .unwrap_or_else(|| panic!("Failed to find definition for {}", name)); - if data_type.constructors.len() > 1 - || (!tipo.is_data() && props.value_type.is_data()) - { + if data_type.constructors.len() > 1 || props.full_check { let (index, _) = data_type .constructors .iter() @@ -759,10 +752,7 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => name.to_string(), Pattern::Assign { name, .. } => name.to_string(), Pattern::Discard { name, .. } => { - if props.kind.is_expect() - && props.value_type.is_data() - && !tipo.is_data() - { + if props.full_check { format!("__discard_{}", name) } else { "_".to_string() @@ -797,7 +787,7 @@ impl<'a> CodeGenerator<'a> { value_type: props.value_type.clone(), kind: props.kind, remove_unused: true, - full_check: false, + full_check: props.full_check, }, ), ) @@ -843,10 +833,7 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => name.to_string(), Pattern::Assign { name, .. } => name.to_string(), Pattern::Discard { name, .. } => { - if props.kind.is_expect() - && props.value_type.is_data() - && !tipo.is_data() - { + if props.full_check { format!("__discard_{}", name) } else { "_".to_string() @@ -879,7 +866,7 @@ impl<'a> CodeGenerator<'a> { value_type: props.value_type.clone(), kind: props.kind, remove_unused: true, - full_check: false, + full_check: props.full_check, }, ), ) @@ -1034,13 +1021,13 @@ impl<'a> CodeGenerator<'a> { props: &mut ClauseProperties, ) -> AirTree { assert!(!clauses.is_empty()); - *props.is_complex_clause() = false; + props.complex_clause = false; if let Some((clause, rest_clauses)) = clauses.split_first() { todo!() } else { // handle final_clause - *props.is_final_clause() = true; + props.final_clause = true; assert!(final_clause.guard.is_none()); let clause_then = self.build(&final_clause.then); let (_, assignments) = self.clause_pattern(&final_clause.pattern, subject_tipo, props); @@ -1058,14 +1045,14 @@ impl<'a> CodeGenerator<'a> { ) -> (AirTree, AirTree) { match pattern { Pattern::Int { value, .. } => { - assert!(!*props.is_final_clause()); + assert!(!props.final_clause); (AirTree::int(value), AirTree::no_op()) } Pattern::Var { name, .. } => ( AirTree::void(), AirTree::let_assignment( name, - AirTree::local_var(props.clause_var_name(), subject_tipo.clone()), + AirTree::local_var(&props.clause_var_name, subject_tipo.clone()), ), ), Pattern::Assign { name, pattern, .. } => { @@ -1075,7 +1062,7 @@ impl<'a> CodeGenerator<'a> { let sequence = vec![ AirTree::let_assignment( name, - AirTree::local_var(props.clause_var_name(), subject_tipo.clone()), + AirTree::local_var(&props.clause_var_name, subject_tipo.clone()), ), inner_assignment, ]; @@ -1083,7 +1070,119 @@ impl<'a> CodeGenerator<'a> { (inner_condition, AirTree::UnhoistedSequence(sequence)) } Pattern::Discard { .. } => (AirTree::void(), AirTree::no_op()), - Pattern::List { .. } => todo!(), + Pattern::List { elements, tail, .. } => { + let ClauseProperties { + specific_clause: + SpecificClause::ListClause { + current_index: _, + defined_tails, + }, + clause_var_name: _, + complex_clause: _, + needs_constr_var: _, + original_subject_name: _, + final_clause: _, + } = props + else { unreachable!()}; + + let list_elem_types = subject_tipo.get_inner_types(); + + let list_elem_type = list_elem_types + .get(0) + .unwrap_or_else(|| unreachable!("No list element type?")); + + let elems = elements + .iter() + .enumerate() + .zip(defined_tails.clone()) + .map(|((index, elem), tail)| { + let elem_name = match elem { + Pattern::Var { name, .. } => name.to_string(), + Pattern::Assign { name, .. } => name.to_string(), + Pattern::Discard { .. } => "_".to_string(), + _ => format!( + "elem_{}_span_{}_{}", + index, + elem.location().start, + elem.location().end + ), + }; + + let mut elem_props = ClauseProperties::init( + list_elem_type, + elem_name.clone(), + elem_name.clone(), + ); + + let statement = + self.nested_clause_condition(elem, list_elem_type, &mut elem_props); + props.complex_clause = props.complex_clause || elem_props.complex_clause; + + (tail, elem_name, statement) + }) + .collect_vec(); + + let defined_tail_heads = elems + .iter() + .map(|(tail, head, _)| (tail.to_string(), head.to_string())) + .collect_vec(); + + let mut air_elems = elems + .into_iter() + .map(|(_, _, statement)| statement) + .collect_vec(); + + let mut list_tail = None; + + tail.iter() + .zip( + defined_tails + .clone() + .get(defined_tails.clone().len() - 1) + .iter(), + ) + .for_each(|(elem, tail)| { + let elem_name = match elem.as_ref() { + Pattern::Var { name, .. } => name.to_string(), + Pattern::Assign { name, .. } => name.to_string(), + Pattern::Discard { .. } => "_".to_string(), + _ => format!( + "tail_span_{}_{}", + elem.location().start, + elem.location().end + ), + }; + + let mut elem_props = ClauseProperties { + clause_var_name: elem_name.clone(), + complex_clause: false, + needs_constr_var: false, + original_subject_name: elem_name.clone(), + final_clause: props.final_clause, + specific_clause: props.specific_clause.clone(), + }; + + let statement = + self.nested_clause_condition(elem, subject_tipo, &mut elem_props); + props.complex_clause = props.complex_clause || elem_props.complex_clause; + + air_elems.push(statement); + list_tail = Some((tail.to_string(), elem_name)); + }); + + let list_assign = AirTree::list_expose( + defined_tail_heads, + list_tail, + subject_tipo.clone(), + AirTree::local_var(&props.original_subject_name, subject_tipo.clone()), + ); + + let mut sequence = vec![list_assign]; + + sequence.append(&mut air_elems); + + (AirTree::void(), AirTree::UnhoistedSequence(sequence)) + } Pattern::Constructor { .. } => todo!(), Pattern::Tuple { .. } => todo!(), } diff --git a/crates/aiken-lang/src/gen_uplc2/builder.rs b/crates/aiken-lang/src/gen_uplc2/builder.rs index 666d3e4f..22d3e832 100644 --- a/crates/aiken-lang/src/gen_uplc2/builder.rs +++ b/crates/aiken-lang/src/gen_uplc2/builder.rs @@ -1,10 +1,6 @@ use std::sync::Arc; -use crate::{ - ast::{Constant, Pattern, TypedClause}, - gen_uplc::builder::{AssignmentProperties, ClauseProperties}, - tipo::{PatternConstructor, Type}, -}; +use crate::{ast::Constant, tipo::Type}; use super::tree::AirTree; diff --git a/crates/aiken-lang/src/gen_uplc2/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs index 627f5201..2689540b 100644 --- a/crates/aiken-lang/src/gen_uplc2/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -1,5 +1,5 @@ use indexmap::IndexSet; -use std::{collections::VecDeque, sync::Arc}; +use std::sync::Arc; use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; use crate::{ @@ -12,54 +12,20 @@ use super::air::Air; #[derive(Debug, Clone, PartialEq)] pub enum AirTree { - Statement(AirStatement), + Statement { + statement: AirStatement, + hoisted_over: Option>, + }, Expression(AirExpression), UnhoistedSequence(Vec), } -pub struct AirIterator<'a> { - deque_pointer: VecDeque<&'a AirTree>, -} - -impl Iterator for AirIterator<'_> { - type Item = Air; - - fn next(&mut self) -> Option { - todo!() - } -} - -impl DoubleEndedIterator for AirIterator<'_> { - fn next_back(&mut self) -> Option { - todo!() - } -} - -pub struct AirTreeIterator<'a> { - deque_pointer: VecDeque<&'a AirTree>, -} - -impl<'a> Iterator for AirTreeIterator<'a> { - fn next(&mut self) -> Option { - self.deque_pointer.pop_front() - } - - type Item = &'a AirTree; -} - -impl DoubleEndedIterator for AirTreeIterator<'_> { - fn next_back(&mut self) -> Option { - self.deque_pointer.pop_back() - } -} - #[derive(Debug, Clone, PartialEq)] pub enum AirStatement { // Assignment Let { name: String, value: Box, - hoisted_over: Option>, }, DefineFunc { func_name: String, @@ -68,25 +34,21 @@ pub enum AirStatement { recursive: bool, variant_name: String, func_body: Box, - hoisted_over: Option>, }, // Assertions AssertConstr { constr_index: usize, constr: Box, - hoisted_over: Option>, }, AssertBool { is_true: bool, value: Box, - hoisted_over: Option>, }, // Field Access FieldsExpose { indices: Vec<(usize, String, Arc)>, check_last_item: bool, record: Box, - hoisted_over: Option>, }, // List Access ListAccessor { @@ -95,14 +57,12 @@ pub enum AirStatement { tail: bool, check_last_item: bool, list: Box, - hoisted_over: Option>, }, ListExpose { tipo: Arc, tail_head_names: Vec<(String, String)>, tail: Option<(String, String)>, list: Box, - hoisted_over: Option>, }, // Tuple Access TupleAccessor { @@ -110,12 +70,9 @@ pub enum AirStatement { tipo: Arc, check_last_item: bool, tuple: Box, - hoisted_over: Option>, }, // Misc. - NoOp { - hoisted_over: Option>, - }, + NoOp, } #[derive(Debug, Clone, PartialEq)] @@ -365,15 +322,17 @@ impl AirTree { recursive: bool, func_body: AirTree, ) -> AirTree { - AirTree::Statement(AirStatement::DefineFunc { - func_name: func_name.to_string(), - module_name: module_name.to_string(), - params, - recursive, - variant_name: variant_name.to_string(), - func_body: func_body.into(), + AirTree::Statement { + statement: AirStatement::DefineFunc { + func_name: func_name.to_string(), + module_name: module_name.to_string(), + params, + recursive, + variant_name: variant_name.to_string(), + func_body: func_body.into(), + }, hoisted_over: None, - }) + } } pub fn anon_func(params: Vec, func_body: AirTree) -> AirTree { AirTree::Expression(AirExpression::Fn { @@ -399,11 +358,13 @@ impl AirTree { }) } pub fn let_assignment(name: impl ToString, value: AirTree) -> AirTree { - AirTree::Statement(AirStatement::Let { - name: name.to_string(), - value: value.into(), + AirTree::Statement { + statement: AirStatement::Let { + name: name.to_string(), + value: value.into(), + }, hoisted_over: None, - }) + } } pub fn unwrap_data(value: AirTree, tipo: Arc) -> AirTree { AirTree::Expression(AirExpression::UnWrapData { @@ -418,18 +379,22 @@ impl AirTree { }) } pub fn assert_constr_index(constr_index: usize, constr: AirTree) -> AirTree { - AirTree::Statement(AirStatement::AssertConstr { - constr_index, - constr: constr.into(), + AirTree::Statement { + statement: AirStatement::AssertConstr { + constr_index, + constr: constr.into(), + }, hoisted_over: None, - }) + } } pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree { - AirTree::Statement(AirStatement::AssertBool { - is_true, - value: value.into(), + AirTree::Statement { + statement: AirStatement::AssertBool { + is_true, + value: value.into(), + }, hoisted_over: None, - }) + } } pub fn when(subject_name: impl ToString, tipo: Arc, clauses: AirTree) -> AirTree { AirTree::Expression(AirExpression::When { @@ -592,12 +557,14 @@ impl AirTree { check_last_item: bool, record: AirTree, ) -> AirTree { - AirTree::Statement(AirStatement::FieldsExpose { - indices, - check_last_item, - record: record.into(), + AirTree::Statement { + statement: AirStatement::FieldsExpose { + indices, + check_last_item, + record: record.into(), + }, hoisted_over: None, - }) + } } pub fn list_access( names: Vec, @@ -606,14 +573,16 @@ impl AirTree { check_last_item: bool, list: AirTree, ) -> AirTree { - AirTree::Statement(AirStatement::ListAccessor { - tipo, - names, - tail, - check_last_item, - list: list.into(), + AirTree::Statement { + statement: AirStatement::ListAccessor { + tipo, + names, + tail, + check_last_item, + list: list.into(), + }, hoisted_over: None, - }) + } } pub fn list_expose( tail_head_names: Vec<(String, String)>, @@ -621,13 +590,15 @@ impl AirTree { tipo: Arc, list: AirTree, ) -> AirTree { - AirTree::Statement(AirStatement::ListExpose { - tipo, - tail_head_names, - tail, - list: list.into(), + AirTree::Statement { + statement: AirStatement::ListExpose { + tipo, + tail_head_names, + tail, + list: list.into(), + }, hoisted_over: None, - }) + } } pub fn tuple_access( names: Vec, @@ -635,13 +606,15 @@ impl AirTree { check_last_item: bool, tuple: AirTree, ) -> AirTree { - AirTree::Statement(AirStatement::TupleAccessor { - names, - tipo, - check_last_item, - tuple: tuple.into(), + AirTree::Statement { + statement: AirStatement::TupleAccessor { + names, + tipo, + check_last_item, + tuple: tuple.into(), + }, hoisted_over: None, - }) + } } pub fn tuple_index(tuple_index: usize, tipo: Arc, tuple: AirTree) -> AirTree { AirTree::Expression(AirExpression::TupleIndex { @@ -661,7 +634,10 @@ impl AirTree { }) } pub fn no_op() -> AirTree { - AirTree::Statement(AirStatement::NoOp { hoisted_over: None }) + AirTree::Statement { + statement: AirStatement::NoOp, + hoisted_over: None, + } } pub fn fields_empty(constr: AirTree) -> AirTree { AirTree::Expression(AirExpression::FieldsEmpty { @@ -673,21 +649,12 @@ impl AirTree { } pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree { match &mut assignment { - AirTree::Statement(st) => match st { - AirStatement::Let { hoisted_over, .. } - | AirStatement::AssertConstr { hoisted_over, .. } - | AirStatement::AssertBool { hoisted_over, .. } - | AirStatement::FieldsExpose { hoisted_over, .. } - | AirStatement::ListAccessor { hoisted_over, .. } - | AirStatement::NoOp { hoisted_over } - | AirStatement::ListExpose { hoisted_over, .. } - | AirStatement::TupleAccessor { hoisted_over, .. } - | AirStatement::DefineFunc { hoisted_over, .. } => { - assert!(hoisted_over.is_none()); - *hoisted_over = Some(next_exp.into()); - assignment - } - }, + AirTree::Statement { hoisted_over, .. } => { + assert!(hoisted_over.is_none()); + *hoisted_over = Some(next_exp.into()); + assignment + } + AirTree::Expression(_) => { unreachable!("Trying to hoist an expression onto an expression.") } @@ -731,7 +698,7 @@ impl AirTree { "__list_to_check", void(), AirTree::void(), - next_call, + AirTree::hoist_over(assign, next_call), None, false, ); @@ -744,183 +711,59 @@ impl AirTree { true, list_clause, ) - - // 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(), - // }); } - pub fn iter(&self) -> AirTreeIterator { - let mut new_vec = vec![]; - self.create_iter(&mut new_vec); - AirTreeIterator { - deque_pointer: new_vec.into(), - } - } - - pub fn air_iter(&self) -> AirIterator { - let mut new_vec = vec![]; - self.create_iter(&mut new_vec); - AirIterator { - deque_pointer: new_vec.into(), - } - } - - fn create_iter<'a>(&'a self, pointer_vec: &mut Vec<&'a AirTree>) { + fn to_vec(&self, air_vec: &mut Vec) { match self { - AirTree::Statement(st) => match st { - AirStatement::Let { - value, - hoisted_over: Some(exp), - .. - } => { - pointer_vec.push(self); - value.create_iter(pointer_vec); - exp.create_iter(pointer_vec); - } - AirStatement::DefineFunc { .. } => todo!(), - AirStatement::AssertConstr { - constr, - hoisted_over: Some(exp), - .. - } => { - pointer_vec.push(self); - constr.create_iter(pointer_vec); - exp.create_iter(pointer_vec); - } - AirStatement::AssertBool { .. } => todo!(), - AirStatement::FieldsExpose { .. } => todo!(), - AirStatement::ListAccessor { .. } => todo!(), - AirStatement::ListExpose { .. } => todo!(), - AirStatement::TupleAccessor { .. } => todo!(), - AirStatement::NoOp { .. } => todo!(), - _ => unreachable!("FOUND UNHOISTED STATEMENT"), - }, + AirTree::Statement { + statement, + hoisted_over: Some(exp), + } => { + match statement { + AirStatement::Let { value, name } => { + air_vec.push(Air::Let { name: name.clone() }); + value.to_vec(air_vec); + } + AirStatement::DefineFunc { + func_name, + module_name, + params, + recursive, + variant_name, + func_body, + } => { + air_vec.push(Air::DefineFunc { + func_name: func_name.clone(), + module_name: module_name.clone(), + params: params.clone(), + recursive: *recursive, + variant_name: variant_name.clone(), + }); + func_body.to_vec(air_vec); + } + AirStatement::AssertConstr { + constr, + constr_index, + } => { + air_vec.push(Air::AssertConstr { + constr_index: *constr_index, + }); + constr.to_vec(air_vec); + } + AirStatement::AssertBool { .. } => todo!(), + AirStatement::FieldsExpose { .. } => todo!(), + AirStatement::ListAccessor { .. } => todo!(), + AirStatement::ListExpose { .. } => todo!(), + AirStatement::TupleAccessor { .. } => todo!(), + AirStatement::NoOp { .. } => todo!(), + }; + exp.to_vec(air_vec); + } AirTree::Expression(_) => todo!(), AirTree::UnhoistedSequence(_) => { - unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES") - } - } - } - - pub fn convert_to_air(&self) -> Air { - match self { - AirTree::Statement(st) => match st { - AirStatement::Let { - name, - value, - hoisted_over: Some(exp), - } => Air::Let { name: name.clone() }, - AirStatement::DefineFunc { .. } => todo!(), - AirStatement::AssertConstr { - constr_index, - constr, - hoisted_over: Some(exp), - } => Air::AssertConstr { - constr_index: *constr_index, - }, - AirStatement::AssertBool { - is_true, - value, - hoisted_over: Some(exp), - } => Air::AssertBool { is_true: *is_true }, - AirStatement::FieldsExpose { - indices, - check_last_item, - record, - hoisted_over: Some(exp), - } => Air::FieldsExpose { - indices: indices.clone(), - check_last_item: *check_last_item, - }, - AirStatement::ListAccessor { - tipo, - names, - tail, - check_last_item, - list, - hoisted_over: Some(exp), - } => Air::ListAccessor { - tipo: tipo.clone(), - names: names.clone(), - tail: *tail, - check_last_item: *check_last_item, - }, - AirStatement::ListExpose { - tipo, - tail_head_names, - tail, - list, - hoisted_over: Some(exp), - } => Air::ListExpose { - tipo: tipo.clone(), - tail_head_names: tail_head_names.clone(), - tail: tail.clone(), - }, - AirStatement::TupleAccessor { - names, - tipo, - check_last_item, - tuple, - hoisted_over: Some(exp), - } => Air::TupleAccessor { - names: names.clone(), - tipo: tipo.clone(), - check_last_item: *check_last_item, - }, - AirStatement::NoOp { - hoisted_over: Some(exp), - } => Air::NoOp, - _ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"), - }, - AirTree::Expression(exp) => match exp { - AirExpression::Int { value } => Air::Int { - value: value.clone(), - }, - AirExpression::String { value } => Air::String { - value: value.clone(), - }, - AirExpression::ByteArray { bytes } => Air::ByteArray { - bytes: bytes.clone(), - }, - AirExpression::Bool { value } => Air::Bool { value: *value }, - AirExpression::List { .. } => todo!(), - AirExpression::Tuple { .. } => todo!(), - AirExpression::Void => todo!(), - AirExpression::Var { .. } => todo!(), - AirExpression::Call { .. } => todo!(), - AirExpression::Fn { .. } => todo!(), - AirExpression::Builtin { .. } => todo!(), - AirExpression::BinOp { .. } => todo!(), - AirExpression::UnOp { .. } => todo!(), - AirExpression::UnWrapData { .. } => todo!(), - AirExpression::WrapData { .. } => todo!(), - AirExpression::When { .. } => todo!(), - AirExpression::Clause { .. } => todo!(), - AirExpression::ListClause { .. } => todo!(), - AirExpression::WrapClause { .. } => todo!(), - AirExpression::TupleClause { .. } => todo!(), - AirExpression::ClauseGuard { .. } => todo!(), - AirExpression::ListClauseGuard { .. } => todo!(), - AirExpression::Finally { .. } => todo!(), - AirExpression::If { .. } => todo!(), - AirExpression::Constr { .. } => todo!(), - AirExpression::RecordUpdate { .. } => todo!(), - AirExpression::RecordAccess { .. } => todo!(), - AirExpression::TupleIndex { .. } => todo!(), - AirExpression::ErrorTerm { .. } => todo!(), - AirExpression::Trace { .. } => todo!(), - AirExpression::FieldsEmpty { .. } => todo!(), - AirExpression::ListEmpty { .. } => todo!(), - }, - AirTree::UnhoistedSequence(_) => { - unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES") + unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES") } + _ => unreachable!("FOUND UNHOISTED STATEMENT"), } } }