Skip to content

Commit

Permalink
fix: Assignment to arrays of structs (#1998)
Browse files Browse the repository at this point in the history
* Fix assignment to arrays of structs

* Fix size of array types
  • Loading branch information
jfecher authored Jul 21, 2023
1 parent 59f92e3 commit 2c3d976
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,9 @@ fn main(x: [u32; 5], y: [u32; 5], mut z: u32, t: u32) {
assert(x_elem != y_elem);
}
}

// Test 7: Arrays of tuples/structs
let mut tuple_array = [(1, 2), (3, 4), (5, 6)];
tuple_array[1] = (7, 8);
assert(tuple_array[1].1 == 8);
}
2 changes: 1 addition & 1 deletion crates/noirc_evaluator/src/ssa_refactor/ir/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Value {
Value::Instruction { typ, .. } => typ.clone(),
Value::Param { typ, .. } => typ.clone(),
Value::NumericConstant { typ, .. } => typ.clone(),
Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len()),
Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len() / element_type.len()),
Value::Function { .. } => Type::Function,
Value::Intrinsic { .. } => Type::Function,
Value::ForeignFunction { .. } => Type::Function,
Expand Down
25 changes: 21 additions & 4 deletions crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,20 @@ impl<'a> FunctionContext<'a> {
pub(super) fn assign_new_value(&mut self, lvalue: LValue, new_value: Values) {
match lvalue {
LValue::Ident(references) => self.assign(references, new_value),
LValue::Index { old_array, index, array_lvalue } => {
let rvalue = new_value.into_leaf().eval(self); // TODO
let new_array = self.builder.insert_array_set(old_array, index, rvalue);
self.assign_new_value(*array_lvalue, new_array.into());
LValue::Index { old_array: mut array, index, array_lvalue } => {
let element_size = self.builder.field_constant(self.element_size(array));

// The actual base index is the user's index * the array element type's size
let mut index = self.builder.insert_binary(index, BinaryOp::Mul, element_size);
let one = self.builder.field_constant(FieldElement::one());

new_value.for_each(|value| {
let value = value.eval(self);
array = self.builder.insert_array_set(array, index, value);
index = self.builder.insert_binary(index, BinaryOp::Add, one);
});

self.assign_new_value(*array_lvalue, array.into());
}
LValue::MemberAccess { old_object, index, object_lvalue } => {
let new_object = Self::replace_field(old_object, index, new_value);
Expand All @@ -573,6 +583,13 @@ impl<'a> FunctionContext<'a> {
}
}

fn element_size(&self, array: ValueId) -> FieldElement {
match self.builder.type_of_value(array) {
Type::Array(elements, _) | Type::Slice(elements) => (elements.len() as u128).into(),
t => panic!("Uncaught type error: tried to take element size of non-array type {t}"),
}
}

/// Given an lhs containing only references, create a store instruction to store each value of
/// rhs into its corresponding value in lhs.
fn assign(&mut self, lhs: Values, rhs: Values) {
Expand Down

0 comments on commit 2c3d976

Please sign in to comment.