diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index 1c063406..42808933 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -117,6 +117,11 @@ pub enum Air { constr_index: usize, }, + AssertBool { + scope: Vec, + is_true: bool, + }, + // When When { scope: Vec, @@ -268,6 +273,7 @@ impl Air { | Air::UnWrapData { scope, .. } | Air::WrapData { scope, .. } | Air::AssertConstr { scope, .. } + | Air::AssertBool { scope, .. } | Air::When { scope, .. } | Air::Clause { scope, .. } | Air::ListClause { scope, .. } @@ -375,6 +381,7 @@ impl Air { | Air::Let { .. } | Air::WrapClause { .. } | Air::AssertConstr { .. } + | Air::AssertBool { .. } | Air::Finally { .. } | Air::FieldsExpose { .. } => None, diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index cd740474..6dacf291 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -2056,66 +2056,78 @@ impl<'a> CodeGenerator<'a> { scope: scope.clone(), check_last_item: false, }); - } else { + } else if !tipo.is_bool() { pattern_vec.push(Air::Let { scope: scope.clone(), name: "_".to_string(), }); } - if matches!(assignment_properties.kind, AssignmentKind::Expect) { - let data_type = - lookup_data_type_by_tipo(self.data_types.clone(), tipo).unwrap(); + match assignment_properties.kind { + AssignmentKind::Let => { + pattern_vec.append(values); + } + AssignmentKind::Expect => { + if tipo.is_bool() { + pattern_vec.push(Air::AssertBool { + scope, + is_true: constr_name == "True", + }); - let (index, _) = data_type - .constructors - .iter() - .enumerate() - .find(|(_, constr)| &constr.name == constr_name) - .unwrap(); + pattern_vec.append(values); + } else { + let data_type = + lookup_data_type_by_tipo(self.data_types.clone(), tipo).unwrap(); - let constr_name = format!("__{}_{}", constr_name, self.id_gen.next()); + let (index, _) = data_type + .constructors + .iter() + .enumerate() + .find(|(_, constr)| &constr.name == constr_name) + .unwrap(); - pattern_vec.push(Air::Let { - scope: scope.clone(), - name: constr_name.clone(), - }); + let constr_name = format!("__{}_{}", constr_name, self.id_gen.next()); - pattern_vec.append(values); + pattern_vec.push(Air::Let { + scope: scope.clone(), + name: constr_name.clone(), + }); - let mut scope = scope; - scope.push(self.id_gen.next()); + pattern_vec.append(values); - pattern_vec.push(Air::AssertConstr { - scope: scope.clone(), - constr_index: index, - }); + let mut scope = scope; + scope.push(self.id_gen.next()); - pattern_vec.push(Air::Var { - scope: scope.clone(), - constructor: ValueConstructor::public( - tipo.clone().into(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: constr_name.clone(), - variant_name: String::new(), - }); + pattern_vec.push(Air::AssertConstr { + scope: scope.clone(), + constr_index: index, + }); - pattern_vec.push(Air::Var { - scope, - constructor: ValueConstructor::public( - tipo.clone().into(), - ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - ), - name: constr_name, - variant_name: String::new(), - }); - } else { - pattern_vec.append(values); + pattern_vec.push(Air::Var { + scope: scope.clone(), + constructor: ValueConstructor::public( + tipo.clone().into(), + ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + ), + name: constr_name.clone(), + variant_name: String::new(), + }); + + pattern_vec.push(Air::Var { + scope, + constructor: ValueConstructor::public( + tipo.clone().into(), + ValueConstructorVariant::LocalVariable { + location: Span::empty(), + }, + ), + name: constr_name, + variant_name: String::new(), + }); + } + } } pattern_vec.append(&mut nested_pattern); @@ -4843,7 +4855,7 @@ impl<'a> CodeGenerator<'a> { Term::Builtin(DefaultFunction::Trace).force_wrap(), Term::Constant( UplcConstant::String( - "Asserted on incorrect constructor variant.".to_string(), + "Expected on incorrect constructor variant.".to_string(), ) .into(), ), @@ -4866,6 +4878,31 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } + Air::AssertBool { is_true, .. } => { + let value = arg_stack.pop().unwrap(); + let mut term = arg_stack.pop().unwrap(); + + let error_term = apply_wrap( + apply_wrap( + Term::Builtin(DefaultFunction::Trace).force_wrap(), + Term::Constant( + UplcConstant::String( + "Expected on incorrect boolean variant.".to_string(), + ) + .into(), + ), + ), + Term::Delay(Term::Error.into()), + ) + .force_wrap(); + + if is_true { + term = delayed_if_else(value, term, error_term); + } else { + term = delayed_if_else(value, error_term, term); + } + arg_stack.push(term); + } Air::When { subject_name, tipo, .. } => { diff --git a/examples/acceptance_tests/071/plutus.json b/examples/acceptance_tests/071/plutus.json index 114b3c20..0cd2e1b3 100644 --- a/examples/acceptance_tests/071/plutus.json +++ b/examples/acceptance_tests/071/plutus.json @@ -164,8 +164,8 @@ ] } }, - "compiledCode": "59030501000032323232323232323232322225333006323232323232323232533300f3370e002900009925130090021533300f3370e0029001099191919299980999b87001480084c8c8cccc8888c8c8c8c8c9289812000980b19299980e99b8748000c080dd500088008a9980fa492a4173736572746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e0016330120070033022001301432533301b3370e9000180f1baa0011001153301d49012a4173736572746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300f005001300d48901ff00010001012005301b001300d00214a0602a6ea8004cc028c02c03120023017001300900213232323253330133370e0029001099191999911119191919192513024001301632533301d3370e900018101baa0011001153301f49012a4173736572746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e0016330120070033022001301432533301b3370e9000180f1baa0011001153301d49012a4173736572746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300f005001300d48901ff00010001012005301b001300d00214a0602a6ea8004cc028c02c031200230170013009002301137540026600c600e0129000119ba548000cc04ccdd2a4004660266ea40052f5c06602666e9520024bd7025eb8088cc010dd6198031803998031803801240009002119baf3300730080014800000888cc00cdd6198029803198029803001240009000119baf3300630073300630070014800920000023001001222533301000213374a900125eb804c8c94ccc034c00c0084cdd2a40006602600497ae013330050050010033014003301200222323330010014800000c888cccc030cdc3802001009919980200219b8000348008c0540040048c02cdd50008a4c2c6002002444a666012004293099802980098058011998018019806001000ab9a5736ae7155ceaab9e5573eae815d0aba201", - "hash": "c95b3842362b77afec21773b7c0b1f09e61bf5e4c58b685533e6d342" + "compiledCode": "59030501000032323232323232323232322225333006323232323232323232533300f3370e002900009925130090021533300f3370e0029001099191919299980999b87001480084c8c8cccc8888c8c8c8c8c9289812000980b19299980e99b8748000c080dd500088008a9980fa492a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e0016330120070033022001301432533301b3370e9000180f1baa0011001153301d49012a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300f005001300d48901ff00010001012005301b001300d00214a0602a6ea8004cc028c02c03120023017001300900213232323253330133370e0029001099191999911119191919192513024001301632533301d3370e900018101baa0011001153301f49012a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e0016330120070033022001301432533301b3370e9000180f1baa0011001153301d49012a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300f005001300d48901ff00010001012005301b001300d00214a0602a6ea8004cc028c02c031200230170013009002301137540026600c600e0129000119ba548000cc04ccdd2a4004660266ea40052f5c06602666e9520024bd7025eb8088cc010dd6198031803998031803801240009002119baf3300730080014800000888cc00cdd6198029803198029803001240009000119baf3300630073300630070014800920000023001001222533301000213374a900125eb804c8c94ccc034c00c0084cdd2a40006602600497ae013330050050010033014003301200222323330010014800000c888cccc030cdc3802001009919980200219b8000348008c0540040048c02cdd50008a4c2c6002002444a666012004293099802980098058011998018019806001000ab9a5736ae7155ceaab9e5573eae815d0aba201", + "hash": "b79dffa847f2b9a55cb6cee2bd6057251f45e6a252587c7f6f3545d0" } ] } \ No newline at end of file diff --git a/examples/acceptance_tests/076/aiken.lock b/examples/acceptance_tests/076/aiken.lock new file mode 100644 index 00000000..3a78b1e7 --- /dev/null +++ b/examples/acceptance_tests/076/aiken.lock @@ -0,0 +1,5 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] diff --git a/examples/acceptance_tests/076/aiken.toml b/examples/acceptance_tests/076/aiken.toml new file mode 100644 index 00000000..2de1a654 --- /dev/null +++ b/examples/acceptance_tests/076/aiken.toml @@ -0,0 +1,3 @@ +name = 'aiken-lang/acceptance_test_076' +version = '0.0.0' +description = '' diff --git a/examples/acceptance_tests/076/lib/tests.ak b/examples/acceptance_tests/076/lib/tests.ak new file mode 100644 index 00000000..983662d8 --- /dev/null +++ b/examples/acceptance_tests/076/lib/tests.ak @@ -0,0 +1,5 @@ +test expect_positive() { + let val = 5 + expect True = val > 0 + True +}