Skip to content

Commit

Permalink
feat(acir): Set dynamic array values (#3054)
Browse files Browse the repository at this point in the history
Co-authored-by: kevaundray <kevtheappdev@gmail.com>
  • Loading branch information
vezenovm and kevaundray authored Oct 9, 2023
1 parent 19ce286 commit e871866
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
44 changes: 40 additions & 4 deletions compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>();

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, RuntimeError>(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");
}
Expand Down Expand Up @@ -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, RuntimeError>(AcirValue::Var(read, AcirType::field()))
})?;
self.array_set_value(AcirValue::Array(values.into()), block_id, var_index)?;
}
}
Ok(())
Expand All @@ -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()
Expand All @@ -965,7 +1001,7 @@ impl Context {
message: format!("Array {array_id} should be initialized"),
call_stack: self.acir_context.get_call_stack(),
}
.into())
.into());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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]);

}

0 comments on commit e871866

Please sign in to comment.