diff --git a/CHANGELOG.md b/CHANGELOG.md index 19bad7b9..87470ec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v1.0.4.alpha - 2023-MM-DD + +### Added + +### Fixed + + +- **aiken-lang**: Negative numbers now show up as a constant instead of 0 - that number +- **aiken-lang**: Expect on constructors without field maps no longer panics +- **aiken-lang**: Expect on constructors with discard as assigned field names now no longer throws free unique + ## v1.0.3.alpha - 2023-04-28 ### Added diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 35a521ee..b81e25bb 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -2122,12 +2122,16 @@ impl<'a> CodeGenerator<'a> { let arguments_index = arguments .iter() - .filter_map(|item| { + .enumerate() + .filter_map(|(index, item)| { let label = item.label.clone().unwrap_or_default(); - let field_map = field_map.as_ref().unwrap_or_else(|| unreachable!()); - let field_index = - field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&0); + let field_index = field_map + .as_ref() + .map(|field_map| { + field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&index) + }) + .unwrap_or(&index); let mut inner_stack = expect_stack.empty_with_scope(); @@ -2177,7 +2181,7 @@ impl<'a> CodeGenerator<'a> { var_stack.local_var(tipo.clone(), constr_var.clone()); expect_stack.expect_constr(index, var_stack); - if !arguments_index.is_empty() { + if !final_args.is_empty() { let mut fields_stack = expect_stack.empty_with_scope(); fields_stack.local_var(tipo.clone(), constr_var); @@ -4868,9 +4872,21 @@ impl<'a> CodeGenerator<'a> { let term = match op { UnOp::Not => value.if_else(Term::bool(false), Term::bool(true)), - UnOp::Negate => Term::sub_integer() - .apply(Term::integer(0.into())) - .apply(value), + UnOp::Negate => { + if let Term::Constant(c) = &value { + if let UplcConstant::Integer(i) = c.as_ref() { + Term::integer(-i) + } else { + Term::sub_integer() + .apply(Term::integer(0.into())) + .apply(value) + } + } else { + Term::sub_integer() + .apply(Term::integer(0.into())) + .apply(value) + } + } }; arg_stack.push(term); diff --git a/crates/aiken-project/src/tests/gen_uplc.rs b/crates/aiken-project/src/tests/gen_uplc.rs index fdb1da74..c52e7a0d 100644 --- a/crates/aiken-project/src/tests/gen_uplc.rs +++ b/crates/aiken-project/src/tests/gen_uplc.rs @@ -1326,51 +1326,52 @@ fn acceptance_test_12_filter_even() { ); } -// #[test] -// fn acceptance_test_14_list_creation() { -// let src = r#" -// test foo() { -// [0 - 2, 0 - 1, 0] == [-2, -1, 0] -// } -// "#; +#[test] +fn acceptance_test_14_list_creation() { + let src = r#" + test foo() { + [0 - 2, 0 - 1, 0] == [-2, -1, 0] + } + "#; -// assert_uplc( -// src, -// Term::equals_data() -// .apply( -// Term::list_data().apply( -// Term::mk_cons() -// .apply( -// Term::i_data().apply( -// Term::sub_integer() -// .apply(Term::integer(0.into())) -// .apply(Term::integer(2.into())), -// ), -// ) -// .apply( -// Term::mk_cons().apply( -// Term::i_data().apply( -// Term::sub_integer() -// .apply(Term::integer(0.into())) -// .apply(Term::integer(1.into())), -// ), -// ), -// ) -// .apply( -// Term::mk_cons() -// .apply(Term::i_data().apply(Term::integer(0.into()))) -// .apply(Term::empty_list()), -// ), -// ), -// ) -// .apply(Term::list_data().apply(Term::list_values(vec![ -// Constant::Data(Data::integer((-2).into())), -// Constant::Data(Data::integer((-1).into())), -// Constant::Data(Data::integer(0.into())), -// ]))), -// false, -// ); -// } + assert_uplc( + src, + Term::equals_data() + .apply( + Term::list_data().apply( + Term::mk_cons() + .apply( + Term::i_data().apply( + Term::sub_integer() + .apply(Term::integer(0.into())) + .apply(Term::integer(2.into())), + ), + ) + .apply( + Term::mk_cons() + .apply( + Term::i_data().apply( + Term::sub_integer() + .apply(Term::integer(0.into())) + .apply(Term::integer(1.into())), + ), + ) + .apply( + Term::mk_cons() + .apply(Term::i_data().apply(Term::integer(0.into()))) + .apply(Term::empty_list()), + ), + ), + ), + ) + .apply(Term::list_data().apply(Term::list_values(vec![ + Constant::Data(Data::integer((-2).into())), + Constant::Data(Data::integer((-1).into())), + Constant::Data(Data::integer(0.into())), + ]))), + false, + ); +} // #[test] // fn when_tuple_deconstruction() { diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 4951c406..be01f137 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -202,6 +202,10 @@ impl Term { pub fn is_unit(&self) -> bool { matches!(self, Term::Constant(c) if c.as_ref() == &Constant::Unit) } + + pub fn is_int(&self) -> bool { + matches!(self, Term::Constant(c) if matches!(c.as_ref(), &Constant::Integer(_))) + } } impl<'a, T> Display for Term