feat(gen_uplc): introduce scope new type
* new module scope which holds some ancestor logic * rework some things to truly hide scope increments Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
		
							parent
							
								
									ca0d896b8d
								
							
						
					
					
						commit
						33a3c5dc13
					
				|  | @ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet}; | ||||||
| use itertools::Itertools; | use itertools::Itertools; | ||||||
| use uplc::{ | use uplc::{ | ||||||
|     ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, |     ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, | ||||||
|     builder::{ASSERT_ON_LIST, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER}, |     builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST}, | ||||||
|     builtins::DefaultFunction, |     builtins::DefaultFunction, | ||||||
|     machine::cost_model::ExBudget, |     machine::cost_model::ExBudget, | ||||||
|     optimize::aiken_optimize_and_intern, |     optimize::aiken_optimize_and_intern, | ||||||
|  | @ -27,6 +27,7 @@ use crate::{ | ||||||
| 
 | 
 | ||||||
| pub mod air; | pub mod air; | ||||||
| pub mod builder; | pub mod builder; | ||||||
|  | pub mod scope; | ||||||
| pub mod stack; | pub mod stack; | ||||||
| 
 | 
 | ||||||
| use air::Air; | use air::Air; | ||||||
|  | @ -185,14 +186,15 @@ impl<'a> CodeGenerator<'a> { | ||||||
|             TypedExpr::String { value, .. } => ir_stack.string(value.to_string()), |             TypedExpr::String { value, .. } => ir_stack.string(value.to_string()), | ||||||
|             TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()), |             TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()), | ||||||
|             TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => { |             TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => { | ||||||
|                 let stacks = Vec::new(); |                 let mut stacks = Vec::new(); | ||||||
| 
 | 
 | ||||||
|                 for (index, expr) in expressions.iter().enumerate() { |                 for (index, expr) in expressions.iter().enumerate() { | ||||||
|                     if index == 0 { |                     if index == 0 { | ||||||
|                         self.build_ir(expr, ir_stack); |                         self.build_ir(expr, ir_stack); | ||||||
|                     } else { |                     } else { | ||||||
|                         let mut stack = ir_stack.in_new_scope(); |                         let mut stack = ir_stack.empty_with_scope(); | ||||||
|                         self.build_ir(expr, &mut stack); |                         self.build_ir(expr, &mut stack); | ||||||
|  |                         stacks.push(stack); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -215,7 +217,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             TypedExpr::Fn { args, body, .. } => { |             TypedExpr::Fn { args, body, .. } => { | ||||||
|                 let mut body_stack = ir_stack.in_new_scope(); |                 let mut body_stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                 self.build_ir(body, &mut body_stack); |                 self.build_ir(body, &mut body_stack); | ||||||
| 
 | 
 | ||||||
|  | @ -234,7 +236,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|             } => { |             } => { | ||||||
|                 let stacks = Vec::new(); |                 let stacks = Vec::new(); | ||||||
|                 for element in elements { |                 for element in elements { | ||||||
|                     let mut stack = ir_stack.in_new_scope(); |                     let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                     self.build_ir(element, &mut stack); |                     self.build_ir(element, &mut stack); | ||||||
| 
 | 
 | ||||||
|  | @ -242,7 +244,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let tail = tail.as_ref().map(|tail| { |                 let tail = tail.as_ref().map(|tail| { | ||||||
|                     let mut tail_stack = ir_stack.in_new_scope(); |                     let mut tail_stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                     self.build_ir(tail, &mut tail_stack); |                     self.build_ir(tail, &mut tail_stack); | ||||||
| 
 | 
 | ||||||
|  | @ -276,7 +278,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                                 let stacks = Vec::new(); |                                 let stacks = Vec::new(); | ||||||
| 
 | 
 | ||||||
|                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { |                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { | ||||||
|                                     let mut stack = ir_stack.in_new_scope(); |                                     let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                                     if func_type.is_data() && !arg.value.tipo().is_data() { |                                     if func_type.is_data() && !arg.value.tipo().is_data() { | ||||||
|                                         stack.wrap_data(arg.value.tipo()); |                                         stack.wrap_data(arg.value.tipo()); | ||||||
|  | @ -301,7 +303,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                             let stacks = Vec::new(); |                             let stacks = Vec::new(); | ||||||
| 
 | 
 | ||||||
|                             for (arg, func_type) in args.iter().zip(fun_arg_types) { |                             for (arg, func_type) in args.iter().zip(fun_arg_types) { | ||||||
|                                 let mut stack = ir_stack.in_new_scope(); |                                 let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                                 if func_type.is_data() && !arg.value.tipo().is_data() { |                                 if func_type.is_data() && !arg.value.tipo().is_data() { | ||||||
|                                     stack.wrap_data(arg.value.tipo()); |                                     stack.wrap_data(arg.value.tipo()); | ||||||
|  | @ -341,7 +343,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                                 let mut stacks = Vec::new(); |                                 let mut stacks = Vec::new(); | ||||||
| 
 | 
 | ||||||
|                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { |                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { | ||||||
|                                     let mut stack = ir_stack.in_new_scope(); |                                     let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                                     if func_type.is_data() && !arg.value.tipo().is_data() { |                                     if func_type.is_data() && !arg.value.tipo().is_data() { | ||||||
|                                         stack.wrap_data(arg.value.tipo()); |                                         stack.wrap_data(arg.value.tipo()); | ||||||
|  | @ -366,7 +368,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
| 
 | 
 | ||||||
|                                 let mut stacks = Vec::new(); |                                 let mut stacks = Vec::new(); | ||||||
|                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { |                                 for (arg, func_type) in args.iter().zip(fun_arg_types) { | ||||||
|                                     let mut stack = ir_stack.in_new_scope(); |                                     let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                                     if func_type.is_data() && !arg.value.tipo().is_data() { |                                     if func_type.is_data() && !arg.value.tipo().is_data() { | ||||||
|                                         stack.wrap_data(arg.value.tipo()); |                                         stack.wrap_data(arg.value.tipo()); | ||||||
|  | @ -385,7 +387,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     _ => {} |                     _ => {} | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let mut fun_stack = ir_stack.in_new_scope(); |                 let mut fun_stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                 self.build_ir(fun, &mut fun_stack); |                 self.build_ir(fun, &mut fun_stack); | ||||||
| 
 | 
 | ||||||
|  | @ -393,7 +395,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
| 
 | 
 | ||||||
|                 let mut stacks = Vec::new(); |                 let mut stacks = Vec::new(); | ||||||
|                 for (arg, func_type) in args.iter().zip(fun_arg_types) { |                 for (arg, func_type) in args.iter().zip(fun_arg_types) { | ||||||
|                     let mut stack = ir_stack.in_new_scope(); |                     let mut stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                     if func_type.is_data() && !arg.value.tipo().is_data() { |                     if func_type.is_data() && !arg.value.tipo().is_data() { | ||||||
|                         stack.wrap_data(arg.value.tipo()); |                         stack.wrap_data(arg.value.tipo()); | ||||||
|  | @ -407,8 +409,8 @@ impl<'a> CodeGenerator<'a> { | ||||||
|             TypedExpr::BinOp { |             TypedExpr::BinOp { | ||||||
|                 name, left, right, .. |                 name, left, right, .. | ||||||
|             } => { |             } => { | ||||||
|                 let mut left_stack = ir_stack.in_new_scope(); |                 let mut left_stack = ir_stack.empty_with_scope(); | ||||||
|                 let mut right_stack = ir_stack.in_new_scope(); |                 let mut right_stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                 self.build_ir(left, &mut left_stack); |                 self.build_ir(left, &mut left_stack); | ||||||
|                 self.build_ir(right, &mut right_stack); |                 self.build_ir(right, &mut right_stack); | ||||||
|  | @ -422,8 +424,8 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                 tipo, |                 tipo, | ||||||
|                 .. |                 .. | ||||||
|             } => { |             } => { | ||||||
|                 let mut value_stack = ir_stack.in_new_scope(); |                 let mut value_stack = ir_stack.empty_with_scope(); | ||||||
|                 let mut pattern_stack = ir_stack.in_new_scope(); |                 let mut pattern_stack = ir_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                 let mut replaced_type = tipo.clone(); |                 let mut replaced_type = tipo.clone(); | ||||||
|                 builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); |                 builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); | ||||||
|  | @ -1756,17 +1758,17 @@ impl<'a> CodeGenerator<'a> { | ||||||
|             && !tipo.is_data() |             && !tipo.is_data() | ||||||
|             && !pattern.is_discard() |             && !pattern.is_discard() | ||||||
|         { |         { | ||||||
|             let mut wrap_stack = pattern_stack.in_new_scope(); |             let mut wrap_stack = pattern_stack.empty_with_scope(); | ||||||
|             wrap_stack.un_wrap_data(tipo.clone().into()); |             wrap_stack.un_wrap_data(tipo.clone().into()); | ||||||
|             wrap_stack.merge(value_stack); |             wrap_stack.merge_child(value_stack); | ||||||
|             wrap_stack |             wrap_stack | ||||||
|         } else if !assignment_properties.value_type.is_data() |         } else if !assignment_properties.value_type.is_data() | ||||||
|             && tipo.is_data() |             && tipo.is_data() | ||||||
|             && !pattern.is_discard() |             && !pattern.is_discard() | ||||||
|         { |         { | ||||||
|             let mut wrap_stack = pattern_stack.in_new_scope(); |             let mut wrap_stack = pattern_stack.empty_with_scope(); | ||||||
|             wrap_stack.wrap_data(assignment_properties.value_type.clone()); |             wrap_stack.wrap_data(assignment_properties.value_type.clone()); | ||||||
|             wrap_stack.merge(value_stack); |             wrap_stack.merge_child(value_stack); | ||||||
|             wrap_stack |             wrap_stack | ||||||
|         } else { |         } else { | ||||||
|             value_stack |             value_stack | ||||||
|  | @ -1775,24 +1777,24 @@ impl<'a> CodeGenerator<'a> { | ||||||
|         match pattern { |         match pattern { | ||||||
|             Pattern::Int { .. } => todo!(), |             Pattern::Int { .. } => todo!(), | ||||||
|             Pattern::Var { name, .. } => { |             Pattern::Var { name, .. } => { | ||||||
|                 let assert_value_stack = value_stack.in_new_scope(); |                 let expect_value_stack = value_stack.empty_with_scope(); | ||||||
|                 pattern_stack.let_assignment(name, value_stack); |                 pattern_stack.let_assignment(name, value_stack); | ||||||
| 
 | 
 | ||||||
|                 if matches!(assignment_properties.kind, AssignmentKind::Expect) |                 if matches!(assignment_properties.kind, AssignmentKind::Expect) | ||||||
|                     && assignment_properties.value_type.is_data() |                     && assignment_properties.value_type.is_data() | ||||||
|                     && !tipo.is_data() |                     && !tipo.is_data() | ||||||
|                 { |                 { | ||||||
|                     let mut assert_stack = pattern_stack.in_new_scope(); |                     let mut expect_stack = pattern_stack.empty_with_scope(); | ||||||
| 
 | 
 | ||||||
|                     self.recursive_assert_pattern( |                     self.expect_pattern( | ||||||
|                         pattern, |                         pattern, | ||||||
|                         &mut assert_stack, |                         &mut expect_stack, | ||||||
|                         assert_value_stack, |                         expect_value_stack, | ||||||
|                         tipo, |                         tipo, | ||||||
|                         assignment_properties, |                         assignment_properties, | ||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     pattern_stack.merge(assert_stack); |                     pattern_stack.merge(expect_stack); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             Pattern::Assign { .. } => todo!("Assign not yet implemented"), |             Pattern::Assign { .. } => todo!("Assign not yet implemented"), | ||||||
|  | @ -1804,7 +1806,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     && assignment_properties.value_type.is_data() |                     && assignment_properties.value_type.is_data() | ||||||
|                     && !tipo.is_data() |                     && !tipo.is_data() | ||||||
|                 { |                 { | ||||||
|                     self.recursive_assert_pattern( |                     self.expect_pattern( | ||||||
|                         list, |                         list, | ||||||
|                         pattern_vec, |                         pattern_vec, | ||||||
|                         value_vec, |                         value_vec, | ||||||
|  | @ -1828,7 +1830,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     && assignment_properties.value_type.is_data() |                     && assignment_properties.value_type.is_data() | ||||||
|                     && !tipo.is_data() |                     && !tipo.is_data() | ||||||
|                 { |                 { | ||||||
|                     self.recursive_assert_pattern( |                     self.expect_pattern( | ||||||
|                         constr, |                         constr, | ||||||
|                         pattern_vec, |                         pattern_vec, | ||||||
|                         value_vec, |                         value_vec, | ||||||
|  | @ -1852,7 +1854,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     && assignment_properties.value_type.is_data() |                     && assignment_properties.value_type.is_data() | ||||||
|                     && !tipo.is_data() |                     && !tipo.is_data() | ||||||
|                 { |                 { | ||||||
|                     self.recursive_assert_pattern( |                     self.expect_pattern( | ||||||
|                         tuple, |                         tuple, | ||||||
|                         pattern_vec, |                         pattern_vec, | ||||||
|                         value_vec, |                         value_vec, | ||||||
|  | @ -2165,10 +2167,10 @@ impl<'a> CodeGenerator<'a> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn recursive_assert_pattern( |     pub fn expect_pattern( | ||||||
|         &mut self, |         &mut self, | ||||||
|         pattern: &Pattern<PatternConstructor, Arc<Type>>, |         pattern: &Pattern<PatternConstructor, Arc<Type>>, | ||||||
|         assert_stack: &mut AirStack, |         expect_stack: &mut AirStack, | ||||||
|         value_stack: AirStack, |         value_stack: AirStack, | ||||||
|         tipo: &Type, |         tipo: &Type, | ||||||
|         assignment_properties: AssignmentProperties, |         assignment_properties: AssignmentProperties, | ||||||
|  | @ -2176,51 +2178,52 @@ impl<'a> CodeGenerator<'a> { | ||||||
|         match pattern { |         match pattern { | ||||||
|             Pattern::Int { .. } => unreachable!(), |             Pattern::Int { .. } => unreachable!(), | ||||||
|             Pattern::Var { name, .. } => { |             Pattern::Var { name, .. } => { | ||||||
|                 assert_stack.merge(value_stack); |                 expect_stack.merge(value_stack); | ||||||
| 
 | 
 | ||||||
|                 self.recursive_assert_tipo(tipo, assert_stack, name); |                 self.expect_type(tipo, expect_stack, name); | ||||||
|             } |             } | ||||||
|             Pattern::Assign { .. } => todo!(), |             Pattern::Assign { .. } => todo!(), | ||||||
|             Pattern::Discard { .. } => unreachable!(), |             Pattern::Discard { .. } => unreachable!(), | ||||||
|             Pattern::List { elements, tail, .. } => { |             Pattern::List { elements, tail, .. } => { | ||||||
|                 let mut assert_list_vec = vec![]; |  | ||||||
|                 let inner_list_type = &tipo.get_inner_types()[0]; |                 let inner_list_type = &tipo.get_inner_types()[0]; | ||||||
|                 let mut names = vec![]; |                 let mut names = vec![]; | ||||||
|  | 
 | ||||||
|  |                 let mut expect_list_stacks = vec![]; | ||||||
|  | 
 | ||||||
|                 for element in elements { |                 for element in elements { | ||||||
|                     match element { |                     match element { | ||||||
|                         Pattern::Var { name, .. } => { |                         Pattern::Var { name, .. } => { | ||||||
|                             names.push(name.clone()); |                             names.push(name.clone()); | ||||||
|                         } |                         } | ||||||
|                         Pattern::Assign { .. } => todo!(), |                         Pattern::Assign { .. } => todo!(), | ||||||
|                         l @ (Pattern::List { .. } |                         element_pattern @ (Pattern::List { .. } | ||||||
|                         | Pattern::Constructor { .. } |                         | Pattern::Constructor { .. } | ||||||
|                         | Pattern::Tuple { .. }) => { |                         | Pattern::Tuple { .. }) => { | ||||||
|                             let name = format!("list_item_id_{}", self.id_gen.next()); |                             let name = format!("list_item_id_{}", self.id_gen.next()); | ||||||
|  | 
 | ||||||
|                             names.push(name.clone()); |                             names.push(name.clone()); | ||||||
| 
 | 
 | ||||||
|                             self.recursive_assert_pattern( |                             let mut element_stack = expect_stack.empty_with_scope(); | ||||||
|                                 l, |                             let mut value_stack = element_stack.empty_with_scope(); | ||||||
|                                 &mut assert_list_vec, | 
 | ||||||
|                                 &mut vec![Air::Var { |                             value_stack.local_var(tipo.clone().into(), name); | ||||||
|                                     scope: scope.clone(), | 
 | ||||||
|                                     constructor: ValueConstructor::public( |                             self.expect_pattern( | ||||||
|                                         tipo.clone().into(), |                                 element_pattern, | ||||||
|                                         ValueConstructorVariant::LocalVariable { |                                 &mut element_stack, | ||||||
|                                             location: Span::empty(), |                                 value_stack, | ||||||
|                                         }, |  | ||||||
|                                     ), |  | ||||||
|                                     name, |  | ||||||
|                                     variant_name: String::new(), |  | ||||||
|                                 }], |  | ||||||
|                                 inner_list_type, |                                 inner_list_type, | ||||||
|                                 assignment_properties.clone(), |                                 assignment_properties.clone(), | ||||||
|                                 scope.clone(), |  | ||||||
|                             ); |                             ); | ||||||
|  | 
 | ||||||
|  |                             expect_list_stacks.push(element_stack); | ||||||
|                         } |                         } | ||||||
|                         _ => {} |                         _ => {} | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 let mut tail_stack = expect_stack.empty_with_scope(); | ||||||
|  | 
 | ||||||
|                 let name = if let Some(tail) = tail { |                 let name = if let Some(tail) = tail { | ||||||
|                     match &**tail { |                     match &**tail { | ||||||
|                         Pattern::Var { name, .. } => name.clone(), |                         Pattern::Var { name, .. } => name.clone(), | ||||||
|  | @ -2230,21 +2233,13 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     format!("__tail_{}", self.id_gen.next()) |                     format!("__tail_{}", self.id_gen.next()) | ||||||
|                 }; |                 }; | ||||||
| 
 | 
 | ||||||
|                 self.recursive_assert_tipo(tipo, &mut assert_list_vec, &name, scope.clone()); |                 self.expect_type(tipo, &mut tail_stack, &name); | ||||||
| 
 | 
 | ||||||
|                 names.push(name); |                 names.push(name); | ||||||
| 
 | 
 | ||||||
|                 pattern_vec.push(Air::ListAccessor { |                 expect_stack.list_accessor(tipo.clone().into(), names, true, false, value_stack); | ||||||
|                     scope, |  | ||||||
|                     tipo: tipo.clone().into(), |  | ||||||
|                     names, |  | ||||||
|                     tail: true, |  | ||||||
|                     check_last_item: false, |  | ||||||
|                 }); |  | ||||||
| 
 | 
 | ||||||
|                 pattern_vec.append(value_vec); |                 expect_stack.merge_children(expect_list_stacks); | ||||||
| 
 |  | ||||||
|                 pattern_vec.append(&mut assert_list_vec); |  | ||||||
|             } |             } | ||||||
|             Pattern::Constructor { |             Pattern::Constructor { | ||||||
|                 arguments, |                 arguments, | ||||||
|  | @ -2306,17 +2301,19 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                         current_index += 1; |                         current_index += 1; | ||||||
|                     } else { |                     } else { | ||||||
|                         let id_next = self.id_gen.next(); |                         let id_next = self.id_gen.next(); | ||||||
|  | 
 | ||||||
|                         final_args.push((format!("__field_{index}_{id_next}"), index)); |                         final_args.push((format!("__field_{index}_{id_next}"), index)); | ||||||
|                         self.recursive_assert_tipo( | 
 | ||||||
|  |                         self.expect_type( | ||||||
|                             type_map.get(&index).unwrap(), |                             type_map.get(&index).unwrap(), | ||||||
|                             &mut nested_pattern, |                             &mut nested_pattern, | ||||||
|                             &format!("__field_{index}_{id_next}"), |                             &format!("__field_{index}_{id_next}"), | ||||||
|                             scope.clone(), |  | ||||||
|                         ) |                         ) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let constr_var = format!("__constr_{}", self.id_gen.next()); |                 let constr_var = format!("__constr_{}", self.id_gen.next()); | ||||||
|  | 
 | ||||||
|                 pattern_vec.push(Air::Let { |                 pattern_vec.push(Air::Let { | ||||||
|                     scope: scope.clone(), |                     scope: scope.clone(), | ||||||
|                     name: constr_var.clone(), |                     name: constr_var.clone(), | ||||||
|  | @ -2411,11 +2408,10 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                     } else { |                     } else { | ||||||
|                         let id_next = self.id_gen.next(); |                         let id_next = self.id_gen.next(); | ||||||
|                         final_args.push((format!("__tuple_{index}_{id_next}"), index)); |                         final_args.push((format!("__tuple_{index}_{id_next}"), index)); | ||||||
|                         self.recursive_assert_tipo( |                         self.expect_type( | ||||||
|                             type_map.get(&index).unwrap(), |                             type_map.get(&index).unwrap(), | ||||||
|                             &mut nested_pattern, |                             &mut nested_pattern, | ||||||
|                             &format!("__tuple_{index}_{id_next}"), |                             &format!("__tuple_{index}_{id_next}"), | ||||||
|                             scope.clone(), |  | ||||||
|                         ) |                         ) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -2436,7 +2432,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn recursive_assert_tipo(&mut self, tipo: &Type, assert_vec: &mut AirStack, name: &str) { |     fn expect_type(&mut self, tipo: &Type, expect_stack: &mut AirStack, name: &str) { | ||||||
|         let mut tipo = tipo.clone().into(); |         let mut tipo = tipo.clone().into(); | ||||||
|         builder::replace_opaque_type(&mut tipo, self.data_types.clone()); |         builder::replace_opaque_type(&mut tipo, self.data_types.clone()); | ||||||
| 
 | 
 | ||||||
|  | @ -2455,231 +2451,103 @@ impl<'a> CodeGenerator<'a> { | ||||||
|             let inner_list_type = &tipo.get_inner_types()[0]; |             let inner_list_type = &tipo.get_inner_types()[0]; | ||||||
|             let inner_pair_types = inner_list_type.get_inner_types(); |             let inner_pair_types = inner_list_type.get_inner_types(); | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Builtin { |             let mut unwrap_function_stack = expect_stack.empty_with_scope(); | ||||||
|                 scope: scope.clone(), |             let mut pair_access_stack = unwrap_function_stack.empty_with_scope(); | ||||||
|                 func: DefaultFunction::ChooseUnit, |             let mut local_var_stack = pair_access_stack.empty_with_scope(); | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|                 count: DefaultFunction::ChooseUnit.arity(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Call { |             local_var_stack.local_var(inner_list_type.clone(), format!("__pair_{new_id}")); | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 count: 2, |  | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Var { |             pair_access_stack.tuple_accessor( | ||||||
|                 scope: scope.clone(), |                 inner_list_type.clone(), | ||||||
|                 constructor: ValueConstructor::public( |                 vec![ | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: ASSERT_ON_LIST.to_string(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Var { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: name.to_owned(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Fn { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 params: vec![format!("__pair_{new_id}")], |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::TupleAccessor { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 names: vec![ |  | ||||||
|                     format!("__pair_fst_{}", id_pair.0), |                     format!("__pair_fst_{}", id_pair.0), | ||||||
|                     format!("__pair_snd_{}", id_pair.1), |                     format!("__pair_snd_{}", id_pair.1), | ||||||
|                 ], |                 ], | ||||||
|                 tipo: inner_list_type.clone(), |                 false, | ||||||
|                 check_last_item: false, |                 local_var_stack, | ||||||
|             }); |             ); | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Var { |             self.expect_type( | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: format!("__pair_{new_id}"), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             self.recursive_assert_tipo( |  | ||||||
|                 &inner_pair_types[0], |                 &inner_pair_types[0], | ||||||
|                 assert_vec, |                 &mut pair_access_stack, | ||||||
|                 &format!("__pair_fst_{}", id_pair.0), |                 &format!("__pair_fst_{}", id_pair.0), | ||||||
|                 scope.clone(), |  | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             self.recursive_assert_tipo( |             self.expect_type( | ||||||
|                 &inner_pair_types[1], |                 &inner_pair_types[1], | ||||||
|                 assert_vec, |                 &mut pair_access_stack, | ||||||
|                 &format!("__pair_snd_{}", id_pair.1), |                 &format!("__pair_snd_{}", id_pair.1), | ||||||
|                 scope.clone(), |  | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Void { scope }); |             unwrap_function_stack | ||||||
|  |                 .anonymous_function(vec![format!("__pair_{new_id}")], pair_access_stack); | ||||||
|  | 
 | ||||||
|  |             expect_stack.expect_list_from_data(tipo.clone(), name, unwrap_function_stack); | ||||||
|  | 
 | ||||||
|  |             expect_stack.void(); | ||||||
|         } else if tipo.is_list() { |         } 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 new_id = self.id_gen.next(); | ||||||
|             let inner_list_type = &tipo.get_inner_types()[0]; |             let inner_list_type = &tipo.get_inner_types()[0]; | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Builtin { |             let mut unwrap_function_stack = expect_stack.empty_with_scope(); | ||||||
|                 scope: scope.clone(), |             let mut list_access_stack = unwrap_function_stack.empty_with_scope(); | ||||||
|                 func: DefaultFunction::ChooseUnit, |             let mut local_var_stack = list_access_stack.empty_with_scope(); | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|                 count: DefaultFunction::ChooseUnit.arity(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Call { |             local_var_stack.un_wrap_data(inner_list_type.clone()); | ||||||
|                 scope: scope.clone(), |             local_var_stack.local_var(inner_list_type.clone(), format!("__list_item_{new_id}")); | ||||||
|                 count: 2, |  | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Var { |             list_access_stack.let_assignment(format!("__list_item_{new_id}"), local_var_stack); | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: ASSERT_ON_LIST.to_string(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Var { |             self.expect_type( | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: name.to_owned(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Fn { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 params: vec![format!("__list_item_{new_id}")], |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Let { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 name: format!("__list_item_{new_id}"), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::UnWrapData { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 tipo: inner_list_type.clone(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Var { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: format!("__list_item_{new_id}"), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             self.recursive_assert_tipo( |  | ||||||
|                 inner_list_type, |                 inner_list_type, | ||||||
|                 assert_vec, |                 &mut list_access_stack, | ||||||
|                 &format!("__list_item_{new_id}"), |                 &format!("__list_item_{new_id}"), | ||||||
|                 scope.clone(), |  | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Void { scope }); |             unwrap_function_stack | ||||||
|  |                 .anonymous_function(vec![format!("__list_item_{new_id}")], list_access_stack); | ||||||
|  | 
 | ||||||
|  |             expect_stack.expect_list_from_data(tipo.clone(), name, unwrap_function_stack); | ||||||
|  | 
 | ||||||
|  |             expect_stack.void(); | ||||||
|         } else if tipo.is_tuple() { |         } else if tipo.is_tuple() { | ||||||
|             let tuple_inner_types = tipo.get_inner_types(); |             let tuple_inner_types = tipo.get_inner_types(); | ||||||
|             let mut new_id_list = vec![]; |             let mut new_id_list = vec![]; | ||||||
|  | 
 | ||||||
|             for (index, _) in tuple_inner_types.iter().enumerate() { |             for (index, _) in tuple_inner_types.iter().enumerate() { | ||||||
|                 new_id_list.push((index, self.id_gen.next())); |                 new_id_list.push((index, self.id_gen.next())); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::TupleAccessor { |             let mut local_var_stack = expect_stack.empty_with_scope(); | ||||||
|                 scope: scope.clone(), | 
 | ||||||
|                 names: new_id_list |             local_var_stack.local_var(tipo, name); | ||||||
|  | 
 | ||||||
|  |             let names = new_id_list | ||||||
|                 .iter() |                 .iter() | ||||||
|                 .map(|(index, id)| format!("__tuple_index_{index}_{id}")) |                 .map(|(index, id)| format!("__tuple_index_{index}_{id}")) | ||||||
|                     .collect_vec(), |                 .collect(); | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|                 check_last_item: true, |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Var { |             expect_stack.tuple_accessor(tipo, names, true, local_var_stack); | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: name.to_owned(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             for (index, name) in new_id_list |             for (index, name) in new_id_list | ||||||
|                 .into_iter() |                 .into_iter() | ||||||
|                 .map(|(index, id)| (index, format!("__tuple_index_{index}_{id}"))) |                 .map(|(index, id)| (index, format!("__tuple_index_{index}_{id}"))) | ||||||
|             { |             { | ||||||
|                 self.recursive_assert_tipo( |                 self.expect_type(&tuple_inner_types[index], expect_stack, &name); | ||||||
|                     &tuple_inner_types[index], |  | ||||||
|                     assert_vec, |  | ||||||
|                     &name, |  | ||||||
|                     scope.clone(), |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             let data_type = |             let data_type = | ||||||
|                 builder::lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap(); |                 builder::lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap(); | ||||||
|  | 
 | ||||||
|             let new_id = self.id_gen.next(); |             let new_id = self.id_gen.next(); | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Builtin { |             // START HERE
 | ||||||
|                 scope: scope.clone(), |             let mut arg_stack = expect_stack.empty_with_scope(); | ||||||
|                 func: DefaultFunction::ChooseUnit, |             let mut clause_stack = expect_stack.empty_with_scope(); | ||||||
|                 tipo: tipo.clone(), |             let mut when_stack = expect_stack.empty_with_scope(); | ||||||
|                 count: DefaultFunction::ChooseUnit.arity(), |             let mut trace_stack = expect_stack.empty_with_scope(); | ||||||
|             }); |             let mut subject_stack = expect_stack.empty_with_scope(); | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::When { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|                 subject_name: format!("__subject_{new_id}"), |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             assert_vec.push(Air::Var { |  | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 constructor: ValueConstructor::public( |  | ||||||
|                     tipo.clone(), |  | ||||||
|                     ValueConstructorVariant::LocalVariable { |  | ||||||
|                         location: Span::empty(), |  | ||||||
|                     }, |  | ||||||
|                 ), |  | ||||||
|                 name: name.to_owned(), |  | ||||||
|                 variant_name: String::new(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             for (index, constr) in data_type.constructors.iter().enumerate() { |             for (index, constr) in data_type.constructors.iter().enumerate() { | ||||||
|                 let arg_indices = constr |                 let arg_indices = constr | ||||||
|  | @ -2691,65 +2559,50 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                             .label |                             .label | ||||||
|                             .clone() |                             .clone() | ||||||
|                             .unwrap_or(format!("__field_{index}_{new_id}")); |                             .unwrap_or(format!("__field_{index}_{new_id}")); | ||||||
|  | 
 | ||||||
|                         (index, arg_name, arg.tipo.clone()) |                         (index, arg_name, arg.tipo.clone()) | ||||||
|                     }) |                     }) | ||||||
|                     .collect_vec(); |                     .collect_vec(); | ||||||
| 
 | 
 | ||||||
|                 assert_vec.push(Air::Clause { |                 for (index, name, tipo) in arg_indices { | ||||||
|                     scope: scope.clone(), |                     self.expect_type(&tipo, &mut arg_stack, &name); | ||||||
|                     tipo: tipo.clone(), |  | ||||||
|                     subject_name: format!("__subject_{new_id}"), |  | ||||||
|                     complex_clause: false, |  | ||||||
|                 }); |  | ||||||
| 
 |  | ||||||
|                 assert_vec.push(Air::Int { |  | ||||||
|                     scope: scope.clone(), |  | ||||||
|                     value: index.to_string(), |  | ||||||
|                 }); |  | ||||||
| 
 |  | ||||||
|                 if !arg_indices.is_empty() { |  | ||||||
|                     assert_vec.push(Air::FieldsExpose { |  | ||||||
|                         scope: scope.clone(), |  | ||||||
|                         indices: arg_indices.clone(), |  | ||||||
|                         check_last_item: true, |  | ||||||
|                     }); |  | ||||||
| 
 |  | ||||||
|                     assert_vec.push(Air::Var { |  | ||||||
|                         scope: scope.clone(), |  | ||||||
|                         constructor: ValueConstructor::public( |  | ||||||
|                             tipo.clone(), |  | ||||||
|                             ValueConstructorVariant::LocalVariable { |  | ||||||
|                                 location: Span::empty(), |  | ||||||
|                             }, |  | ||||||
|                         ), |  | ||||||
|                         name: name.to_owned(), |  | ||||||
|                         variant_name: String::new(), |  | ||||||
|                     }); |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 for (_, name, tipo) in arg_indices { |                 arg_stack = if !arg_indices.is_empty() { | ||||||
|                     self.recursive_assert_tipo(&tipo, assert_vec, &name, scope.clone()); |                     arg_stack.local_var(tipo, name); | ||||||
|  | 
 | ||||||
|  |                     let field_expose_stack = expect_stack.empty_with_scope(); | ||||||
|  | 
 | ||||||
|  |                     field_expose_stack.fields_expose(arg_indices.clone(), true, arg_stack); | ||||||
|  | 
 | ||||||
|  |                     field_expose_stack | ||||||
|  |                 } else { | ||||||
|  |                     arg_stack | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 arg_stack.void(); | ||||||
|  | 
 | ||||||
|  |                 clause_stack.clause(tipo, format!("__subject_{new_id}"), index, false, arg_stack); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|                 assert_vec.push(Air::Void { |             trace_stack.trace(tipo.clone()); | ||||||
|                     scope: scope.clone(), |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::Trace { |             trace_stack.string("Constr index did not match any type variant"); | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 tipo: tipo.clone(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::String { |             trace_stack.error(tipo.clone()); | ||||||
|                 scope: scope.clone(), |  | ||||||
|                 value: "Constr index did not match any type variant".to_string(), |  | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|             assert_vec.push(Air::ErrorTerm { |             subject_stack.local_var(tipo, name); | ||||||
|                 scope, | 
 | ||||||
|                 tipo: tipo.clone(), |             when_stack.when( | ||||||
|             }); |                 tipo, | ||||||
|  |                 format!("__subject_{new_id}"), | ||||||
|  |                 subject_stack, | ||||||
|  |                 clause_stack, | ||||||
|  |                 trace_stack, | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             // Only used here
 | ||||||
|  |             expect_stack.expect_constr_from_data(tipo.clone(), when_stack); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -2774,7 +2627,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                         && assignment_properties.value_type.is_data() |                         && assignment_properties.value_type.is_data() | ||||||
|                         && !tipo.is_data() |                         && !tipo.is_data() | ||||||
|                     { |                     { | ||||||
|                         self.recursive_assert_pattern( |                         self.expect_pattern( | ||||||
|                             a, |                             a, | ||||||
|                             nested_pattern, |                             nested_pattern, | ||||||
|                             &mut vec![Air::Var { |                             &mut vec![Air::Var { | ||||||
|  | @ -2827,7 +2680,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                         && assignment_properties.value_type.is_data() |                         && assignment_properties.value_type.is_data() | ||||||
|                         && !tipo.is_data() |                         && !tipo.is_data() | ||||||
|                     { |                     { | ||||||
|                         self.recursive_assert_pattern( |                         self.expect_pattern( | ||||||
|                             a, |                             a, | ||||||
|                             nested_pattern, |                             nested_pattern, | ||||||
|                             &mut vec![Air::Var { |                             &mut vec![Air::Var { | ||||||
|  | @ -2876,7 +2729,7 @@ impl<'a> CodeGenerator<'a> { | ||||||
|                         && assignment_properties.value_type.is_data() |                         && assignment_properties.value_type.is_data() | ||||||
|                         && !tipo.is_data() |                         && !tipo.is_data() | ||||||
|                     { |                     { | ||||||
|                         self.recursive_assert_pattern( |                         self.expect_pattern( | ||||||
|                             a, |                             a, | ||||||
|                             nested_pattern, |                             nested_pattern, | ||||||
|                             &mut vec![Air::Var { |                             &mut vec![Air::Var { | ||||||
|  |  | ||||||
|  | @ -7,53 +7,55 @@ use crate::{ | ||||||
|     tipo::{Type, ValueConstructor}, |     tipo::{Type, ValueConstructor}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | use super::scope::Scope; | ||||||
|  | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub enum Air { | pub enum Air { | ||||||
|     // Primitives
 |     // Primitives
 | ||||||
|     Int { |     Int { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         value: String, |         value: String, | ||||||
|     }, |     }, | ||||||
|     String { |     String { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         value: String, |         value: String, | ||||||
|     }, |     }, | ||||||
|     ByteArray { |     ByteArray { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         bytes: Vec<u8>, |         bytes: Vec<u8>, | ||||||
|     }, |     }, | ||||||
|     Bool { |     Bool { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         value: bool, |         value: bool, | ||||||
|     }, |     }, | ||||||
|     List { |     List { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         count: usize, |         count: usize, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         tail: bool, |         tail: bool, | ||||||
|     }, |     }, | ||||||
|     Tuple { |     Tuple { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         count: usize, |         count: usize, | ||||||
|     }, |     }, | ||||||
|     Void { |     Void { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|     }, |     }, | ||||||
|     Var { |     Var { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         constructor: ValueConstructor, |         constructor: ValueConstructor, | ||||||
|         name: String, |         name: String, | ||||||
|         variant_name: String, |         variant_name: String, | ||||||
|     }, |     }, | ||||||
|     // Functions
 |     // Functions
 | ||||||
|     Call { |     Call { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         count: usize, |         count: usize, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     DefineFunc { |     DefineFunc { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         func_name: String, |         func_name: String, | ||||||
|         module_name: String, |         module_name: String, | ||||||
|         params: Vec<String>, |         params: Vec<String>, | ||||||
|  | @ -61,70 +63,70 @@ pub enum Air { | ||||||
|         variant_name: String, |         variant_name: String, | ||||||
|     }, |     }, | ||||||
|     Fn { |     Fn { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         params: Vec<String>, |         params: Vec<String>, | ||||||
|     }, |     }, | ||||||
|     Builtin { |     Builtin { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         count: usize, |         count: usize, | ||||||
|         func: DefaultFunction, |         func: DefaultFunction, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     // Operators
 |     // Operators
 | ||||||
|     BinOp { |     BinOp { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         name: BinOp, |         name: BinOp, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     UnOp { |     UnOp { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         op: UnOp, |         op: UnOp, | ||||||
|     }, |     }, | ||||||
|     // Assignment
 |     // Assignment
 | ||||||
|     Let { |     Let { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         name: String, |         name: String, | ||||||
|     }, |     }, | ||||||
|     UnWrapData { |     UnWrapData { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     WrapData { |     WrapData { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     AssertConstr { |     AssertConstr { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         constr_index: usize, |         constr_index: usize, | ||||||
|     }, |     }, | ||||||
|     AssertBool { |     AssertBool { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         is_true: bool, |         is_true: bool, | ||||||
|     }, |     }, | ||||||
|     // When
 |     // When
 | ||||||
|     When { |     When { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         subject_name: String, |         subject_name: String, | ||||||
|     }, |     }, | ||||||
|     Clause { |     Clause { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         subject_name: String, |         subject_name: String, | ||||||
|         complex_clause: bool, |         complex_clause: bool, | ||||||
|     }, |     }, | ||||||
|     ListClause { |     ListClause { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         tail_name: String, |         tail_name: String, | ||||||
|         next_tail_name: Option<String>, |         next_tail_name: Option<String>, | ||||||
|         complex_clause: bool, |         complex_clause: bool, | ||||||
|     }, |     }, | ||||||
|     WrapClause { |     WrapClause { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|     }, |     }, | ||||||
|     TupleClause { |     TupleClause { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         indices: IndexSet<(usize, String)>, |         indices: IndexSet<(usize, String)>, | ||||||
|         predefined_indices: IndexSet<(usize, String)>, |         predefined_indices: IndexSet<(usize, String)>, | ||||||
|  | @ -133,88 +135,88 @@ pub enum Air { | ||||||
|         complex_clause: bool, |         complex_clause: bool, | ||||||
|     }, |     }, | ||||||
|     ClauseGuard { |     ClauseGuard { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         subject_name: String, |         subject_name: String, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     ListClauseGuard { |     ListClauseGuard { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         tail_name: String, |         tail_name: String, | ||||||
|         next_tail_name: Option<String>, |         next_tail_name: Option<String>, | ||||||
|         inverse: bool, |         inverse: bool, | ||||||
|     }, |     }, | ||||||
|     Finally { |     Finally { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|     }, |     }, | ||||||
|     // If
 |     // If
 | ||||||
|     If { |     If { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     // Record Creation
 |     // Record Creation
 | ||||||
|     Record { |     Record { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tag: usize, |         tag: usize, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         count: usize, |         count: usize, | ||||||
|     }, |     }, | ||||||
|     RecordUpdate { |     RecordUpdate { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         highest_index: usize, |         highest_index: usize, | ||||||
|         indices: Vec<(usize, Arc<Type>)>, |         indices: Vec<(usize, Arc<Type>)>, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     // Field Access
 |     // Field Access
 | ||||||
|     RecordAccess { |     RecordAccess { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         record_index: u64, |         record_index: u64, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     FieldsExpose { |     FieldsExpose { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         indices: Vec<(usize, String, Arc<Type>)>, |         indices: Vec<(usize, String, Arc<Type>)>, | ||||||
|         check_last_item: bool, |         check_last_item: bool, | ||||||
|     }, |     }, | ||||||
|     // ListAccess
 |     // ListAccess
 | ||||||
|     ListAccessor { |     ListAccessor { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         names: Vec<String>, |         names: Vec<String>, | ||||||
|         tail: bool, |         tail: bool, | ||||||
|         check_last_item: bool, |         check_last_item: bool, | ||||||
|     }, |     }, | ||||||
|     ListExpose { |     ListExpose { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         tail_head_names: Vec<(String, String)>, |         tail_head_names: Vec<(String, String)>, | ||||||
|         tail: Option<(String, String)>, |         tail: Option<(String, String)>, | ||||||
|     }, |     }, | ||||||
|     // Tuple Access
 |     // Tuple Access
 | ||||||
|     TupleAccessor { |     TupleAccessor { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         names: Vec<String>, |         names: Vec<String>, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         check_last_item: bool, |         check_last_item: bool, | ||||||
|     }, |     }, | ||||||
|     TupleIndex { |     TupleIndex { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|         tuple_index: usize, |         tuple_index: usize, | ||||||
|     }, |     }, | ||||||
|     // Misc.
 |     // Misc.
 | ||||||
|     ErrorTerm { |     ErrorTerm { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
|     Trace { |     Trace { | ||||||
|         scope: Vec<u64>, |         scope: Scope, | ||||||
|         tipo: Arc<Type>, |         tipo: Arc<Type>, | ||||||
|     }, |     }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Air { | impl Air { | ||||||
|     pub fn scope(&self) -> Vec<u64> { |     pub fn scope(&self) -> Scope { | ||||||
|         match self { |         match self { | ||||||
|             Air::Int { scope, .. } |             Air::Int { scope, .. } | ||||||
|             | Air::String { scope, .. } |             | Air::String { scope, .. } | ||||||
|  | @ -256,7 +258,7 @@ impl Air { | ||||||
|             | Air::Trace { scope, .. } => scope.clone(), |             | Air::Trace { scope, .. } => scope.clone(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     pub fn scope_mut(&mut self) -> &mut Vec<u64> { |     pub fn scope_mut(&mut self) -> &mut Scope { | ||||||
|         match self { |         match self { | ||||||
|             Air::Int { scope, .. } |             Air::Int { scope, .. } | ||||||
|             | Air::String { scope, .. } |             | Air::String { scope, .. } | ||||||
|  |  | ||||||
|  | @ -636,29 +636,6 @@ pub fn list_access_to_uplc( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn get_common_ancestor(scope: &[u64], scope_prev: &[u64]) -> Vec<u64> { |  | ||||||
|     let longest_length = if scope.len() >= scope_prev.len() { |  | ||||||
|         scope.len() |  | ||||||
|     } else { |  | ||||||
|         scope_prev.len() |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     if *scope == *scope_prev { |  | ||||||
|         return scope.to_vec(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for index in 0..longest_length { |  | ||||||
|         if scope.get(index).is_none() { |  | ||||||
|             return scope.to_vec(); |  | ||||||
|         } else if scope_prev.get(index).is_none() { |  | ||||||
|             return scope_prev.to_vec(); |  | ||||||
|         } else if scope[index] != scope_prev[index] { |  | ||||||
|             return scope[0..index].to_vec(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     vec![] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn check_when_pattern_needs( | pub fn check_when_pattern_needs( | ||||||
|     pattern: &Pattern<PatternConstructor, Arc<Type>>, |     pattern: &Pattern<PatternConstructor, Arc<Type>>, | ||||||
|     clause_properties: &mut ClauseProperties, |     clause_properties: &mut ClauseProperties, | ||||||
|  |  | ||||||
|  | @ -0,0 +1,65 @@ | ||||||
|  | #[derive(Debug, Clone, Default)] | ||||||
|  | pub struct Scope(Vec<u64>); | ||||||
|  | 
 | ||||||
|  | impl Scope { | ||||||
|  |     pub fn push(&mut self, value: u64) { | ||||||
|  |         self.0.push(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn is_empty(&self) -> bool { | ||||||
|  |         self.0.is_empty() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn replace(&mut self, pattern: &Scope, replacement: Scope) { | ||||||
|  |         let mut result = Vec::new(); | ||||||
|  | 
 | ||||||
|  |         let mut index = 0; | ||||||
|  |         let mut pattern_index = 0; | ||||||
|  | 
 | ||||||
|  |         let mut no_matches = true; | ||||||
|  | 
 | ||||||
|  |         while index < self.0.len() { | ||||||
|  |             if self.0[index] == pattern.0[pattern_index] { | ||||||
|  |                 if pattern_index == pattern.0.len() - 1 { | ||||||
|  |                     no_matches = false; | ||||||
|  |                     result.extend(replacement.0.clone()); | ||||||
|  |                     pattern_index = 0; | ||||||
|  |                 } else { | ||||||
|  |                     pattern_index += 1; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 result.push(self.0[index]); | ||||||
|  |                 pattern_index = 0; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             index += 1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if no_matches { | ||||||
|  |             replacement.0.extend(self.0); | ||||||
|  |             self.0 = replacement.0; | ||||||
|  |         } else { | ||||||
|  |             self.0 = result; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn common_ancestor(&self, other: &Self) -> Scope { | ||||||
|  |         let longest_length = self.0.len().max(other.0.len()); | ||||||
|  | 
 | ||||||
|  |         if *self.0 == *other.0 { | ||||||
|  |             return self.clone(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for index in 0..longest_length { | ||||||
|  |             if self.0.get(index).is_none() { | ||||||
|  |                 return self.clone(); | ||||||
|  |             } else if other.0.get(index).is_none() { | ||||||
|  |                 return other.clone(); | ||||||
|  |             } else if self.0[index] != other.0[index] { | ||||||
|  |                 return Scope(self.0[0..index].to_vec()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Scope::default() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,30 +1,34 @@ | ||||||
| use std::sync::Arc; | use std::sync::Arc; | ||||||
| 
 | 
 | ||||||
| use uplc::builtins::DefaultFunction; | use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     tipo::{Type, ValueConstructor}, |     ast::Span, | ||||||
|  |     tipo::{Type, ValueConstructor, ValueConstructorVariant}, | ||||||
|     IdGenerator, |     IdGenerator, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::air::Air; | use super::{air::Air, scope::Scope}; | ||||||
| 
 | 
 | ||||||
|  | /// A builder for [`Air`].
 | ||||||
| pub struct AirStack<'a> { | pub struct AirStack<'a> { | ||||||
|     pub id_gen: &'a mut IdGenerator, |     pub id_gen: &'a mut IdGenerator, | ||||||
|     pub scope: Vec<u64>, |     pub scope: Scope, | ||||||
|     pub air: Vec<Air>, |     pub air: Vec<Air>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> AirStack<'a> { | impl<'a> AirStack<'a> { | ||||||
|  |     /// Create a new [`AirStack`] with an [`IdGenerator`]
 | ||||||
|     pub fn new(id_gen: &'a mut IdGenerator) -> Self { |     pub fn new(id_gen: &'a mut IdGenerator) -> Self { | ||||||
|         AirStack { |         AirStack { | ||||||
|             id_gen, |             id_gen, | ||||||
|             scope: vec![id_gen.next()], |             scope: Scope::default(), | ||||||
|             air: vec![], |             air: vec![], | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn with_scope(id_gen: &'a mut IdGenerator, scope: Vec<u64>) -> Self { |     /// Create a new [`AirStack`] with an [`IdGenerator`] and [`Scope`].
 | ||||||
|  |     pub fn with_scope(id_gen: &'a mut IdGenerator, scope: Scope) -> Self { | ||||||
|         AirStack { |         AirStack { | ||||||
|             id_gen, |             id_gen, | ||||||
|             scope, |             scope, | ||||||
|  | @ -32,22 +36,37 @@ impl<'a> AirStack<'a> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn in_new_scope(&mut self) -> Self { |     /// Create a new empty [`AirStack`] with the current stack's scope.
 | ||||||
|         let mut new_stack = AirStack::with_scope(&mut self.id_gen, self.scope.clone()); |     pub fn empty_with_scope(&mut self) -> Self { | ||||||
| 
 |         AirStack::with_scope(&mut self.id_gen, self.scope.clone()) | ||||||
|         new_stack.new_scope(); |  | ||||||
| 
 |  | ||||||
|         new_stack |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new_scope(&mut self) { |     /// Increment the [`Scope`]
 | ||||||
|  |     fn new_scope(&mut self) { | ||||||
|         self.scope.push(self.id_gen.next()); |         self.scope.push(self.id_gen.next()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Merge two [`AirStack`]'s together while maintaining the current stack's [`Scope`]
 | ||||||
|     pub fn merge(&mut self, mut other: AirStack) { |     pub fn merge(&mut self, mut other: AirStack) { | ||||||
|         self.air.append(&mut other.air); |         self.air.append(&mut other.air); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn merge_child(&mut self, mut other: AirStack) { | ||||||
|  |         let pattern = self.scope.common_ancestor(&other.scope); | ||||||
|  | 
 | ||||||
|  |         for ir in other.air.iter_mut() { | ||||||
|  |             ir.scope_mut().replace(&pattern, self.scope.clone()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.merge(other); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn merge_children(&mut self, stacks: Vec<AirStack>) { | ||||||
|  |         for stack in stacks { | ||||||
|  |             self.merge_child(stack) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn sequence(&mut self, stacks: Vec<AirStack>) { |     pub fn sequence(&mut self, stacks: Vec<AirStack>) { | ||||||
|         for stack in stacks { |         for stack in stacks { | ||||||
|             self.merge(stack) |             self.merge(stack) | ||||||
|  | @ -55,20 +74,26 @@ impl<'a> AirStack<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn integer(&mut self, value: String) { |     pub fn integer(&mut self, value: String) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Int { |         self.air.push(Air::Int { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             value, |             value, | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn string(&mut self, value: String) { |     pub fn string(&mut self, value: impl ToString) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::String { |         self.air.push(Air::String { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             value, |             value: value.to_string(), | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn byte_array(&mut self, bytes: Vec<u8>) { |     pub fn byte_array(&mut self, bytes: Vec<u8>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::ByteArray { |         self.air.push(Air::ByteArray { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             bytes, |             bytes, | ||||||
|  | @ -76,6 +101,8 @@ impl<'a> AirStack<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirStack>) { |     pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirStack>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Builtin { |         self.air.push(Air::Builtin { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             count: args.len(), |             count: args.len(), | ||||||
|  | @ -83,7 +110,7 @@ impl<'a> AirStack<'a> { | ||||||
|             tipo, |             tipo, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.sequence(args); |         self.merge_children(args); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn var( |     pub fn var( | ||||||
|  | @ -92,6 +119,8 @@ impl<'a> AirStack<'a> { | ||||||
|         name: impl ToString, |         name: impl ToString, | ||||||
|         variant_name: impl ToString, |         variant_name: impl ToString, | ||||||
|     ) { |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Var { |         self.air.push(Air::Var { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             constructor, |             constructor, | ||||||
|  | @ -100,16 +129,36 @@ impl<'a> AirStack<'a> { | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn local_var(&mut self, tipo: Arc<Type>, name: impl ToString) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Var { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             constructor: ValueConstructor::public( | ||||||
|  |                 tipo, | ||||||
|  |                 ValueConstructorVariant::LocalVariable { | ||||||
|  |                     location: Span::empty(), | ||||||
|  |                 }, | ||||||
|  |             ), | ||||||
|  |             name: name.to_string(), | ||||||
|  |             variant_name: String::new(), | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn anonymous_function(&mut self, params: Vec<String>, body: AirStack) { |     pub fn anonymous_function(&mut self, params: Vec<String>, body: AirStack) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Fn { |         self.air.push(Air::Fn { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             params, |             params, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.merge(body); |         self.merge_child(body); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn list(&mut self, tipo: Arc<Type>, elements: Vec<AirStack>, tail: Option<AirStack>) { |     pub fn list(&mut self, tipo: Arc<Type>, elements: Vec<AirStack>, tail: Option<AirStack>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::List { |         self.air.push(Air::List { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             count: elements.len(), |             count: elements.len(), | ||||||
|  | @ -117,14 +166,16 @@ impl<'a> AirStack<'a> { | ||||||
|             tail: tail.is_some(), |             tail: tail.is_some(), | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.sequence(elements); |         self.merge_children(elements); | ||||||
| 
 | 
 | ||||||
|         if let Some(tail) = tail { |         if let Some(tail) = tail { | ||||||
|             self.merge(tail); |             self.merge_child(tail); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn record(&mut self, tipo: Arc<Type>, tag: usize, fields: Vec<AirStack>) { |     pub fn record(&mut self, tipo: Arc<Type>, tag: usize, fields: Vec<AirStack>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Record { |         self.air.push(Air::Record { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             tag, |             tag, | ||||||
|  | @ -132,19 +183,21 @@ impl<'a> AirStack<'a> { | ||||||
|             count: fields.len(), |             count: fields.len(), | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.sequence(fields); |         self.merge_children(fields); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn call(&mut self, tipo: Arc<Type>, fun: AirStack, args: Vec<AirStack>) { |     pub fn call(&mut self, tipo: Arc<Type>, fun: AirStack, args: Vec<AirStack>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Call { |         self.air.push(Air::Call { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             count: args.len(), |             count: args.len(), | ||||||
|             tipo, |             tipo, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.merge(fun); |         self.merge_child(fun); | ||||||
| 
 | 
 | ||||||
|         self.sequence(args); |         self.merge_children(args); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn binop( |     pub fn binop( | ||||||
|  | @ -154,26 +207,62 @@ impl<'a> AirStack<'a> { | ||||||
|         left: AirStack, |         left: AirStack, | ||||||
|         right: AirStack, |         right: AirStack, | ||||||
|     ) { |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::BinOp { |         self.air.push(Air::BinOp { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             name, |             name, | ||||||
|             tipo, |             tipo, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.merge(left); |         self.merge_child(left); | ||||||
|         self.merge(right); |         self.merge_child(right); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) { |     pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::Let { |         self.air.push(Air::Let { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             name: name.to_string(), |             name: name.to_string(), | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         self.merge(value); |         self.merge_child(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn expect_list_from_data( | ||||||
|  |         &mut self, | ||||||
|  |         tipo: Arc<Type>, | ||||||
|  |         name: impl ToString, | ||||||
|  |         unwrap_function: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Builtin { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             func: DefaultFunction::ChooseUnit, | ||||||
|  |             tipo: tipo.clone(), | ||||||
|  |             count: DefaultFunction::ChooseUnit.arity(), | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Call { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             count: 2, | ||||||
|  |             tipo, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.local_var(tipo.clone(), EXPECT_ON_LIST); | ||||||
|  | 
 | ||||||
|  |         self.local_var(tipo, name); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(unwrap_function); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn wrap_data(&mut self, tipo: Arc<Type>) { |     pub fn wrap_data(&mut self, tipo: Arc<Type>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::WrapData { |         self.air.push(Air::WrapData { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             tipo, |             tipo, | ||||||
|  | @ -181,9 +270,150 @@ impl<'a> AirStack<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn un_wrap_data(&mut self, tipo: Arc<Type>) { |     pub fn un_wrap_data(&mut self, tipo: Arc<Type>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|         self.air.push(Air::UnWrapData { |         self.air.push(Air::UnWrapData { | ||||||
|             scope: self.scope.clone(), |             scope: self.scope.clone(), | ||||||
|             tipo, |             tipo, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn void(&mut self) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Void { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn tuple_accessor( | ||||||
|  |         &mut self, | ||||||
|  |         tipo: Arc<Type>, | ||||||
|  |         names: Vec<String>, | ||||||
|  |         check_last_item: bool, | ||||||
|  |         value: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::TupleAccessor { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             names, | ||||||
|  |             tipo, | ||||||
|  |             check_last_item, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn fields_expose( | ||||||
|  |         &mut self, | ||||||
|  |         indices: Vec<(usize, String, Arc<Type>)>, | ||||||
|  |         check_last_item: bool, | ||||||
|  |         value: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::FieldsExpose { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             indices, | ||||||
|  |             check_last_item, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn clause( | ||||||
|  |         &mut self, | ||||||
|  |         tipo: Arc<Type>, | ||||||
|  |         subject_name: impl ToString, | ||||||
|  |         tag: usize, | ||||||
|  |         complex_clause: bool, | ||||||
|  |         body: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Clause { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             subject_name: subject_name.to_string(), | ||||||
|  |             complex_clause, | ||||||
|  |             tipo, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.integer(tag.to_string()); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(body); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn trace(&mut self, tipo: Arc<Type>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Trace { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             tipo, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn error(&mut self, tipo: Arc<Type>) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::ErrorTerm { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             tipo, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn expect_constr_from_data(&mut self, tipo: Arc<Type>, when_stack: AirStack) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::Builtin { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             func: DefaultFunction::ChooseUnit, | ||||||
|  |             tipo: tipo.clone(), | ||||||
|  |             count: DefaultFunction::ChooseUnit.arity(), | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(when_stack); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn when( | ||||||
|  |         &mut self, | ||||||
|  |         tipo: Arc<Type>, | ||||||
|  |         subject_name: impl ToString, | ||||||
|  |         subject_stack: AirStack, | ||||||
|  |         clauses_stack: AirStack, | ||||||
|  |         else_stack: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::When { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             subject_name: subject_name.to_string(), | ||||||
|  |             tipo, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(subject_stack); | ||||||
|  |         self.merge_child(clauses_stack); | ||||||
|  |         self.merge_child(else_stack); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn list_accessor( | ||||||
|  |         &mut self, | ||||||
|  |         tipo: Arc<Type>, | ||||||
|  |         names: Vec<String>, | ||||||
|  |         tail: bool, | ||||||
|  |         check_last_item: bool, | ||||||
|  |         value: AirStack, | ||||||
|  |     ) { | ||||||
|  |         self.new_scope(); | ||||||
|  | 
 | ||||||
|  |         self.air.push(Air::ListAccessor { | ||||||
|  |             scope: self.scope.clone(), | ||||||
|  |             names, | ||||||
|  |             tail, | ||||||
|  |             check_last_item, | ||||||
|  |             tipo, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         self.merge_child(value); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ use crate::{ | ||||||
| pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer"; | pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer"; | ||||||
| pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer"; | pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer"; | ||||||
| pub const CONSTR_GET_FIELD: &str = "__constr_get_field"; | pub const CONSTR_GET_FIELD: &str = "__constr_get_field"; | ||||||
| pub const ASSERT_ON_LIST: &str = "__assert_on_list"; | pub const EXPECT_ON_LIST: &str = "__expect_on_list"; | ||||||
| 
 | 
 | ||||||
| impl Term<Name> { | impl Term<Name> { | ||||||
|     pub fn apply(self, arg: Self) -> Self { |     pub fn apply(self, arg: Self) -> Self { | ||||||
|  | @ -213,11 +213,11 @@ impl Term<Name> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn assert_on_list(self) -> Term<Name> { |     pub fn assert_on_list(self) -> Term<Name> { | ||||||
|         self.lambda(ASSERT_ON_LIST.to_string()) |         self.lambda(EXPECT_ON_LIST.to_string()) | ||||||
|             .apply( |             .apply( | ||||||
|                 Term::var(ASSERT_ON_LIST.to_string()).apply(Term::var(ASSERT_ON_LIST.to_string())), |                 Term::var(EXPECT_ON_LIST.to_string()).apply(Term::var(EXPECT_ON_LIST.to_string())), | ||||||
|             ) |             ) | ||||||
|             .lambda(ASSERT_ON_LIST.to_string()) |             .lambda(EXPECT_ON_LIST.to_string()) | ||||||
|             .apply( |             .apply( | ||||||
|                 Term::var("__list_to_check".to_string()) |                 Term::var("__list_to_check".to_string()) | ||||||
|                     .delayed_choose_list( |                     .delayed_choose_list( | ||||||
|  | @ -227,8 +227,8 @@ impl Term<Name> { | ||||||
|                                 Term::head_list().apply(Term::var("__list_to_check".to_string())), |                                 Term::head_list().apply(Term::var("__list_to_check".to_string())), | ||||||
|                             ) |                             ) | ||||||
|                             .choose_unit( |                             .choose_unit( | ||||||
|                                 Term::var(ASSERT_ON_LIST.to_string()) |                                 Term::var(EXPECT_ON_LIST.to_string()) | ||||||
|                                     .apply(Term::var(ASSERT_ON_LIST.to_string())) |                                     .apply(Term::var(EXPECT_ON_LIST.to_string())) | ||||||
|                                     .apply( |                                     .apply( | ||||||
|                                         Term::tail_list() |                                         Term::tail_list() | ||||||
|                                             .apply(Term::var("__list_to_check".to_string())), |                                             .apply(Term::var("__list_to_check".to_string())), | ||||||
|  | @ -238,7 +238,7 @@ impl Term<Name> { | ||||||
|                     ) |                     ) | ||||||
|                     .lambda("__check_with".to_string()) |                     .lambda("__check_with".to_string()) | ||||||
|                     .lambda("__list_to_check".to_string()) |                     .lambda("__list_to_check".to_string()) | ||||||
|                     .lambda(ASSERT_ON_LIST), |                     .lambda(EXPECT_ON_LIST), | ||||||
|             ) |             ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 rvcas
						rvcas