Skip to content

Commit

Permalink
Merge branch 'master' into jf/fix-mut-check
Browse files Browse the repository at this point in the history
  • Loading branch information
kevaundray authored Oct 10, 2023
2 parents f79e971 + 7857624 commit 1f86b52
Show file tree
Hide file tree
Showing 4 changed files with 498 additions and 17 deletions.
5 changes: 3 additions & 2 deletions compiler/noirc_frontend/src/hir/type_check/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,13 @@ impl<'interner> TypeChecker<'interner> {
let (result, array, mutable) = self.check_lvalue(array, assign_span);
let array = Box::new(array);

let typ = match result {
let typ = match array_type.follow_bindings() {
Type::Array(_, elem_type) => *elem_type,
Type::Error => Type::Error,
other => {
// TODO: Need a better span here
self.errors.push(TypeCheckError::TypeMismatch {
expected_typ: "an array".to_string(),
expected_typ: "array".to_string(),
expr_typ: other.to_string(),
expr_span: assign_span,
});
Expand All @@ -273,6 +273,7 @@ impl<'interner> TypeChecker<'interner> {

let element_type = Type::type_variable(self.interner.next_type_variable_id());
let expected_type = Type::MutableReference(Box::new(element_type.clone()));

self.unify(&reference_type, &expected_type, || TypeCheckError::TypeMismatch {
expected_typ: expected_type.to_string(),
expr_typ: reference_type.to_string(),
Expand Down
29 changes: 17 additions & 12 deletions compiler/noirc_frontend/src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,29 +949,34 @@ enum LValueRhs {
Index(Expression),
}

fn lvalue<'a, P>(expr_parser: P) -> impl NoirParser<LValue>
fn lvalue<'a, P>(expr_parser: P) -> impl NoirParser<LValue> + 'a
where
P: ExprParser + 'a,
{
let l_ident = ident().map(LValue::Ident);
recursive(|lvalue| {
let l_ident = ident().map(LValue::Ident);

let l_member_rhs = just(Token::Dot).ignore_then(field_name()).map(LValueRhs::MemberAccess);
let dereferences = just(Token::Star)
.ignore_then(lvalue.clone())
.map(|lvalue| LValue::Dereference(Box::new(lvalue)));

let l_index = expr_parser
.delimited_by(just(Token::LeftBracket), just(Token::RightBracket))
.map(LValueRhs::Index);
let parenthesized = lvalue.delimited_by(just(Token::LeftParen), just(Token::RightParen));

let term = choice((parenthesized, dereferences, l_ident));

let dereferences = just(Token::Star).repeated();
let l_member_rhs = just(Token::Dot).ignore_then(field_name()).map(LValueRhs::MemberAccess);

let lvalues =
l_ident.then(l_member_rhs.or(l_index).repeated()).foldl(|lvalue, rhs| match rhs {
let l_index = expr_parser
.delimited_by(just(Token::LeftBracket), just(Token::RightBracket))
.map(LValueRhs::Index);

term.then(l_member_rhs.or(l_index).repeated()).foldl(|lvalue, rhs| match rhs {
LValueRhs::MemberAccess(field_name) => {
LValue::MemberAccess { object: Box::new(lvalue), field_name }
}
LValueRhs::Index(index) => LValue::Index { array: Box::new(lvalue), index },
});

dereferences.then(lvalues).foldr(|_, lvalue| LValue::Dereference(Box::new(lvalue)))
})
})
}

fn parse_type<'a>() -> impl NoirParser<UnresolvedType> + 'a {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@ fn main(x: Field, y: Field) {
assert(z == 3);
z = x * y;
assert(z == 2);

regression_3057();
}

// Ensure parsing parenthesized lvalues works
fn regression_3057() {
let mut array = [[0, 1], [2, 3]];
(array[0])[1] = 2;
assert(array[0][1] == 2);
}
Loading

0 comments on commit 1f86b52

Please sign in to comment.