Skip to content

Commit

Permalink
Using assignable_expr and value_expr in more places.
Browse files Browse the repository at this point in the history
  • Loading branch information
g-r-a-n-t committed Aug 2, 2021
1 parent 851a316 commit b807131
Show file tree
Hide file tree
Showing 20 changed files with 930 additions and 255 deletions.
25 changes: 17 additions & 8 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,24 @@ pub fn expr_list(

let inner_type = if let Some(expected) = expected_type {
for elt in elts {
let attr = expr(
let element_attributes = assignable_expr(
Rc::clone(&scope),
context,
elt,
Some(&Type::Base(expected.inner)),
)?;
if attr.typ != Type::Base(expected.inner) {
context.type_error("type mismatch", elt.span, &expected.inner, attr.typ);
if element_attributes.typ != Type::Base(expected.inner) {
context.type_error(
"type mismatch",
elt.span,
&expected.inner,
element_attributes.typ,
);
}
}
expected.inner
} else {
let first_attr = expr(Rc::clone(&scope), context, &elts[0], None)?;
let first_attr = assignable_expr(Rc::clone(&scope), context, &elts[0], None)?;
let inner = match first_attr.typ {
Type::Base(base) => base,
_ => {
Expand All @@ -105,13 +110,17 @@ pub fn expr_list(
// Assuming every element attribute should match the attribute of 0th element
// of list.
for elt in &elts[1..] {
let attr = expr(Rc::clone(&scope), context, elt, Some(&first_attr.typ))?;
if attr.typ != first_attr.typ {
let element_attributes =
assignable_expr(Rc::clone(&scope), context, elt, Some(&first_attr.typ))?;
if element_attributes.typ != first_attr.typ {
context.fancy_error(
"array elements must have same type",
vec![
Label::primary(elts[0].span, format!("this has type `{}`", first_attr.typ)),
Label::secondary(elt.span, format!("this has type `{}`", attr.typ)),
Label::secondary(
elt.span,
format!("this has type `{}`", element_attributes.typ),
),
],
vec![],
);
Expand All @@ -121,7 +130,7 @@ pub fn expr_list(
};

// TODO: Right now we are only supporting Base type arrays
// Potential we can support the tuples as well.
// Potentially we can support tuples as well.
let array_typ = Array {
size: elts.len(),
inner: inner_type,
Expand Down
19 changes: 10 additions & 9 deletions crates/analyzer/src/traversal/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,10 @@ fn for_loop(
fe::FuncStmt::For { target, iter, body } => {
// Create the for loop body scope.
let body_scope = BlockScope::from_block_scope(BlockScopeType::Loop, Rc::clone(&scope));
// Make sure iter is in the function scope & it should be an array.

let iter_type = expressions::expr(Rc::clone(&scope), context, iter, None)?.typ;
// Make sure iter is in the function scope and it should be an array.
let iter_type =
expressions::assignable_expr(Rc::clone(&scope), context, iter, None)?.typ;
let target_type = if let Type::Array(array) = iter_type {
FixedSize::Base(array.inner)
} else {
Expand All @@ -264,8 +265,7 @@ fn for_loop(
);
return Err(FatalError::new());
};
if let Err(AlreadyDefined) = body_scope.borrow_mut().add_var(&target.kind, target_type)
{
if let Err(_) = body_scope.borrow_mut().add_var(&target.kind, target_type) {
context.fancy_error(
"a variable with the same name already exists in this scope",
// TODO: figure out how to include the previously defined var
Expand Down Expand Up @@ -317,7 +317,7 @@ fn if_statement(
body,
or_else,
} => {
let test_type = expressions::expr(Rc::clone(&scope), context, test, None)?.typ;
let test_type = expressions::value_expr(Rc::clone(&scope), context, test, None)?.typ;
if test_type != Type::Base(Base::Bool) {
context.type_error(
"`if` statement condition is not bool",
Expand Down Expand Up @@ -346,7 +346,7 @@ fn while_loop(
) -> Result<(), FatalError> {
match &stmt.kind {
fe::FuncStmt::While { test, body } => {
let test_type = expressions::expr(Rc::clone(&scope), context, test, None)?.typ;
let test_type = expressions::value_expr(Rc::clone(&scope), context, test, None)?.typ;
if test_type != Type::Base(Base::Bool) {
context.type_error(
"`while` loop condition is not bool",
Expand Down Expand Up @@ -412,7 +412,7 @@ fn assert(
stmt: &Node<fe::FuncStmt>,
) -> Result<(), FatalError> {
if let fe::FuncStmt::Assert { test, msg } = &stmt.kind {
let test_type = expressions::expr(Rc::clone(&scope), context, test, None)?.typ;
let test_type = expressions::value_expr(Rc::clone(&scope), context, test, None)?.typ;
if test_type != Type::Base(Base::Bool) {
context.type_error(
"`assert` condition is not bool",
Expand All @@ -423,7 +423,7 @@ fn assert(
}

if let Some(msg) = msg {
let msg_attributes = expressions::expr(scope, context, msg, None)?;
let msg_attributes = expressions::assignable_expr(scope, context, msg, None)?;
if !matches!(msg_attributes.typ, Type::String(_)) {
context.error(
"`assert` reason must be a string",
Expand All @@ -446,7 +446,8 @@ fn revert(
) -> Result<(), FatalError> {
if let fe::FuncStmt::Revert { error } = &stmt.kind {
if let Some(error_expr) = error {
let error_attributes = expressions::expr(Rc::clone(&scope), context, error_expr, None)?;
let error_attributes =
expressions::assignable_expr(Rc::clone(&scope), context, error_expr, None)?;
if !matches!(error_attributes.typ, Type::Struct(_)) {
context.error(
"`revert` error must be a struct",
Expand Down
3 changes: 3 additions & 0 deletions crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,6 @@ test_file! { struct_call_without_kw_args }
test_file! { non_pub_init }
test_file! { abi_encode_u256 }
test_file! { abi_encode_from_storage }
test_file! { assert_sto_msg_no_copy }
test_file! { for_loop_sto_iter_no_copy }
test_file! { revert_sto_error_no_copy }
Loading

0 comments on commit b807131

Please sign in to comment.