From 714863694bf9e36b9ce9dccf29f01ba0d664da14 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Mon, 9 Oct 2023 20:42:45 +0100 Subject: [PATCH] feat(acir): Set dynamic array values (#3054) Co-authored-by: kevaundray --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 44 +++++++++++++++++-- .../nested_array_dynamic/src/main.nr | 37 ++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 3feeaba58b0..36e54132a38 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -766,6 +766,36 @@ impl Context { Ok(AcirValue::Array(elements)) } + ( + AcirValue::DynamicArray(AcirDynamicArray { block_id, len, .. }), + AcirValue::Array(dummy_values), + ) => { + let dummy_values = dummy_values + .into_iter() + .flat_map(|val| val.clone().flatten()) + .map(|(var, typ)| AcirValue::Var(var, typ)) + .collect::>(); + + assert_eq!( + *len, + dummy_values.len(), + "ICE: The store value and dummy must have the same number of inner values" + ); + + let values = try_vecmap(0..*len, |i| { + let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + + let read = self.acir_context.read_from_memory(*block_id, &index_var)?; + Ok::(AcirValue::Var(read, AcirType::field())) + })?; + + let mut elements = im::Vector::new(); + for (val, dummy_val) in values.iter().zip(dummy_values) { + elements.push_back(self.convert_array_set_store_value(val, &dummy_val)?); + } + + Ok(AcirValue::Array(elements)) + } (AcirValue::DynamicArray(_), AcirValue::DynamicArray(_)) => { unimplemented!("ICE: setting a dynamic array not supported"); } @@ -925,8 +955,14 @@ impl Context { self.array_set_value(value, block_id, var_index)?; } } - AcirValue::DynamicArray(_) => { - unimplemented!("ICE: setting a dynamic array not supported"); + AcirValue::DynamicArray(AcirDynamicArray { block_id: inner_block_id, len, .. }) => { + let values = try_vecmap(0..len, |i| { + let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + + let read = self.acir_context.read_from_memory(inner_block_id, &index_var)?; + Ok::(AcirValue::Var(read, AcirType::field())) + })?; + self.array_set_value(AcirValue::Array(values.into()), block_id, var_index)?; } } Ok(()) @@ -951,7 +987,7 @@ impl Context { if !already_initialized { let value = &dfg[array_id]; match value { - Value::Array { .. } => { + Value::Array { .. } | Value::Instruction { .. } => { let value = self.convert_value(array_id, dfg); let len = if matches!(array_typ, Type::Array(_, _)) { array_typ.flattened_size() @@ -965,7 +1001,7 @@ impl Context { message: format!("Array {array_id} should be initialized"), call_stack: self.acir_context.get_call_stack(), } - .into()) + .into()); } } } diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr index 076c2b68f11..5f15905dfba 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr @@ -8,6 +8,11 @@ struct Foo { bar: Bar, } +struct FooParent { + array: [Field; 3], + foos: [Foo; 4], +} + fn main(mut x : [Foo; 4], y : pub Field) { assert(x[y - 3].a == 1); assert(x[y - 3].b == [2, 3, 20]); @@ -38,5 +43,37 @@ fn main(mut x : [Foo; 4], y : pub Field) { assert(x[y - 2].bar.inner == [103, 104, 105]); assert(x[y - 1].bar.inner == [106, 107, 108]); assert(x[y].bar.inner == [109, 110, 111]); + + let foo_parent_one = FooParent { array: [0, 1, 2], foos: x }; + let foo_parent_two = FooParent { array: [3, 4, 5], foos: x }; + let mut foo_parents = [foo_parent_one, foo_parent_two]; + + assert(foo_parents[y - 3].foos[y - 3].b == [2, 3, 20]); + assert(foo_parents[y - 3].foos[y - 2].b == [5, 6, 21]); + assert(foo_parents[y - 3].foos[y - 1].b == [100, 101, 102]); + assert(foo_parents[y - 3].foos[y].b == [11, 12, 23]); + + assert(foo_parents[y - 3].foos[y].a == 50); + + assert(foo_parents[1].foos[1].b == [5, 6, 21]); + if y == 2 { + foo_parents[y - 2].foos[y - 2].b = [10, 9, 8]; + } else { + foo_parents[y - 2].foos[y - 2].b = [20, 19, 18]; + } + assert(foo_parents[1].foos[1].b == [20, 19, 18]); + + assert(foo_parents[1].foos[1].b[2] == 18); + if y == 3 { + foo_parents[y - 2].foos[y - 2].b[y - 1] = 5000; + } else { + foo_parents[y - 2].foos[y - 2].b[y - 1] = 1000; + } + assert(foo_parents[1].foos[1].b[2] == 5000); + + // Set a dynamic array value + foo_parents[y - 2].foos[y - 3].b = foo_parents[y - 2].foos[y - 2].b; + assert(foo_parents[1].foos[0].b == [20, 19, 5000]); + }