diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index a3220a1e6..20e7b373d 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -1679,6 +1679,7 @@ pub type TypedAssignmentKind = AssignmentKind<()>; #[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)] pub enum AssignmentKind { + Is, Let { backpassing: T }, Expect { backpassing: T }, } @@ -1686,6 +1687,7 @@ pub enum AssignmentKind { impl From for TypedAssignmentKind { fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind { match kind { + AssignmentKind::Is => AssignmentKind::Is, AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () }, AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () }, } @@ -1701,8 +1703,13 @@ impl AssignmentKind { matches!(self, AssignmentKind::Expect { .. }) } + pub fn if_is(&self) -> bool { + matches!(self, AssignmentKind::Is) + } + pub fn location_offset(&self) -> usize { match self { + AssignmentKind::Is => 2, AssignmentKind::Let { .. } => 3, AssignmentKind::Expect { .. } => 6, } @@ -1712,6 +1719,7 @@ impl AssignmentKind { impl AssignmentKind { pub fn is_backpassing(&self) -> bool { match self { + Self::Is => unreachable!(), Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing, } } @@ -1724,6 +1732,10 @@ impl AssignmentKind { } } + pub fn is() -> Self { + AssignmentKind::Is + } + pub fn expect() -> Self { AssignmentKind::Expect { backpassing: Default::default(), @@ -1885,13 +1897,14 @@ impl TypedClauseGuard { } } -pub type TypedIfBranch = IfBranch; -pub type UntypedIfBranch = IfBranch; +pub type TypedIfBranch = IfBranch; +pub type UntypedIfBranch = IfBranch; #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct IfBranch { +pub struct IfBranch { pub condition: Expr, pub body: Expr, + pub is: Option, pub location: Span, } diff --git a/crates/aiken-lang/src/expr.rs b/crates/aiken-lang/src/expr.rs index cb7bf79c9..3571a4128 100644 --- a/crates/aiken-lang/src/expr.rs +++ b/crates/aiken-lang/src/expr.rs @@ -2,10 +2,10 @@ use crate::{ ast::{ self, Annotation, ArgBy, ArgName, AssignmentPattern, BinOp, Bls12_381Point, ByteArrayFormatPreference, CallArg, Curve, DataType, DataTypeKey, DefinitionLocation, - IfBranch, Located, LogicalOpChainKind, ParsedCallArg, Pattern, RecordConstructorArg, + Located, LogicalOpChainKind, ParsedCallArg, Pattern, RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypedArg, TypedAssignmentKind, TypedClause, - TypedDataType, TypedRecordUpdateArg, UnOp, UntypedArg, UntypedAssignmentKind, - UntypedClause, UntypedRecordUpdateArg, + TypedDataType, TypedIfBranch, TypedRecordUpdateArg, UnOp, UntypedArg, + UntypedAssignmentKind, UntypedClause, UntypedIfBranch, UntypedRecordUpdateArg, }, builtins::void, parser::token::Base, @@ -127,7 +127,7 @@ pub enum TypedExpr { If { location: Span, #[serde(with = "Vec1Ref")] - branches: Vec1>, + branches: Vec1, final_else: Box, tipo: Rc, }, @@ -564,7 +564,7 @@ pub enum UntypedExpr { If { location: Span, - branches: Vec1>, + branches: Vec1, final_else: Box, }, diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index c5a36dfc9..4bcded89f 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -2,10 +2,10 @@ use crate::{ ast::{ Annotation, ArgBy, ArgName, ArgVia, AssignmentKind, AssignmentPattern, BinOp, ByteArrayFormatPreference, CallArg, ClauseGuard, Constant, CurveType, DataType, Definition, - Function, IfBranch, LogicalOpChainKind, ModuleConstant, OnTestFailure, Pattern, - RecordConstructor, RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, - TypedArg, UnOp, UnqualifiedImport, UntypedArg, UntypedArgVia, UntypedAssignmentKind, - UntypedClause, UntypedClauseGuard, UntypedDefinition, UntypedFunction, UntypedModule, + Function, LogicalOpChainKind, ModuleConstant, OnTestFailure, Pattern, RecordConstructor, + RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, UnOp, + UnqualifiedImport, UntypedArg, UntypedArgVia, UntypedAssignmentKind, UntypedClause, + UntypedClauseGuard, UntypedDefinition, UntypedFunction, UntypedIfBranch, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, Validator, CAPTURE_VARIABLE, }, docvec, @@ -703,6 +703,7 @@ impl<'comments> Formatter<'comments> { kind: UntypedAssignmentKind, ) -> Document<'a> { let keyword = match kind { + AssignmentKind::Is => unreachable!(), AssignmentKind::Let { .. } => "let", AssignmentKind::Expect { .. } => "expect", }; @@ -1195,7 +1196,7 @@ impl<'comments> Formatter<'comments> { pub fn if_expr<'a>( &mut self, - branches: &'a Vec1>, + branches: &'a Vec1, final_else: &'a UntypedExpr, ) -> Document<'a> { let if_branches = self @@ -1223,10 +1224,44 @@ impl<'comments> Formatter<'comments> { pub fn if_branch<'a>( &mut self, if_keyword: Document<'a>, - branch: &'a IfBranch, + branch: &'a UntypedIfBranch, ) -> Document<'a> { let if_begin = if_keyword .append(self.wrap_expr(&branch.condition)) + .append(match &branch.is { + Some(AssignmentPattern { + pattern, + annotation, + .. + }) => { + let is_sugar = matches!( + (&pattern, &branch.condition), + ( + Pattern::Var { name, .. }, + UntypedExpr::Var { name: var_name, .. } + ) if name == var_name + ); + + let Some(annotation) = &annotation else { + unreachable!() + }; + + let is = if is_sugar { + self.annotation(annotation) + } else { + self.pattern(pattern) + .append(": ") + .append(self.annotation(annotation)) + .group() + }; + + break_("", " ") + .append("is") + .append(break_("", " ")) + .append(is) + } + None => nil(), + }) .append(break_("{", " {")) .group(); diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 27f661047..f80b07e6d 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -5,11 +5,11 @@ pub mod tree; use self::{ air::Air, builder::{ - air_holds_msg, cast_validator_args, constants_ir, convert_type_to_data, extract_constant, + cast_validator_args, constants_ir, convert_type_to_data, extract_constant, modify_cyclic_calls, modify_self_calls, rearrange_list_clauses, AssignmentProperties, ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames, HoistableFunction, Variant, }, - tree::{AirMsg, AirTree, TreePath}, + tree::{AirTree, TreePath}, }; use crate::{ ast::{ @@ -17,7 +17,7 @@ use crate::{ Span, TraceLevel, Tracing, TypedArg, TypedClause, TypedDataType, TypedFunction, TypedPattern, TypedValidator, UnOp, }, - builtins::{bool, data, int, list, string, void}, + builtins::{bool, data, int, list, void}, expr::TypedExpr, gen_uplc::{ air::ExpectLevel, @@ -42,6 +42,8 @@ use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use petgraph::{algo, Graph}; use std::{collections::HashMap, rc::Rc}; +use tree::Fields; + use uplc::{ ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST}, @@ -258,36 +260,31 @@ impl<'a> CodeGenerator<'a> { let air_value = self.build(value, module_build_name, &[]); - let msg_func = match self.tracing { - TraceLevel::Silent => None, - TraceLevel::Verbose | TraceLevel::Compact => { - if kind.is_expect() { - let msg = match self.tracing { - TraceLevel::Silent => unreachable!("excluded from pattern guards"), - TraceLevel::Compact => get_line_columns_by_span( - module_build_name, - location, - &self.module_src, - ) - .to_string(), - TraceLevel::Verbose => { - get_src_code_by_span(module_build_name, location, &self.module_src) - } - }; - - let msg_func_name = msg.split_whitespace().join(""); + let otherwise_delayed = { + let msg = match (self.tracing, kind) { + (TraceLevel::Silent, _) | (_, AssignmentKind::Let { .. }) => "".to_string(), + (TraceLevel::Compact, _) => { + get_line_columns_by_span(module_build_name, location, &self.module_src) + .to_string() + } + (TraceLevel::Verbose, _) => { + get_src_code_by_span(module_build_name, location, &self.module_src) + } + }; - self.special_functions.insert_new_function( - msg_func_name.clone(), - Term::string(msg), - string(), - ); + let msg_func_name = msg.split_whitespace().join(""); - Some(self.special_functions.use_function_msg(msg_func_name)) + self.special_functions.insert_new_function( + msg_func_name.clone(), + if msg.is_empty() { + Term::Error.delay() } else { - None - } - } + Term::Error.delayed_trace(Term::string(msg)).delay() + }, + void(), + ); + + self.special_functions.use_function_tree(msg_func_name) }; let (then, context) = context.split_first().unwrap(); @@ -304,7 +301,7 @@ impl<'a> CodeGenerator<'a> { kind: *kind, remove_unused: kind.is_let(), full_check: !tipo.is_data() && value.tipo().is_data() && kind.is_expect(), - msg_func, + otherwise: otherwise_delayed, }, ) } else { @@ -337,6 +334,7 @@ impl<'a> CodeGenerator<'a> { .map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string()) .collect_vec(), self.build(body, module_build_name, &[]), + false, ), TypedExpr::List { @@ -574,7 +572,7 @@ impl<'a> CodeGenerator<'a> { kind: AssignmentKind::let_(), remove_unused: false, full_check: false, - msg_func: None, + otherwise: AirTree::error(void(), false), }, ) } else { @@ -625,24 +623,44 @@ impl<'a> CodeGenerator<'a> { ) } } - + // let pattern = branch.condition + // branch.body + // + // if is : { } + // [(builtin ifThenElse) (condition is pattern) (body) (else) ] TypedExpr::If { branches, final_else, tipo, .. - } => AirTree::if_branches( - branches - .iter() - .map(|branch| { - ( - self.build(&branch.condition, module_build_name, &[]), - self.build(&branch.body, module_build_name, &[]), - ) - }) - .collect_vec(), - tipo.clone(), + } => branches.iter().rfold( self.build(final_else, module_build_name, &[]), + |acc, branch| { + let condition = self.build(&branch.condition, module_build_name, &[]); + let body = self.build(&branch.body, module_build_name, &[]); + + match &branch.is { + Some(pattern) => AirTree::let_assignment( + "acc_var", + // use anon function as a delay to avoid evaluating the acc + AirTree::anon_func(vec![], acc, true), + self.assignment( + pattern, + condition, + body, + &pattern.tipo(&branch.condition).unwrap(), + AssignmentProperties { + value_type: branch.condition.tipo(), + kind: AssignmentKind::Expect { backpassing: () }, + remove_unused: false, + full_check: true, + otherwise: AirTree::local_var("acc_var", void()), + }, + ), + ), + None => AirTree::if_branch(tipo.clone(), condition, body, acc), + } + }, ), TypedExpr::RecordAccess { @@ -878,7 +896,7 @@ impl<'a> CodeGenerator<'a> { // Cast value to or from data so we don't have to worry from this point onward if props.value_type.is_data() && props.kind.is_expect() && !tipo.is_data() { - value = AirTree::cast_from_data(value, tipo.clone(), props.msg_func.clone()); + value = AirTree::cast_from_data(value, tipo.clone(), props.otherwise.clone(), true); } else if !props.value_type.is_data() && tipo.is_data() { value = AirTree::cast_to_data(value, props.value_type.clone()); } @@ -906,7 +924,7 @@ impl<'a> CodeGenerator<'a> { let expr = AirTree::let_assignment(name, value, expect); - AirTree::assert_bool(true, expr, props.msg_func.clone(), then) + AirTree::assert_bool(true, expr, then, props.otherwise.clone()) } Pattern::Var { name, .. } => { @@ -925,7 +943,7 @@ impl<'a> CodeGenerator<'a> { val, &mut index_map, pattern.location(), - props.msg_func, + props.otherwise, ); let assign_expect = AirTree::let_assignment("_", expect, then); @@ -965,7 +983,7 @@ impl<'a> CodeGenerator<'a> { val, &mut index_map, pattern.location(), - props.msg_func, + props.otherwise, ); let assignment = AirTree::let_assignment("_", expect, then); @@ -975,7 +993,7 @@ impl<'a> CodeGenerator<'a> { } else if !props.remove_unused { AirTree::let_assignment(name, value, then) } else { - AirTree::no_op(then) + then } } @@ -1025,7 +1043,7 @@ impl<'a> CodeGenerator<'a> { kind: props.kind, remove_unused: true, full_check: props.full_check, - msg_func: props.msg_func.clone(), + otherwise: props.otherwise.clone(), }, ) } else { @@ -1073,7 +1091,7 @@ impl<'a> CodeGenerator<'a> { kind: props.kind, remove_unused: true, full_check: props.full_check, - msg_func: props.msg_func.clone(), + otherwise: props.otherwise.clone(), }, ) } else { @@ -1088,20 +1106,20 @@ impl<'a> CodeGenerator<'a> { elems.reverse(); if elements.is_empty() { - AirTree::list_empty(value, props.msg_func, then) + AirTree::list_empty(value, then, props.otherwise.clone()) } else { AirTree::list_access( elems, tipo.clone(), tail.is_some(), value, - props.msg_func, if props.full_check { ExpectLevel::Full } else { ExpectLevel::Items }, then, + props.otherwise.clone(), ) } } @@ -1164,7 +1182,7 @@ impl<'a> CodeGenerator<'a> { kind: props.kind, remove_unused: true, full_check: props.full_check, - msg_func: props.msg_func.clone(), + otherwise: props.otherwise.clone(), }, ) } else { @@ -1190,11 +1208,6 @@ impl<'a> CodeGenerator<'a> { let local_value = AirTree::local_var(&constructor_name, tipo.clone()); let then = { - let (is_expect, msg) = if props.full_check { - (true, props.msg_func.clone()) - } else { - (false, None) - }; assert!(fields.len() == 2); AirTree::pair_access( @@ -1208,9 +1221,9 @@ impl<'a> CodeGenerator<'a> { .unwrap(), tipo.clone(), local_value, - msg, - is_expect, + props.full_check, then, + props.otherwise.clone(), ) }; @@ -1223,7 +1236,7 @@ impl<'a> CodeGenerator<'a> { } if tipo.is_bool() => { assert!(props.kind.is_expect()); - AirTree::assert_bool(name == "True", value, props.msg_func, then) + AirTree::assert_bool(name == "True", value, then, props.otherwise.clone()) } Pattern::Constructor { .. } if tipo.is_void() => { @@ -1308,7 +1321,7 @@ impl<'a> CodeGenerator<'a> { kind: props.kind, remove_unused: true, full_check: props.full_check, - msg_func: props.msg_func.clone(), + otherwise: props.otherwise.clone(), }, ) } else { @@ -1331,17 +1344,25 @@ impl<'a> CodeGenerator<'a> { pattern.location().end ); + let subject_name = format!( + "__subject_{}_span_{}_{}", + name, + pattern.location().start, + pattern.location().end + ); + let local_value = AirTree::local_var(&constructor_name, tipo.clone()); let then = if check_replaceable_opaque_type(tipo, &self.data_types) { AirTree::let_assignment(&fields[0].1, local_value, then) } else { - let (is_expect, msg) = if props.full_check { - (true, props.msg_func.clone()) - } else { - (false, None) - }; - AirTree::fields_expose(fields, local_value, msg, is_expect, then) + AirTree::fields_expose( + fields, + local_value, + props.full_check, + then, + props.otherwise.clone(), + ) }; let data_type = lookup_data_type_by_tipo(&self.data_types, tipo) @@ -1359,13 +1380,20 @@ impl<'a> CodeGenerator<'a> { panic!("Found constructor type {} with 0 constructors", name) }); - AirTree::assert_constr_index( - index, + AirTree::when( + &subject_name, + void(), + tipo.clone(), AirTree::local_var(&constructor_name, tipo.clone()), - props.msg_func, - then, + AirTree::assert_constr_index( + index, + AirTree::local_var(&subject_name, tipo.clone()), + then, + props.otherwise.clone(), + ), ) } else { + assert!(data_type.constructors.len() == 1); then }; @@ -1425,7 +1453,7 @@ impl<'a> CodeGenerator<'a> { kind: props.kind, remove_unused: true, full_check: props.full_check, - msg_func: props.msg_func.clone(), + otherwise: props.otherwise.clone(), }, ) } else { @@ -1439,15 +1467,16 @@ impl<'a> CodeGenerator<'a> { fields.reverse(); - let (is_expect, msg) = if props.full_check { - (true, props.msg_func) - } else { - (false, None) - }; - // This `value` is either value param that was passed in or local var - AirTree::tuple_access(fields, tipo.clone(), value, msg, is_expect, then) + AirTree::tuple_access( + fields, + tipo.clone(), + value, + props.full_check, + then, + props.otherwise.clone(), + ) } } } @@ -1458,7 +1487,7 @@ impl<'a> CodeGenerator<'a> { value: AirTree, defined_data_types: &mut IndexMap, location: Span, - msg_func: Option, + otherwise: AirTree, ) -> AirTree { assert!(tipo.get_generic().is_none()); // Shouldn't be needed but still here just in case @@ -1468,6 +1497,7 @@ impl<'a> CodeGenerator<'a> { match uplc_type { // primitives + // Untyped Data Some( UplcType::Integer | UplcType::String @@ -1476,10 +1506,9 @@ impl<'a> CodeGenerator<'a> { | UplcType::Unit | UplcType::Bls12_381G1Element | UplcType::Bls12_381G2Element - | UplcType::Bls12_381MlResult, + | UplcType::Bls12_381MlResult + | UplcType::Data, ) => value, - // Untyped Data - Some(UplcType::Data) => value, // Map type Some(UplcType::List(_)) if tipo.is_map() => { @@ -1500,7 +1529,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(fst_name.clone(), inner_pair_types[0].clone()), defined_data_types, location, - msg_func.clone(), + otherwise.clone(), ); let expect_snd = self.expect_type_assign( @@ -1508,7 +1537,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(snd_name.clone(), inner_pair_types[1].clone()), defined_data_types, location, - msg_func.clone(), + otherwise.clone(), ); let anon_func_body = AirTree::pair_access( @@ -1516,12 +1545,12 @@ impl<'a> CodeGenerator<'a> { Some(snd_name), inner_list_type.clone(), AirTree::local_var(&pair_name, inner_list_type.clone()), - msg_func.clone(), true, AirTree::let_assignment("_", expect_fst, expect_snd), + otherwise.clone(), ); - let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body); + let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body, false); let function = self.code_gen_functions.get(EXPECT_ON_LIST); @@ -1587,7 +1616,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(&tuple_index_name, arg.clone()), defined_data_types, location, - msg_func.clone(), + otherwise.clone(), ); tuple_expect_items.push(tuple_index_name); @@ -1602,9 +1631,9 @@ impl<'a> CodeGenerator<'a> { tuple_expect_items, tipo.clone(), AirTree::local_var(&tuple_name, tipo.clone()), - msg_func, true, then, + otherwise, ); AirTree::let_assignment(&tuple_name, value, tuple_access) @@ -1626,16 +1655,18 @@ impl<'a> CodeGenerator<'a> { AirTree::cast_from_data( AirTree::local_var(&item_name, data()), inner_list_type.clone(), - msg_func.clone(), + otherwise.clone(), + true, ), defined_data_types, location, - msg_func, + otherwise, ); let anon_func_body = expect_item; - let unwrap_function = AirTree::anon_func(vec![item_name], anon_func_body); + let unwrap_function = + AirTree::anon_func(vec![item_name], anon_func_body, false); let function = self.code_gen_functions.get(EXPECT_ON_LIST); @@ -1701,7 +1732,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(fst_name.clone(), tuple_inner_types[0].clone()), defined_data_types, location, - msg_func.clone(), + otherwise.clone(), ); let expect_snd = self.expect_type_assign( @@ -1709,7 +1740,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(snd_name.clone(), tuple_inner_types[1].clone()), defined_data_types, location, - msg_func.clone(), + otherwise.clone(), ); let pair_access = AirTree::pair_access( @@ -1717,9 +1748,9 @@ impl<'a> CodeGenerator<'a> { Some(snd_name.clone()), tipo.clone(), AirTree::local_var(&pair_name, tipo.clone()), - msg_func.clone(), true, AirTree::let_assignment("_", expect_fst, expect_snd), + otherwise, ); AirTree::let_assignment(&pair_name, value, pair_access) @@ -1757,28 +1788,13 @@ impl<'a> CodeGenerator<'a> { // mutate code_gen_funcs and defined_data_types in this if branch if function.is_none() && defined_data_types.get(&data_type_name).is_none() { - let (msg_term, error_term) = match self.tracing { - TraceLevel::Silent => (None, AirTree::error(tipo.clone(), false)), - TraceLevel::Compact | TraceLevel::Verbose => { - let msg = AirMsg::LocalVar("__param_msg".to_string()); - ( - Some(msg.clone()), - AirTree::trace( - msg.to_air_tree(), - tipo.clone(), - AirTree::error(tipo.clone(), false), - ), - ) - } - }; - defined_data_types.insert(data_type_name.clone(), 1); let current_defined = defined_data_types.clone(); let mut diff_defined_types = vec![]; let constr_clauses = data_type.constructors.iter().enumerate().rfold( - error_term, + otherwise.clone(), |acc, (index, constr)| { let mut constr_args = vec![]; @@ -1800,7 +1816,7 @@ impl<'a> CodeGenerator<'a> { AirTree::local_var(arg_name, arg_tipo), defined_data_types, location, - msg_term.clone(), + otherwise.clone(), ), then, ) @@ -1817,8 +1833,8 @@ impl<'a> CodeGenerator<'a> { ), tipo.clone(), ), - msg_term.clone(), constr_then, + otherwise.clone(), ) } else { AirTree::fields_expose( @@ -1830,19 +1846,28 @@ impl<'a> CodeGenerator<'a> { ), tipo.clone(), ), - msg_term.clone(), true, constr_then, + otherwise.clone(), ) }; - AirTree::clause( - format!("__subject_span_{}_{}", location.start, location.end), - AirTree::int(index), - tipo.clone(), - then, - acc, - false, + // Special case here for future refactoring + AirTree::anon_func( + vec![], + AirTree::assert_constr_index( + index, + AirTree::local_var( + format!( + "__subject_span_{}_{}", + location.start, location.end + ), + tipo.clone(), + ), + then, + acc, + ), + true, ) }, ); @@ -1855,7 +1880,7 @@ impl<'a> CodeGenerator<'a> { format!("__constr_var_span_{}_{}", location.start, location.end), tipo.clone(), ), - constr_clauses, + AirTree::call(constr_clauses, void(), vec![]), ); let func_body = AirTree::let_assignment( @@ -1895,12 +1920,7 @@ impl<'a> CodeGenerator<'a> { let args = match self.tracing { TraceLevel::Silent => vec![value], - TraceLevel::Compact | TraceLevel::Verbose => vec![ - value, - msg_func - .expect("should be unreachable: no msg func with tracing enabled.") - .to_air_tree(), - ], + TraceLevel::Compact | TraceLevel::Verbose => vec![value, otherwise], }; let module_fn = ValueConstructorVariant::ModuleFn { @@ -2459,9 +2479,9 @@ impl<'a> CodeGenerator<'a> { // One special usage of list access here // So for the msg we pass in empty string if tracing is on // Since check_last_item is false this will never get added to the final uplc anyway - None, ExpectLevel::None, elems_then, + AirTree::error(void(), false), ) } else { assert!(defined_tails.len() >= elems.len()); @@ -2540,9 +2560,9 @@ impl<'a> CodeGenerator<'a> { name_index_assigns[1].0.clone(), subject_tipo.clone(), AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()), - None, false, next_then, + AirTree::error(void(), false), ) }; @@ -2667,9 +2687,9 @@ impl<'a> CodeGenerator<'a> { AirTree::fields_expose( fields, AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()), - None, false, next_then, + AirTree::error(void(), false), ) }; @@ -2796,9 +2816,9 @@ impl<'a> CodeGenerator<'a> { names, subject_tipo.clone(), AirTree::local_var(&props.clause_var_name, subject_tipo.clone()), - None, false, tuple_name_assigns, + AirTree::error(void(), false), ), ) } else { @@ -3020,7 +3040,7 @@ impl<'a> CodeGenerator<'a> { itertools::Position::First(arg) if has_context => { let arg_name = arg.arg_name.get_variable_name().unwrap_or("_").to_string(); - AirTree::anon_func(vec![arg_name], inner_then) + AirTree::anon_func(vec![arg_name], inner_then, true) } itertools::Position::First(arg) | itertools::Position::Middle(arg) @@ -3034,33 +3054,32 @@ impl<'a> CodeGenerator<'a> { let actual_type = convert_opaque_type(&arg.tipo, &self.data_types, true); - let msg_func = match self.tracing { - TraceLevel::Silent => None, - TraceLevel::Compact | TraceLevel::Verbose => { - let msg = match self.tracing { - TraceLevel::Silent => { - unreachable!("excluded from pattern guards") - } - TraceLevel::Compact => lines - .line_and_column_number(arg_span.start) - .expect("Out of bounds span") - .to_string(), - TraceLevel::Verbose => src_code - .get(arg_span.start..arg_span.end) - .expect("Out of bounds span") - .to_string(), - }; + let otherwise_delayed = { + let msg = match self.tracing { + TraceLevel::Silent => "".to_string(), + TraceLevel::Compact => lines + .line_and_column_number(arg_span.start) + .expect("Out of bounds span") + .to_string(), + TraceLevel::Verbose => src_code + .get(arg_span.start..arg_span.end) + .expect("Out of bounds span") + .to_string(), + }; - let msg_func_name = msg.split_whitespace().join(""); + let msg_func_name = msg.split_whitespace().join(""); - self.special_functions.insert_new_function( - msg_func_name.to_string(), - Term::string(msg), - string(), - ); + self.special_functions.insert_new_function( + msg_func_name.clone(), + if msg.is_empty() { + Term::Error.delay() + } else { + Term::Error.delayed_trace(Term::string(msg)).delay() + }, + void(), + ); - Some(self.special_functions.use_function_msg(msg_func_name)) - } + self.special_functions.use_function_tree(msg_func_name) }; let inner_then = self.assignment( @@ -3076,11 +3095,11 @@ impl<'a> CodeGenerator<'a> { kind: AssignmentKind::expect(), remove_unused: false, full_check: true, - msg_func, + otherwise: otherwise_delayed, }, ); - AirTree::anon_func(vec![arg_name], inner_then) + AirTree::anon_func(vec![arg_name], inner_then, true) } itertools::Position::Only(_) => unreachable!(), }) @@ -3107,7 +3126,7 @@ impl<'a> CodeGenerator<'a> { &mut used_functions, &mut TreePath::new(), 0, - 0, + Fields::FirstField, ); validator_hoistable = used_functions.clone(); @@ -3761,7 +3780,7 @@ impl<'a> CodeGenerator<'a> { current_function_deps, &mut function_tree_path, depth + 1, - 0, + Fields::FirstField, ); for (generic_function_key, variant_name) in current_function_deps.iter() { @@ -3787,7 +3806,7 @@ impl<'a> CodeGenerator<'a> { dependency_functions: &mut Vec<(FunctionAccessKey, String)>, path: &mut TreePath, current_depth: usize, - depth_index: usize, + depth_index: Fields, ) { air_tree.traverse_tree_with_path( path, @@ -3850,7 +3869,7 @@ impl<'a> CodeGenerator<'a> { let mut function_variant_path = IndexMap::new(); - let mut body = body.clone(); + let mut body = AirTree::no_op(body.clone()); body.traverse_tree_with( &mut |air_tree, _| { @@ -3937,11 +3956,11 @@ impl<'a> CodeGenerator<'a> { }) .collect_vec(); - let mut function_air_tree_body = self.build( + let mut function_air_tree_body = AirTree::no_op(self.build( &function_def.body, &generic_function_key.module_name, &[], - ); + )); function_air_tree_body.traverse_tree_with( &mut |air_tree, _| { @@ -3970,8 +3989,11 @@ impl<'a> CodeGenerator<'a> { .map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string()) .collect_vec(); - let mut function_air_tree_body = - self.build(&function_def.body, &generic_function_key.module_name, &[]); + let mut function_air_tree_body = AirTree::no_op(self.build( + &function_def.body, + &generic_function_key.module_name, + &[], + )); function_air_tree_body.traverse_tree_with( &mut |air_tree, _| { @@ -4017,24 +4039,11 @@ impl<'a> CodeGenerator<'a> { } fn gen_uplc(&mut self, ir: Air, arg_stack: &mut Vec>) -> Option> { - // Going to mark the changes made to code gen after air tree implementation - let error_term = match self.tracing { - TraceLevel::Silent => Term::Error, - TraceLevel::Compact | TraceLevel::Verbose => { - if air_holds_msg(&ir) { - let msg = arg_stack.pop().unwrap(); - Term::Error.delayed_trace(msg) - } else { - Term::Error - } - } - }; - - let convert_data_to_type = |term, tipo| { - if error_term == Term::Error { + let convert_data_to_type = |term, tipo, otherwise| { + if otherwise == Term::Error.delay() { builder::unknown_data_to_type(term, tipo) } else { - builder::unknown_data_to_type_debug(term, tipo, error_term.clone()) + builder::unknown_data_to_type_otherwise(term, tipo, otherwise) } }; @@ -4337,6 +4346,12 @@ impl<'a> CodeGenerator<'a> { let mut term = arg_stack.pop().unwrap(); + let otherwise = if matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) { + arg_stack.pop().unwrap() + } else { + Term::Error.delay() + }; + let list_id = self.id_gen.next(); let mut id_list = vec![]; @@ -4362,7 +4377,7 @@ impl<'a> CodeGenerator<'a> { term, true, expect_level, - error_term, + otherwise, ) .apply(value); @@ -4397,17 +4412,25 @@ impl<'a> CodeGenerator<'a> { Some(term) } - Air::Fn { params } => { + Air::Fn { + params, + allow_inline, + } => { let mut term = arg_stack.pop().unwrap(); for param in params.iter().rev() { term = term.lambda(param); } + term = if allow_inline { + term + } else { + term.lambda(NO_INLINE) + }; if params.is_empty() { - Some(term.lambda(NO_INLINE).delay()) + Some(term.delay()) } else { - Some(term.lambda(NO_INLINE)) + Some(term) } } Air::Call { count, .. } => { @@ -4425,61 +4448,62 @@ impl<'a> CodeGenerator<'a> { // How we handle zero arg anon functions has changed // We now delay zero arg anon functions and force them on a call operation - if let Term::Var(name) = &term { - let zero_arg_functions = self.zero_arg_functions.clone(); - let text = &name.text; - - if let Some((_, air_vec)) = zero_arg_functions.iter().find( - |( - ( - FunctionAccessKey { - module_name, - function_name, - }, - variant, - ), - _, - )| { - let name_module = format!("{module_name}_{function_name}{variant}"); - let name = format!("{function_name}{variant}"); + match &term { + Term::Var(name) => { + let zero_arg_functions = self.zero_arg_functions.clone(); + let text = &name.text; + + if let Some((_, air_vec)) = zero_arg_functions.iter().find( + |( + ( + FunctionAccessKey { + module_name, + function_name, + }, + variant, + ), + _, + )| { + let name_module = + format!("{module_name}_{function_name}{variant}"); + let name = format!("{function_name}{variant}"); - text == &name || text == &name_module - }, - ) { - let mut term = self.uplc_code_gen(air_vec.clone()); + text == &name || text == &name_module + }, + ) { + let mut term = self.uplc_code_gen(air_vec.clone()); - term = term.constr_fields_exposer().constr_index_exposer(); + term = term.constr_fields_exposer().constr_index_exposer(); - let mut program: Program = Program { - version: (1, 0, 0), - term: self.special_functions.apply_used_functions(term), - }; + let mut program: Program = Program { + version: (1, 0, 0), + term: self.special_functions.apply_used_functions(term), + }; - let mut interner = CodeGenInterner::new(); + let mut interner = CodeGenInterner::new(); - interner.program(&mut program); + interner.program(&mut program); - let eval_program: Program = - program.remove_no_inlines().try_into().unwrap(); + let eval_program: Program = + program.remove_no_inlines().try_into().unwrap(); - let result = eval_program.eval(ExBudget::max()).result(); + let result = eval_program.eval(ExBudget::max()).result(); - let evaluated_term: Term = result.unwrap_or_else(|e| { - panic!("Evaluated a zero argument function and received this error: {e:#?}") - }); + let evaluated_term: Term = result.unwrap_or_else(|e| { + panic!("Evaluated a zero argument function and received this error: {e:#?}") + }); - Some(evaluated_term.try_into().unwrap()) - } else { - Some(term.force()) + Some(evaluated_term.try_into().unwrap()) + } else { + Some(term.force()) + } } - } else if let Term::Apply { .. } = &term { - // Case for mutually recursive zero arg functions - Some(term.force()) - } else { - unreachable!( - "Shouldn't call anything other than var or apply {:#?}", + Term::Delay(inner_term) => Some(inner_term.as_ref().clone()), + Term::Apply { .. } => Some(term.force()), + _ => unreachable!( + "Shouldn't call anything other than var or apply\n{:#?}", term - ) + ), } } } @@ -4772,10 +4796,20 @@ impl<'a> CodeGenerator<'a> { Some(term) } - Air::CastFromData { tipo, .. } => { + Air::CastFromData { tipo, full_cast } => { let mut term = arg_stack.pop().unwrap(); - term = convert_data_to_type(term, &tipo); + let otherwise = if full_cast { + arg_stack.pop().unwrap() + } else { + Term::Error.delay() + }; + + term = if full_cast { + convert_data_to_type(term, &tipo, otherwise) + } else { + known_data_to_type(term, &tipo) + }; if extract_constant(&term).is_some() { let mut program: Program = Program { @@ -4834,17 +4868,13 @@ impl<'a> CodeGenerator<'a> { let constr = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = arg_stack.pop().unwrap(); term = Term::equals_integer() .apply(Term::integer(constr_index.into())) - .apply( - Term::var( - self.special_functions - .use_function_uplc(CONSTR_INDEX_EXPOSER.to_string()), - ) - .apply(constr), - ) - .delayed_if_then_else(term, error_term); + .apply(constr) + .if_then_else(term.delay(), otherwise) + .force(); Some(term) } @@ -4852,11 +4882,12 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = arg_stack.pop().unwrap(); if is_true { - term = value.delayed_if_then_else(term, error_term) + term = value.if_then_else(term.delay(), otherwise).force() } else { - term = value.delayed_if_then_else(error_term, term) + term = value.if_then_else(otherwise, term.delay()).force() } Some(term) } @@ -5286,6 +5317,13 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + + let otherwise = if is_expect { + arg_stack.pop().unwrap() + } else { + Term::Error.delay() + }; + let list_id = self.id_gen.next(); id_list.push(list_id); @@ -5313,7 +5351,7 @@ impl<'a> CodeGenerator<'a> { term, false, is_expect.into(), - error_term, + otherwise, ); term = term.apply( @@ -5333,13 +5371,15 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = arg_stack.pop().unwrap(); term = Term::var( self.special_functions .use_function_uplc(CONSTR_FIELDS_EXPOSER.to_string()), ) .apply(value) - .delayed_choose_list(term, error_term); + .choose_list(term.delay(), otherwise) + .force(); Some(term) } @@ -5347,8 +5387,9 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = arg_stack.pop().unwrap(); - term = value.delayed_choose_list(term, error_term); + term = value.choose_list(term.delay(), otherwise).force(); Some(term) } @@ -5545,6 +5586,11 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = if is_expect { + arg_stack.pop().unwrap() + } else { + Term::Error.delay() + }; let list_id = self.id_gen.next(); let mut id_list = vec![]; @@ -5567,7 +5613,7 @@ impl<'a> CodeGenerator<'a> { term, false, is_expect.into(), - error_term, + otherwise, ) .apply(value); @@ -5583,6 +5629,12 @@ impl<'a> CodeGenerator<'a> { let value = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap(); + let otherwise = if is_expect { + arg_stack.pop().unwrap() + } else { + Term::Error.delay() + }; + let list_id = self.id_gen.next(); if let Some(name) = snd { @@ -5590,6 +5642,7 @@ impl<'a> CodeGenerator<'a> { convert_data_to_type( Term::snd_pair().apply(Term::var(format!("__pair_{list_id}"))), &inner_types[1], + otherwise.clone(), ) } else { known_data_to_type( @@ -5604,6 +5657,7 @@ impl<'a> CodeGenerator<'a> { convert_data_to_type( Term::fst_pair().apply(Term::var(format!("__pair_{list_id}"))), &inner_types[0], + otherwise, ) } else { known_data_to_type( diff --git a/crates/aiken-lang/src/gen_uplc/air.rs b/crates/aiken-lang/src/gen_uplc/air.rs index a3df8503b..57a55b9cc 100644 --- a/crates/aiken-lang/src/gen_uplc/air.rs +++ b/crates/aiken-lang/src/gen_uplc/air.rs @@ -81,6 +81,7 @@ pub enum Air { }, Fn { params: Vec, + allow_inline: bool, }, Builtin { count: usize, @@ -102,7 +103,7 @@ pub enum Air { }, CastFromData { tipo: Rc, - is_expect: bool, + full_cast: bool, }, CastToData { tipo: Rc, diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index bc68b1759..4ad6b63dd 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -1,5 +1,5 @@ use super::{ - air::{Air, ExpectLevel}, + air::ExpectLevel, tree::{AirMsg, AirTree, TreePath}, }; use crate::{ @@ -71,7 +71,7 @@ pub struct AssignmentProperties { pub kind: TypedAssignmentKind, pub remove_unused: bool, pub full_check: bool, - pub msg_func: Option, + pub otherwise: AirTree, } #[derive(Clone, Debug)] @@ -659,6 +659,7 @@ pub fn modify_cyclic_calls( AirTree::anon_func( names.clone(), AirTree::local_var(index_name, tipo), + false, ), ], ); @@ -1035,123 +1036,144 @@ pub fn unknown_data_to_type(term: Term, field_type: &Type) -> Term { /// Due to the nature of the types BLS12_381_G1Element and BLS12_381_G2Element and String coming from bytearray /// We don't have error handling if the bytearray is not properly aligned to the type. Oh well lol /// For BLS12_381_G1Element and BLS12_381_G2Element, hash to group exists so just adopt that. -pub fn unknown_data_to_type_debug( +pub fn unknown_data_to_type_otherwise( term: Term, field_type: &Type, - error_term: Term, + otherwise_delayed: Term, ) -> Term { let uplc_type = field_type.get_uplc_type(); match uplc_type { Some(UplcType::Integer) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - error_term.clone(), - Term::un_i_data().apply(Term::var("__val")), - error_term.clone(), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::un_i_data().apply(Term::var("__val")).delay(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::ByteString) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), - Term::un_b_data().apply(Term::var("__val")), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::un_b_data().apply(Term::var("__val")).delay(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::String) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), - Term::decode_utf8().apply(Term::un_b_data().apply(Term::var("__val"))), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::decode_utf8() + .apply(Term::un_b_data().apply(Term::var("__val"))) + .delay(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::List(_)) if field_type.is_map() => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - Term::unmap_data().apply(Term::var("__val")), - error_term.clone(), - error_term.clone(), - error_term.clone(), + .choose_data( + otherwise_delayed.clone(), + Term::unmap_data().apply(Term::var("__val")).delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::List(_)) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - Term::unlist_data().apply(Term::var("__val")), - error_term.clone(), - error_term.clone(), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::unlist_data().apply(Term::var("__val")).delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Bls12_381G1Element) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), - Term::bls12_381_g1_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::bls12_381_g1_uncompress() + .apply(Term::un_b_data().apply(Term::var("__val"))) + .delay(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Bls12_381G2Element) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), - Term::bls12_381_g2_uncompress().apply(Term::un_b_data().apply(Term::var("__val"))), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + Term::bls12_381_g2_uncompress() + .apply(Term::un_b_data().apply(Term::var("__val"))) + .delay(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Bls12_381MlResult) => panic!("ML Result not supported"), Some(UplcType::Pair(_, _)) => Term::var("__val") - .delayed_choose_data( - error_term.clone(), - error_term.clone(), + .choose_data( + otherwise_delayed.clone(), + otherwise_delayed.clone(), Term::var("__list_data") - .delayed_choose_list( - error_term.clone(), + .choose_list( + otherwise_delayed.clone(), Term::var("__tail") - .delayed_choose_list( - error_term.clone(), + .choose_list( + otherwise_delayed.clone(), Term::tail_list() .apply(Term::var("__tail")) - .delayed_choose_list( + .choose_list( Term::mk_pair_data() .apply( Term::head_list().apply(Term::var("__list_data")), ) - .apply(Term::head_list().apply(Term::var("__tail"))), - error_term.clone(), - ), + .apply(Term::head_list().apply(Term::var("__tail"))) + .delay(), + otherwise_delayed.clone(), + ) + .force() + .delay(), ) + .force() .lambda("__tail") - .apply(Term::tail_list().apply(Term::var("__list_data"))), + .apply(Term::tail_list().apply(Term::var("__list_data"))) + .delay(), ) + .force() .lambda("__list_data") - .apply(Term::unlist_data().apply(Term::var("__val"))), - error_term.clone(), - error_term.clone(), + .apply(Term::unlist_data().apply(Term::var("__val"))) + .delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Bool) => Term::var("__val") - .delayed_choose_data( + .choose_data( Term::snd_pair() .apply(Term::var("__pair__")) - .delayed_choose_list( + .choose_list( Term::equals_integer() .apply(Term::integer(1.into())) .apply(Term::fst_pair().apply(Term::var("__pair__"))) @@ -1160,48 +1182,62 @@ pub fn unknown_data_to_type_debug( Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::fst_pair().apply(Term::var("__pair__"))) - .delayed_if_then_else(Term::bool(false), error_term.clone()), - ), - error_term.clone(), + .if_then_else( + Term::bool(false).delay(), + otherwise_delayed.clone(), + ) + .force(), + ) + .delay(), + otherwise_delayed.clone(), ) + .force() .lambda("__pair__") - .apply(Term::unconstr_data().apply(Term::var("__val"))), - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), + .apply(Term::unconstr_data().apply(Term::var("__val"))) + .delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Unit) => Term::var("__val") - .delayed_choose_data( + .choose_data( Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::fst_pair().apply(Term::unconstr_data().apply(Term::var("__val")))) - .delayed_if_then_else( + .if_then_else( Term::snd_pair() .apply(Term::unconstr_data().apply(Term::var("__val"))) - .delayed_choose_list(Term::unit(), error_term.clone()), - error_term.clone(), - ), - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), + .choose_list(Term::unit().delay(), otherwise_delayed.clone()) + .force() + .delay(), + otherwise_delayed.clone(), + ) + .force() + .delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), Some(UplcType::Data) => term, // constr type None => Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - error_term.clone(), - error_term.clone(), - error_term.clone(), - error_term.clone(), + .choose_data( + Term::var("__val").delay(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), + otherwise_delayed.clone(), ) + .force() .lambda("__val") .apply(term), } @@ -1362,7 +1398,7 @@ pub fn list_access_to_uplc( term: Term, is_list_accessor: bool, expect_level: ExpectLevel, - error_term: Term, + otherwise_delayed: Term, ) -> Term { let names_len = names_types_ids.len(); @@ -1393,7 +1429,8 @@ pub fn list_access_to_uplc( } return Term::var("empty_list") - .delayed_choose_list(term, error_term) + .choose_list(term.delay(), otherwise_delayed) + .force() .lambda("empty_list"); } @@ -1412,16 +1449,16 @@ pub fn list_access_to_uplc( Term::head_list().apply(Term::var(tail_name.to_string())) } else if matches!(expect_level, ExpectLevel::Full) { // Expect level is full so we have an unknown piece of data to cast - if error_term == Term::Error { + if otherwise_delayed == Term::Error.delay() { unknown_data_to_type( Term::head_list().apply(Term::var(tail_name.to_string())), &tipo.to_owned(), ) } else { - unknown_data_to_type_debug( + unknown_data_to_type_otherwise( Term::head_list().apply(Term::var(tail_name.to_string())), &tipo.to_owned(), - error_term.clone(), + otherwise_delayed.clone(), ) } } else { @@ -1456,36 +1493,41 @@ pub fn list_access_to_uplc( ExpectLevel::None => acc.lambda(name).apply(head_item).lambda(tail_name), ExpectLevel::Full | ExpectLevel::Items => { - if error_term == Term::Error && tail_present { + if otherwise_delayed == Term::Error.delay() && tail_present { // No need to check last item if tail was present acc.lambda(name).apply(head_item).lambda(tail_name) } else if tail_present { // Custom error instead of trying to do head_item on a possibly empty list. Term::var(tail_name.to_string()) - .delayed_choose_list( - error_term.clone(), - acc.lambda(name).apply(head_item), + .choose_list( + otherwise_delayed.clone(), + acc.lambda(name).apply(head_item).delay(), ) + .force() .lambda(tail_name) - } else if error_term == Term::Error { + } else if otherwise_delayed == Term::Error.delay() { // Check head is last item in this list Term::tail_list() .apply(Term::var(tail_name.to_string())) - .delayed_choose_list(acc, error_term.clone()) + .choose_list(acc.delay(), Term::Error.delay()) + .force() .lambda(name) .apply(head_item) .lambda(tail_name) } else { // Custom error if list is not empty after this head Term::var(tail_name.to_string()) - .delayed_choose_list( - error_term.clone(), + .choose_list( + otherwise_delayed.clone(), Term::tail_list() .apply(Term::var(tail_name.to_string())) - .delayed_choose_list(acc, error_term.clone()) + .choose_list(acc.delay(), otherwise_delayed.clone()) + .force() .lambda(name) - .apply(head_item), + .apply(head_item) + .delay(), ) + .force() .lambda(tail_name) } } @@ -1498,7 +1540,9 @@ pub fn list_access_to_uplc( let head_item = head_item(name, tipo, &tail_name); - if matches!(expect_level, ExpectLevel::None) || error_term == Term::Error { + if matches!(expect_level, ExpectLevel::None) + || otherwise_delayed == Term::Error.delay() + { acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string()))) .lambda(name) .apply(head_item) @@ -1506,14 +1550,16 @@ pub fn list_access_to_uplc( } else { // case for a custom error if the list is empty at this point Term::var(tail_name.to_string()) - .delayed_choose_list( - error_term.clone(), + .choose_list( + otherwise_delayed.clone(), acc.apply( Term::tail_list().apply(Term::var(tail_name.to_string())), ) .lambda(name) - .apply(head_item), + .apply(head_item) + .delay(), ) + .force() .lambda(tail_name) } } @@ -1778,7 +1824,6 @@ pub fn cast_validator_args(term: Term, arguments: &[TypedArg]) -> Term AirTree { - let success_branch = vec![(air_tree, AirTree::void())]; let otherwise = match trace { TraceLevel::Silent | TraceLevel::Compact => AirTree::error(void(), true), TraceLevel::Verbose => AirTree::trace( @@ -1788,7 +1833,7 @@ pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree ), }; - AirTree::if_branches(success_branch, void(), otherwise) + AirTree::if_branch(void(), air_tree, AirTree::void(), otherwise) } pub fn extract_constant(term: &Term) -> Option> { @@ -1841,22 +1886,3 @@ pub fn get_line_columns_by_span( .line_and_column_number(span.start) .expect("Out of bounds span") } - -pub fn air_holds_msg(air: &Air) -> bool { - match air { - Air::AssertConstr { .. } | Air::AssertBool { .. } | Air::FieldsEmpty | Air::ListEmpty => { - true - } - - Air::FieldsExpose { is_expect, .. } - | Air::TupleAccessor { is_expect, .. } - | Air::PairAccessor { is_expect, .. } - | Air::CastFromData { is_expect, .. } => *is_expect, - - Air::ListAccessor { expect_level, .. } => { - matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) - } - - _ => false, - } -} diff --git a/crates/aiken-lang/src/gen_uplc/tree.rs b/crates/aiken-lang/src/gen_uplc/tree.rs index de07950f9..d3d9f13c2 100644 --- a/crates/aiken-lang/src/gen_uplc/tree.rs +++ b/crates/aiken-lang/src/gen_uplc/tree.rs @@ -9,9 +9,22 @@ use itertools::Itertools; use std::{borrow::BorrowMut, rc::Rc, slice::Iter}; use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; +#[derive(Clone, Debug, PartialEq, Copy)] +pub enum Fields { + FirstField, + SecondField, + ThirdField, + FourthField, + FifthField, + SixthField, + SeventhField, + EighthField, + ArgsField(usize), +} + #[derive(Clone, Debug, PartialEq)] pub struct TreePath { - path: Vec<(usize, usize)>, + path: Vec<(usize, Fields)>, } impl TreePath { @@ -23,11 +36,11 @@ impl TreePath { self.path.is_empty() } - pub fn push(&mut self, depth: usize, index: usize) { + pub fn push(&mut self, depth: usize, index: Fields) { self.path.push((depth, index)); } - pub fn pop(&mut self) -> Option<(usize, usize)> { + pub fn pop(&mut self) -> Option<(usize, Fields)> { self.path.pop() } @@ -133,14 +146,14 @@ pub enum AirTree { AssertConstr { constr_index: usize, constr: Box, - msg: Option, then: Box, + otherwise: Box, }, AssertBool { is_true: bool, value: Box, - msg: Option, then: Box, + otherwise: Box, }, // Clause Guards ClauseGuard { @@ -174,8 +187,8 @@ pub enum AirTree { indices: Vec<(usize, String, Rc)>, record: Box, is_expect: bool, - msg: Option, then: Box, + otherwise: Box, }, // List Access ListAccessor { @@ -184,8 +197,8 @@ pub enum AirTree { tail: bool, list: Box, expect_level: ExpectLevel, - msg: Option, then: Box, + otherwise: Box, }, ListExpose { tipo: Rc, @@ -199,8 +212,8 @@ pub enum AirTree { tipo: Rc, tuple: Box, is_expect: bool, - msg: Option, then: Box, + otherwise: Box, }, // Pair Access PairAccessor { @@ -208,20 +221,20 @@ pub enum AirTree { snd: Option, tipo: Rc, is_expect: bool, - msg: Option, pair: Box, then: Box, + otherwise: Box, }, // Misc. FieldsEmpty { constr: Box, - msg: Option, then: Box, + otherwise: Box, }, ListEmpty { list: Box, - msg: Option, then: Box, + otherwise: Box, }, NoOp { then: Box, @@ -275,6 +288,7 @@ pub enum AirTree { Fn { params: Vec, func_body: Box, + allow_inline: bool, }, Builtin { func: DefaultFunction, @@ -297,7 +311,8 @@ pub enum AirTree { CastFromData { tipo: Rc, value: Box, - msg: Option, + otherwise: Box, + full_cast: bool, }, CastToData { tipo: Rc, @@ -359,7 +374,7 @@ pub enum AirTree { // If If { tipo: Rc, - pattern: Box, + condition: Box, then: Box, otherwise: Box, }, @@ -390,6 +405,10 @@ pub enum AirTree { } impl AirTree { + pub fn is_error(&self) -> bool { + matches!(self, AirTree::ErrorTerm { .. }) + } + pub fn int(value: impl ToString) -> AirTree { AirTree::Int { value: value.to_string(), @@ -520,10 +539,11 @@ impl AirTree { } } - pub fn anon_func(params: Vec, func_body: AirTree) -> AirTree { + pub fn anon_func(params: Vec, func_body: AirTree, allow_inline: bool) -> AirTree { AirTree::Fn { params, func_body: func_body.into(), + allow_inline, } } @@ -562,11 +582,17 @@ impl AirTree { } } - pub fn cast_from_data(value: AirTree, tipo: Rc, msg: Option) -> AirTree { + pub fn cast_from_data( + value: AirTree, + tipo: Rc, + otherwise: AirTree, + full_cast: bool, + ) -> AirTree { AirTree::CastFromData { tipo, value: value.into(), - msg, + otherwise: otherwise.into(), + full_cast, } } @@ -580,28 +606,28 @@ impl AirTree { pub fn assert_constr_index( constr_index: usize, constr: AirTree, - msg: Option, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::AssertConstr { constr_index, constr: constr.into(), - msg, then: then.into(), + otherwise: otherwise.into(), } } pub fn assert_bool( is_true: bool, value: AirTree, - msg: Option, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::AssertBool { is_true, value: value.into(), - msg, then: then.into(), + otherwise: otherwise.into(), } } @@ -771,31 +797,18 @@ impl AirTree { } } - pub fn if_branches( - mut branches: Vec<(AirTree, AirTree)>, + pub fn if_branch( tipo: Rc, + condition: AirTree, + branch: AirTree, otherwise: AirTree, ) -> AirTree { - assert!(!branches.is_empty()); - let last_if = branches.pop().unwrap(); - - let mut final_if = AirTree::If { - tipo: tipo.clone(), - pattern: Box::new(last_if.0), - then: Box::new(last_if.1), + AirTree::If { + tipo, + condition: condition.into(), + then: branch.into(), otherwise: otherwise.into(), - }; - - while let Some(branch) = branches.pop() { - final_if = AirTree::If { - tipo: tipo.clone(), - pattern: Box::new(branch.0), - then: Box::new(branch.1), - otherwise: final_if.into(), - }; } - - final_if } pub fn create_constr(tag: usize, tipo: Rc, args: Vec) -> AirTree { @@ -845,23 +858,24 @@ impl AirTree { vec![list_of_fields], ), tipo.clone(), - None, + AirTree::error(void(), false), + false, ) } pub fn fields_expose( indices: Vec<(usize, String, Rc)>, record: AirTree, - msg: Option, is_expect: bool, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::FieldsExpose { indices, record: record.into(), - msg, is_expect, then: then.into(), + otherwise: otherwise.into(), } } @@ -870,9 +884,10 @@ impl AirTree { tipo: Rc, tail: bool, list: AirTree, - msg: Option, + expect_level: ExpectLevel, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::ListAccessor { tipo, @@ -880,8 +895,8 @@ impl AirTree { tail, list: list.into(), expect_level, - msg, then: then.into(), + otherwise: otherwise.into(), } } @@ -903,17 +918,17 @@ impl AirTree { names: Vec, tipo: Rc, tuple: AirTree, - msg: Option, is_expect: bool, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::TupleAccessor { names, tipo, tuple: tuple.into(), - msg, is_expect, then: then.into(), + otherwise: otherwise.into(), } } @@ -922,18 +937,18 @@ impl AirTree { snd: Option, tipo: Rc, pair: AirTree, - msg: Option, is_expect: bool, then: AirTree, + otherwise: AirTree, ) -> AirTree { AirTree::PairAccessor { fst, snd, tipo, is_expect, - msg, pair: pair.into(), then: then.into(), + otherwise: otherwise.into(), } } @@ -949,7 +964,8 @@ impl AirTree { vec![tuple], ), tipo.clone(), - None, + AirTree::error(void(), false), + false, ) } @@ -968,19 +984,20 @@ impl AirTree { AirTree::NoOp { then: then.into() } } - pub fn fields_empty(constr: AirTree, msg: Option, then: AirTree) -> AirTree { + pub fn fields_empty(constr: AirTree, then: AirTree, otherwise: AirTree) -> AirTree { AirTree::FieldsEmpty { constr: constr.into(), - msg, then: then.into(), + otherwise: otherwise.into(), } } - pub fn list_empty(list: AirTree, msg: Option, then: AirTree) -> AirTree { + pub fn list_empty(list: AirTree, then: AirTree, otherwise: AirTree) -> AirTree { AirTree::ListEmpty { list: list.into(), - msg, + then: then.into(), + otherwise: otherwise.into(), } } @@ -1114,8 +1131,8 @@ impl AirTree { AirTree::AssertConstr { constr, constr_index, - msg, then, + otherwise, } => { air_vec.push(Air::AssertConstr { constr_index: *constr_index, @@ -1123,27 +1140,21 @@ impl AirTree { // msg is first so we can pop it off first in uplc_gen // if traces are on - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - constr.create_air_vec(air_vec); then.create_air_vec(air_vec); + otherwise.create_air_vec(air_vec); } AirTree::AssertBool { is_true, value, - msg, then, + otherwise, } => { air_vec.push(Air::AssertBool { is_true: *is_true }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - value.create_air_vec(air_vec); then.create_air_vec(air_vec); + otherwise.create_air_vec(air_vec); } AirTree::ClauseGuard { subject_name, @@ -1205,30 +1216,29 @@ impl AirTree { AirTree::FieldsExpose { indices, record, - msg, is_expect, then, + otherwise, } => { air_vec.push(Air::FieldsExpose { indices: indices.clone(), is_expect: *is_expect, }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - record.create_air_vec(air_vec); then.create_air_vec(air_vec); + if *is_expect { + otherwise.create_air_vec(air_vec); + } } AirTree::ListAccessor { tipo, names, tail, list, - msg, expect_level, then, + otherwise, } => { air_vec.push(Air::ListAccessor { tipo: tipo.clone(), @@ -1237,12 +1247,11 @@ impl AirTree { expect_level: *expect_level, }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - list.create_air_vec(air_vec); then.create_air_vec(air_vec); + if matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) { + otherwise.create_air_vec(air_vec); + } } AirTree::ListExpose { tipo, @@ -1261,9 +1270,9 @@ impl AirTree { names, tipo, tuple, - msg, is_expect, then, + otherwise, } => { air_vec.push(Air::TupleAccessor { names: names.clone(), @@ -1271,21 +1280,20 @@ impl AirTree { is_expect: *is_expect, }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - tuple.create_air_vec(air_vec); then.create_air_vec(air_vec); + if *is_expect { + otherwise.create_air_vec(air_vec); + } } AirTree::PairAccessor { fst, snd, tipo, is_expect, - msg, pair, then, + otherwise, } => { air_vec.push(Air::PairAccessor { fst: fst.clone(), @@ -1294,32 +1302,33 @@ impl AirTree { is_expect: *is_expect, }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - pair.create_air_vec(air_vec); then.create_air_vec(air_vec); + if *is_expect { + otherwise.create_air_vec(air_vec); + } } - AirTree::FieldsEmpty { constr, msg, then } => { + AirTree::FieldsEmpty { + constr, + then, + otherwise, + } => { air_vec.push(Air::FieldsEmpty); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - constr.create_air_vec(air_vec); then.create_air_vec(air_vec); + otherwise.create_air_vec(air_vec); } - AirTree::ListEmpty { list, msg, then } => { + AirTree::ListEmpty { + list, + then, + otherwise, + } => { air_vec.push(Air::ListEmpty); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - list.create_air_vec(air_vec); then.create_air_vec(air_vec); + otherwise.create_air_vec(air_vec); } AirTree::NoOp { then } => { air_vec.push(Air::NoOp); @@ -1381,9 +1390,14 @@ impl AirTree { arg.create_air_vec(air_vec); } } - AirTree::Fn { params, func_body } => { + AirTree::Fn { + params, + func_body, + allow_inline, + } => { air_vec.push(Air::Fn { params: params.clone(), + allow_inline: *allow_inline, }); func_body.create_air_vec(air_vec); } @@ -1417,17 +1431,21 @@ impl AirTree { air_vec.push(Air::UnOp { op: *op }); arg.create_air_vec(air_vec); } - AirTree::CastFromData { tipo, value, msg } => { + AirTree::CastFromData { + tipo, + value, + otherwise, + full_cast, + } => { air_vec.push(Air::CastFromData { tipo: tipo.clone(), - is_expect: msg.is_some(), + full_cast: *full_cast, }); - if let Some(msg) = msg { - msg.to_air_tree().create_air_vec(air_vec); - } - value.create_air_vec(air_vec); + if *full_cast { + otherwise.create_air_vec(air_vec); + } } AirTree::CastToData { tipo, value } => { air_vec.push(Air::CastToData { tipo: tipo.clone() }); @@ -1532,7 +1550,7 @@ impl AirTree { } AirTree::If { tipo, - pattern, + condition: pattern, then, otherwise, } => { @@ -1717,14 +1735,20 @@ impl AirTree { apply_with_func_last: bool, ) { let mut tree_path = TreePath::new(); - self.do_traverse_tree_with(&mut tree_path, 0, 0, with, apply_with_func_last); + self.do_traverse_tree_with( + &mut tree_path, + 0, + Fields::FirstField, + with, + apply_with_func_last, + ); } pub fn traverse_tree_with_path( &mut self, path: &mut TreePath, current_depth: usize, - depth_index: usize, + depth_index: Fields, with: &mut impl FnMut(&mut AirTree, &TreePath), apply_with_func_last: bool, ) { @@ -1735,138 +1759,270 @@ impl AirTree { &mut self, tree_path: &mut TreePath, current_depth: usize, - depth_index: usize, + field_index: Fields, with: &mut impl FnMut(&mut AirTree, &TreePath), apply_with_func_last: bool, ) { - let mut index_count = IndexCounter::new(); - tree_path.push(current_depth, depth_index); - let mut tuple_then_index = None; + tree_path.push(current_depth, field_index); // Assignments'/Statements' values get traversed here // Then the body under these assignments/statements get traversed later on match self { - AirTree::Let { value, .. } => { + AirTree::Let { + name: _, + value, + then: _, + } => { value.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } - AirTree::AssertConstr { constr, .. } => { + AirTree::AssertConstr { + constr_index: _, + constr, + then: _, + otherwise, + } => { constr.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ) } - AirTree::AssertBool { value, .. } => { + AirTree::AssertBool { + is_true: _, + value, + then: _, + otherwise, + } => { value.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ) } - AirTree::ClauseGuard { pattern, .. } => { + AirTree::ClauseGuard { + subject_name: _, + subject_tipo: _, + pattern, + then: _, + } => { pattern.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); } - AirTree::FieldsExpose { record, .. } => { + AirTree::FieldsExpose { + indices: _, + record, + is_expect: _, + then: _, + otherwise, + } => { record.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FifthField, + with, + apply_with_func_last, + ) } - AirTree::ListAccessor { list, .. } => { + AirTree::ListAccessor { + tipo: _, + names: _, + tail: _, + list, + expect_level: _, + then: _, + otherwise, + } => { list.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FourthField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SeventhField, + with, + apply_with_func_last, + ) } - AirTree::TupleAccessor { tuple, .. } => { + AirTree::TupleAccessor { + names: _, + tipo: _, + tuple, + is_expect: _, + then: _, + otherwise, + } => { tuple.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SixthField, + with, + apply_with_func_last, + ) } - AirTree::PairAccessor { pair, .. } => { + AirTree::PairAccessor { + fst: _, + snd: _, + tipo: _, + is_expect: _, + pair, + then: _, + otherwise, + } => { pair.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FifthField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SeventhField, + with, + apply_with_func_last, + ) } - AirTree::FieldsEmpty { constr, .. } => { + AirTree::FieldsEmpty { + constr, + then: _, + otherwise, + } => { constr.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FirstField, + with, + apply_with_func_last, + ); + + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::ThirdField, with, apply_with_func_last, ); } - AirTree::ListEmpty { list, .. } => { + AirTree::ListEmpty { + list, + then: _, + otherwise, + } => { list.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FirstField, with, apply_with_func_last, ); + otherwise.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::ThirdField, + with, + apply_with_func_last, + ) } - AirTree::When { subject, .. } => subject.do_traverse_tree_with( + AirTree::When { + tipo: _, + subject_name: _, + subject, + subject_tipo: _, + clauses: _, + } => subject.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ), - AirTree::TupleClause { otherwise, .. } => { - tuple_then_index = Some(index_count.next_number()); + AirTree::TupleClause { + subject_tipo: _, + indices: _, + predefined_indices: _, + subject_name: _, + complex_clause: _, + then: _, + otherwise, + } => { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SeventhField, with, apply_with_func_last, ); } - AirTree::PairClause { otherwise, .. } => { - tuple_then_index = Some(index_count.next_number()); + AirTree::PairClause { + subject_tipo: _, + subject_name: _, + fst_name: _, + snd_name: _, + complex_clause: _, + then: _, + otherwise, + } => { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SeventhField, with, apply_with_func_last, ); } + AirTree::DefineFunc { .. } | AirTree::DefineCyclicFuncs { .. } | AirTree::ListClauseGuard { .. } @@ -1908,91 +2064,95 @@ impl AirTree { // Expressions or an assignment that hoist over a expression are traversed here match self { - AirTree::Let { then, .. } - | AirTree::AssertConstr { then, .. } - | AirTree::AssertBool { then, .. } - | AirTree::ClauseGuard { then, .. } - | AirTree::FieldsExpose { then, .. } - | AirTree::ListAccessor { then, .. } - | AirTree::TupleAccessor { then, .. } - | AirTree::PairAccessor { then, .. } - | AirTree::FieldsEmpty { then, .. } - | AirTree::ListEmpty { then, .. } - | AirTree::ListExpose { then, .. } - | AirTree::ListClauseGuard { then, .. } - | AirTree::TupleGuard { then, .. } - | AirTree::PairGuard { then, .. } - | AirTree::NoOp { then } => { + AirTree::NoOp { then } => { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FirstField, with, apply_with_func_last, ); } - AirTree::When { clauses, .. } => { + AirTree::When { + tipo: _, + subject_name: _, + subject: _, + subject_tipo: _, + clauses, + } => { clauses.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FifthField, with, apply_with_func_last, ); } - AirTree::TupleClause { then, .. } => { - let Some(index) = tuple_then_index else { - unreachable!() - }; - + AirTree::TupleClause { + subject_tipo: _, + indices: _, + predefined_indices: _, + subject_name: _, + complex_clause: _, + then, + otherwise: _, + } => { then.do_traverse_tree_with( tree_path, current_depth + 1, - index, + Fields::SixthField, with, apply_with_func_last, ); } - AirTree::PairClause { then, .. } => { - let Some(index) = tuple_then_index else { - unreachable!() - }; - + AirTree::PairClause { + subject_tipo: _, + subject_name: _, + fst_name: _, + snd_name: _, + complex_clause: _, + then, + otherwise: _, + } => { then.do_traverse_tree_with( tree_path, current_depth + 1, - index, + Fields::SixthField, with, apply_with_func_last, ); } - AirTree::List { items, .. } => { - for item in items { + AirTree::List { + tipo: _, + tail: _, + items, + } => { + for (index, item) in items.iter_mut().enumerate() { item.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::Tuple { items, .. } => { - for item in items { + AirTree::Tuple { tipo: _, items } => { + for (index, item) in items.iter_mut().enumerate() { item.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::Pair { fst, snd, .. } => { + AirTree::Pair { tipo: _, fst, snd } => { fst.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); @@ -2000,55 +2160,73 @@ impl AirTree { snd.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); } - AirTree::Call { func, args, .. } => { + AirTree::Call { + tipo: _, + func, + args, + } => { func.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); - for arg in args { + for (index, arg) in args.iter_mut().enumerate() { arg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::Fn { func_body, .. } => { + AirTree::Fn { + params: _, + func_body, + allow_inline: _, + } => { func_body.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } - AirTree::Builtin { args, .. } => { - for arg in args { + AirTree::Builtin { + func: _, + tipo: _, + args, + } => { + for (index, arg) in args.iter_mut().enumerate() { arg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::BinOp { left, right, .. } => { + AirTree::BinOp { + name: _, + tipo: _, + left, + right, + argument_tipo: _, + } => { left.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); @@ -2056,49 +2234,56 @@ impl AirTree { right.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FourthField, with, apply_with_func_last, ); } - AirTree::UnOp { arg, .. } => { + AirTree::UnOp { op: _, arg } => { arg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } - AirTree::CastFromData { value, .. } => { + AirTree::CastFromData { + tipo: _, + value, + otherwise: _, + full_cast: _, + } => { value.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } - AirTree::CastToData { value, .. } => { + AirTree::CastToData { tipo: _, value } => { value.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } AirTree::Clause { + subject_tipo: _, + subject_name: _, + complex_clause: _, pattern, then, otherwise, - .. } => { pattern.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FourthField, with, apply_with_func_last, ); @@ -2106,7 +2291,7 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FifthField, with, apply_with_func_last, ); @@ -2114,18 +2299,23 @@ impl AirTree { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SixthField, with, apply_with_func_last, ); } AirTree::ListClause { - then, otherwise, .. + subject_tipo: _, + tail_name: _, + next_tail_name: _, + complex_clause: _, + then, + otherwise, } => { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FifthField, with, apply_with_func_last, ); @@ -2133,7 +2323,7 @@ impl AirTree { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SixthField, with, apply_with_func_last, ); @@ -2142,7 +2332,7 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FirstField, with, apply_with_func_last, ); @@ -2150,7 +2340,7 @@ impl AirTree { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); @@ -2160,7 +2350,7 @@ impl AirTree { pattern.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FirstField, with, apply_with_func_last, ); @@ -2168,21 +2358,21 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); } AirTree::If { - pattern, + tipo: _, + condition: pattern, then, otherwise, - .. } => { pattern.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); @@ -2190,7 +2380,7 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); @@ -2198,45 +2388,56 @@ impl AirTree { otherwise.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FourthField, with, apply_with_func_last, ); } - AirTree::Constr { args, .. } => { - for arg in args { + AirTree::Constr { + tag: _, + tipo: _, + args, + } => { + for (index, arg) in args.iter_mut().enumerate() { arg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::RecordUpdate { record, args, .. } => { + AirTree::RecordUpdate { + highest_index: _, + indices: _, + tipo: _, + record, + args, + } => { record.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FourthField, with, apply_with_func_last, ); - for arg in args { + + for (index, arg) in args.iter_mut().enumerate() { arg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); } } - AirTree::Trace { msg, then, .. } => { + AirTree::Trace { tipo: _, msg, then } => { msg.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SecondField, with, apply_with_func_last, ); @@ -2244,39 +2445,48 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ThirdField, with, apply_with_func_last, ); } AirTree::DefineFunc { - func_body, then, .. + func_name: _, + module_name: _, + params: _, + recursive: _, + recursive_nonstatic_params: _, + variant_name: _, + func_body, + then, } => { func_body.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::SeventhField, with, apply_with_func_last, ); then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::EighthField, with, apply_with_func_last, ) } AirTree::DefineCyclicFuncs { + func_name: _, + module_name: _, + variant_name: _, contained_functions, then, - .. } => { - for (_, func_body) in contained_functions { + for (index, (_, func_body)) in contained_functions.iter_mut().enumerate() { func_body.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::ArgsField(index), with, apply_with_func_last, ); @@ -2284,7 +2494,7 @@ impl AirTree { then.do_traverse_tree_with( tree_path, current_depth + 1, - index_count.next_number(), + Fields::FifthField, with, apply_with_func_last, ); @@ -2297,13 +2507,217 @@ impl AirTree { | AirTree::Void | AirTree::Var { .. } | AirTree::ErrorTerm { .. } => {} - } - - if apply_with_func_last { - with(self, tree_path); - } - - tree_path.pop(); + AirTree::Let { + name: _, + value: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::ThirdField, + with, + apply_with_func_last, + ); + } + AirTree::AssertConstr { + constr_index: _, + constr: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::ThirdField, + with, + apply_with_func_last, + ); + } + AirTree::AssertBool { + is_true: _, + value: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::ThirdField, + with, + apply_with_func_last, + ); + } + AirTree::ClauseGuard { + subject_name: _, + subject_tipo: _, + pattern: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ); + } + AirTree::ListClauseGuard { + subject_tipo: _, + tail_name: _, + next_tail_name: _, + inverse: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FifthField, + with, + apply_with_func_last, + ); + } + AirTree::TupleGuard { + subject_tipo: _, + indices: _, + subject_name: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ); + } + AirTree::PairGuard { + subject_tipo: _, + subject_name: _, + fst_name: _, + snd_name: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FifthField, + with, + apply_with_func_last, + ); + } + AirTree::FieldsExpose { + indices: _, + record: _, + is_expect: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ); + } + AirTree::ListAccessor { + tipo: _, + names: _, + tail: _, + list: _, + expect_level: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SixthField, + with, + apply_with_func_last, + ); + } + AirTree::ListExpose { + tipo: _, + tail_head_names: _, + tail: _, + then, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FourthField, + with, + apply_with_func_last, + ); + } + AirTree::TupleAccessor { + names: _, + tipo: _, + tuple: _, + is_expect: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::FifthField, + with, + apply_with_func_last, + ); + } + AirTree::PairAccessor { + fst: _, + snd: _, + tipo: _, + is_expect: _, + pair: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SixthField, + with, + apply_with_func_last, + ); + } + AirTree::FieldsEmpty { + constr: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SecondField, + with, + apply_with_func_last, + ); + } + AirTree::ListEmpty { + list: _, + then, + otherwise: _, + } => { + then.do_traverse_tree_with( + tree_path, + current_depth + 1, + Fields::SecondField, + with, + apply_with_func_last, + ); + } + } + + if apply_with_func_last { + with(self, tree_path); + } + + tree_path.pop(); } /// Used in function hoisting to find the exact node to hoist over @@ -2315,320 +2729,344 @@ impl AirTree { fn do_find_air_tree_node<'a>( &'a mut self, - tree_path_iter: &mut Iter<(usize, usize)>, + tree_path_iter: &mut Iter<(usize, Fields)>, ) -> &'a mut AirTree { // For finding the air node we skip over the define func ops since those are added later on. if let AirTree::DefineFunc { then, .. } | AirTree::DefineCyclicFuncs { then, .. } = self { then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if let Some((_depth, index)) = tree_path_iter.next() { - let mut children_nodes = vec![]; + } else if let Some((_depth, field)) = tree_path_iter.next() { match self { - AirTree::Let { value, then, .. } => { - if *index == 0 { - value.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::AssertConstr { constr, then, .. } => { - if *index == 0 { - constr.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::AssertBool { value, then, .. } => { - if *index == 0 { - value.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::ClauseGuard { pattern, then, .. } => { - if *index == 0 { - pattern.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::ListClauseGuard { then, .. } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::TupleGuard { then, .. } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::PairGuard { then, .. } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::FieldsExpose { record, then, .. } => { - if *index == 0 { - record.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::ListAccessor { list, then, .. } => { - if *index == 0 { - list.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::ListExpose { then, .. } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::TupleAccessor { tuple, then, .. } => { - if *index == 0 { - tuple.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::PairAccessor { pair, then, .. } => { - if *index == 0 { - pair.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") + AirTree::Let { + name: _, + value, + then, + } => match field { + Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::AssertConstr { + constr_index: _, + constr, + then, + otherwise, + } => match field { + Fields::SecondField => constr.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::AssertBool { + is_true: _, + value, + then, + otherwise, + } => match field { + Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::ClauseGuard { + subject_name: _, + subject_tipo: _, + pattern, + then, + } => match field { + Fields::ThirdField => pattern.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::ListClauseGuard { + subject_tipo: _, + tail_name: _, + next_tail_name: _, + inverse: _, + then, + } => match field { + Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::TupleGuard { + subject_tipo: _, + indices: _, + subject_name: _, + then, + } => match field { + Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::PairGuard { + subject_tipo: _, + subject_name: _, + fst_name: _, + snd_name: _, + then, + } => match field { + Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::FieldsExpose { + indices: _, + record, + is_expect: _, + then, + otherwise, + } => match field { + Fields::SecondField => record.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FifthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::ListAccessor { + tipo: _, + names: _, + tail: _, + list, + expect_level: _, + then, + otherwise, + } => match field { + Fields::FourthField => list.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SeventhField => { + otherwise.as_mut().do_find_air_tree_node(tree_path_iter) } - } - AirTree::NoOp { then } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::ListExpose { + tipo: _, + tail_head_names: _, + tail: _, + then, + } => match field { + Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::TupleAccessor { + names: _, + tipo: _, + tuple, + is_expect: _, + then, + otherwise, + } => match field { + Fields::ThirdField => tuple.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SixthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::PairAccessor { + fst: _, + snd: _, + tipo: _, + is_expect: _, + pair, + then, + otherwise, + } => match field { + Fields::FifthField => pair.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SeventhField => { + otherwise.as_mut().do_find_air_tree_node(tree_path_iter) } - } + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::NoOp { then } => match field { + Fields::FirstField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::DefineFunc { .. } | AirTree::DefineCyclicFuncs { .. } => unreachable!(), - AirTree::FieldsEmpty { constr, then, .. } => { - if *index == 0 { - constr.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::ListEmpty { list, then, .. } => { - if *index == 0 { - list.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } + AirTree::FieldsEmpty { + constr, + then, + otherwise, + } => match field { + Fields::FirstField => constr.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SecondField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::ListEmpty { + list, + then, + otherwise, + } => match field { + Fields::FirstField => list.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SecondField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::List { items, .. } | AirTree::Tuple { items, .. } - | AirTree::Builtin { args: items, .. } => { - let item = items + | AirTree::Builtin { args: items, .. } + | AirTree::Constr { args: items, .. } => match field { + Fields::ArgsField(index) => items .get_mut(*index) - .expect("Tree Path index outside tree children nodes"); - item.do_find_air_tree_node(tree_path_iter) - } - AirTree::Pair { fst, snd, .. } => { - if *index == 0 { - fst.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - snd.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::Call { func, args, .. } => { - children_nodes.push(func.as_mut()); - children_nodes.extend(args.iter_mut()); - - let item = children_nodes.swap_remove(*index); - - item.do_find_air_tree_node(tree_path_iter) - } - AirTree::Fn { func_body, .. } => { - if *index == 0 { - func_body.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::BinOp { left, right, .. } => { - if *index == 0 { - left.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - right.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::UnOp { arg, .. } => { - if *index == 0 { - arg.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::CastFromData { value, .. } => { - if *index == 0 { - value.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::CastToData { value, .. } => { - if *index == 0 { - value.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } + .expect("Tree Path index outside tree children nodes") + .do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::Pair { tipo: _, fst, snd } => match field { + Fields::SecondField => fst.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => snd.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::Call { + tipo: _, + func, + args, + } => match field { + Fields::SecondField => func.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ArgsField(index) => args + .get_mut(*index) + .expect("Tree Path index outside tree children nodes") + .do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::Fn { + params: _, + func_body, + allow_inline: _, + } => match field { + Fields::SecondField => func_body.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::BinOp { + name: _, + tipo: _, + left, + right, + argument_tipo: _, + } => match field { + Fields::ThirdField => left.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => right.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::UnOp { op: _, arg } => match field { + Fields::SecondField => arg.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::CastFromData { + tipo: _, + value, + otherwise, + full_cast: _, + } => match field { + Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::CastToData { tipo: _, value } => match field { + Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::When { - subject, clauses, .. - } => { - if *index == 0 { - subject.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - clauses.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } + tipo: _, + subject_name: _, + subject, + subject_tipo: _, + clauses, + } => match field { + Fields::ThirdField => subject.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FifthField => clauses.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::Clause { + subject_tipo: _, + subject_name: _, + complex_clause: _, pattern, then, otherwise, - .. - } => { - if *index == 0 { - pattern.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 2 { - otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } + } => match field { + Fields::FourthField => pattern.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SixthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::ListClause { - then, otherwise, .. - } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::WrapClause { then, otherwise } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } + subject_tipo: _, + tail_name: _, + next_tail_name: _, + complex_clause: _, + then, + otherwise, + } => match field { + Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SixthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::WrapClause { then, otherwise } => match field { + Fields::FirstField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SecondField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::TupleClause { - then, otherwise, .. - } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { + subject_tipo: _, + indices: _, + predefined_indices: _, + subject_name: _, + complex_clause: _, + then, + otherwise, + } => match field { + Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SeventhField => { otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") } - } + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::PairClause { - then, otherwise, .. - } => { - if *index == 0 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { + subject_tipo: _, + subject_name: _, + fst_name: _, + snd_name: _, + complex_clause: _, + then, + otherwise, + } => match field { + Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SeventhField => { otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::Finally { pattern, then } => { - if *index == 0 { - pattern.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") } - } + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::Finally { pattern, then } => match field { + Fields::FirstField => pattern.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::SecondField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::If { - pattern, + tipo: _, + condition: pattern, then, otherwise, - .. - } => { - if *index == 0 { - pattern.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 2 { - otherwise.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - AirTree::Constr { args, .. } => { - let item = args + } => match field { + Fields::SecondField => pattern.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::FourthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::RecordUpdate { + highest_index: _, + indices: _, + tipo: _, + record, + args, + } => match field { + Fields::FourthField => record.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ArgsField(index) => args .get_mut(*index) - .expect("Tree Path index outside tree children nodes"); - item.do_find_air_tree_node(tree_path_iter) - } - AirTree::RecordUpdate { record, args, .. } => { - children_nodes.push(record.as_mut()); - children_nodes.extend(args.iter_mut()); - - let item = children_nodes.swap_remove(*index); - - item.do_find_air_tree_node(tree_path_iter) - } - AirTree::Trace { msg, then, .. } => { - if *index == 0 { - msg.as_mut().do_find_air_tree_node(tree_path_iter) - } else if *index == 1 { - then.as_mut().do_find_air_tree_node(tree_path_iter) - } else { - panic!("Tree Path index outside tree children nodes") - } - } - + .expect("Tree Path index outside tree children nodes") + .do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, + AirTree::Trace { tipo: _, msg, then } => match field { + Fields::SecondField => msg.as_mut().do_find_air_tree_node(tree_path_iter), + Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter), + _ => panic!("Tree Path index outside tree children nodes"), + }, AirTree::Int { .. } | AirTree::String { .. } | AirTree::ByteArray { .. } diff --git a/crates/aiken-lang/src/parser/expr/assignment.rs b/crates/aiken-lang/src/parser/expr/assignment.rs index c7960ff01..7561bc162 100644 --- a/crates/aiken-lang/src/parser/expr/assignment.rs +++ b/crates/aiken-lang/src/parser/expr/assignment.rs @@ -33,6 +33,13 @@ pub fn let_( } fn assignment_patterns() -> impl Parser, Error = ParseError> { + assignment_pattern() + .separated_by(just(Token::Comma)) + .allow_trailing() + .at_least(1) +} + +pub fn assignment_pattern() -> impl Parser { pattern() .then(just(Token::Colon).ignore_then(annotation()).or_not()) .map_with_span(|(pattern, annotation), span| ast::AssignmentPattern { @@ -40,9 +47,6 @@ fn assignment_patterns() -> impl Parser, Erro annotation, location: span, }) - .separated_by(just(Token::Comma)) - .allow_trailing() - .at_least(1) } pub fn expect( diff --git a/crates/aiken-lang/src/parser/expr/if_else.rs b/crates/aiken-lang/src/parser/expr/if_else.rs index 9a90ee7dd..4855bc784 100644 --- a/crates/aiken-lang/src/parser/expr/if_else.rs +++ b/crates/aiken-lang/src/parser/expr/if_else.rs @@ -1,41 +1,21 @@ -use chumsky::prelude::*; - +use super::block; use crate::{ ast, expr::UntypedExpr, - parser::{error::ParseError, token::Token}, + parser::{annotation, error::ParseError, pattern, token::Token}, }; - -use super::block; +use chumsky::prelude::*; pub fn parser<'a>( sequence: Recursive<'a, Token, UntypedExpr, ParseError>, expression: Recursive<'a, Token, UntypedExpr, ParseError>, ) -> impl Parser + 'a { just(Token::If) - .ignore_then( - expression - .clone() - .then(block(sequence.clone())) - .map_with_span(|(condition, body), span| ast::IfBranch { - condition, - body, - location: span, - }), - ) + .ignore_then(if_branch(sequence.clone(), expression.clone())) .then( just(Token::Else) .ignore_then(just(Token::If)) - .ignore_then( - expression - .clone() - .then(block(sequence.clone())) - .map_with_span(|(condition, body), span| ast::IfBranch { - condition, - body, - location: span, - }), - ) + .ignore_then(if_branch(sequence.clone(), expression)) .repeated(), ) .then_ignore(just(Token::Else)) @@ -53,6 +33,52 @@ pub fn parser<'a>( }) } +fn if_branch<'a>( + sequence: Recursive<'a, Token, UntypedExpr, ParseError>, + expression: Recursive<'a, Token, UntypedExpr, ParseError>, +) -> impl Parser + 'a { + expression + .then( + just(Token::Is) + .ignore_then( + pattern() + .then_ignore(just(Token::Colon)) + .or_not() + .then(annotation()) + .map_with_span(|(pattern, annotation), span| (pattern, annotation, span)), + ) + .or_not(), + ) + .then(block(sequence)) + .map_with_span(|((condition, is), body), span| { + let is = is.map(|(pattern, annotation, is_span)| { + let pattern = pattern.unwrap_or_else(|| match &condition { + UntypedExpr::Var { name, location } => ast::Pattern::Var { + name: name.clone(), + location: *location, + }, + _ => ast::Pattern::Discard { + location: is_span, + name: "_".to_string(), + }, + }); + + ast::AssignmentPattern { + pattern, + annotation: Some(annotation), + location: is_span, + } + }); + + ast::IfBranch { + condition, + body, + is, + location: span, + } + }) +} + #[cfg(test)] mod tests { use crate::assert_expr; @@ -86,4 +112,49 @@ mod tests { "# ); } + + #[test] + fn if_else_with_soft_cast() { + assert_expr!( + r#" + if ec1 is Some(x): Option { + ec2 + } else if ec1 is Foo { foo }: Foo { + ec1 + } else if ec1 is Option { + let Some(x) = ec1 + + x + } else { + Infinity + } + "# + ); + } + + #[test] + fn if_soft_cast_discard_assign() { + assert_expr!( + r#" + if foo() is Foo { + todo + } else { + todo + } + "# + ); + } + + #[test] + fn if_soft_cast_not_var_condition() { + assert_expr!( + r#" + if foo() is Foo { a }: Foo { + todo + } else { + todo + } + "# + ); + } } diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_else_ambiguous_record.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_else_ambiguous_record.snap index 645514698..f2287624b 100644 --- a/crates/aiken-lang/src/parser/expr/snapshots/if_else_ambiguous_record.snap +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_else_ambiguous_record.snap @@ -22,6 +22,7 @@ If { location: 23..26, name: "ec2", }, + is: None, location: 3..28, }, IfBranch { @@ -56,6 +57,7 @@ If { location: 60..63, name: "ec1", }, + is: None, location: 37..65, }, ], diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap index 4493776de..de0af5170 100644 --- a/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_else_basic.snap @@ -28,6 +28,7 @@ If { }, }, }, + is: None, location: 3..19, }, IfBranch { @@ -53,6 +54,7 @@ If { numeric_underscore: false, }, }, + is: None, location: 28..41, }, ], diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_else_with_soft_cast.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_else_with_soft_cast.snap new file mode 100644 index 000000000..393b13b8e --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_else_with_soft_cast.snap @@ -0,0 +1,183 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif ec1 is Some(x): Option {\n ec2\n} else if ec1 is Foo { foo }: Foo {\n ec1\n} else if ec1 is Option {\n let Some(x) = ec1\n\n x\n} else {\n Infinity\n}\n" +--- +If { + location: 0..158, + branches: [ + IfBranch { + condition: Var { + location: 3..6, + name: "ec1", + }, + body: Var { + location: 35..38, + name: "ec2", + }, + is: Some( + AssignmentPattern { + pattern: Constructor { + is_record: false, + location: 10..17, + name: "Some", + arguments: [ + CallArg { + label: None, + location: 15..16, + value: Var { + location: 15..16, + name: "x", + }, + }, + ], + module: None, + constructor: (), + spread_location: None, + tipo: (), + }, + annotation: Some( + Constructor { + location: 19..30, + module: None, + name: "Option", + arguments: [ + Constructor { + location: 26..29, + module: None, + name: "Int", + arguments: [], + }, + ], + }, + ), + location: 10..30, + }, + ), + location: 3..40, + }, + IfBranch { + condition: Var { + location: 49..52, + name: "ec1", + }, + body: Var { + location: 77..80, + name: "ec1", + }, + is: Some( + AssignmentPattern { + pattern: Constructor { + is_record: true, + location: 56..67, + name: "Foo", + arguments: [ + CallArg { + label: Some( + "foo", + ), + location: 62..65, + value: Var { + location: 62..65, + name: "foo", + }, + }, + ], + module: None, + constructor: (), + spread_location: None, + tipo: (), + }, + annotation: Some( + Constructor { + location: 69..72, + module: None, + name: "Foo", + arguments: [], + }, + ), + location: 56..72, + }, + ), + location: 49..82, + }, + IfBranch { + condition: Var { + location: 91..94, + name: "ec1", + }, + body: Sequence { + location: 114..136, + expressions: [ + Assignment { + location: 114..131, + value: Var { + location: 128..131, + name: "ec1", + }, + patterns: [ + AssignmentPattern { + pattern: Constructor { + is_record: false, + location: 118..125, + name: "Some", + arguments: [ + CallArg { + label: None, + location: 123..124, + value: Var { + location: 123..124, + name: "x", + }, + }, + ], + module: None, + constructor: (), + spread_location: None, + tipo: (), + }, + annotation: None, + location: 118..125, + }, + ], + kind: Let { + backpassing: false, + }, + }, + Var { + location: 135..136, + name: "x", + }, + ], + }, + is: Some( + AssignmentPattern { + pattern: Var { + location: 91..94, + name: "ec1", + }, + annotation: Some( + Constructor { + location: 98..109, + module: None, + name: "Option", + arguments: [ + Constructor { + location: 105..108, + module: None, + name: "Int", + arguments: [], + }, + ], + }, + ), + location: 98..109, + }, + ), + location: 91..138, + }, + ], + final_else: Var { + location: 148..156, + name: "Infinity", + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap new file mode 100644 index 000000000..aab73ee8d --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_discard_assign.snap @@ -0,0 +1,59 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif foo() is Foo {\n todo\n} else {\n todo\n}\n" +--- +If { + location: 0..42, + branches: [ + IfBranch { + condition: Call { + arguments: [], + fun: Var { + location: 3..6, + name: "foo", + }, + location: 3..8, + }, + body: Trace { + kind: Todo, + location: 20..24, + then: ErrorTerm { + location: 20..24, + }, + text: String { + location: 20..24, + value: "aiken::todo", + }, + }, + is: Some( + AssignmentPattern { + pattern: Discard { + name: "_", + location: 12..15, + }, + annotation: Some( + Constructor { + location: 12..15, + module: None, + name: "Foo", + arguments: [], + }, + ), + location: 12..15, + }, + ), + location: 3..26, + }, + ], + final_else: Trace { + kind: Todo, + location: 36..40, + then: ErrorTerm { + location: 36..40, + }, + text: String { + location: 36..40, + value: "aiken::todo", + }, + }, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap new file mode 100644 index 000000000..e8fd4f35e --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/if_soft_cast_not_var_condition.snap @@ -0,0 +1,76 @@ +--- +source: crates/aiken-lang/src/parser/expr/if_else.rs +description: "Code:\n\nif foo() is Foo { a }: Foo {\n todo\n} else {\n todo\n}\n" +--- +If { + location: 0..53, + branches: [ + IfBranch { + condition: Call { + arguments: [], + fun: Var { + location: 3..6, + name: "foo", + }, + location: 3..8, + }, + body: Trace { + kind: Todo, + location: 31..35, + then: ErrorTerm { + location: 31..35, + }, + text: String { + location: 31..35, + value: "aiken::todo", + }, + }, + is: Some( + AssignmentPattern { + pattern: Constructor { + is_record: true, + location: 12..21, + name: "Foo", + arguments: [ + CallArg { + label: Some( + "a", + ), + location: 18..19, + value: Var { + location: 18..19, + name: "a", + }, + }, + ], + module: None, + constructor: (), + spread_location: None, + tipo: (), + }, + annotation: Some( + Constructor { + location: 23..26, + module: None, + name: "Foo", + arguments: [], + }, + ), + location: 12..26, + }, + ), + location: 3..37, + }, + ], + final_else: Trace { + kind: Todo, + location: 47..51, + then: ErrorTerm { + location: 47..51, + }, + text: String { + location: 47..51, + value: "aiken::todo", + }, + }, +} diff --git a/crates/aiken-lang/src/tests/check.rs b/crates/aiken-lang/src/tests/check.rs index b9d19b0b0..b3bb32f02 100644 --- a/crates/aiken-lang/src/tests/check.rs +++ b/crates/aiken-lang/src/tests/check.rs @@ -198,7 +198,7 @@ fn illegal_function_comparison() { "#; assert!(matches!( - dbg!(check_validator(parse(source_code))), + check_validator(parse(source_code)), Err((_, Error::IllegalComparison { .. })) )) } @@ -287,7 +287,7 @@ fn illegal_unserialisable_in_generic_miller_loop() { "#; assert!(matches!( - dbg!(check(parse(source_code))), + check(parse(source_code)), Err((_, Error::IllegalTypeInData { .. })) )) } @@ -2417,7 +2417,7 @@ fn partial_eq_call_args() { "#; assert!(matches!( - dbg!(check(parse(source_code))), + check(parse(source_code)), Err((_, Error::IncorrectFieldsArity { .. })) )); } @@ -2435,7 +2435,7 @@ fn partial_eq_callback_args() { "#; assert!(matches!( - dbg!(check(parse(source_code))), + check(parse(source_code)), Err((_, Error::CouldNotUnify { .. })) )); } @@ -2453,7 +2453,7 @@ fn partial_eq_callback_return() { "#; assert!(matches!( - dbg!(check(parse(source_code))), + check(parse(source_code)), Err((_, Error::CouldNotUnify { .. })) )); } @@ -2488,7 +2488,7 @@ fn pair_index_out_of_bound() { "#; assert!(matches!( - dbg!(check_validator(parse(source_code))), + check_validator(parse(source_code)), Err((_, Error::PairIndexOutOfBound { .. })) )) } @@ -2502,7 +2502,7 @@ fn not_indexable() { "#; assert!(matches!( - dbg!(check_validator(parse(source_code))), + check_validator(parse(source_code)), Err((_, Error::NotIndexable { .. })) )) } @@ -2520,7 +2520,7 @@ fn out_of_scope_access() { "#; assert!(matches!( - dbg!(check_validator(parse(source_code))), + check_validator(parse(source_code)), Err((_, Error::UnknownVariable { .. })) )) } @@ -2552,7 +2552,7 @@ fn fn_single_variant_pattern() { } "#; - assert!(dbg!(check(parse(source_code))).is_ok()); + assert!(check(parse(source_code)).is_ok()); } #[test] @@ -2569,7 +2569,154 @@ fn fn_multi_variant_pattern() { "#; assert!(matches!( - dbg!(check_validator(parse(source_code))), + check_validator(parse(source_code)), Err((_, Error::NotExhaustivePatternMatch { .. })) )) } + +#[test] +fn if_soft_cast() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is bar: Foo { + bar.a + } else { + 0 + } + } + "#; + + assert!(check(parse(source_code)).is_ok()); +} + +#[test] +fn if_soft_cast_sugar() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { + foo.a + } else { + 0 + } + } + "#; + + assert!(check(parse(source_code)).is_ok()); +} + +#[test] +fn if_soft_cast_record() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + a + } else { + 0 + } + } + "#; + + assert!(check(parse(source_code)).is_ok()); +} + +#[test] +fn if_soft_cast_no_scope_leak() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is bar: Foo { + bar.a + } else { + bar + } + } + "#; + + assert!(matches!( + check_validator(parse(source_code)), + Err((_, Error::UnknownVariable { name, .. })) if name == "bar" + )) +} + +#[test] +fn if_soft_cast_no_scope_leak_2() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + a + } else { + a + } + } + "#; + + assert!(matches!( + check_validator(parse(source_code)), + Err((_, Error::UnknownVariable { name, .. })) if name == "a" + )) +} + +#[test] +fn if_soft_cast_unused_pattern() { + let source_code = r#" + pub type Foo { + a: Int + } + + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + 1 + } else { + 0 + } + } + "#; + + let (warnings, _ast) = check(parse(source_code)).unwrap(); + + assert!(matches!( + warnings[0], + Warning::UnusedVariable { ref name, .. } if name == "a" + )) +} + +#[test] +fn if_soft_cast_not_data() { + let source_code = r#" + pub type Foo { + Bar { a: Int } + Buzz { b: Int } + } + + pub fn foo(foo: Foo) -> Int { + if foo is Bar { a }: Foo { + a + } else { + 0 + } + } + "#; + + let (warnings, _ast) = check(parse(source_code)).unwrap(); + + assert!(matches!(warnings[0], Warning::UseWhenInstead { .. })) +} diff --git a/crates/aiken-lang/src/tests/format.rs b/crates/aiken-lang/src/tests/format.rs index a9d951dba..5fed0458b 100644 --- a/crates/aiken-lang/src/tests/format.rs +++ b/crates/aiken-lang/src/tests/format.rs @@ -86,6 +86,43 @@ fn format_if() { ); } +#[test] +fn format_if_soft_cast() { + assert_format!( + r#" + pub fn foo(a) { + if a is Option { 14 } else { 42 } + } + "# + ); +} + +#[test] +fn format_if_soft_cast_pattern() { + assert_format!( + r#" + pub fn foo(a) { + if a is Some(x): Option { 14 } else if b is Foo { b } else { 42 } + } + "# + ); +} + +#[test] +fn format_if_soft_cast_record() { + assert_format!( + r#" + pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + a + } else { + 0 + } + } + "# + ); +} + #[test] fn format_logic_op_with_code_block() { assert_format!( diff --git a/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast.snap b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast.snap new file mode 100644 index 000000000..e087d5ff0 --- /dev/null +++ b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast.snap @@ -0,0 +1,11 @@ +--- +source: crates/aiken-lang/src/tests/format.rs +description: "Code:\n\npub fn foo(a) {\n if a is Option { 14 } else { 42 }\n }\n" +--- +pub fn foo(a) { + if a is Option { + 14 + } else { + 42 + } +} diff --git a/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_pattern.snap b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_pattern.snap new file mode 100644 index 000000000..9750f9f8d --- /dev/null +++ b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_pattern.snap @@ -0,0 +1,13 @@ +--- +source: crates/aiken-lang/src/tests/format.rs +description: "Code:\n\npub fn foo(a) {\n if a is Some(x): Option { 14 } else if b is Foo { b } else { 42 }\n }\n" +--- +pub fn foo(a) { + if a is Some(x): Option { + 14 + } else if b is Foo { + b + } else { + 42 + } +} diff --git a/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_record.snap b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_record.snap new file mode 100644 index 000000000..93263858b --- /dev/null +++ b/crates/aiken-lang/src/tests/snapshots/format_if_soft_cast_record.snap @@ -0,0 +1,11 @@ +--- +source: crates/aiken-lang/src/tests/format.rs +description: "Code:\n\npub fn foo(foo: Data) -> Int {\n if foo is Foo { a }: Foo {\n a\n } else {\n 0\n }\n}\n" +--- +pub fn foo(foo: Data) -> Int { + if foo is Foo { a }: Foo { + a + } else { + 0 + } +} diff --git a/crates/aiken-lang/src/tipo/error.rs b/crates/aiken-lang/src/tipo/error.rs index c183ad34a..dde1b2945 100644 --- a/crates/aiken-lang/src/tipo/error.rs +++ b/crates/aiken-lang/src/tipo/error.rs @@ -1671,6 +1671,26 @@ pub enum Warning { name: String, }, + #[error( + "I found an {} {}", + "if/is".if_supports_color(Stderr, |s| s.purple()), + "that checks an expression with a known type.".if_supports_color(Stderr, |s| s.yellow()) + )] + #[diagnostic( + code("if_is_on_non_data"), + help( + "Prefer using a {} to match on all known constructors.", + "when/is".if_supports_color(Stderr, |s| s.purple()) + ) + )] + UseWhenInstead { + #[label( + "use {}", + "when/is".if_supports_color(Stderr, |s| s.purple()) + )] + location: Span, + }, + #[error( "I came across a discarded variable in a let assignment: {}", name.if_supports_color(Stderr, |s| s.default_color()) @@ -1755,7 +1775,8 @@ impl ExtraData for Warning { | Warning::UnusedType { .. } | Warning::UnusedVariable { .. } | Warning::DiscardedLetAssignment { .. } - | Warning::ValidatorInLibraryModule { .. } => None, + | Warning::ValidatorInLibraryModule { .. } + | Warning::UseWhenInstead { .. } => None, Warning::Utf8ByteArrayIsValidHexString { value, .. } => Some(value.clone()), Warning::UnusedImportedModule { location, .. } => { Some(format!("{},{}", false, location.start)) diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 036a166f6..cc5733c76 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -700,6 +700,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { branches: vec1::vec1![IfBranch { condition: typed_value, body: var_true, + is: None, location, }], final_else: Box::new(TypedExpr::Trace { @@ -1191,13 +1192,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let ann_typ = if let Some(ann) = annotation { let ann_typ = self .type_from_annotation(ann) - .map(|t| self.instantiate(t, &mut HashMap::new(), location))??; + .and_then(|t| self.instantiate(t, &mut HashMap::new(), location))?; self.unify( ann_typ.clone(), value_typ.clone(), typed_value.type_defining_location(), - (kind.is_let() && ann_typ.is_data()) || kind.is_expect(), + (kind.is_let() && ann_typ.is_data()) || kind.is_expect() || kind.if_is(), )?; value_typ = ann_typ.clone(); @@ -1238,6 +1239,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { // If `expect` is explicitly used, we still check exhaustiveness but instead of returning an // error we emit a warning which explains that using `expect` is unnecessary. match kind { + AssignmentKind::Is => (), AssignmentKind::Let { .. } => { self.environment .check_exhaustiveness(&[&pattern], location, true)? @@ -1695,60 +1697,33 @@ impl<'a, 'b> ExprTyper<'a, 'b> { final_else: UntypedExpr, location: Span, ) -> Result { - let first = branches.first(); + let mut branches = branches.into_iter(); + let first = branches.next().unwrap(); - let condition = self.infer(first.condition.clone())?; + let first_typed_if_branch = self.infer_if_branch(first)?; - self.unify( - bool(), - condition.tipo(), - condition.type_defining_location(), - false, - )?; + let first_body_type = first_typed_if_branch.body.tipo(); - assert_no_assignment(&first.body)?; - let body = self.infer(first.body.clone())?; - - let tipo = body.tipo(); - - let mut typed_branches = vec1::vec1![TypedIfBranch { - body, - condition, - location: first.location, - }]; - - for branch in &branches[1..] { - let condition = self.infer(branch.condition.clone())?; - - self.unify( - bool(), - condition.tipo(), - condition.type_defining_location(), - false, - )?; + let mut typed_branches = vec1::vec1![first_typed_if_branch]; - assert_no_assignment(&branch.body)?; - let body = self.infer(branch.body.clone())?; + for branch in branches { + let typed_branch = self.infer_if_branch(branch)?; self.unify( - tipo.clone(), - body.tipo(), - body.type_defining_location(), + first_body_type.clone(), + typed_branch.body.tipo(), + typed_branch.body.type_defining_location(), false, )?; - typed_branches.push(TypedIfBranch { - body, - condition, - location: branch.location, - }); + typed_branches.push(typed_branch); } assert_no_assignment(&final_else)?; let typed_final_else = self.infer(final_else)?; self.unify( - tipo.clone(), + first_body_type.clone(), typed_final_else.tipo(), typed_final_else.type_defining_location(), false, @@ -1758,7 +1733,63 @@ impl<'a, 'b> ExprTyper<'a, 'b> { location, branches: typed_branches, final_else: Box::new(typed_final_else), - tipo, + tipo: first_body_type, + }) + } + + fn infer_if_branch(&mut self, branch: UntypedIfBranch) -> Result { + let (condition, body, is) = match branch.is { + Some(is) => self.in_new_scope(|typer| { + let AssignmentPattern { + pattern, + annotation, + location, + } = is; + + let TypedExpr::Assignment { value, pattern, .. } = typer.infer_assignment( + pattern, + branch.condition.clone(), + AssignmentKind::is(), + &annotation, + location, + )? + else { + unreachable!() + }; + + if !value.tipo().is_data() { + typer.environment.warnings.push(Warning::UseWhenInstead { + location: branch.condition.location().union(location), + }) + } + + assert_no_assignment(&branch.body)?; + let body = typer.infer(branch.body.clone())?; + + Ok((*value, body, Some(pattern))) + })?, + None => { + let condition = self.infer(branch.condition.clone())?; + + self.unify( + bool(), + condition.tipo(), + condition.type_defining_location(), + false, + )?; + + assert_no_assignment(&branch.body)?; + let body = self.infer(branch.body.clone())?; + + (condition, body, None) + } + }; + + Ok(TypedIfBranch { + body, + condition, + is, + location: branch.location, }) } @@ -2072,6 +2103,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { .into(), // erase backpassing while preserving assignment kind. kind: match kind { + AssignmentKind::Is => unreachable!(), AssignmentKind::Let { .. } => AssignmentKind::let_(), AssignmentKind::Expect { .. } if pattern_is_var && annotation.is_none() => diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__generics.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__generics.snap index 74275d626..5ad0817c5 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__generics.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__generics.snap @@ -10,8 +10,8 @@ description: "Code:\n\ntype Either {\n Left(left)\n Right(rig "$ref": "#/definitions/test_module~1Either$ByteArray_test_module~1Interval$Int" } }, - "compiledCode": "5901c2010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c73650013656323253330053370e900000089929998050008a998038028b099299980598068010a4c2a6601000c2c64a66666601c0022a6601000c2c2a6601000c2c2a6601000c2c2a6601000c2c26eb8004c02c004c020dd50010a99980299b87480080044c94ccc02800454cc01c014584c94ccc02cc0340084c9263253330083370e900000089929998068008a998050040b099299980718080010a4c2a660160122c64a6666660220022a660160122c2a660160122c2a660160122c26eb400454cc02c02458c038004c02cdd50010a99980419b874800800454ccc030c02cdd50010a4c2a6601200e2c2a6601200e2c60126ea800454cc02001858c94cccccc038004400454cc0200185854cc0200185854cc0200185854cc02001858c02c004c020dd50010a998030020b18031baa001533333300a00110011533004002161533004002161533004002161533004002164912a72656465656d65723a204569746865723c4279746541727261792c20496e74657276616c3c496e743e3e005734ae7155ceaab9e5573eae855d12ba41", - "hash": "962d5aa7bc55c0df812ec6f4bfcba6eedc1e1b5c92669949974f5dcf", + "compiledCode": "590156010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c73650013656323253330053370e90000008992999805000802899299980598068010a4c00c64a66666601c00200c00c00c00c26eb8004c02c004c020dd50010a99980299b87480080044c94ccc0280040144c94ccc02cc0340084c9263253330083370e90000008992999806800804099299980718080010a4c01264a66666602200201201201226eb4004024c038004c02cdd50010a99980419b874800800454ccc030c02cdd50010a4c00e00e60126ea8004018c94cccccc0380044004018018018018c02c004c020dd500100218031baa001533333300a001100100200200200215330024912a72656465656d65723a204569746865723c4279746541727261792c20496e74657276616c3c496e743e3e00165734ae7155ceaab9e5573eae855d12ba41", + "hash": "d9891fd7080a2e6e3a68d330ef987b6950115bbe0700f1dfeab7af2f", "definitions": { "ByteArray": { "dataType": "bytes" diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_2_tuples_as_list.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_2_tuples_as_list.snap index ec07e3da8..7fb197634 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_2_tuples_as_list.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_2_tuples_as_list.snap @@ -10,8 +10,8 @@ description: "Code:\n\ntype Dict {\n inner: List<(ByteArray, valu "$ref": "#/definitions/test_module~1Dict$test_module~1UUID_Int" } }, - "compiledCode": "59019c010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c736500136563253330043370e900018031baa0011325333009001153300600416132533300a300c002132498c8cc004004008894ccc03000452613233003003300f0023232533300e001153300b00916132325333010001153300d00b1613253330113013002149854cc03803058c94cccccc05000454cc0380305854cc0380305854cc038030584dd68008a998070060b180880098088011929999998090008a998060050b0a998060050b0a998060050b0a998060050b09bae001300f0015333333010001153300a00816153300a00816137580022a660140102c2a660140102c601a0022a6600e00a2c64a66666601a0022a6600e00a2c2a6600e00a2c26eb000454cc01c0145854cc01c01458c028004c01cdd50008a998028018b299999980500088008a998020010b0a998020010b0a998020010b0a998020010b2491972656465656d65723a20446963743c555549442c20496e743e005734ae7155ceaab9e5573eae855d12ba41", - "hash": "6027685dde99d967b45333852fe9f59531237d85fcb6b6feb2890672", + "compiledCode": "59012c010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c736500136563253330043370e900018031baa0011325333009001004132533300a300c002132498c8cc004004008894ccc03000452613233003003300f0023232533300e00100913232533301000100b132533301130130021498030c94cccccc0500040300300304dd68008061808800980880119299999980900080500500500509bae001300f001533333301000100800813758002010010601a00200a64a66666601a00200a00a26eb0004014014c028004c01cdd5000801a99999980500088008010010010010a9980124811972656465656d65723a20446963743c555549442c20496e743e00165734ae7155ceaab9e5573eae855d12ba41", + "hash": "41a2fefe69a528618655adf8d9c426133a166851b2acf234ff889400", "definitions": { "ByteArray": { "dataType": "bytes" diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_pairs_as_map.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_pairs_as_map.snap index 6037567e5..1e470b965 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_pairs_as_map.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__list_pairs_as_map.snap @@ -10,8 +10,8 @@ description: "Code:\n\ntype Dict {\n inner: List {\n Cons(a, LinkedList)\n Nil "$ref": "#/definitions/test_module~1LinkedList$Int" } }, - "compiledCode": "590403010000323232323232323232322323232322322533300b4a22930a998062491856616c696461746f722072657475726e65642066616c736500136563300353333330100011001153300a00716153300a00716153300a00716153300a00716007323253330093005001132533300e001153300b00916132533300f3011002132498c8cc00400400888c94ccc038c0280044c94ccc04c00454cc040038584c8c94ccc05400454cc048040584c94ccc058c0600084c926330070070011533013011163253333330190011001153301301116153301301116153301301116153301301116301600130160023253333330170011325333015301400115333011300c301300114a22a666022601a6026002294054cc0480405854cc04804058dd50008a998088078b0a998088078b0a998088078b0a998088078b180a00098089baa0021533300e300900115333012301137540042930a998078068b0a998078068b18079baa001153300c00a163253333330120011001153300c00a16153300c00a16153300c00a16153300c00a16300f001300c37540042a6660126008002264a66601c0022a660160122c26464a6660200022a6601a0162c264a66602260260042649329998088008a998070060b0991929998098008a998080070b099299980a180b00109924c646600200200444a66602c00229309919801801980c8011919806a99999980d00088008a9980a0090b0a9980a0090b0a9980a0090b0a9980a0090b009180b8008a998088078b19299999980b8008a998088078b0a998088078b09bac001153301100f16153301100f1630140013014002325333333015001153300f00d16153300f00d16153300f00d16153300f00d161375c00260240022a6601c0182c64a6666660280022a6601c0182c2a6601c0182c26eb000454cc0380305854cc03803058c044004c044008c94cccccc04800454cc0300285854cc0300285854cc030028584dd68008a998060050b180780098061baa002153300a00816300a3754002a66666601c00820082a6601000c2c2a6601000c2c2a6601000c2c2a6601000c2c4464660020020064464a666016600e002264a6660200022a6601a00a2c26464a6660240022a6601e00e2c264a666026602a00426493198038038008a998080040b19299999980b00088008a998080040b0a998080040b0a998080040b0a998080040b1809800980980119299999980a0008a998070030b0a998070030b0a998070030b09bad001153300e006163011001300e37540042a666016600c0022a66601e601c6ea8008526153300c00416153300c00416300c37540026e1d2002370e90002491972656465656d65723a204c696e6b65644c6973743c496e743e0049010a646174756d3a20466f6f005734ae7155ceaab9e5573eae855d12ba41", - "hash": "ff1413d8a35753076ff26df84e7829fde430f9920208fe0ba8ae3c52", + "compiledCode": "5902dc01000032323232323232323232232323232322322533300c4a22930a99806a491856616c696461746f722072657475726e65642066616c73650013656330035333333011001100100800800800800833232232533300c3008001132533301100100c13253330123014002132498cc014004034034c94cccccc0540044004034034034034c048004c03cdd50010a99980618038008992999808800806099192999809800807099299980a180b00109924ca66602800201e26464a66602c002022264a66602e603200426493191980080080111299980c8008a4c264660060066038004646601ea66666603a002200202a02a02a02a02a603400202464a66666603400202402426eb0004048048c05c004c05c008c94cccccc0600040400400400404dd7000980a80080799299999980b80080780789bac00100f00f3014001301400232533333301500100d00d00d1375a00201a6024002601e6ea800802cc034dd5000980080091119299980618040008992999808800806099192999809800807099299980a180b00109924c66601001000201e01e64a66666602e002200201e01e01e01e6028002602800464a66666602a002264a66602660240022a66601e60146022002294454ccc03cc02cc0440045280070071baa00100d00d00d00d3012001300f37540062a666018600e0022a666020601e6ea800c52600b00b300d3754004a66666601e00a200a00e00e00e00e600200244464a666014600c002264a66601e00201226464a666022002016264a66602460280042649319980400400080600619299999980a80088008060060060061809000980900119299999980980080500500509bad00100a3010001300d37540062a666014600a0022a66601c601a6ea800c526008008300b37540046e1d2002370e90000a99801a4811972656465656d65723a204c696e6b65644c6973743c496e743e001615330024910a646174756d3a20466f6f00165734ae7155ceaab9e5573eae855d12ba41", + "hash": "84b32ffc00b858865c8047f8145074fd841a828bfa1cd48c25e204ec", "definitions": { "Bool": { "title": "Bool", diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__recursive_types.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__recursive_types.snap index 93e3e769e..c6d9c9fdd 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__recursive_types.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__recursive_types.snap @@ -10,8 +10,8 @@ description: "Code:\n\npub type Expr {\n Val(Int)\n Sum(Expr, Expr)\n Mul(Exp "$ref": "#/definitions/test_module~1Expr" } }, - "compiledCode": "590207010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c736500136563233001001533333300b0021002153300500316153300500316153300500316153300500316223253330063370e900000089929998058008a998040030b099299980618070010a4c2a6601200e2c64a66666601e0022a6601200e2c2a6601200e2c2a6601200e2c26eb400454cc02401c58c030004c024dd50010a99980319b87480080044c94ccc02c00454cc020018584c8c94ccc03400454cc028020584c94ccc038c0400084c8c9263300800800233007007003153300b009163253333330110011001153300b00916153300b00916153300b00916153300b00916300e001300e00232533333300f0011001153300900716153300900716153300900716153300900716300c001300937540042a66600c66e1d2004001132533300b00115330080061613232533300d001153300a00816132533300e301000213232498cc020020008cc01c01c00c54cc02c02458c94cccccc044004400454cc02c0245854cc02c0245854cc02c0245854cc02c02458c038004c038008c94cccccc03c004400454cc02401c5854cc02401c5854cc02401c5854cc02401c58c030004c024dd50010a998038028b18039baa0014910e72656465656d65723a2045787072005734ae7155ceaab9e5573eae855d12ba41", - "hash": "ad10f49980a840966b7dc6c3f88e3f196a3291d34b0b4483ec527d7e", + "compiledCode": "590182010000323232323232323232232253330054a22930a9980324811856616c696461746f722072657475726e65642066616c73650013656333230010012223253330073370e90000008992999806000803899299980698078010a4c01064a66666602000201001001026eb4004020c034004c028dd50018a99980399b87480080044c94ccc03000401c4c8c94ccc0380040244c94ccc03cc0440084c8c92633300900900200b33300800800300a00a325333333012001100100a00a00a00a300f001300f0023253333330100011001008008008008300d001300a37540062a66600e66e1d2004001132533300c00100713232533300e001009132533300f301100213232498ccc02402400802cccc02002000c028028c94cccccc0480044004028028028028c03c004c03c008c94cccccc0400044004020020020020c034004c028dd500180318041baa002533333300a0011001002002002002002153300249010e72656465656d65723a204578707200165734ae7155ceaab9e5573eae855d12ba41", + "hash": "5e5d31d96828f3f0b12ac296adc263de4ac0964cae3cac0164f525e1", "definitions": { "Int": { "dataType": "integer" diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__simplified_hydra.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__simplified_hydra.snap index 6e8418c42..915850e43 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__simplified_hydra.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__simplified_hydra.snap @@ -16,8 +16,8 @@ description: "Code:\n\n/// On-chain state\ntype State {\n /// The contestatio "$ref": "#/definitions/test_module~1Input" } }, - "compiledCode": "5902710100003232323232323232323223232232253330094a22930a998052491856616c696461746f722072657475726e65642066616c736500136563232533300930050011533300d300c37540042930a998050038b0a99980499b874800800454ccc034c030dd50010a4c2a6601400e2c2a66601266e1d20040011533300d300c37540042930a998050038b0a998050038b18051baa001533333300e0011001153300800516153300800516153300800516153300800516325333006300230083754002264a6660160022a6601000c2c26464a66601a0022a660140102c26464a66601e0022a660180142c264a6660206024004264649319198008008029129998098008a4c26466006006602c00464a66666602e0022a6602201e2c2a6602201e2c2a6602201e2c2a6602201e2c26eb8004c0500054ccc030c020c038dd500289929998088008a998070060b0992999809180a0010a4c2a6601e01a2c64a66666602a0022a6601e01a2c2a6601e01a2c2a6601e01a2c26eb400454cc03c03458c048004c03cdd50028a998068058b0a998068058b1929999998098008a998068058b0a998068058b0a998068058b0a998068058b09bae00130100013010002325333333011001153300b00916153300b00916137580022a660160122c2a660160122c601c002601c00464a66666601e00220022a6601200e2c2a6601200e2c2a6601200e2c2a6601200e2c601800260126ea800454cc01c014594cccccc030008400854cc0180105854cc0180105854cc0180105854cc01801058dc3a40009210f72656465656d65723a20496e7075740049010c646174756d3a205374617465005734ae7155ceaab9e5573eae855d12ba41", - "hash": "a35efe623ea7738b61a9f152e14a9abc30c15f0ceff540b66e42c406", + "compiledCode": "5901c60100003232323232323232323223232232253330094a22930a998052491856616c696461746f722072657475726e65642066616c736500136563232533300930050011533300d300c37540042930038a99980499b874800800454ccc034c030dd50010a4c00e2a66601266e1d20040011533300d300c375400429300380398051baa001533333300e0011001005005005005325333006300230083754002264a66601600200c26464a66601a00201026464a66601e002014264a6660206024004264649319198008008029129998098008a4c26466006006602c00464a66666602e00201e01e01e01e26eb8004c0500054ccc030c020c038dd500289929998088008060992999809180a0010a4c01a64a66666602a00201a01a01a26eb4004034c048004c03cdd500280580599299999980980080580580580589bae0013010001301000232533333301100100900913758002012012601c002601c00464a66666601e002200200e00e00e00e601800260126ea80040154cccccc0300084008010010010010dc3a40002a6600692010f72656465656d65723a20496e707574001615330024910c646174756d3a20537461746500165734ae7155ceaab9e5573eae855d12ba41", + "hash": "02a625742f53a006e38b3c9abbcd3c77002815705ad1f6a5a6b02813", "definitions": { "ByteArray": { "dataType": "bytes" diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__tuples.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__tuples.snap index d2369ff18..0dd55e607 100644 --- a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__tuples.snap +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__tuples.snap @@ -16,8 +16,8 @@ description: "Code:\n\nvalidator {\n fn tuples(datum: (Int, ByteArray), redeeme "$ref": "#/definitions/Tuple$Int_Int_Int" } }, - "compiledCode": "5901ed010000323232323232323223232232322533300a4a22930a99805a491856616c696461746f722072657475726e65642066616c73650013656533300a00115330090061613232533300c001153300b0081613232533300e001153300d00a16132533300f3011002149854cc03802c58c94cccccc04800454cc03802c5854cc03802c5854cc03802c584dd68008a998070058b180780098078011929999998080008a998060048b0a998060048b0a998060048b09bad001153300c00916300d001300d00232533333300e001153300a00716153300a00716153300a007161375a0022a6601400e2c6016002a6666660180022a6601000a2c2a6601000a2c26eb000454cc0200145854cc020014594ccc01c00454cc018010584c8c94ccc02400454cc020018584c94ccc028c03000852615330090071632533333300d0011533009007161533009007161533009007161533009007161375c0026014002601400464a6666660160022a6600e00a2c2a6600e00a2c2a6600e00a2c26eb400454cc01c01458c0200054cccccc02400454cc01400c5854cc01400c584dd60008a998028018b0a998028018b24811972656465656d65723a2028496e742c20496e742c20496e742900490117646174756d3a2028496e742c2042797465417272617929005734ae7155cfaba15744ae91", - "hash": "9d5de9c290eb221450ae3f039b1ce3b9057f06cff7498d761e223eee", + "compiledCode": "590158010000323232323232323223232232322533300a4a22930a99805a491856616c696461746f722072657475726e65642066616c73650013656533300a00100613232533300c00100813232533300e00100a132533300f3011002149802cc94cccccc04800402c02c02c4dd68008059807800980780119299999980800080480480489bad001009300d001300d00232533333300e0010070070071375a00200e6016002a66666601800200a00a26eb00040140154ccc01c0040104c8c94ccc0240040184c94ccc028c03000852600732533333300d0010070070070071375c0026014002601400464a66666601600200a00a00a26eb4004014c0200054cccccc02400400c00c4dd60008018018a99801a4811972656465656d65723a2028496e742c20496e742c20496e74290016153300249117646174756d3a2028496e742c204279746541727261792900165734ae7155cfaba15744ae91", + "hash": "a537eed4619425e300f33b8a9734144c9e8d4ab2177e563e9a2881c3", "definitions": { "ByteArray": { "dataType": "bytes" diff --git a/crates/aiken-project/src/tests/gen_uplc.rs b/crates/aiken-project/src/tests/gen_uplc.rs index 8baa5ff8a..20c88855d 100644 --- a/crates/aiken-project/src/tests/gen_uplc.rs +++ b/crates/aiken-project/src/tests/gen_uplc.rs @@ -3752,35 +3752,37 @@ fn when_tuple_deconstruction() { .apply(Term::var("subject")) .delayed_if_then_else( Term::var("red_constr_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::tail_list() .apply(Term::var("red_constr_fields")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::unit().delay(), + Term::var("param_msg"), ) + .force() .lambda("field_1") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_i_data() + .apply(Term::var("__val")) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list() .apply(Term::var("red_constr_fields")), ), - ), + ) + .delay(), ) + .force() .lambda("red_constr_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("red")), @@ -3788,15 +3790,18 @@ fn when_tuple_deconstruction() { Term::equals_integer() .apply(Term::integer(1.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("red")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), - ), + .choose_list( + Term::unit().delay(), + Term::var("param_msg"), + ) + .force() + .delay(), + Term::var("param_msg"), + ) + .force(), ) .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("red"))) @@ -3809,13 +3814,14 @@ fn when_tuple_deconstruction() { .lambda("red") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error.delayed_trace(Term::var("red:RedSpend")), - Term::Error.delayed_trace(Term::var("red:RedSpend")), - Term::Error.delayed_trace(Term::var("red:RedSpend")), - Term::Error.delayed_trace(Term::var("red:RedSpend")), + .choose_data( + Term::var("__val").delay(), + Term::var("red:RedSpend"), + Term::var("red:RedSpend"), + Term::var("red:RedSpend"), + Term::var("red:RedSpend"), ) + .force() .lambda("__val") .apply(Term::var("red")), ) @@ -3830,39 +3836,42 @@ fn when_tuple_deconstruction() { .apply(Term::var("subject")) .delayed_if_then_else( Term::var("dat_constr_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::tail_list() .apply(Term::var("dat_constr_fields")) - .delayed_choose_list( - Term::unit().lambda("_").apply( - Term::var("expect_Thing") - .apply(Term::var("field_1")) - .apply(Term::var("param_msg")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::unit() + .lambda("_") + .apply( + Term::var("expect_Thing") + .apply(Term::var("field_1")) + .apply(Term::var("param_msg")), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("field_1") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_data( + Term::var("__val").delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list() .apply(Term::var("dat_constr_fields")), ), - ), + ) + .delay(), ) + .force() .lambda("dat_constr_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("dat")), @@ -3870,15 +3879,18 @@ fn when_tuple_deconstruction() { Term::equals_integer() .apply(Term::integer(1.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("dat")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), - ), + .choose_list( + Term::unit().delay(), + Term::var("param_msg"), + ) + .force() + .delay(), + Term::var("param_msg"), + ) + .force(), ) .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("dat"))) @@ -3890,45 +3902,49 @@ fn when_tuple_deconstruction() { Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var("field_1_constr_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::tail_list() .apply(Term::var("field_1_constr_fields")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::unit().delay(), + Term::var("param_msg"), ) + .force() .lambda("idx") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_i_data() + .apply(Term::var("__val")) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list().apply(Term::var( "field_1_constr_fields", )), ), - ), + ) + .delay(), ) + .force() .lambda("field_1_constr_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("field_1")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("field_1"))) .lambda("param_msg") @@ -3940,13 +3956,14 @@ fn when_tuple_deconstruction() { .lambda("dat") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error.delayed_trace(Term::var("dat:Datum")), - Term::Error.delayed_trace(Term::var("dat:Datum")), - Term::Error.delayed_trace(Term::var("dat:Datum")), - Term::Error.delayed_trace(Term::var("dat:Datum")), + .choose_data( + Term::var("__val").delay(), + Term::var("dat:Datum"), + Term::var("dat:Datum"), + Term::var("dat:Datum"), + Term::var("dat:Datum"), ) + .force() .lambda("__val") .apply(Term::var("dat")), ) @@ -3960,9 +3977,17 @@ fn when_tuple_deconstruction() { .lambda("x"), ) .lambda("red:RedSpend") - .apply(Term::string("red: RedSpend")) + .apply( + Term::Error + .delayed_trace(Term::string("red: RedSpend")) + .delay(), + ) .lambda("dat:Datum") - .apply(Term::string("dat: Datum")) + .apply( + Term::Error + .delayed_trace(Term::string("dat: Datum")) + .delay(), + ) .lambda(CONSTR_INDEX_EXPOSER) .apply( Term::fst_pair() @@ -4079,15 +4104,15 @@ fn generic_validator_type_test() { let void_check = Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::fst_pair().apply(Term::unconstr_data().apply(Term::var("__val")))) - .delayed_if_then_else( + .if_then_else( Term::snd_pair() .apply(Term::unconstr_data().apply(Term::var("__val"))) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), - ); + .choose_list(Term::unit().delay(), Term::var("param_msg")) + .force() + .delay(), + Term::var("param_msg"), + ) + .force(); assert_uplc( src, @@ -4135,57 +4160,53 @@ fn generic_validator_type_test() { .delayed_if_then_else( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("param_0")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), - ), + .choose_list(Term::unit().delay(), Term::var("param_msg")) + .force(), Term::equals_integer() .apply(Term::integer(1.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var("r_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::var("tail_1") - .delayed_choose_list( - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::tail_list() .apply(Term::var("tail_1")) - .delayed_choose_list( - Term::unit().lambda("_").apply( - Term::var("__expect_B") - .apply(Term::var("field_B")) - .apply(Term::var( - "param_msg", - )), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), + .choose_list( + Term::unit() + .lambda("_") + .apply( + Term::var("__expect_B") + .apply(Term::var( + "field_B", + )) + .apply(Term::var( + "param_msg", + )), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("field_B") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), + .choose_data( + Term::var("__val").delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply(field_b), - ), + ) + .delay(), ) + .force() .lambda("tail_1") .apply( Term::tail_list() @@ -4194,35 +4215,32 @@ fn generic_validator_type_test() { .lambda("field_0") .apply( Term::var("__val") - .delayed_choose_data( - void_check.clone(), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), - Term::Error.delayed_trace( - Term::var("param_msg"), - ), + .choose_data( + void_check.clone().delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list() .apply(Term::var("r_fields")), ), - ), + ) + .delay(), ) + .force() .lambda("r_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("param_0")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), - ), + ) + .delay(), + Term::var("param_msg"), + ) + .force(), ) .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("param_0"))) @@ -4234,44 +4252,46 @@ fn generic_validator_type_test() { Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var("B_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::tail_list() .apply(Term::var("B_fields")) - .delayed_choose_list( - Term::unit(), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::unit().delay(), + Term::var("param_msg"), ) + .force() .lambda("something") .apply( Term::var("__val") - .delayed_choose_data( - void_check, - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_data( + void_check.delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list() .apply(Term::var("B_fields")), ), - ), + ) + .delay(), ) + .force() .lambda("B_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("param_0")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("param_0"))) .lambda("param_msg") @@ -4283,13 +4303,14 @@ fn generic_validator_type_test() { .lambda("r") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error.delayed_trace(Term::var("r:A")), - Term::Error.delayed_trace(Term::var("r:A")), - Term::Error.delayed_trace(Term::var("r:A")), - Term::Error.delayed_trace(Term::var("r:A")), + .choose_data( + Term::var("__val").delay(), + Term::var("r:A"), + Term::var("r:A"), + Term::var("r:A"), + Term::var("r:A"), ) + .force() .lambda("__val") .apply(Term::var("r")), ) @@ -4297,7 +4318,7 @@ fn generic_validator_type_test() { .apply(Term::var("r")) .lambda("r") .lambda("r:A") - .apply(Term::string("r: A")) + .apply(Term::Error.delayed_trace(Term::string("r: A")).delay()) .lambda(CONSTR_FIELDS_EXPOSER) .apply( Term::snd_pair() @@ -4955,19 +4976,23 @@ fn expect_head_no_tail() { assert_uplc( src, Term::var("a") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h]=a")), + .choose_list( + Term::var("expect[h]=a"), Term::tail_list() .apply(Term::var("a")) - .delayed_choose_list( + .choose_list( Term::equals_integer() .apply(Term::var("h")) - .apply(Term::var("h")), - Term::Error.delayed_trace(Term::var("expect[h]=a")), + .apply(Term::var("h")) + .delay(), + Term::var("expect[h]=a"), ) + .force() .lambda("h") - .apply(Term::un_i_data().apply(Term::head_list().apply(Term::var("a")))), + .apply(Term::un_i_data().apply(Term::head_list().apply(Term::var("a")))) + .delay(), ) + .force() .lambda("a") .apply(Term::list_values(vec![ Constant::Data(Data::integer(1.into())), @@ -4975,7 +5000,11 @@ fn expect_head_no_tail() { Constant::Data(Data::integer(3.into())), ])) .lambda("expect[h]=a") - .apply(Term::string("expect [h] = a")), + .apply( + Term::Error + .delayed_trace(Term::string("expect [h] = a")) + .delay(), + ), true, ); } @@ -4993,17 +5022,17 @@ fn expect_head3_no_tail() { assert_uplc( src, Term::var("a") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]=a")), + .choose_list( + Term::var("expect[h,i,j]=a"), Term::var("tail_1") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]=a")), + .choose_list( + Term::var("expect[h,i,j]=a"), Term::var("tail_2") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]=a")), + .choose_list( + Term::var("expect[h,i,j]=a"), Term::tail_list() .apply(Term::var("tail_2")) - .delayed_choose_list( + .choose_list( Term::equals_integer() .apply(Term::var("h")) .apply(Term::var("h")) @@ -5018,28 +5047,36 @@ fn expect_head3_no_tail() { .apply(Term::var("j")) .apply(Term::var("j")), Term::bool(false), - ), - Term::Error.delayed_trace(Term::var("expect[h,i,j]=a")), + ) + .delay(), + Term::var("expect[h,i,j]=a"), ) + .force() .lambda("j") .apply( Term::un_i_data() .apply(Term::head_list().apply(Term::var("tail_2"))), - ), + ) + .delay(), ) + .force() .lambda("tail_2") .apply(Term::tail_list().apply(Term::var("tail_1"))) .lambda("i") .apply( Term::un_i_data() .apply(Term::head_list().apply(Term::var("tail_1"))), - ), + ) + .delay(), ) + .force() .lambda("tail_1") .apply(Term::tail_list().apply(Term::var("a"))) .lambda("h") - .apply(Term::un_i_data().apply(Term::head_list().apply(Term::var("a")))), + .apply(Term::un_i_data().apply(Term::head_list().apply(Term::var("a")))) + .delay(), ) + .force() .lambda("a") .apply(Term::list_values(vec![ Constant::Data(Data::integer(1.into())), @@ -5047,7 +5084,11 @@ fn expect_head3_no_tail() { Constant::Data(Data::integer(3.into())), ])) .lambda(Term::var("expect[h,i,j]=a")) - .apply(Term::string("expect [h, i, j] = a")), + .apply( + Term::Error + .delayed_trace(Term::string("expect [h, i, j] = a")) + .delay(), + ), false, ); } @@ -5065,17 +5106,17 @@ fn expect_head3_cast_data_no_tail() { assert_uplc( src, Term::var("tail_0") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_list( + Term::var("expect[h,i,j]:List=a"), Term::var("tail_1") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_list( + Term::var("expect[h,i,j]:List=a"), Term::var("tail_2") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_list( + Term::var("expect[h,i,j]:List=a"), Term::tail_list() .apply(Term::var("tail_2")) - .delayed_choose_list( + .choose_list( Term::equals_integer() .apply(Term::var("h")) .apply(Term::var("h")) @@ -5090,68 +5131,66 @@ fn expect_head3_cast_data_no_tail() { .apply(Term::var("j")) .apply(Term::var("j")), Term::bool(false), - ), - Term::Error - .delayed_trace(Term::var("expect[h,i,j]:List=a")), + ) + .delay(), + Term::var("expect[h,i,j]:List=a"), ) + .force() .lambda("j") .apply( Term::var("__var") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var( - "expect[h,i,j]:List=a", - )), - Term::Error.delayed_trace(Term::var( - "expect[h,i,j]:List=a", - )), - Term::Error.delayed_trace(Term::var( - "expect[h,i,j]:List=a", - )), - Term::un_i_data().apply(Term::var("__var")), - Term::Error.delayed_trace(Term::var( - "expect[h,i,j]:List=a", - )), + .choose_data( + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::un_i_data().apply(Term::var("__var")).delay(), + Term::var("expect[h,i,j]:List=a"), ) + .force() .lambda("__var") .apply(Term::head_list().apply(Term::var("tail_2"))), - ), + ) + .delay(), ) + .force() .lambda("tail_2") .apply(Term::tail_list().apply(Term::var("tail_1"))) .lambda("i") .apply( Term::var("__var") - .delayed_choose_data( - Term::Error - .delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error - .delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error - .delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::un_i_data().apply(Term::var("__var")), - Term::Error - .delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_data( + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::un_i_data().apply(Term::var("__var")).delay(), + Term::var("expect[h,i,j]:List=a"), ) + .force() .lambda("__var") .apply(Term::head_list().apply(Term::var("tail_1"))), - ), + ) + .delay(), ) + .force() .lambda("tail_1") .apply(Term::tail_list().apply(Term::var("tail_0"))) .lambda("h") .apply( Term::var("__var") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::un_i_data().apply(Term::var("__var")), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_data( + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + Term::un_i_data().apply(Term::var("__var")).delay(), + Term::var("expect[h,i,j]:List=a"), ) + .force() .lambda("__var") .apply(Term::head_list().apply(Term::var("tail_0"))), - ), + ) + .delay(), ) + .force() .lambda("tail_0") .apply( Term::data(Data::list(vec![ @@ -5159,24 +5198,29 @@ fn expect_head3_cast_data_no_tail() { Data::integer(2.into()), Data::integer(3.into()), ])) - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), + .choose_data( + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), Term::list_values(vec![ Constant::Data(Data::integer(1.into())), Constant::Data(Data::integer(2.into())), Constant::Data(Data::integer(3.into())), - ]), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,i,j]:List=a")), - ), + ]) + .delay(), + Term::var("expect[h,i,j]:List=a"), + Term::var("expect[h,i,j]:List=a"), + ) + .force(), ) .lambda("expect[h,i,j]:List=a") - .apply(Term::string("expect [h, i, j]: List = a")), + .apply( + Term::Error + .delayed_trace(Term::string("expect [h, i, j]: List = a")) + .delay(), + ), false, ); } - #[test] fn expect_head_cast_data_no_tail() { let src = r#" @@ -5190,30 +5234,35 @@ fn expect_head_cast_data_no_tail() { assert_uplc( src, Term::var("tail_0") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), + .choose_list( + Term::var("expect[h]:List=a"), Term::tail_list() .apply(Term::var("tail_0")) - .delayed_choose_list( + .choose_list( Term::equals_integer() .apply(Term::var("h")) - .apply(Term::var("h")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), + .apply(Term::var("h")) + .delay(), + Term::var("expect[h]:List=a"), ) + .force() .lambda("h") .apply( Term::var("__var") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - Term::un_i_data().apply(Term::var("__var")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), + .choose_data( + Term::var("expect[h]:List=a"), + Term::var("expect[h]:List=a"), + Term::var("expect[h]:List=a"), + Term::un_i_data().apply(Term::var("__var")).delay(), + Term::var("expect[h]:List=a"), ) + .force() .lambda("__var") .apply(Term::head_list().apply(Term::var("tail_0"))), - ), + ) + .delay(), ) + .force() .lambda("tail_0") .apply( Term::data(Data::list(vec![ @@ -5221,20 +5270,26 @@ fn expect_head_cast_data_no_tail() { Data::integer(2.into()), Data::integer(3.into()), ])) - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), + .choose_data( + Term::var("expect[h]:List=a"), + Term::var("expect[h]:List=a"), Term::list_values(vec![ Constant::Data(Data::integer(1.into())), Constant::Data(Data::integer(2.into())), Constant::Data(Data::integer(3.into())), - ]), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h]:List=a")), - ), + ]) + .delay(), + Term::var("expect[h]:List=a"), + Term::var("expect[h]:List=a"), + ) + .force(), ) .lambda("expect[h]:List=a") - .apply(Term::string("expect [h]: List = a")), + .apply( + Term::Error + .delayed_trace(Term::string("expect [h]: List = a")) + .delay(), + ), true, ); } @@ -5252,11 +5307,11 @@ fn expect_head_cast_data_with_tail() { assert_uplc( src, Term::var("unwrap_a") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), + .choose_list( + Term::var("expect[h,j,..]:List=a"), Term::var("tail_1") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), + .choose_list( + Term::var("expect[h,j,..]:List=a"), Term::equals_integer() .apply(Term::var("h")) .apply(Term::var("h")) @@ -5302,21 +5357,14 @@ fn expect_head_cast_data_with_tail() { .apply(Term::var("tail_2")) .apply( Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var( - "expect[h,j,..]:List=a", - )), - Term::Error.delayed_trace(Term::var( - "expect[h,j,..]:List=a", - )), - Term::Error.delayed_trace(Term::var( - "expect[h,j,..]:List=a", - )), - Term::un_i_data().apply(Term::var("__val")), - Term::Error.delayed_trace(Term::var( - "expect[h,j,..]:List=a", - )), + .choose_data( + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::un_i_data().apply(Term::var("__val")).delay(), + Term::var("expect[h,j,..]:List=a"), ) + .force() .lambda("__val") .apply(Term::var("list_item")) .lambda("list_item"), @@ -5327,51 +5375,55 @@ fn expect_head_cast_data_with_tail() { .lambda("j") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error - .delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error - .delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error - .delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error - .delayed_trace(Term::var("expect[h,j,..]:List=a")), + .choose_data( + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::un_i_data().apply(Term::var("__val")).delay(), + Term::var("expect[h,j,..]:List=a"), ) + .force() .lambda("__val") .apply(Term::head_list().apply(Term::var("tail_1"))), - ), + ) + .delay(), ) + .force() .lambda("tail_1") .apply(Term::tail_list().apply(Term::var("unwrap_a"))) .lambda("h") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), + .choose_data( + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), + Term::un_i_data().apply(Term::var("__val")).delay(), + Term::var("expect[h,j,..]:List=a"), ) + .force() .lambda("__val") .apply(Term::head_list().apply(Term::var("unwrap_a"))), - ), + ) + .delay(), ) + .force() .lambda("unwrap_a") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), + .choose_data( + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), Term::list_values(vec![ Constant::Data(Data::integer(1.into())), Constant::Data(Data::integer(2.into())), Constant::Data(Data::integer(3.into())), - ]), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), - Term::Error.delayed_trace(Term::var("expect[h,j,..]:List=a")), + ]) + .delay(), + Term::var("expect[h,j,..]:List=a"), + Term::var("expect[h,j,..]:List=a"), ) + .force() .lambda("__val") .apply(Term::data(Data::list(vec![ Data::integer(1.into()), @@ -5380,7 +5432,11 @@ fn expect_head_cast_data_with_tail() { ]))), ) .lambda("expect[h,j,..]:List=a") - .apply(Term::string("expect [h, j, ..]: List = a")), + .apply( + Term::Error + .delayed_trace(Term::string("expect [h, j, ..]: List = a")) + .delay(), + ), false, ); } @@ -6201,78 +6257,87 @@ fn opaque_value_in_datum() { let expect_on_tail = Term::tail_list() .apply(Term::var("tail_1")) - .delayed_choose_list( - Term::unit().lambda("_").apply( - Term::var("expect_on_list").apply(Term::var("a")).apply( - Term::var("expect_on_list") - .apply(Term::var("pair_snd_outer")) - .apply( - Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error.delayed_trace(Term::var("param_msg")), - ) - .lambda("__val") - .apply(Term::snd_pair().apply(Term::var("pair"))) - .lambda("pair_fst") - .apply( - Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::un_b_data().apply(Term::var("__val")), - ) - .lambda("__val") - .apply(Term::fst_pair().apply(Term::var("pair"))), - ) - .lambda("pair"), - ) - .lambda("pair_snd_outer") - .apply( - Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("param_msg")), - Term::unmap_data().apply(Term::var("__val")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - ) - .lambda("__val") - .apply(Term::snd_pair().apply(Term::var("pair_outer"))), - ) - .lambda("pair_fst_outer") - .apply( - Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::un_b_data().apply(Term::var("__val")), - ) - .lambda("__val") - .apply(Term::fst_pair().apply(Term::var("pair_outer"))), - ) - .lambda("pair_outer"), - ), - ), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::unit() + .lambda("_") + .apply( + Term::var("expect_on_list").apply(Term::var("a")).apply( + Term::var("expect_on_list") + .apply(Term::var("pair_snd_outer")) + .apply( + Term::var("__val") + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_i_data().apply(Term::var("__val")).delay(), + Term::var("param_msg"), + ) + .force() + .lambda("__val") + .apply(Term::snd_pair().apply(Term::var("pair"))) + .lambda("pair_fst") + .apply( + Term::var("__val") + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_b_data().apply(Term::var("__val")).delay(), + ) + .force() + .lambda("__val") + .apply(Term::fst_pair().apply(Term::var("pair"))), + ) + .lambda("pair"), + ) + .lambda("pair_snd_outer") + .apply( + Term::var("__val") + .choose_data( + Term::var("param_msg"), + Term::unmap_data().apply(Term::var("__val")).delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + ) + .force() + .lambda("__val") + .apply(Term::snd_pair().apply(Term::var("pair_outer"))), + ) + .lambda("pair_fst_outer") + .apply( + Term::var("__val") + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_b_data().apply(Term::var("__val")).delay(), + ) + .force() + .lambda("__val") + .apply(Term::fst_pair().apply(Term::var("pair_outer"))), + ) + .lambda("pair_outer"), + ), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("a") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error.delayed_trace(Term::var("param_msg")), - Term::unmap_data().apply(Term::var("__val")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_data( + Term::var("param_msg"), + Term::unmap_data().apply(Term::var("__val")).delay(), + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply(Term::head_list().apply(Term::var("tail_1"))), ); @@ -6280,11 +6345,11 @@ fn opaque_value_in_datum() { assert_uplc( src, Term::var("val") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[Pair(_,amount)]=val.inner.inner")), + .choose_list( + Term::var("expect[Pair(_,amount)]=val.inner.inner"), Term::tail_list() .apply(Term::var("val")) - .delayed_choose_list( + .choose_list( Term::equals_data() .apply(Term::map_data().apply(Term::var("final_amount"))) .apply(Term::map_data().apply(Term::var("amount"))) @@ -6299,13 +6364,16 @@ fn opaque_value_in_datum() { .apply( Term::unmap_data() .apply(Term::snd_pair().apply(Term::var("tuple_item_0"))), - ), - Term::Error - .delayed_trace(Term::var("expect[Pair(_,amount)]=val.inner.inner")), + ) + .delay(), + Term::var("expect[Pair(_,amount)]=val.inner.inner"), ) + .force() .lambda("tuple_item_0") - .apply(Term::head_list().apply(Term::var("val"))), + .apply(Term::head_list().apply(Term::var("val"))) + .delay(), ) + .force() .lambda("val") .apply( Term::unmap_data().apply( @@ -6331,45 +6399,49 @@ fn opaque_value_in_datum() { Term::equals_integer() .apply(Term::integer(0.into())) .apply(Term::var("subject")) - .delayed_if_then_else( + .if_then_else( Term::var("dat_fields") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), + .choose_list( + Term::var("param_msg"), Term::var("tail_1") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("param_msg")), - expect_on_tail, + .choose_list( + Term::var("param_msg"), + expect_on_tail.delay(), ) + .force() .lambda("tail_1") .apply(Term::tail_list().apply(Term::var("dat_fields"))) .lambda("c") .apply( Term::var("__val") - .delayed_choose_data( - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::Error - .delayed_trace(Term::var("param_msg")), - Term::un_i_data().apply(Term::var("__val")), - Term::Error - .delayed_trace(Term::var("param_msg")), + .choose_data( + Term::var("param_msg"), + Term::var("param_msg"), + Term::var("param_msg"), + Term::un_i_data() + .apply(Term::var("__val")) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("__val") .apply( Term::head_list() .apply(Term::var("dat_fields")), ), - ), + ) + .delay(), ) + .force() .lambda("dat_fields") .apply( Term::var(CONSTR_FIELDS_EXPOSER) .apply(Term::var("param_0")), - ), - Term::Error.delayed_trace(Term::var("param_msg")), + ) + .delay(), + Term::var("param_msg"), ) + .force() .lambda("subject") .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("param_0"))) .lambda("param_msg") @@ -6407,22 +6479,27 @@ fn opaque_value_in_datum() { .lambda("dat") .apply( Term::var("__val") - .delayed_choose_data( - Term::var("__val"), - Term::Error.delayed_trace(Term::var("dat:Dat")), - Term::Error.delayed_trace(Term::var("dat:Dat")), - Term::Error.delayed_trace(Term::var("dat:Dat")), - Term::Error.delayed_trace(Term::var("dat:Dat")), + .choose_data( + Term::var("__val").delay(), + Term::var("dat:Dat"), + Term::var("dat:Dat"), + Term::var("dat:Dat"), + Term::var("dat:Dat"), ) + .force() .lambda("__val") .apply(Term::var("dat")), ) .lambda("dat") .constr_fields_exposer() .lambda("expect[Pair(_,amount)]=val.inner.inner") - .apply(Term::string("expect [Pair(_, amount)] = val.inner.inner")) + .apply( + Term::Error + .delayed_trace(Term::string("expect [Pair(_, amount)] = val.inner.inner")) + .delay(), + ) .lambda("dat:Dat") - .apply(Term::string("dat: Dat")) + .apply(Term::Error.delayed_trace(Term::string("dat: Dat")).delay()) .constr_index_exposer(), false, ); @@ -6469,11 +6546,11 @@ fn opaque_value_in_test() { assert_uplc( src, Term::var("val") - .delayed_choose_list( - Term::Error.delayed_trace(Term::var("expect[Pair(_,amount)]=val.inner.inner")), + .choose_list( + Term::var("expect[Pair(_,amount)]=val.inner.inner"), Term::tail_list() .apply(Term::var("val")) - .delayed_choose_list( + .choose_list( Term::equals_data() .apply(Term::map_data().apply(Term::var("final_amount"))) .apply(Term::map_data().apply(Term::var("amount"))) @@ -6488,13 +6565,16 @@ fn opaque_value_in_test() { .apply( Term::unmap_data() .apply(Term::snd_pair().apply(Term::var("tuple_item_0"))), - ), - Term::Error - .delayed_trace(Term::var("expect[Pair(_,amount)]=val.inner.inner")), + ) + .delay(), + Term::var("expect[Pair(_,amount)]=val.inner.inner"), ) + .force() .lambda("tuple_item_0") - .apply(Term::head_list().apply(Term::var("val"))), + .apply(Term::head_list().apply(Term::var("val"))) + .delay(), ) + .force() .lambda("val") .apply(Term::unmap_data().apply(Term::head_list().apply( Term::tail_list().apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("dat"))), @@ -6525,7 +6605,11 @@ fn opaque_value_in_test() { .into(), )])) .lambda("expect[Pair(_,amount)]=val.inner.inner") - .apply(Term::string("expect [Pair(_, amount)] = val.inner.inner")) + .apply( + Term::Error + .delayed_trace(Term::string("expect [Pair(_, amount)] = val.inner.inner")) + .delay(), + ) .constr_fields_exposer(), false, ); diff --git a/crates/uplc/src/optimize/shrinker.rs b/crates/uplc/src/optimize/shrinker.rs index 065165696..a5cdaf8be 100644 --- a/crates/uplc/src/optimize/shrinker.rs +++ b/crates/uplc/src/optimize/shrinker.rs @@ -1029,6 +1029,12 @@ impl Program { if let Some((arg_id, arg_term)) = arg_stack.pop() { match &arg_term { Term::Constant(c) if matches!(c.as_ref(), Constant::String(_)) => {} + Term::Delay(e) if matches!(e.as_ref(), Term::Error) => { + let body = Rc::make_mut(body); + lambda_applied_ids.push(arg_id); + // creates new body that replaces all var occurrences with the arg + *term = substitute_var(body, parameter_name.clone(), &arg_term); + } Term::Constant(_) | Term::Var(_) | Term::Builtin(_) => { let body = Rc::make_mut(body); lambda_applied_ids.push(arg_id); diff --git a/examples/acceptance_tests/036/aiken.lock b/examples/acceptance_tests/036/aiken.lock index 49efa49a4..c07eb7761 100644 --- a/examples/acceptance_tests/036/aiken.lock +++ b/examples/acceptance_tests/036/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407096, nanos_since_epoch = 481443000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353062, nanos_since_epoch = 479061000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/036/plutus.json b/examples/acceptance_tests/036/plutus.json index 820f11281..52b5ff9a9 100644 --- a/examples/acceptance_tests/036/plutus.json +++ b/examples/acceptance_tests/036/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -25,8 +25,8 @@ } } ], - "compiledCode": "589e0100003232323232323222322533300553330053370e900018031baa3232330010013758600460126ea8c008c024dd50019129998058008a6103d87a800013232533300a3375e600a60186ea80080244cdd2a40006601c00497ae0133004004001300f002300d0012300b00114a22940526136563253330043370e900018028008a99980398030008a4c2c2c6ea80055cd2ab9d5573caae7d5d02ba15745", - "hash": "4317a8dff6fa9fcbc49190374190a59933e04bafbd486b713873be69" + "compiledCode": "58e90100003232323232323232323222322533300653330063370e900018041baa3232330010013758600460166ea8c008c02cdd50019129998068008a6103d87a800013232533300b3375e600a601c6ea80080244cdd2a40006602000497ae01330040040013011002300f0012300d00114a22940526153300749011856616c696461746f722072657475726e65642066616c73650013656533333300c001153330043370e900018031baa00115333008300737540022930018018018018018018a998012490f5f72656465656d65723a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "eb7578af9370ca9210a58fbf6a7000c627e7b714cbd30016a12ed270" }, { "title": "spend.spend", @@ -42,8 +42,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "58ef01000032323232323232222533300432330010013758601460166016600e6ea8c028c01cdd50011129998048008a501325333007333007533300a3253330083370e900118049baa00114bd6f7b63009bab300d300a375400264660020026eacc034c038c028dd518068019129998060008a60103d87a8000132323232533300d33722911050000000000000021533300d3371e91010500000000000000213374a9000198089ba60014bd700a6103d87a80001330060060033756601c0066eb8c030008c040008c0380045288a504a094452889980180180098060008a4c26cacae6955ceaab9e5573eae815d0aba21", - "hash": "f56561e01063b11146809755d9907147e79d3166aa5c65fba4040fd1" + "compiledCode": "590112010000323232323232323222253330043233001001375860166018601860106ea8c02cc020dd50011129998050008a501325333007333007533300b3253330083370e900118051baa00114bd6f7b63009bab300e300b375400264660020026eacc038c03cc02cdd518070019129998068008a60103d87a8000132323232533300d33722911050000000000000021533300d3371e91010500000000000000213374a9000198091ba60014bd700a6103d87a80001330060060033756601e0066eb8c034008c044008c03c0045288a504a094452889980180180098068008a4c2a6600a92011856616c696461746f722072657475726e65642066616c736500136565734ae7155ceaab9e5573eae815d0aba201", + "hash": "874827f25676e53d8d40f1ebb5a69f901c9c79e3797059b3a7bc36b3" } ], "definitions": { diff --git a/examples/acceptance_tests/047/plutus.json b/examples/acceptance_tests/047/plutus.json index 6f8d5edb9..3246de4b3 100644 --- a/examples/acceptance_tests/047/plutus.json +++ b/examples/acceptance_tests/047/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/Void" } }, - "compiledCode": "585401000032323232232232253330064a229309b2b19299980299b8748000c01800454ccc020c01c0045261616375400264a66600666e1d2000300400115333006300500114985858dd5000ab9a5573aaae7955cf81", - "hash": "705a180bd5fb906789dbf005092d4724261b0154f460c2f8c859ff2c" + "compiledCode": "58c00100003232323232323232232232253330084a22930a99804a491856616c696461746f722072657475726e65642066616c73650013656533333300b001153330063370e900018041baa0011533300a3009375400229300200200200200200229999998048008a99980219b8748000c018dd50008a99980418039baa001149800c00c00c00c00c00c54cc00d2410f5f72656465656d65723a20566f6964001615330024910c5f646174756d3a20566f696400165734ae7155ceaab9e5573eae91", + "hash": "3b52a75a0bb17b0a8abbaef7e73e30a6bde7693dd79715f9d3534b75" } ], "definitions": { diff --git a/examples/acceptance_tests/054/aiken.lock b/examples/acceptance_tests/054/aiken.lock index 744c6793a..d4ab988c6 100644 --- a/examples/acceptance_tests/054/aiken.lock +++ b/examples/acceptance_tests/054/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407101, nanos_since_epoch = 859911000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353060, nanos_since_epoch = 816466000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/055/aiken.lock b/examples/acceptance_tests/055/aiken.lock index dc76a09d7..83346c1ca 100644 --- a/examples/acceptance_tests/055/aiken.lock +++ b/examples/acceptance_tests/055/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407096, nanos_since_epoch = 167055000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353064, nanos_since_epoch = 692755000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/061/aiken.lock b/examples/acceptance_tests/061/aiken.lock index e57a3f982..213341324 100644 --- a/examples/acceptance_tests/061/aiken.lock +++ b/examples/acceptance_tests/061/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407110, nanos_since_epoch = 628540000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353086, nanos_since_epoch = 153535000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/063/aiken.lock b/examples/acceptance_tests/063/aiken.lock index e6aeb26ae..9ebd5dd3a 100644 --- a/examples/acceptance_tests/063/aiken.lock +++ b/examples/acceptance_tests/063/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407094, nanos_since_epoch = 891156000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353064, nanos_since_epoch = 356223000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/067/aiken.lock b/examples/acceptance_tests/067/aiken.lock index f9c980ae0..40e3ad30f 100644 --- a/examples/acceptance_tests/067/aiken.lock +++ b/examples/acceptance_tests/067/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407114, nanos_since_epoch = 974279000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353090, nanos_since_epoch = 867160000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/068/aiken.lock b/examples/acceptance_tests/068/aiken.lock index 74bbb237c..78d270ed5 100644 --- a/examples/acceptance_tests/068/aiken.lock +++ b/examples/acceptance_tests/068/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407110, nanos_since_epoch = 818921000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353088, nanos_since_epoch = 668124000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/069/aiken.lock b/examples/acceptance_tests/069/aiken.lock index 30c09a0db..b048619f2 100644 --- a/examples/acceptance_tests/069/aiken.lock +++ b/examples/acceptance_tests/069/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407111, nanos_since_epoch = 974946000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353089, nanos_since_epoch = 828993000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/070/aiken.lock b/examples/acceptance_tests/070/aiken.lock index a3a1dd8e0..bf9b83305 100644 --- a/examples/acceptance_tests/070/aiken.lock +++ b/examples/acceptance_tests/070/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407088, nanos_since_epoch = 812897000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353049, nanos_since_epoch = 385317000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/071/aiken.lock b/examples/acceptance_tests/071/aiken.lock index 63851348d..59e743656 100644 --- a/examples/acceptance_tests/071/aiken.lock +++ b/examples/acceptance_tests/071/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407088, nanos_since_epoch = 266980000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353054, nanos_since_epoch = 415860000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/071/plutus.json b/examples/acceptance_tests/071/plutus.json index 68a2136ca..416972534 100644 --- a/examples/acceptance_tests/071/plutus.json +++ b/examples/acceptance_tests/071/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/spend~1PoolRedeemer" } }, - "compiledCode": "59031a0100003232323232323223232322323225333009323232533300c300a00114a226464646464a666022601600c26464a666026601a60286ea80044c8c8c94ccc058c050c05cdd500089919299980c180b180c9baa0011324a2603a60346ea800458cc01c03c00cc06cc060dd50008b198038068009804244101ff003018301537540022940c00cc050dd5005180b18099baa007132325333013300d301437540022646464a66602c6028602e6ea80044c8c94ccc060c058c064dd5000899251301d301a37540022c6600e01e006603660306ea800458cc01c034004c021220101ff003018301537540022940c00cc050dd5005180b18099baa00722330053758601260286ea8c024c050dd5001119baf300a301537546008602a6ea80040088c054c05800488cc00cdd6180a980b180b18091baa300730123754004466ebcc020c04cdd500080111191980080080191299980a0008a6103d87a8000132325333013300500213374a90001980b80125eb804cc010010004c060008c0580048cdd2a40006602266e95200233011375200297ae0330114c103d87a80004bd7018061baa0013001300c375400a4601e00229309b2b2999803980298041baa00213232533300c300f002132498c94ccc028c0200044c8c94ccc03cc04800852616375a602000260186ea800854ccc028c0100044c8c94ccc03cc0480084c926533300c300a300d3754002264646464a666026602c0042649318068018b1bad301400130140023012001300e37540022c2c602000260186ea800854ccc028cdc3a400800226464a66601e6024004264932999806180518069baa00113232323253330133016002132498c03400c58dd6980a000980a001180900098071baa00116163010001300c37540042c60146ea800458c034004c024dd50010b1b87480094ccc010c008c014dd500189919191919192999806980800109924c600e00a2c6eb4c038004c038008dd698060009806001180500098031baa0031625333004300230053754002264646464a666016601c0042930b1bae300c001300c002375c6014002600c6ea800458dc3a4000ae6955ceaab9e5573eae815d0aba201", - "hash": "d097893ac2008f2537d8f180c4f9d380752f086abd9ed749728af23c" + "compiledCode": "5905540100003232323232323232323232323223232323223232322533300f3232325333012300b00114a226464646464a66602e601600c26464a666032601a60366ea80044c8c8c94ccc070c054c078dd500089919299980f180b98101baa0011324a2604860426ea8004074cc01c03c00cc088c07cdd500080d198038068009804244101ff00301f301c37540022940c00cc06cdd5005180e980d1baa007132325333019300d301b37540022646464a666038602a603c6ea80044c8c94ccc078c05cc080dd500089925130243021375400203a6600e01e0066044603e6ea8004068cc01c034004c021220101ff00301f301c37540022940c00cc06cdd5005180e980d1baa00722330053758601260366ea8c024c06cdd5001119baf300a301c3754600860386ea80040088c070c07400488cc00cdd6180e180e980e980c9baa300730193754004466ebcc020c068dd500080111191980080080191299980d8008a6103d87a8000132325333019300500213374a90001980f00125eb804cc010010004c07c008c0740048cdd2a40006603066e95200233018375200297ae0330184c103d87a80004bd7018099baa00130013013375400a4602c0022930a998082491856616c696461746f722072657475726e65642066616c73650013656533300d3006300f3754004264a666024002014264a666026602c004264931929998081804800899299980a800806899299980b180c8010a4c01c64a66666603400201c01c01c26eb4004038c05c004c04cdd50010a9998081802000899299980a800806899299980b180c80109924ca666024601660286ea80044c94ccc05c00403c4c8c94ccc0640040444c94ccc068c0740084c9263300e00301201232533333301e0010120120121375a0020246036002603600464a66666603800220020200200200206032002602a6ea8004038038c94cccccc0680044004038038038038c05c004c04cdd50010a99980819b87480100044c94ccc0540040344c94ccc058c0640084c9265333012300b30143754002264a66602e00201e26464a666032002022264a666034603a004264931980700180900919299999980f00080900900909bad001012301b001301b00232533333301c001100101001001001030190013015375400201c01c64a666666034002200201c01c01c01c602e00260266ea8008030c044dd500080599299999980b8008800805805805805980a00098081baa002009370e900129999998098008800803803803803a999804980118059baa003132533300e00100713232533301000100913232533301200100b13253330133016002132498cc01c014030030c94cccccc05c0040300300304dd6800806180a000980a00119299999980a80080500500509bad00100a3012001301200232533333301300110010080080080083010001300c375400600c44a666014600660186ea80084c94ccc03c00401c4c8c94ccc0440040244c94ccc048c05400852600a32533333301600100a00a00a00a1375c0026026002602600464a66666602800201001001001026eb8004c044004c034dd50010031b87480014cccccc038004400400c00c00c00c54cc01524011672656465656d65723a20506f6f6c52656465656d65720016153300449110646174756d3a20506f6f6c446174756d001615330034913d65787065637420536f6d6528706f6f6c5f6f757470757429203d206765745f6f7574707574286374782c2076616c696461746f725f6164647265737329001615330024913b65787065637420536f6d6528706f6f6c5f696e70757429203d206765745f696e707574286374782c2076616c696461746f725f616464726573732900165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "3ac593e0e8c626918e776b2b4c1d7578719464f516e9f1ac78bcdd22" } ], "definitions": { diff --git a/examples/acceptance_tests/072/aiken.lock b/examples/acceptance_tests/072/aiken.lock index b1782f547..f264ff161 100644 --- a/examples/acceptance_tests/072/aiken.lock +++ b/examples/acceptance_tests/072/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407098, nanos_since_epoch = 612481000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353079, nanos_since_epoch = 869301000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/073/aiken.lock b/examples/acceptance_tests/073/aiken.lock index 6cda2018c..2fc372da8 100644 --- a/examples/acceptance_tests/073/aiken.lock +++ b/examples/acceptance_tests/073/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407092, nanos_since_epoch = 27004000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353073, nanos_since_epoch = 642619000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/074/aiken.lock b/examples/acceptance_tests/074/aiken.lock index b9030d1db..b07c47795 100644 --- a/examples/acceptance_tests/074/aiken.lock +++ b/examples/acceptance_tests/074/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407107, nanos_since_epoch = 237676000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353074, nanos_since_epoch = 601697000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/077/aiken.lock b/examples/acceptance_tests/077/aiken.lock index 5d5a39454..a7ec3aa1d 100644 --- a/examples/acceptance_tests/077/aiken.lock +++ b/examples/acceptance_tests/077/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407089, nanos_since_epoch = 703441000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719352929, nanos_since_epoch = 982815000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/077/plutus.json b/examples/acceptance_tests/077/plutus.json index ec67947ad..6ffce1f2e 100644 --- a/examples/acceptance_tests/077/plutus.json +++ b/examples/acceptance_tests/077/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -31,8 +31,8 @@ } } ], - "compiledCode": "5901cc010000323232323232322322232323225333009323232533300c3007300d3754002264646464a666026602c00426464a666024601a60266ea803854ccc048c8cc004004018894ccc05c004528099299980a99baf301a30173754603400402429444cc00c00c004c06800454ccc048c0300044cdc78010080a501616375a60260046eb8c04400458c050004c94ccc03cc024c040dd50008a5eb7bdb1804dd5980a18089baa00132323300100132330010013756602c602e602e602e602e00a44a66602a002297adef6c6013232323253330163372291100002153330163371e9101000021003100513301a337606ea4008dd3000998030030019bab3017003375c602a0046032004602e00244a666028002298103d87a800013232323253330153372200e0042a66602a66e3c01c0084cdd2a4000660326e980052f5c02980103d87a80001330060060033756602c0066eb8c050008c060008c058004dd7180998081baa00337586024002601c6ea800858c040c044008c03c004c02cdd50008a4c26cac64a66601060060022a66601660146ea8010526161533300830020011533300b300a37540082930b0b18041baa003370e90011b8748000dd7000ab9a5573aaae7955cfaba05742ae89", - "hash": "df50e06b40d42b2c399ebcec4c2a8e51a6b28ef99790d950cc251caa" + "compiledCode": "590347010000323232323232323232323223222323232322533300c323232533300f3007301137540022646464a66602c002020264a66602e603400426464a66602a601a602e6ea803854ccc054c8cc004004018894ccc06c004528099299980c19baf301e301b3754603c00402629444cc00c00c004c07800454ccc054c0300044cdc78010088a5015330164901536578706563740a202020202020202020206c6973742e616e7928696e707574732c20666e28696e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d207574786f5f726566207d2900161533016491046275726e0016375a602e0046eb8c054004044c060004c94ccc048c024c050dd50008a5eb7bdb1804dd5980c180a9baa001323233001001323300100137566034603660366036603600a44a666032002297adef6c6013232323253330193372291100002153330193371e9101000021003100513301e337606ea4008dd3000998030030019bab301b003375c6032004603a004603600244a666030002298103d87a800013232323253330183372200e0042a66603066e3c01c0084cdd2a40006603a6e980052f5c02980103d87a8000133006006003375660340066eb8c060008c070008c068004dd7180b980a1baa0033758602c00260246ea800854cc041241236578706563742074782e4d696e7428706f6c6963795f696429203d20707572706f73650016301430150023013001300f37540022930a99806a491856616c696461746f722072657475726e65642066616c7365001365632533300b30030011533300f300e37540082930050a99980598010008a99980798071baa0041498028028c030dd50019b8748008dc3a4000a66666601e002200200c00c00c00c6eb800454cc00d24018f657870656374205b506169722861737365745f6e616d652c20616d6f756e74295d203d0a2020202020206d696e740a20202020202020207c3e2076616c75652e66726f6d5f6d696e7465645f76616c75650a20202020202020207c3e2076616c75652e746f6b656e7328706f6c6963795f6964290a20202020202020207c3e20646963742e746f5f70616972732829001615330024910c72646d723a20416374696f6e00165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "e8c0b6d7c88bce7578f598ed61f172854b78a78c4ec251b45d6da4c4" }, { "title": "spend2.backtrace", @@ -48,8 +48,8 @@ "$ref": "#/definitions/Void" } }, - "compiledCode": "58ad010000323232323232322323223225333007533300730053008375464660020026eb0c034c038c038c028dd5180698051baa00222533300c00114c0103d87a800013232533300b4a2266e9520003300f0024bd70099802002000980800118070008a511614984d958c94ccc018c010c01c00454ccc024c0200045261616375400264a6660086004600a0022a66600e600c0022930b0b1baa002370e90002b9a5573aaae7955cfaba05742ae881", - "hash": "aae5a1fcf239d541c67a7efb006436be41c5ee7f6f4a8fd7b39b97a8" + "compiledCode": "5901680100003232323232323232323232232322322533300953330093005300b375464660020026eb0c040c044c044c034dd5180818069baa00222533300f00114c0103d87a800013232533300d4a2266e952000330120024bd70099802002000980980118088008a51153300a4914765787065637420536f6d65285f29203d206c6973742e66696e6428636f6e746578742e7472616e73616374696f6e2e6f7574707574732c20666e285f29207b2054727565207d290016149854cc0292411856616c696461746f722072657475726e65642066616c73650013656533333300f001153330073003300937540022a66601660146ea8004526005005005005005005533333300d002153330053001300737540042a66601260106ea8008526004004004004004004370e90000a99801a4810f5f72656465656d65723a20566f6964001615330024910c5f646174756d3a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "f86c88144df93f3925cf048d1b50615fa95249f063a07242f70a6bd8" } ], "definitions": { diff --git a/examples/acceptance_tests/079/plutus.json b/examples/acceptance_tests/079/plutus.json index a2a351f50..696c7c968 100644 --- a/examples/acceptance_tests/079/plutus.json +++ b/examples/acceptance_tests/079/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/RedeemerWrapper$Int" } }, - "compiledCode": "5853010000323232322253330033370e900018021baa00113253330043370e002902a0a4c26cac6eb40084c8c894ccc018cdc399b800030024815052613656375a600e600c6ea8008dd68012b9a5573aaae795d081", - "hash": "1cb810eff560f2aa83e3bf8bc1c8bb44b5d90b3c3fa9bb5b3008ec63" + "compiledCode": "5901e401000032323232323232322232533333300b002153330063370e900018041baa002153300749011c52756e6e696e672032206172672076616c696461746f72206d696e7400153330063370ea66666601600600800800826eb400c0112054149854cc01d2411856616c696461746f722072657475726e65642066616c73650013656153300749011d52756e6e696e672033206172672076616c696461746f72207370656e640013322322533300a3370e66e000100092054149854cc02d24011856616c696461746f722072657475726e65642066616c73650013656533333300d0010060060061375a00200ca66666601600600a00a00a26eb400c014c028c024dd50010a998038008b0a998038008b0a998038008b0a998038008b24991496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e0015330034910d72656465656d65723a20496e74001615330024910a646174756d3a20496e7400165734ae7155ceaab9e5742ae901", + "hash": "e2a34772b7901ffaed1c3d4bdf61bf613f028921738ec4b79329b105" }, { "title": "foo.mint", @@ -34,8 +34,8 @@ "$ref": "#/definitions/Int" } }, - "compiledCode": "5853010000323232322253330033370e900018021baa00113253330043370e002902a0a4c26cac6eb40084c8c894ccc018cdc399b800030024815052613656375a600e600c6ea8008dd68012b9a5573aaae795d081", - "hash": "1cb810eff560f2aa83e3bf8bc1c8bb44b5d90b3c3fa9bb5b3008ec63" + "compiledCode": "5901e401000032323232323232322232533333300b002153330063370e900018041baa002153300749011c52756e6e696e672032206172672076616c696461746f72206d696e7400153330063370ea66666601600600800800826eb400c0112054149854cc01d2411856616c696461746f722072657475726e65642066616c73650013656153300749011d52756e6e696e672033206172672076616c696461746f72207370656e640013322322533300a3370e66e000100092054149854cc02d24011856616c696461746f722072657475726e65642066616c73650013656533333300d0010060060061375a00200ca66666601600600a00a00a26eb400c014c028c024dd50010a998038008b0a998038008b0a998038008b0a998038008b24991496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e0015330034910d72656465656d65723a20496e74001615330024910a646174756d3a20496e7400165734ae7155ceaab9e5742ae901", + "hash": "e2a34772b7901ffaed1c3d4bdf61bf613f028921738ec4b79329b105" } ], "definitions": { diff --git a/examples/acceptance_tests/082/aiken.lock b/examples/acceptance_tests/082/aiken.lock index e4e7b1f78..23cb9fdc4 100644 --- a/examples/acceptance_tests/082/aiken.lock +++ b/examples/acceptance_tests/082/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407089, nanos_since_epoch = 560055000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353055, nanos_since_epoch = 72091000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/083/aiken.lock b/examples/acceptance_tests/083/aiken.lock index 79ce28897..d50c6bc91 100644 --- a/examples/acceptance_tests/083/aiken.lock +++ b/examples/acceptance_tests/083/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407096, nanos_since_epoch = 162798000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353049, nanos_since_epoch = 708406000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/084/aiken.lock b/examples/acceptance_tests/084/aiken.lock index 39623b02b..fabfcab5d 100644 --- a/examples/acceptance_tests/084/aiken.lock +++ b/examples/acceptance_tests/084/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407088, nanos_since_epoch = 853030000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353048, nanos_since_epoch = 606702000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/086/aiken.lock b/examples/acceptance_tests/086/aiken.lock index b315ccb41..dbe22577f 100644 --- a/examples/acceptance_tests/086/aiken.lock +++ b/examples/acceptance_tests/086/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407097, nanos_since_epoch = 304608000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353080, nanos_since_epoch = 562940000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/086/plutus.json b/examples/acceptance_tests/086/plutus.json index b0c178712..2bb905849 100644 --- a/examples/acceptance_tests/086/plutus.json +++ b/examples/acceptance_tests/086/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "5901c5010000323232323232222533300432325333006300230073754601460106ea80145288a503232533300730033008375400c26464a666018601c004264931929998051803000899192999807980880109924ca6660186010601a6ea80044c8c94ccc044c04c0084c926533300e300a300f3754002264646464a66602a602e004264649319299980a180800089919299980c980d80109924c64a66602e602600226464a666038603c0042649318098008b180e000980c9baa002153330173012001132323232323253330203022002149858dd6981000098100011bad301e001301e002375a603800260326ea800858c05cdd50008b180c800980b1baa00315333014300f00115333017301637540062930b0b180a1baa002300c00316301500130150023013001301037540022c2c6022002601c6ea80045858c03c004c030dd50010a99980518028008a99980698061baa00214985858c028dd50008b180600098049baa006162325333008300400113232533300d300f002149858dd7180680098051baa00215333008300300113232533300d300f002149858dd7180680098051baa00216300837540026e1d2002370e90000a4c26cacae6955ceaab9e5573eae855d101", - "hash": "155818624d971a460dc184b0816707ccecfad99bd7c546d55b7c0cce" + "compiledCode": "590341010000323232323232323232222533300532323253330083002300a3754601a60166ea800c5288a50323253330093003300b3754008264a66601c002012264a66601e602200426493192999806180300089929998088008060992999809180a00109924ca66601c601060206ea80044c94ccc04c0040384c94ccc050c0580084c9265333010300a30123754002264a66602a00202026464a66602e002024264a6660306034004264649319299980b1808000899299980d80080b099299980e180f00109924c64a6660326026002264a66603c002032264a66603e6042004264931980980080d00d192999999811000880080d00d00d00d180f800980e1baa002153330193012001132533301e00101913232533302000101b13232533302200101d132533302330250021498078c94cccccc0980040780780784dd680080f1811800981180119299999981200080e00e00e09bad00101c3021001302100232533333302200101a01a01a1375a002034603e00260386ea8008060c068dd500080b99299999980f800880080b80b80b80b980e000980c9baa00315333016300f0011533301a3019375400629300a80a980b9baa0023300c00301301332533333301b001100101301301301330180013018002325333333019001100101101101101130160013013375400201e01e64a66666602e002200201e01e01e01e602800260226ea8004034034c94cccccc0540044004034034034034c048004c03cdd50010a99980618028008a99980818079baa002149802c02cc034dd50008051929999998090008800805005005005180780098061baa0040082232533300b3005001132533301000100b132533301130130021498030c94cccccc0500040300300300304dd7000980880098071baa0031533300b3004001132533301000100b132533301130130021498030c94cccccc0500040300300300304dd7000980880098071baa00300a300c37540046e1d2002370e9000299999980600188018020020020020a4c2a6600c9211856616c696461746f722072657475726e65642066616c73650013656153300249012365787065637420646174756d3a2054657374446174756d203d207261775f646174756d00165734ae7155ceaab9e5573eae855d12ba41", + "hash": "4ab81bc59370bdc62dc58c35c91f0e6703a4c4b3b9cd1e76c8ded83b" } ], "definitions": { diff --git a/examples/acceptance_tests/087/aiken.lock b/examples/acceptance_tests/087/aiken.lock index dccd175e9..1b5035bff 100644 --- a/examples/acceptance_tests/087/aiken.lock +++ b/examples/acceptance_tests/087/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407092, nanos_since_epoch = 232992000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353073, nanos_since_epoch = 614646000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/088/aiken.lock b/examples/acceptance_tests/088/aiken.lock index d77079ba6..341243226 100644 --- a/examples/acceptance_tests/088/aiken.lock +++ b/examples/acceptance_tests/088/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407097, nanos_since_epoch = 984333000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353080, nanos_since_epoch = 542677000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/089/aiken.lock b/examples/acceptance_tests/089/aiken.lock index 356bd58ca..93925f565 100644 --- a/examples/acceptance_tests/089/aiken.lock +++ b/examples/acceptance_tests/089/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407106, nanos_since_epoch = 432431000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353072, nanos_since_epoch = 273966000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/089/plutus.json b/examples/acceptance_tests/089/plutus.json index e6677bbbd..c82a4c65e 100644 --- a/examples/acceptance_tests/089/plutus.json +++ b/examples/acceptance_tests/089/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -25,8 +25,8 @@ } } ], - "compiledCode": "58d9010000323232323232322232322533300632325333008300530093754601a601c00426464a666014600e60166ea8cc00400c8cdd7980198069baa00100a1533300a3007300b375466002006466ebcc00cc034dd50008050a5114a02c44646600200200644a6660200022980103d87a800013232533300f300500213374a90001980980125eb804cc010010004c050008c0480048c03800458dd6180618049baa300c0013008375400229309b2b192999802980118030008a99980418038008a4c2c2c6ea8008dc3a4000ae6955ceaab9e5573eae815d0aba21", - "hash": "18a0ccabc469bf3db721839b2672babd105af32656284818934c2cd4" + "compiledCode": "5901ac0100003232323232323232323222323225333007323253330093005300b3754601e602000426464a666016600e601a6ea8cc00400c8cdd7980198079baa00100a1533300b3007300d375466002006466ebcc00cc03cdd50008050a5114a02a660189215f65787065637420536f6d65285f696e70757429203d0a2020202020206c6973742e66696e6428696e707574732c20666e28696e70757429207b20696e7075742e6f75747075745f7265666572656e6365203d3d207574786f5f726566207d29001622323300100100322533301200114c0103d87a8000132325333010300500213374a90001980a80125eb804cc010010004c058008c0500048c04000454cc029240121657870656374204d696e74285f706f6c6963795f696429203d20707572706f736500163758601c60166ea8c038004c028dd50008a4c2a6601092011856616c696461746f722072657475726e65642066616c73650013656533333300d002153330053001300737540042a66601260106ea8008526004004004004004004370e90000a998012481085f723a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "befc649df2b68f298c49e4cff0e9649e2ccf2cfc1665be4c507f15d6" } ], "definitions": { diff --git a/examples/acceptance_tests/090/plutus.json b/examples/acceptance_tests/090/plutus.json index 434450345..2f0cb61e3 100644 --- a/examples/acceptance_tests/090/plutus.json +++ b/examples/acceptance_tests/090/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "583f010000322322253330053370e00690487777c9cfdde5c8f27bf4c1637fc55b5eeef7d8c4d9e0d4454967ff7d6e7ee6e242eb60c6318a4c26cac6eb40055cd1", - "hash": "6c5f960b7a078766778eef14cef347f3b5cd3c5fc4a7797f031aad70" + "compiledCode": "5884010000323232322322253330063370e00690487777c9cfdde5c8f27bf4c1637fc55b5eeef7d8c4d9e0d4454967ff7d6e7ee6e242eb60c6318a4c2a6600e9211856616c696461746f722072657475726e65642066616c7365001365653333330050010020020021375a0020042a660049210a646174756d3a20496e7400165734ae715d21", + "hash": "7fb7ba29b94d55ef2cb11efc85ec3e85ce32f092c41743b2cb8a6e08" } ], "definitions": { diff --git a/examples/acceptance_tests/096/plutus.json b/examples/acceptance_tests/096/plutus.json index ae770fa39..16acc0b00 100644 --- a/examples/acceptance_tests/096/plutus.json +++ b/examples/acceptance_tests/096/plutus.json @@ -6,7 +6,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" }, "license": "Apache-2.0" }, @@ -25,8 +25,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "583c01000032222533300453330043375e004006266e3d22010b68656c6c6f20776f726c640048810b68656c6c6f20776f726c640014a029309b2b2b9a01", - "hash": "d1a4ef5efcf38bdca9dc8eec2684d3c2004390fa6fd1b5bed6faa488" + "compiledCode": "585e0100003232222533300453330043375e004006266e3d22010b68656c6c6f20776f726c640048810b68656c6c6f20776f726c640014a02930a99802a4811856616c696461746f722072657475726e65642066616c736500136565734ae701", + "hash": "7dfcec1b2545d65c610e85bc608458efc30b94ebb6171bb5f2759a45" } ], "definitions": { diff --git a/examples/acceptance_tests/101/aiken.lock b/examples/acceptance_tests/101/aiken.lock index be05d508e..e2436fe54 100644 --- a/examples/acceptance_tests/101/aiken.lock +++ b/examples/acceptance_tests/101/aiken.lock @@ -24,5 +24,5 @@ requirements = [] source = "github" [etags] -"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1716407093, nanos_since_epoch = 166109000 }, "d7aadd4a9b25589bd6d5e3bbedcd809cdf97fe3eddb365cf89cd6ac6bc829643"] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407092, nanos_since_epoch = 908456000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1719353072, nanos_since_epoch = 396481000 }, "a8294651f1577c671d580c99c9bc5445ef1fd44e4aa3dde550434a4cbc8d50b6"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353072, nanos_since_epoch = 284242000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/102/aiken.lock b/examples/acceptance_tests/102/aiken.lock index 13ddfacec..e4e08a771 100644 --- a/examples/acceptance_tests/102/aiken.lock +++ b/examples/acceptance_tests/102/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407088, nanos_since_epoch = 875368000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353045, nanos_since_epoch = 658069000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/104/aiken.lock b/examples/acceptance_tests/104/aiken.lock index 7319f59c9..86eb2ab3c 100644 --- a/examples/acceptance_tests/104/aiken.lock +++ b/examples/acceptance_tests/104/aiken.lock @@ -24,5 +24,5 @@ requirements = [] source = "github" [etags] -"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1717767691, nanos_since_epoch = 206091000 }, "98cf81aa68f9ccf68bc5aba9be06d06cb1db6e8eff60b668ed5e8ddf3588206b"] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1717767690, nanos_since_epoch = 920449000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] +"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1719353045, nanos_since_epoch = 907622000 }, "a8294651f1577c671d580c99c9bc5445ef1fd44e4aa3dde550434a4cbc8d50b6"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353045, nanos_since_epoch = 657299000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/104/plutus.json b/examples/acceptance_tests/104/plutus.json index e2c093d5f..9e6f61bc8 100644 --- a/examples/acceptance_tests/104/plutus.json +++ b/examples/acceptance_tests/104/plutus.json @@ -6,7 +6,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.29-alpha+257bd23" + "version": "v1.0.29-alpha+e856fc6" }, "license": "Apache-2.0" }, @@ -27,8 +27,8 @@ } } ], - "compiledCode": "582401000032323222253330043370e6eb4c018c014dd5001a400429309b2b2b9a5573cae841", - "hash": "047dafbc61fb4a550a28398bde3680c48ff2000cf1022efc883124cd" + "compiledCode": "58460100003232323222253330043370e6eb4c01cc018dd5001a40042930a99802a4811856616c696461746f722072657475726e65642066616c736500136565734ae7155cf2ba11", + "hash": "0f3b69fc2e974a443d2e09c6bb99985d83e905a74db65f78c0da2191" } ], "definitions": { diff --git a/examples/acceptance_tests/105/aiken.lock b/examples/acceptance_tests/105/aiken.lock new file mode 100644 index 000000000..6e350cdaa --- /dev/null +++ b/examples/acceptance_tests/105/aiken.lock @@ -0,0 +1,7 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] + +[etags] diff --git a/examples/acceptance_tests/105/aiken.toml b/examples/acceptance_tests/105/aiken.toml new file mode 100644 index 000000000..c7fec73f7 --- /dev/null +++ b/examples/acceptance_tests/105/aiken.toml @@ -0,0 +1,9 @@ +name = "aiken-lang/105" +version = "0.0.0" +license = "Apache-2.0" +description = "Aiken contracts for project 'aiken-lang/102'" + +[repository] +user = "aiken-lang" +project = "105" +platform = "github" diff --git a/examples/acceptance_tests/105/lib/tests.ak b/examples/acceptance_tests/105/lib/tests.ak new file mode 100644 index 000000000..7e6f26eee --- /dev/null +++ b/examples/acceptance_tests/105/lib/tests.ak @@ -0,0 +1,45 @@ +pub type Foo { + a: Int, +} + +pub type Bar { + Bazz(Int) + Buzz(Int) +} + +test if_soft_cast() { + let d: Data = Foo { a: 1 } + + if d is Foo { + d.a == 1 + } else { + False + } +} + +test if_soft_cast_2() { + let d: Data = Bazz(1) + + if d is Foo { + d.a == 1 + } else if d is Bazz(y): Bar { + y == 1 + } else { + False + } +} + +test if_soft_cast_3() { + let d: Data = Bazz(1) + let x: Data = Buzz(2) + + if d is Foo { + d.a == 1 + } else if d is Bazz(y): Bar { + y == 1 + } else if x is Buzz(y): Bar { + y == 2 + } else { + False + } +} diff --git a/examples/acceptance_tests/script_context/aiken.lock b/examples/acceptance_tests/script_context/aiken.lock index 1d7887754..868f7f1d3 100644 --- a/examples/acceptance_tests/script_context/aiken.lock +++ b/examples/acceptance_tests/script_context/aiken.lock @@ -13,4 +13,4 @@ requirements = [] source = "github" [etags] -"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1716407124, nanos_since_epoch = 316651000 }, "6b89f2c51314a7bc2cc377d37c9eade9a4239086fe636ac6030c6979182f1247"] +"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1719353165, nanos_since_epoch = 165401000 }, "a746f5b5cd3c2ca5dc19c43bcfc64230c546fafea2ba5f8e340c227b85886078"] diff --git a/examples/acceptance_tests/script_context/plutus.json b/examples/acceptance_tests/script_context/plutus.json index 84fde24a8..1f76e4cd9 100644 --- a/examples/acceptance_tests/script_context/plutus.json +++ b/examples/acceptance_tests/script_context/plutus.json @@ -5,7 +5,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.26-alpha+c3ad52b" + "version": "v1.0.29-alpha+e856fc6" } }, "validators": [ @@ -23,8 +23,8 @@ "$ref": "#/definitions/Void" } }, - "compiledCode": "5903290100003232323232323223232232253330073253330083330083375e601a601c601c601c601c601c601c601c601c601c601c601c60146ea8c004c028dd5001260126d8799f58200000000000000000000000000000000000000000000000000000000000000000ff004a09444c94ccc024c94ccc028cdc3a400460166ea80044c94ccc02ccdd7980218069baa0014c0126d8799f58200000000000000000000000000000000000000000000000000000000000000000ff0013009375a6006601a6ea8004528180798061baa001163001300b375400626464a6660166464a6660200022c2a6660206026002264a66601c66ebcc018c040dd50009ba6300448202a35ae41c54ccc038cdd7980398081baa30073010375400298122d8799f581c11111111111111111111111111111111111111111111111111111111ff001533300e533300e300c300f3754600c60206ea8c01cc040dd50008a5014a22a66601c66ebcc00cc040dd5000a60103d879800013375e600a60206ea800530103d87a800014a029405280a5030120011637586002601c6ea8c014c038dd50031180898091809000899baf3002300d37546008601a6ea8014dd31800a40a8294094ccc02cc02400452f5bded8c0264646600200297adef6c6022533301100113301233760981014000374c00697adef6c60132323232533301233720910100002133016337609801014000374c00e00a2a66602466e3d22100002133016337609801014000374c00e00626602c66ec0dd48011ba600133006006003375660260066eb8c044008c054008c04c004c8cc0040052f5bded8c044a66602000226602266ec13001014000375000697adef6c60132323232533301133720910100002133015337609801014000375000e00a2a66602266e3d22100002133015337609801014000375000e00626602a66ec0dd48011ba800133006006003375a60240066eb8c040008c050008c0480048c03cc040c040c0400045281180718078008a502300d00114984d958c94ccc018c010c01c00454ccc024c0200045261616375400264a6660086004600a0022a66600e600c0022930b0b1baa002370e90002b9a5573aaae7955cfaba05742ae881", - "hash": "c1f48659f124f9dcd673c40fef80ecfa5b42a17949ff12fab7f1c269" + "compiledCode": "5904000100003232323232323232323232232322322533300932533300a33300a3375e602060226022602260226022602260226022602260226022601a6ea8c004c034dd5001260126d8799f58200000000000000000000000000000000000000000000000000000000000000000ff004a09444c94ccc02cc94ccc030cdc3a4004601c6ea80044c94ccc034cdd7980218081baa0014c0126d8799f58200000000000000000000000000000000000000000000000000000000000000000ff0013009375a600660206ea8004528180918079baa001153300d4911c73637269707420707572706f73652069736e277420275370656e642700163001300e375400626464a66601a6464a6660260022a6602092011c756e6578706563746564206e756d626572206f66206f757470757473001615333013301600113253330103375e600c60266ea8004dd318022410151ad720e2a66602066ebcc01cc04cdd5180398099baa0014c0122d8799f581c11111111111111111111111111111111111111111111111111111111ff00153330105333010300c30123754600c60266ea8c01cc04cdd50008a5014a22a66602066ebcc00cc04cdd5000a60103d879800013375e600a60266ea800530103d87a800014a029405280a50301500115330104911c756e6578706563746564206e756d626572206f66206f75747075747300163758600260226ea8c014c044dd50031180a180a980a800899baf300230103754600860206ea8014dd31800a40a8294094ccc034c02400452f5bded8c0264646600200297adef6c6022533301400113301533760981014000374c00697adef6c60132323232533301433720910100002133019337609801014000374c00e00a2a66602866e3d22100002133019337609801014000374c00e00626603266ec0dd48011ba6001330060060033756602c0066eb8c050008c060008c058004c8cc0040052f5bded8c044a66602600226602866ec13001014000375000697adef6c60132323232533301333720910100002133018337609801014000375000e00a2a66602666e3d22100002133018337609801014000375000e00626603066ec0dd48011ba800133006006003375a602a0066eb8c04c008c05c008c0540048c048c04cc04cc04c0045281180898090008a5023010001149854cc0292411856616c696461746f722072657475726e65642066616c73650013656533333300f001153330073003300937540022a66601660146ea8004526005005005005005005533333300d002153330053001300737540042a66601260106ea8008526004004004004004004370e90000a99801a4810f5f72656465656d65723a20566f6964001615330024910c5f646174756d3a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "226bec4fd3005ec13cdd5d68226362cd6a9a107726eee2e6ee8fd299" }, { "title": "deploy.spend", @@ -40,8 +40,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "59023e01000032323232323232222533300453330043375e00698103d879800013253330053323223253330093370e900018051baa00113232533300b3375e980106d8799f182aff0000213370e600a00890020a50533300a3370e900018059baa00113232533300f3012002149858dd6980800098061baa00116300e300b37540022c64646600200200644a66601c0022980103d87a8000132323232533300f3372200e0042a66601e66e3c01c0084cdd2a40006602600297ae014c0103d87a80001330060060033010003375c601c004602400460200026e50dd9a6106d8799f182aff00300100122533300a0011480004cdc02400466004004601a0026eacc028c02cc02cc02cc02cc02cc02cc02cc02cc02cc02cc01cdd5180098039baa00213232533300a00116132533300b00116132533300932533300a3375e600a60186ea800530126d87a9f5820fcaa61fb85676101d9e3398a484674e71c45c3fd41b492682f3b0054f4cf3273ff0013375e601e60206020602060186ea800530122d8799f581ce37db487fbd58c45d059bcbf5cd6b1604d3bec16cf888f1395a4ebc4ff0014a0601c0062a66601266ebcc038c03cc02cdd5180298059baa0014c012ad8799fd8799fd8799f581c66666666666666666666666666666666666666666666666666666666ffffff00153330093370e900218051baa3004300b37540022944585280a50300d001300d0013758600260106ea8c008c020dd500191805980618060008a502300a00114a029309b2b2b9a5573aaae7955cfaba05742ae881", - "hash": "a77ca3bb8551334cbed20bafe31b3a2ac2d1862d065b7994864ebc5b" + "compiledCode": "59039d01000032323232323232323232222533300553330053375e00698103d8798000132533300633232232533300a3370e900018061baa0011323232533300d3375e980106d8799f182aff0000213370e600c00a90020a50533300c3370e900018071baa001132533301100100c132533301230150021498034c94cccccc0580040340340344dd6800806980980098079baa00100b5333333013001100100a00a00a00a3010300d37540022a660169215865787065637420536f6d6528646174756d29203d0a20202020646963742e67657428646174756d732c20626c616b6532625f323536286275696c74696e2e73657269616c6973655f64617461286d795f646174756d292929001632323300100100322533301000114c0103d87a800013232323253330103372200e0042a66602066e3c01c0084cdd2a40006602a00297ae014c0103d87a80001330060060033012003375c6020004602800460240026e50dd9a6106d8799f182aff00300100122533300c0011480004cdc02400466004004601e0026eacc030c034c034c034c034c034c034c034c034c034c034c024dd5180098049baa00213232533300c00115330094901316578706563746564207472616e73616374696f6e20746f206861766520286174206c65617374292032206f7574707574730016132533300d001153300a4901316578706563746564207472616e73616374696f6e20746f206861766520286174206c65617374292032206f7574707574730016132533300a32533300b3375e600a601c6ea800530126d87a9f5820fcaa61fb85676101d9e3398a484674e71c45c3fd41b492682f3b0054f4cf3273ff0013375e6022602460246024601c6ea800530122d8799f581ce37db487fbd58c45d059bcbf5cd6b1604d3bec16cf888f1395a4ebc4ff0014a060200062a66601466ebcc040c044c034dd5180298069baa0014c012ad8799fd8799fd8799f581c66666666666666666666666666666666666666666666666666666666ffffff001533300a3370e900218061baa3004300d3754002294454cc02d24115657870656374656420696e6c696e6520646174756d001614a02940c03c004c03c004dd6180098051baa3002300a37540064601a601c601c00229408c0300045280a4c2a6600c92011856616c696461746f722072657475726e65642066616c73650013656153300249011d65787065637420646174756d3a204d79446174756d203d20646174756d00165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "9b1c63d96ca0f51733f625fa71daccce4e921ab5d2ac71e1683471d7" }, { "title": "mint.mint", @@ -51,8 +51,8 @@ "$ref": "#/definitions/Data" } }, - "compiledCode": "590300010000323232323232322253330033232323232533233009323232533300f3012002132533300d3005300e3754002266e3c008dd7180918079baa001163008300e37540142c6eb8c040004cc004004cc010c00cdd5980298061baa3007300c37540109110022533300e00114bd70099807980618080009980100118088008a999191980599912999806980298071baa002132533300e3005300f37540022c266e1cdd6980998081baa001483c850c8cc004004c94ccc03cc018c040dd50008a5eb7bdb1804dd5980a18089baa00132323300100130093756601660246ea8010894ccc0500045300103d87a800013232323253330153372200e0042a66602a66e3c01c0084c02ccc064dd3000a5eb80530103d87a80001330060060033756602c0066eb8c050008c060008c058004dd7180998081baa00322533301200114c103d87a800013232323253330133372291103666f6f00002153330133371e910103666f6f000021300933017375000297ae014c0103d87a8000133006006003375a60280066eb8c048008c058008c05000458c01cc034dd5004980418069baa009132323232533300f3007301037540022a66601e66ebc038c044c8cdd8180a800980a980b0009bac3014301137540022600c60046eacc010c044dd5180618089baa00d14a02c64660020026eacc010c044dd5180618089baa00d22533301300114c103d87a80001323253330123375e6026004601c60286ea80404c020cc058dd39980b18098011980b180a00125eb812f5c0266008008002602e004602a002600200244a66602200229000099b8048008cc008008c0500048c044c048c048c048c048c048c048c048c048c048004dd2a40006e1d200214a06e1d200014a046600400291010022323300100100322533300d00114bd6f7b630099191919299980719b910070021533300e3371e00e0042006200a26602466ec0dd48011ba6001330060060033756601e0066eb8c034008c044008c03c0048c02cc030c030c030c0300048c028c02c0048c024004526136565734aae7555cf2ab9f5740ae855d101", - "hash": "f557530d177449d0609a60cbe4f48b221c04a6ca7f9f235fcdc8c741" + "compiledCode": "590496010000323232323232323232225333004323232323253323300a3232533301000100b13253330113014002132533300e300530103754002266e3c008dd7180a18089baa001153300f49124657870656374204d696e7428706f6c6963795f696429203d206374782e707572706f736500163008301037540140186eb8c048004cc004004cc010c00cdd5980298071baa3007300e375401091010022533301000114bd70099808980718090009980100118098008a999191980619912999807180298081baa002132533300f3005301137540022a6602092010f746f6b656e206e6f7420666f756e64001613370e6eb4c054c048dd5000a41e428646600200264a666020600c60246ea800452f5bded8c026eacc058c04cdd500099191980080098049bab300b3014375400844a66602c002298103d87a800013232323253330163372200e0042a66602c66e3c01c0084c02ccc06cdd3000a5eb80530103d87a8000133006006003375660300066eb8c058008c068008c060004dd7180a98091baa00322533301400114c103d87a800013232323253330143372291103666f6f00002153330143371e910103666f6f000021300933019375000297ae014c0103d87a8000133006006003375a602c0066eb8c050008c060008c05800454cc03d24120657870656374204d696e7428706f6c6963795f696429203d20707572706f736500163007300f37540126010601e6ea80244c8c8c8c94ccc040c01cc048dd50008a99980819baf00e30133233760602e002602e60300026eb0c058c04cdd50008980318011bab300430133754601860266ea80345280a99808a496b65787065637420536f6d652850616972285f2c2072656465656d65722929203d0a202020206c6973742e66696e64286374782e7472616e73616374696f6e2e72656465656d6572732c20666e286b7629207b206b762e317374203d3d206374782e707572706f7365207d29001632330010013756600860266ea8c030c04cdd500691299980a8008a6103d87a80001323253330133375e602a004601c602c6ea80404c020cc060dd39980c180a8011980c180b00125eb812f5c02660080080026032004602e002600200244a66602600229000099b8048008cc008008c0580048c04cc050c050c050c050c050c050c050c050c050004dd2a40006e1d200214a06e1d200014a046600400291010022323300100100322533300f00114bd6f7b630099191919299980799b910070021533300f3371e00e0042006200a26602866ec0dd48011ba600133006006003375660220066eb8c03c008c04c008c0440048c034c038c038c038c0380048c030c0340048c02c00452615330054911856616c696461746f722072657475726e65642066616c736500136561533002490189657870656374205b6d795f706f6c6963795f69645d203d0a202020206374782e7472616e73616374696f6e2e6d696e740a2020202020207c3e2076616c75652e66726f6d5f6d696e7465645f76616c75650a2020202020207c3e2076616c75652e776974686f75745f6c6f76656c6163650a2020202020207c3e2076616c75652e706f6c696369657300165734ae7155ceaab9e5573eae815d0aba21", + "hash": "8372367de2b0391b1bec0489dc72cb65de1a791f4e9712b9149d6392" }, { "title": "withdrawals.spend", @@ -68,8 +68,8 @@ "$ref": "#/definitions/Void" } }, - "compiledCode": "5902310100003232323232323223223225333006323232533300932533300a3370e900118059baa0011613370e6eb4c030c8cdd81808000980818088009bac300f300c3754002902a198009bab3002300b3754600660166ea80108cdd79805800a6126d8799fd8799f581c22222222222222222222222222222222222222222222222222222222ffff001533300932533300a3370e900118059baa0011613370e6eb4c030c8cdd81808000980818088009bac300f300c3754002900e198009bab3002300b3754600660166ea80108cdd79805800a60126d8799fd87a9f581cafddc16c18e7d8de379fb9aad39b3d1b5afd27603e5ebac818432a72ffff0013375e6e9cc8cc004004dd5980198061baa3004300c375400a44a66601c002297ae013300f300c3010001330020023011001374e6601a98126d8799fd8799f581c22222222222222222222222222222222222222222222222222222222ffff003300d4c126d8799fd87a9f581cafddc16c18e7d8de379fb9aad39b3d1b5afd27603e5ebac818432a72ffff004bd700a5014a044646600200200644a66601e002298103d87a800013232533300e300500213374a9000198091ba733012300f0023301230100024bd7025eb804cc010010004c04c008c0440048c034c038c038c038c038c038c0380048c030004526136563253330053370e900018030008a99980418038008a4c2c2c6ea8004c94ccc00ccdc3a400060080022a66600c600a0022930b0b1baa0015734aae7555cf2ab9f5740ae855d11", - "hash": "0ce02b31bca5fbbbb9e4e1f050781b2272590945dc6e1094dc3d2bde" + "compiledCode": "5902e2010000323232323232323232323223223225333008323232533300b32533300c3370e900118071baa001153300d4911c616c6963652773207769746864726177616c206e6f7420666f756e64001613370e6eb4c03cc8cdd818098009809980a0009bac3012300f3754002902a198009bab3002300e37546006601c6ea80108cdd79807000a6126d8799fd8799f581c22222222222222222222222222222222222222222222222222222222ffff001533300b32533300c3370e900118071baa001153300d49011a626f622773207769746864726177616c206e6f7420666f756e64001613370e6eb4c03cc8cdd818098009809980a0009bac3012300f3754002900e198009bab3002300e37546006601c6ea80108cdd79807000a6126d8799fd87a9f581cafddc16c18e7d8de379fb9aad39b3d1b5afd27603e5ebac818432a72ffff0013375e6e9cc8cc004004dd5980198079baa3004300f375400a44a666022002297ae0133012300f3013001330020023014001374e6602098126d8799fd8799f581c22222222222222222222222222222222222222222222222222222222ffff00330104c126d8799fd87a9f581cafddc16c18e7d8de379fb9aad39b3d1b5afd27603e5ebac818432a72ffff004bd700a5014a044646600200200644a666024002298103d87a8000132325333010300500213374a90001980a9ba73301530120023301530130024bd7025eb804cc010010004c058008c0500048c040c044c044c044c044c044c0440048c03c00452615330094911856616c696461746f722072657475726e65642066616c73650013656533333300e001153330063370e900018041baa0011533300a3009375400229300200200200200200229999998060008a99980219b8748000c018dd50008a99980418039baa001149800c00c00c00c00c00c54cc00d2410f5f72656465656d65723a20566f6964001615330024910c5f646174756d3a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "2278726afe2d74b58a5314acc2b66c12feda88d18d821abd456b2561" } ], "definitions": {