Skip to content

Commit

Permalink
Merge pull request #413 from stacks-network/fix/double-append
Browse files Browse the repository at this point in the history
Fix `append` to `append` issue
  • Loading branch information
Acaccia committed May 20, 2024
2 parents 797b449 + 3487a50 commit 0c5402c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
52 changes: 36 additions & 16 deletions clar2wasm/src/words/sequences.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use clarity::vm::clarity_wasm::get_type_size;
use clarity::vm::types::{FunctionType, SequenceSubtype, StringSubtype, TypeSignature};
use clarity::vm::types::{
FunctionType, ListTypeData, SequenceSubtype, StringSubtype, TypeSignature,
};
use clarity::vm::{ClarityName, SymbolicExpression};
use walrus::ir::{self, BinaryOp, IfElse, InstrSeqType, Loop, UnaryOp};
use walrus::ValType;
Expand Down Expand Up @@ -270,6 +272,28 @@ impl ComplexWord for Append {
.ok_or_else(|| GeneratorError::TypeError("append result must be typed".to_string()))?
.clone();

let list = args.get_expr(0)?;
let elem = args.get_expr(1)?;

// WORKAROUND: setting correct types for arguments
match &ty {
TypeSignature::SequenceType(SequenceSubtype::ListType(ltd)) => {
generator.set_expr_type(
list,
#[allow(clippy::expect_used)]
ListTypeData::new_list(ltd.get_list_item_type().clone(), ltd.get_max_len() - 1)
.expect("Argument type should be correct as it is the same as the expression type with a smaller max_len")
.into(),
)?;
generator.set_expr_type(elem, ltd.get_list_item_type().clone())?;
}
_ => {
return Err(GeneratorError::TypeError(
"append result should be a list".to_owned(),
))
}
}

let memory = generator.get_memory()?;

// Allocate stack space for the new list.
Expand All @@ -283,9 +307,6 @@ impl ComplexWord for Append {

// Traverse the list to append to, leaving the offset and length on
// top of the stack.
let list = args.get_expr(0)?;
// WORKAROUND: setting types of list argument
generator.set_expr_type(list, ty.clone())?;
generator.traverse_expr(builder, list)?;

// The stack now has the destination, source and length arguments in
Expand All @@ -303,18 +324,6 @@ impl ComplexWord for Append {
.local_set(write_ptr);

// Traverse the element that we're appending to the list.
let elem = args.get_expr(1)?;
// WORKAROUND: setting type of elem
match ty {
TypeSignature::SequenceType(SequenceSubtype::ListType(ltd)) => {
generator.set_expr_type(elem, ltd.get_list_item_type().clone())?;
}
_ => {
return Err(GeneratorError::TypeError(
"append result should be a list".to_owned(),
))
}
}
generator.traverse_expr(builder, elem)?;

// Get the type of the element that we're appending.
Expand Down Expand Up @@ -1979,4 +1988,15 @@ mod tests {
fn slice_full() {
crosscheck("(slice? \"abc\" u0 u3)", evaluate("(some \"abc\")"));
}

#[test]
fn double_append() {
let snippet = "(append (append (list 1) 2) 3)";

let expected =
Value::cons_list_unsanitized(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
.unwrap();

crosscheck(snippet, Ok(Some(expected)))
}
}
11 changes: 11 additions & 0 deletions clar2wasm/tests/wasm-generation/sequences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ proptest! {

crosscheck(&format!("(append {values} {elem})"), Ok(Some(expected)))
}

#[test]
fn double_append_value_to_list(mut values in (prop_signature(), 2usize..16).prop_flat_map(|(ty, size)| PropValue::many_from_type(ty, size))) {
let expected = Value::cons_list_unsanitized(values.iter().cloned().map(Value::from).collect()).unwrap();

let elem_last = values.pop().unwrap();
let elem_before_last = values.pop().unwrap();
let values = PropValue::try_from(values).unwrap();

crosscheck(&format!("(append (append {values} {elem_before_last}) {elem_last})"), Ok(Some(expected)))
}
}

proptest! {
Expand Down

0 comments on commit 0c5402c

Please sign in to comment.