From d0be704a9c6ddb08218449445980a24059e87f75 Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Tue, 21 Jun 2022 22:32:00 -0600 Subject: [PATCH] Array repeat expression and decloration checks. --- crates/analyzer/src/traversal/const_expr.rs | 1 + crates/analyzer/src/traversal/declarations.rs | 18 + crates/analyzer/src/traversal/expressions.rs | 72 +- crates/analyzer/tests/errors.rs | 2 + .../tests/snapshots/analysis__aug_assign.snap | 16 +- .../snapshots/analysis__const_generics.snap | 748 +++++++++++++++--- .../snapshots/analysis__const_local.snap | 15 +- .../analysis__data_copying_stress.snap | 16 +- .../tests/snapshots/analysis__events.snap | 22 +- .../analysis__external_contract.snap | 16 +- .../analysis__for_loop_with_break.snap | 16 +- .../analysis__for_loop_with_continue.snap | 16 +- .../analysis__for_loop_with_static_array.snap | 16 +- .../snapshots/analysis__module_const.snap | 63 +- .../snapshots/analysis__multi_param.snap | 16 +- .../snapshots/analysis__return_array.snap | 16 +- .../errors__invalid_repeat_length.snap | 14 + .../snapshots/errors__uninit_values.snap | 24 + crates/mir/src/lower/function.rs | 16 + crates/parser/src/ast.rs | 7 + crates/parser/src/grammar/expressions.rs | 66 +- crates/parser/tests/cases/parse_ast.rs | 2 + .../cases__parse_ast__expr_repeat.snap | 33 + .../cases__parse_ast__expr_repeat2.snap | 55 ++ .../fixtures/compile_errors/cannot_move2.fe | 4 +- .../duplicate_var_in_child_scope.fe | 2 +- .../compile_errors/invalid_repeat_length.fe | 5 + .../compile_errors/undefined_type_param.fe | 2 +- .../fixtures/compile_errors/uninit_values.fe | 11 + .../fixtures/features/array_repeat.fe | 14 + .../fixtures/features/aug_assign.fe | 2 +- .../fixtures/features/const_generics.fe | 56 +- .../fixtures/features/const_local.fe | 2 +- crates/test-files/fixtures/features/events.fe | 2 +- .../fixtures/features/external_contract.fe | 2 +- .../fixtures/features/for_loop_with_break.fe | 2 +- .../features/for_loop_with_continue.fe | 2 +- .../features/for_loop_with_static_array.fe | 2 +- .../fixtures/features/module_const.fe | 6 +- .../fixtures/features/multi_param.fe | 2 +- .../fixtures/features/return_array.fe | 2 +- .../fixtures/stress/data_copying_stress.fe | 2 +- crates/tests/src/features.rs | 15 + ...fe_compiler_tests__features__case_001.snap | 3 +- ...fe_compiler_tests__features__case_002.snap | 3 +- ...fe_compiler_tests__features__case_004.snap | 3 +- ...fe_compiler_tests__features__case_005.snap | 3 +- .../fe_compiler_tests__features__case_13.snap | 3 +- .../fe_compiler_tests__features__events.snap | 3 +- ...er_tests__features__external_contract.snap | 3 +- ...compiler_tests__features__multi_param.snap | 3 +- ...ompiler_tests__features__return_array.snap | 3 +- ...er_tests__stress__data_copying_stress.snap | 3 +- newsfragments/747.feature.md | 9 + 54 files changed, 1221 insertions(+), 239 deletions(-) create mode 100644 crates/analyzer/tests/snapshots/errors__invalid_repeat_length.snap create mode 100644 crates/analyzer/tests/snapshots/errors__uninit_values.snap create mode 100644 crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat.snap create mode 100644 crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat2.snap create mode 100644 crates/test-files/fixtures/compile_errors/invalid_repeat_length.fe create mode 100644 crates/test-files/fixtures/compile_errors/uninit_values.fe create mode 100644 crates/test-files/fixtures/features/array_repeat.fe create mode 100644 newsfragments/747.feature.md diff --git a/crates/analyzer/src/traversal/const_expr.rs b/crates/analyzer/src/traversal/const_expr.rs index 0aa5e43c62..b8e0042151 100644 --- a/crates/analyzer/src/traversal/const_expr.rs +++ b/crates/analyzer/src/traversal/const_expr.rs @@ -59,6 +59,7 @@ pub(crate) fn eval_expr( | ast::Expr::Attribute { .. } | ast::Expr::Call { .. } | ast::Expr::List { .. } + | ast::Expr::Repeat { .. } | ast::Expr::Tuple { .. } | ast::Expr::Unit => Err(not_const_error(context, expr.span)), } diff --git a/crates/analyzer/src/traversal/declarations.rs b/crates/analyzer/src/traversal/declarations.rs index 8f002c5c74..f6a8a4c447 100644 --- a/crates/analyzer/src/traversal/declarations.rs +++ b/crates/analyzer/src/traversal/declarations.rs @@ -31,6 +31,24 @@ pub fn var_decl(scope: &mut BlockScope, stmt: &Node) -> Result<(), value_attributes.typ, ); } + } else if matches!(declared_type.typ(scope.db()), Type::Array(_)) { + scope.error( + "uninitialized variable", + target.span, + "array types must be initialized at declaration site", + ); + } else if matches!(declared_type.typ(scope.db()), Type::Struct(_)) { + scope.error( + "uninitialized variable", + target.span, + "struct types must be initialized at declaration site", + ); + } else if matches!(declared_type.typ(scope.db()), Type::Tuple(_)) { + scope.error( + "uninitialized variable", + target.span, + "tuple types must be initialized at declaration site", + ); } add_var(scope, target, declared_type)?; diff --git a/crates/analyzer/src/traversal/expressions.rs b/crates/analyzer/src/traversal/expressions.rs index 9136dd2cf0..709f7e42c7 100644 --- a/crates/analyzer/src/traversal/expressions.rs +++ b/crates/analyzer/src/traversal/expressions.rs @@ -1,5 +1,7 @@ use crate::builtins::{ContractTypeMethod, GlobalFunction, Intrinsic, ValueMethod}; -use crate::context::{AnalyzerContext, CallType, ExpressionAttributes, Location, NamedThing}; +use crate::context::{ + AnalyzerContext, CallType, Constant, ExpressionAttributes, Location, NamedThing, +}; use crate::display::Displayable; use crate::errors::{FatalError, IndexingError}; use crate::namespace::items::{Class, FunctionId, Item, StructId, TypeDef}; @@ -7,15 +9,17 @@ use crate::namespace::scopes::BlockScopeType; use crate::namespace::types::{Array, Base, FeString, Integer, Tuple, Type, TypeDowncast, TypeId}; use crate::operations; use crate::traversal::call_args::{validate_arg_count, validate_named_args}; +use crate::traversal::const_expr::eval_expr; use crate::traversal::types::apply_generic_type_args; use crate::traversal::utils::add_bin_operations_errors; use fe_common::diagnostics::Label; use fe_common::{numeric, Span}; use fe_parser::ast as fe; -use fe_parser::ast::UnaryOperator; +use fe_parser::ast::GenericArg; use fe_parser::node::Node; use num_bigint::BigInt; +use num_traits::ToPrimitive; use smol_str::SmolStr; use std::ops::RangeInclusive; use std::rc::Rc; @@ -45,9 +49,9 @@ pub fn expr( args, } => expr_call(context, func, generic_args, args), fe::Expr::List { elts } => expr_list(context, elts, expected_type), + fe::Expr::Repeat { .. } => expr_repeat(context, exp, expected_type), fe::Expr::Tuple { .. } => expr_tuple(context, exp, expected_type), fe::Expr::Str(_) => expr_str(context, exp, expected_type), - fe::Expr::Bool(_) => Ok(ExpressionAttributes::new( TypeId::bool(context.db()), Location::Value, @@ -134,6 +138,66 @@ pub fn expr_list( }) } +pub fn expr_repeat( + context: &mut dyn AnalyzerContext, + expr: &Node, + expected_type: Option, +) -> Result { + let (value, len) = if let fe::Expr::Repeat { value, len } = &expr.kind { + (value, len) + } else { + unreachable!() + }; + + let value = assignable_expr(context, value, None)?; + + let size = match &len.kind { + GenericArg::Int(size) => size.kind, + GenericArg::TypeDesc(_) => { + return Err(FatalError::new(context.fancy_error( + "expected a constant u256 value", + vec![Label::primary(len.span, "Array length")], + vec!["Note: Array length must be a constant u256".to_string()], + ))); + } + GenericArg::ConstExpr(expr) => { + assignable_expr(context, expr, None)?; + if let Constant::Int(len) = eval_expr(context, expr)? { + len.to_usize().unwrap() + } else { + return Err(FatalError::new(context.fancy_error( + "expected a constant u256 value", + vec![Label::primary(len.span, "Array length")], + vec!["Note: Array length must be a constant u256".to_string()], + ))); + } + } + }; + + let array_typ = context.db().intern_type(Type::Array(Array { + size, + inner: value.typ, + })); + + if let Some(expected_typ) = expected_type { + if expected_typ.typ(context.db()) != array_typ.typ(context.db()) { + return Err(FatalError::new(context.type_error( + "type mismatch", + expr.span, + expected_typ, + array_typ, + ))); + } + } + + Ok(ExpressionAttributes { + typ: array_typ, + location: Location::Memory, + move_location: None, + const_value: None, + }) +} + /// Gather context information for expressions and check for type errors. /// /// Also ensures that the expression is on the stack. @@ -781,7 +845,7 @@ fn expr_unary_operation( Location::Value, )) } - UnaryOperator::Invert => { + fe::UnaryOperator::Invert => { if !operand_attributes.typ.is_integer(context.db()) { emit_err(context, "a numeric type") } diff --git a/crates/analyzer/tests/errors.rs b/crates/analyzer/tests/errors.rs index 00d5793db3..d792dab347 100644 --- a/crates/analyzer/tests/errors.rs +++ b/crates/analyzer/tests/errors.rs @@ -341,3 +341,5 @@ test_file! { ctx_builtins_param_incorrect_type } test_file! { ctx_undefined_create } test_file! { ctx_undefined_create2 } test_file! { ctx_undefined_event } +test_file! { uninit_values } +test_file! { invalid_repeat_length } diff --git a/crates/analyzer/tests/snapshots/analysis__aug_assign.snap b/crates/analyzer/tests/snapshots/analysis__aug_assign.snap index 86bc81dc9b..0e77c6fb0e 100644 --- a/crates/analyzer/tests/snapshots/analysis__aug_assign.snap +++ b/crates/analyzer/tests/snapshots/analysis__aug_assign.snap @@ -264,7 +264,7 @@ note: ┌─ aug_assign.fe:65:5 │ 65 │ ╭ pub fn add_from_mem(a: u256, b: u256) -> u256 { -66 │ │ let my_array: Array +66 │ │ let my_array: Array = [0; 10] 67 │ │ my_array[7] = a 68 │ │ my_array[7] += b 69 │ │ return my_array[7] @@ -274,12 +274,22 @@ note: note: ┌─ aug_assign.fe:66:13 │ -66 │ let my_array: Array +66 │ let my_array: Array = [0; 10] │ ^^^^^^^^ Array note: - ┌─ aug_assign.fe:67:9 + ┌─ aug_assign.fe:66:42 + │ +66 │ let my_array: Array = [0; 10] + │ ^ ^^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ aug_assign.fe:66:41 │ +66 │ let my_array: Array = [0; 10] + │ ^^^^^^^ Array: Memory 67 │ my_array[7] = a │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__const_generics.snap b/crates/analyzer/tests/snapshots/analysis__const_generics.snap index 5b4d285694..8a1ffa654d 100644 --- a/crates/analyzer/tests/snapshots/analysis__const_generics.snap +++ b/crates/analyzer/tests/snapshots/analysis__const_generics.snap @@ -8,74 +8,74 @@ note: │ 2 │ ╭ pub fn bar() { 3 │ │ # const generics with literal. - 4 │ │ let array_lit: Array - 5 │ │ let array_lit2: Array + 4 │ │ let array_lit: Array = [i32(0); 8] + 5 │ │ let array_lit2: Array = [i32(0); 8] · │ -46 │ │ let array_with_const: Array +46 │ │ let array_with_const: Array = [i32(0); 8] 47 │ │ } │ ╰─────^ self: None, params: [] -> () note: ┌─ const_generics.fe:4:13 │ - 4 │ let array_lit: Array + 4 │ let array_lit: Array = [i32(0); 8] │ ^^^^^^^^^ Array - 5 │ let array_lit2: Array + 5 │ let array_lit2: Array = [i32(0); 8] │ ^^^^^^^^^^ Array · - 8 │ let array_ternary: Array + 8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] │ ^^^^^^^^^^^^^ Array · -11 │ let array_logical_or: Array +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] │ ^^^^^^^^^^^^^^^^ Array -12 │ let array_logical_and: Array +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] │ ^^^^^^^^^^^^^^^^^ Array · -15 │ let array_add: Array +15 │ let array_add: Array = [i32(42); 8] │ ^^^^^^^^^ Array -16 │ let array_sub: Array +16 │ let array_sub: Array = [i32(26); 8] │ ^^^^^^^^^ Array -17 │ let array_mul: Array +17 │ let array_mul: Array = [i32(0); 8] │ ^^^^^^^^^ Array -18 │ let array_div: Array +18 │ let array_div: Array = [i32(0); 8] │ ^^^^^^^^^ Array -19 │ let array_mod: Array +19 │ let array_mod: Array = [i32(0); 8] │ ^^^^^^^^^ Array -20 │ let array_pow: Array +20 │ let array_pow: Array = [i32(0); 8] │ ^^^^^^^^^ Array -21 │ let array_shl: Array +21 │ let array_shl: Array = [i32(0); 8] │ ^^^^^^^^^ Array -22 │ let array_shr: Array> 2 }> +22 │ let array_shr: Array> 2 }> = [i32(0); 8] │ ^^^^^^^^^ Array -23 │ let array_bitor: Array +23 │ let array_bitor: Array = [i32(0); 8] │ ^^^^^^^^^^^ Array -24 │ let array_xor: Array +24 │ let array_xor: Array = [i32(0); 8] │ ^^^^^^^^^ Array -25 │ let array_bitand: Array +25 │ let array_bitand: Array = [i32(0); 8] │ ^^^^^^^^^^^^ Array · -28 │ let array_eq: Array +28 │ let array_eq: Array = [i32(0); 8] │ ^^^^^^^^ Array -29 │ let array_ne: Array +29 │ let array_ne: Array = [i32(0); 8] │ ^^^^^^^^ Array -30 │ let array_lt1: Array +30 │ let array_lt1: Array = [i32(0); 8] │ ^^^^^^^^^ Array -31 │ let array_lt2: Array +31 │ let array_lt2: Array = [i32(0); 8] │ ^^^^^^^^^ Array -32 │ let array_lte: Array +32 │ let array_lte: Array = [i32(0); 8] │ ^^^^^^^^^ Array -33 │ let array_lte2: Array +33 │ let array_lte2: Array = [i32(0); 8] │ ^^^^^^^^^^ Array -34 │ let array_gt: Array 0 else 0 }> +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] │ ^^^^^^^^ Array -35 │ let array_gt2: Array 10 else 8 }> +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] │ ^^^^^^^^^ Array -36 │ let array_gte: Array= 10 else 8 }> +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] │ ^^^^^^^^^ Array -37 │ let array_gte2: Array= 10 else 0 }> +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] │ ^^^^^^^^^^ Array · -40 │ let array_not: Array +40 │ let array_not: Array = [i32(0); 8] │ ^^^^^^^^^ Array · 43 │ const DOUBLE_ARRAY_LENGTH: u64 = 16 @@ -83,33 +83,95 @@ note: 44 │ const TWO: u64 = 2 │ ^^^ u64 45 │ -46 │ let array_with_const: Array +46 │ let array_with_const: Array = [i32(0); 8] │ ^^^^^^^^^^^^^^^^ Array note: - ┌─ const_generics.fe:5:38 + ┌─ const_generics.fe:4:45 │ -5 │ let array_lit2: Array - │ ^ u256: Value +4 │ let array_lit: Array = [i32(0); 8] + │ ^ i32: Value + +note: + ┌─ const_generics.fe:4:41 + │ +4 │ let array_lit: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:4:40 + │ +4 │ let array_lit: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +5 │ let array_lit2: Array = [i32(0); 8] + │ ^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:5:46 + │ +5 │ let array_lit2: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:5:45 + │ +5 │ let array_lit2: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory · -8 │ let array_ternary: Array +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] │ ^^^^^ bool: Value note: ┌─ const_generics.fe:8:41 │ -8 │ let array_ternary: Array +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] │ ^ ^ u256: Value │ │ │ u256: Value note: - ┌─ const_generics.fe:8:41 + ┌─ const_generics.fe:8:41 + │ +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] + │ ^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:8:65 + │ +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] + │ ^^^^^^ ^^^^^ bool: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:8:75 + │ +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:8:75 + │ +8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] + │ ^^^^^^^^^^^^^^^^^ u256: Value + +note: + ┌─ const_generics.fe:8:64 │ - 8 │ let array_ternary: Array - │ ^^^^^^^^^^^^^^^^^ u256: Value + 8 │ let array_ternary: Array = [i32(0); { 3 if false else 8 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Array: Memory · -11 │ let array_logical_or: Array +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] │ ^^^^ ^^^^^ bool: Value │ │ │ bool: Value @@ -117,7 +179,7 @@ note: note: ┌─ const_generics.fe:11:44 │ -11 │ let array_logical_or: Array +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] │ ^ ^^^^^^^^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -126,9 +188,41 @@ note: note: ┌─ const_generics.fe:11:44 │ -11 │ let array_logical_or: Array - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ u256: Value -12 │ let array_logical_and: Array +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:11:78 + │ +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + │ ^^^^^^ ^^^^ ^^^^^ bool: Value + │ │ │ + │ │ bool: Value + │ i32: Value + +note: + ┌─ const_generics.fe:11:88 + │ +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + │ ^ ^^^^^^^^^^^^^^^ ^ u256: Value + │ │ │ + │ │ bool: Value + │ u256: Value + +note: + ┌─ const_generics.fe:11:88 + │ +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ u256: Value + +note: + ┌─ const_generics.fe:11:77 + │ +11 │ let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Array: Memory +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] │ ^^^^ ^^^^^ bool: Value │ │ │ bool: Value @@ -136,7 +230,7 @@ note: note: ┌─ const_generics.fe:12:45 │ -12 │ let array_logical_and: Array +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] │ ^ ^^^^^^^^^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -145,10 +239,42 @@ note: note: ┌─ const_generics.fe:12:45 │ -12 │ let array_logical_and: Array - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ u256: Value +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:12:80 + │ +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] + │ ^^^^^^ ^^^^ ^^^^^ bool: Value + │ │ │ + │ │ bool: Value + │ i32: Value + +note: + ┌─ const_generics.fe:12:90 + │ +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] + │ ^ ^^^^^^^^^^^^^^^^ ^ u256: Value + │ │ │ + │ │ bool: Value + │ u256: Value + +note: + ┌─ const_generics.fe:12:90 + │ +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ u256: Value + +note: + ┌─ const_generics.fe:12:79 + │ +12 │ let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Array: Memory · -15 │ let array_add: Array +15 │ let array_add: Array = [i32(42); 8] │ ^ ^ u256: Value │ │ │ u256: Value @@ -156,9 +282,25 @@ note: note: ┌─ const_generics.fe:15:37 │ -15 │ let array_add: Array - │ ^^^^^ u256: Value -16 │ let array_sub: Array +15 │ let array_add: Array = [i32(42); 8] + │ ^^^^^ ^^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:15:49 + │ +15 │ let array_add: Array = [i32(42); 8] + │ ^^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:15:48 + │ +15 │ let array_add: Array = [i32(42); 8] + │ ^^^^^^^^^^^^ Array: Memory +16 │ let array_sub: Array = [i32(26); 8] │ ^^ ^ u256: Value │ │ │ u256: Value @@ -166,9 +308,25 @@ note: note: ┌─ const_generics.fe:16:37 │ -16 │ let array_sub: Array - │ ^^^^^^^ u256: Value -17 │ let array_mul: Array +16 │ let array_sub: Array = [i32(26); 8] + │ ^^^^^^^ ^^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:16:51 + │ +16 │ let array_sub: Array = [i32(26); 8] + │ ^^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:16:50 + │ +16 │ let array_sub: Array = [i32(26); 8] + │ ^^^^^^^^^^^^ Array: Memory +17 │ let array_mul: Array = [i32(0); 8] │ ^ ^ u256: Value │ │ │ u256: Value @@ -176,9 +334,25 @@ note: note: ┌─ const_generics.fe:17:37 │ -17 │ let array_mul: Array - │ ^^^^^ u256: Value -18 │ let array_div: Array +17 │ let array_mul: Array = [i32(0); 8] + │ ^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:17:49 + │ +17 │ let array_mul: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:17:48 + │ +17 │ let array_mul: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +18 │ let array_div: Array = [i32(0); 8] │ ^^ ^ u256: Value │ │ │ u256: Value @@ -186,9 +360,25 @@ note: note: ┌─ const_generics.fe:18:37 │ -18 │ let array_div: Array - │ ^^^^^^ u256: Value -19 │ let array_mod: Array +18 │ let array_div: Array = [i32(0); 8] + │ ^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:18:50 + │ +18 │ let array_div: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:18:49 + │ +18 │ let array_div: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +19 │ let array_mod: Array = [i32(0); 8] │ ^^ ^ u256: Value │ │ │ u256: Value @@ -196,9 +386,25 @@ note: note: ┌─ const_generics.fe:19:37 │ -19 │ let array_mod: Array - │ ^^^^^^ u256: Value -20 │ let array_pow: Array +19 │ let array_mod: Array = [i32(0); 8] + │ ^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:19:50 + │ +19 │ let array_mod: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:19:49 + │ +19 │ let array_mod: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +20 │ let array_pow: Array = [i32(0); 8] │ ^ ^ u256: Value │ │ │ u256: Value @@ -206,9 +412,25 @@ note: note: ┌─ const_generics.fe:20:37 │ -20 │ let array_pow: Array - │ ^^^^^^ u256: Value -21 │ let array_shl: Array +20 │ let array_pow: Array = [i32(0); 8] + │ ^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:20:50 + │ +20 │ let array_pow: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:20:49 + │ +20 │ let array_pow: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +21 │ let array_shl: Array = [i32(0); 8] │ ^^^^^^ ^ u256: Value │ │ │ u256: Value @@ -216,9 +438,25 @@ note: note: ┌─ const_generics.fe:21:37 │ -21 │ let array_shl: Array - │ ^^^^^^^^^^^ u256: Value -22 │ let array_shr: Array> 2 }> +21 │ let array_shl: Array = [i32(0); 8] + │ ^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:21:55 + │ +21 │ let array_shl: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:21:54 + │ +21 │ let array_shl: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +22 │ let array_shr: Array> 2 }> = [i32(0); 8] │ ^^^^^^^^ ^ u256: Value │ │ │ u256: Value @@ -226,9 +464,25 @@ note: note: ┌─ const_generics.fe:22:37 │ -22 │ let array_shr: Array> 2 }> - │ ^^^^^^^^^^^^^ u256: Value -23 │ let array_bitor: Array +22 │ let array_shr: Array> 2 }> = [i32(0); 8] + │ ^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:22:57 + │ +22 │ let array_shr: Array> 2 }> = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:22:56 + │ +22 │ let array_shr: Array> 2 }> = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +23 │ let array_bitor: Array = [i32(0); 8] │ ^^^^^^ ^^^^^^ u256: Value │ │ │ u256: Value @@ -236,9 +490,25 @@ note: note: ┌─ const_generics.fe:23:39 │ -23 │ let array_bitor: Array - │ ^^^^^^^^^^^^^^^^ u256: Value -24 │ let array_xor: Array +23 │ let array_bitor: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:23:62 + │ +23 │ let array_bitor: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:23:61 + │ +23 │ let array_bitor: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +24 │ let array_xor: Array = [i32(0); 8] │ ^^^^^^ ^^^^^^ u256: Value │ │ │ u256: Value @@ -246,9 +516,25 @@ note: note: ┌─ const_generics.fe:24:37 │ -24 │ let array_xor: Array - │ ^^^^^^^^^^^^^^^ u256: Value -25 │ let array_bitand: Array +24 │ let array_xor: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:24:59 + │ +24 │ let array_xor: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:24:58 + │ +24 │ let array_xor: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +25 │ let array_bitand: Array = [i32(0); 8] │ ^^^^^^ ^^^^^^ u256: Value │ │ │ u256: Value @@ -256,10 +542,26 @@ note: note: ┌─ const_generics.fe:25:40 │ -25 │ let array_bitand: Array - │ ^^^^^^^^^^^^^^^ u256: Value +25 │ let array_bitand: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:25:62 + │ +25 │ let array_bitand: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:25:61 + │ +25 │ let array_bitand: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory · -28 │ let array_eq: Array +28 │ let array_eq: Array = [i32(0); 8] │ ^^ ^^ u256: Value │ │ │ u256: Value @@ -267,7 +569,7 @@ note: note: ┌─ const_generics.fe:28:36 │ -28 │ let array_eq: Array +28 │ let array_eq: Array = [i32(0); 8] │ ^ ^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -276,9 +578,25 @@ note: note: ┌─ const_generics.fe:28:36 │ -28 │ let array_eq: Array - │ ^^^^^^^^^^^^^^^^^^^^ u256: Value -29 │ let array_ne: Array +28 │ let array_eq: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:28:63 + │ +28 │ let array_eq: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:28:62 + │ +28 │ let array_eq: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +29 │ let array_ne: Array = [i32(0); 8] │ ^^ ^ u256: Value │ │ │ u256: Value @@ -286,7 +604,7 @@ note: note: ┌─ const_generics.fe:29:36 │ -29 │ let array_ne: Array +29 │ let array_ne: Array = [i32(0); 8] │ ^ ^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -295,9 +613,25 @@ note: note: ┌─ const_generics.fe:29:36 │ -29 │ let array_ne: Array - │ ^^^^^^^^^^^^^^^^^^^ u256: Value -30 │ let array_lt1: Array +29 │ let array_ne: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:29:62 + │ +29 │ let array_ne: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:29:61 + │ +29 │ let array_ne: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +30 │ let array_lt1: Array = [i32(0); 8] │ ^ ^^ u256: Value │ │ │ u256: Value @@ -305,7 +639,7 @@ note: note: ┌─ const_generics.fe:30:37 │ -30 │ let array_lt1: Array +30 │ let array_lt1: Array = [i32(0); 8] │ ^ ^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -314,9 +648,25 @@ note: note: ┌─ const_generics.fe:30:37 │ -30 │ let array_lt1: Array - │ ^^^^^^^^^^^^^^^^^^ u256: Value -31 │ let array_lt2: Array +30 │ let array_lt1: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:30:62 + │ +30 │ let array_lt1: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:30:61 + │ +30 │ let array_lt1: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +31 │ let array_lt2: Array = [i32(0); 8] │ ^^ ^^ u256: Value │ │ │ u256: Value @@ -324,7 +674,7 @@ note: note: ┌─ const_generics.fe:31:37 │ -31 │ let array_lt2: Array +31 │ let array_lt2: Array = [i32(0); 8] │ ^ ^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -333,9 +683,25 @@ note: note: ┌─ const_generics.fe:31:37 │ -31 │ let array_lt2: Array - │ ^^^^^^^^^^^^^^^^^^^ u256: Value -32 │ let array_lte: Array +31 │ let array_lt2: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:31:63 + │ +31 │ let array_lt2: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:31:62 + │ +31 │ let array_lt2: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +32 │ let array_lte: Array = [i32(0); 8] │ ^ ^^ u256: Value │ │ │ u256: Value @@ -343,7 +709,7 @@ note: note: ┌─ const_generics.fe:32:37 │ -32 │ let array_lte: Array +32 │ let array_lte: Array = [i32(0); 8] │ ^ ^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -352,9 +718,25 @@ note: note: ┌─ const_generics.fe:32:37 │ -32 │ let array_lte: Array - │ ^^^^^^^^^^^^^^^^^^^ u256: Value -33 │ let array_lte2: Array +32 │ let array_lte: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:32:63 + │ +32 │ let array_lte: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:32:62 + │ +32 │ let array_lte: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +33 │ let array_lte2: Array = [i32(0); 8] │ ^^ ^^ u256: Value │ │ │ u256: Value @@ -362,7 +744,7 @@ note: note: ┌─ const_generics.fe:33:38 │ -33 │ let array_lte2: Array +33 │ let array_lte2: Array = [i32(0); 8] │ ^ ^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -371,9 +753,25 @@ note: note: ┌─ const_generics.fe:33:38 │ -33 │ let array_lte2: Array - │ ^^^^^^^^^^^^^^^^^^^^ u256: Value -34 │ let array_gt: Array 0 else 0 }> +33 │ let array_lte2: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:33:65 + │ +33 │ let array_lte2: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:33:64 + │ +33 │ let array_lte2: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] │ ^^ ^ u256: Value │ │ │ u256: Value @@ -381,7 +779,7 @@ note: note: ┌─ const_generics.fe:34:36 │ -34 │ let array_gt: Array 0 else 0 }> +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] │ ^ ^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -390,9 +788,25 @@ note: note: ┌─ const_generics.fe:34:36 │ -34 │ let array_gt: Array 0 else 0 }> - │ ^^^^^^^^^^^^^^^^^^ u256: Value -35 │ let array_gt2: Array 10 else 8 }> +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:34:61 + │ +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:34:60 + │ +34 │ let array_gt: Array 0 else 0 }> = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] │ ^^ ^^ u256: Value │ │ │ u256: Value @@ -400,7 +814,7 @@ note: note: ┌─ const_generics.fe:35:37 │ -35 │ let array_gt2: Array 10 else 8 }> +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] │ ^ ^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -409,9 +823,25 @@ note: note: ┌─ const_generics.fe:35:37 │ -35 │ let array_gt2: Array 10 else 8 }> - │ ^^^^^^^^^^^^^^^^^^^ u256: Value -36 │ let array_gte: Array= 10 else 8 }> +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:35:63 + │ +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:35:62 + │ +35 │ let array_gt2: Array 10 else 8 }> = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] │ ^ ^^ u256: Value │ │ │ u256: Value @@ -419,7 +849,7 @@ note: note: ┌─ const_generics.fe:36:37 │ -36 │ let array_gte: Array= 10 else 8 }> +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] │ ^ ^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -428,9 +858,25 @@ note: note: ┌─ const_generics.fe:36:37 │ -36 │ let array_gte: Array= 10 else 8 }> - │ ^^^^^^^^^^^^^^^^^^^ u256: Value -37 │ let array_gte2: Array= 10 else 0 }> +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:36:63 + │ +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:36:62 + │ +36 │ let array_gte: Array= 10 else 8 }> = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] │ ^^ ^^ u256: Value │ │ │ u256: Value @@ -438,7 +884,7 @@ note: note: ┌─ const_generics.fe:37:38 │ -37 │ let array_gte2: Array= 10 else 0 }> +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] │ ^ ^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -447,16 +893,32 @@ note: note: ┌─ const_generics.fe:37:38 │ -37 │ let array_gte2: Array= 10 else 0 }> - │ ^^^^^^^^^^^^^^^^^^^^ u256: Value +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:37:65 + │ +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:37:64 + │ +37 │ let array_gte2: Array= 10 else 0 }> = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory · -40 │ let array_not: Array +40 │ let array_not: Array = [i32(0); 8] │ ^^^^^ bool: Value note: ┌─ const_generics.fe:40:37 │ -40 │ let array_not: Array +40 │ let array_not: Array = [i32(0); 8] │ ^ ^^^^^^^^^ ^ u256: Value │ │ │ │ │ bool: Value @@ -465,15 +927,31 @@ note: note: ┌─ const_generics.fe:40:37 │ -40 │ let array_not: Array - │ ^^^^^^^^^^^^^^^^^^^^^ u256: Value +40 │ let array_not: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u256: Value + +note: + ┌─ const_generics.fe:40:65 + │ +40 │ let array_not: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:40:64 + │ +40 │ let array_not: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory · 43 │ const DOUBLE_ARRAY_LENGTH: u64 = 16 │ ^^ u64: Value 44 │ const TWO: u64 = 2 │ ^ u64: Value 45 │ -46 │ let array_with_const: Array +46 │ let array_with_const: Array = [i32(0); 8] │ ^^^^^^^^^^^^^^^^^^^ ^^^ u64: Value │ │ │ u64: Value @@ -481,7 +959,23 @@ note: note: ┌─ const_generics.fe:46:44 │ -46 │ let array_with_const: Array - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ u64: Value +46 │ let array_with_const: Array = [i32(0); 8] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^ i32: Value + │ │ + │ u64: Value + +note: + ┌─ const_generics.fe:46:76 + │ +46 │ let array_with_const: Array = [i32(0); 8] + │ ^^^^^^ ^ u256: Value + │ │ + │ i32: Value + +note: + ┌─ const_generics.fe:46:75 + │ +46 │ let array_with_const: Array = [i32(0); 8] + │ ^^^^^^^^^^^ Array: Memory diff --git a/crates/analyzer/tests/snapshots/analysis__const_local.snap b/crates/analyzer/tests/snapshots/analysis__const_local.snap index 29c2e294a1..e7a2e87663 100644 --- a/crates/analyzer/tests/snapshots/analysis__const_local.snap +++ b/crates/analyzer/tests/snapshots/analysis__const_local.snap @@ -40,7 +40,7 @@ note: │ ^^ bool 13 │ const C10: u256 = 42 if C9 else 0 # 42 │ ^^^ u256 -14 │ let _arr: Array +14 │ let _arr: Array = [true; { C10 }] │ ^^^^ Array note: @@ -145,8 +145,17 @@ note: │ 13 │ const C10: u256 = 42 if C9 else 0 # 42 │ ^^^^^^^^^^^^^^^ u256: Value -14 │ let _arr: Array - │ ^^^ u256: Value +14 │ let _arr: Array = [true; { C10 }] + │ ^^^ ^^^^ ^^^ u256: Value + │ │ │ + │ │ bool: Value + │ u256: Value + +note: + ┌─ const_local.fe:14:42 + │ +14 │ let _arr: Array = [true; { C10 }] + │ ^^^^^^^^^^^^^^^ Array: Memory 15 │ return C10 │ ^^^ u256: Value diff --git a/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap b/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap index 5e3ef4c1d6..b48d0043f4 100644 --- a/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap +++ b/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap @@ -389,7 +389,7 @@ note: ┌─ data_copying_stress.fe:56:5 │ 56 │ ╭ pub fn assign_my_nums_and_return(self) -> Array { -57 │ │ let my_nums_mem: Array +57 │ │ let my_nums_mem: Array = [0; 5] 58 │ │ self.my_nums[0] = 42 59 │ │ self.my_nums[1] = 26 · │ @@ -400,12 +400,22 @@ note: note: ┌─ data_copying_stress.fe:57:13 │ -57 │ let my_nums_mem: Array +57 │ let my_nums_mem: Array = [0; 5] │ ^^^^^^^^^^^ Array note: - ┌─ data_copying_stress.fe:58:9 + ┌─ data_copying_stress.fe:57:44 + │ +57 │ let my_nums_mem: Array = [0; 5] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ data_copying_stress.fe:57:43 │ +57 │ let my_nums_mem: Array = [0; 5] + │ ^^^^^^ Array: Memory 58 │ self.my_nums[0] = 42 │ ^^^^ Foo: Value diff --git a/crates/analyzer/tests/snapshots/analysis__events.snap b/crates/analyzer/tests/snapshots/analysis__events.snap index abd80467a6..856fccd544 100644 --- a/crates/analyzer/tests/snapshots/analysis__events.snap +++ b/crates/analyzer/tests/snapshots/analysis__events.snap @@ -94,7 +94,7 @@ note: ┌─ events.fe:37:5 │ 37 │ ╭ pub fn emit_addresses(ctx: Context, addr1: address, addr2: address) { -38 │ │ let addrs: Array +38 │ │ let addrs: Array = [address(0); 2] 39 │ │ addrs[0] = addr1 40 │ │ addrs[1] = addr2 41 │ │ emit Addresses(ctx, addrs) @@ -104,12 +104,28 @@ note: note: ┌─ events.fe:38:13 │ -38 │ let addrs: Array +38 │ let addrs: Array = [address(0); 2] │ ^^^^^ Array note: - ┌─ events.fe:39:9 + ┌─ events.fe:38:49 + │ +38 │ let addrs: Array = [address(0); 2] + │ ^ u256: Value + +note: + ┌─ events.fe:38:41 + │ +38 │ let addrs: Array = [address(0); 2] + │ ^^^^^^^^^^ ^ u256: Value + │ │ + │ address: Value + +note: + ┌─ events.fe:38:40 │ +38 │ let addrs: Array = [address(0); 2] + │ ^^^^^^^^^^^^^^^ Array: Memory 39 │ addrs[0] = addr1 │ ^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__external_contract.snap b/crates/analyzer/tests/snapshots/analysis__external_contract.snap index b1d63a92b1..f7bece3e0f 100644 --- a/crates/analyzer/tests/snapshots/analysis__external_contract.snap +++ b/crates/analyzer/tests/snapshots/analysis__external_contract.snap @@ -35,7 +35,7 @@ note: ┌─ external_contract.fe:14:5 │ 14 │ ╭ pub fn build_array(a: u256, b: u256) -> Array { -15 │ │ let my_array: Array +15 │ │ let my_array: Array = [0; 3] 16 │ │ my_array[0] = a 17 │ │ my_array[1] = a * b 18 │ │ my_array[2] = b @@ -46,12 +46,22 @@ note: note: ┌─ external_contract.fe:15:13 │ -15 │ let my_array: Array +15 │ let my_array: Array = [0; 3] │ ^^^^^^^^ Array note: - ┌─ external_contract.fe:16:9 + ┌─ external_contract.fe:15:41 + │ +15 │ let my_array: Array = [0; 3] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ external_contract.fe:15:40 │ +15 │ let my_array: Array = [0; 3] + │ ^^^^^^ Array: Memory 16 │ my_array[0] = a │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__for_loop_with_break.snap b/crates/analyzer/tests/snapshots/analysis__for_loop_with_break.snap index dd5b079bc4..0e10c4e1b6 100644 --- a/crates/analyzer/tests/snapshots/analysis__for_loop_with_break.snap +++ b/crates/analyzer/tests/snapshots/analysis__for_loop_with_break.snap @@ -7,7 +7,7 @@ note: ┌─ for_loop_with_break.fe:2:5 │ 2 │ ╭ pub fn bar() -> u256 { - 3 │ │ let my_array: Array + 3 │ │ let my_array: Array = [0; 3] 4 │ │ my_array[0] = 5 5 │ │ my_array[1] = 10 · │ @@ -18,7 +18,7 @@ note: note: ┌─ for_loop_with_break.fe:3:13 │ -3 │ let my_array: Array +3 │ let my_array: Array = [0; 3] │ ^^^^^^^^ Array · 7 │ let sum: u256 = 0 @@ -27,8 +27,18 @@ note: │ ^ u256 note: - ┌─ for_loop_with_break.fe:4:9 + ┌─ for_loop_with_break.fe:3:41 + │ +3 │ let my_array: Array = [0; 3] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ for_loop_with_break.fe:3:40 │ +3 │ let my_array: Array = [0; 3] + │ ^^^^^^ Array: Memory 4 │ my_array[0] = 5 │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__for_loop_with_continue.snap b/crates/analyzer/tests/snapshots/analysis__for_loop_with_continue.snap index 0b02640564..a62c9af962 100644 --- a/crates/analyzer/tests/snapshots/analysis__for_loop_with_continue.snap +++ b/crates/analyzer/tests/snapshots/analysis__for_loop_with_continue.snap @@ -7,7 +7,7 @@ note: ┌─ for_loop_with_continue.fe:2:5 │ 2 │ ╭ pub fn bar() -> u256 { - 3 │ │ let my_array: Array + 3 │ │ let my_array: Array = [0; 5] 4 │ │ my_array[0] = 2 5 │ │ my_array[1] = 3 · │ @@ -18,7 +18,7 @@ note: note: ┌─ for_loop_with_continue.fe:3:13 │ - 3 │ let my_array: Array + 3 │ let my_array: Array = [0; 5] │ ^^^^^^^^ Array · 9 │ let sum: u256 = 0 @@ -27,8 +27,18 @@ note: │ ^ u256 note: - ┌─ for_loop_with_continue.fe:4:9 + ┌─ for_loop_with_continue.fe:3:41 + │ +3 │ let my_array: Array = [0; 5] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ for_loop_with_continue.fe:3:40 │ +3 │ let my_array: Array = [0; 5] + │ ^^^^^^ Array: Memory 4 │ my_array[0] = 2 │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__for_loop_with_static_array.snap b/crates/analyzer/tests/snapshots/analysis__for_loop_with_static_array.snap index 0095d57e82..39051c85cc 100644 --- a/crates/analyzer/tests/snapshots/analysis__for_loop_with_static_array.snap +++ b/crates/analyzer/tests/snapshots/analysis__for_loop_with_static_array.snap @@ -7,7 +7,7 @@ note: ┌─ for_loop_with_static_array.fe:2:5 │ 2 │ ╭ pub fn bar() -> u256 { - 3 │ │ let my_array: Array + 3 │ │ let my_array: Array = [0; 3] 4 │ │ my_array[0] = 5 5 │ │ my_array[1] = 10 · │ @@ -18,7 +18,7 @@ note: note: ┌─ for_loop_with_static_array.fe:3:13 │ -3 │ let my_array: Array +3 │ let my_array: Array = [0; 3] │ ^^^^^^^^ Array · 7 │ let sum: u256 = 0 @@ -27,8 +27,18 @@ note: │ ^ u256 note: - ┌─ for_loop_with_static_array.fe:4:9 + ┌─ for_loop_with_static_array.fe:3:41 + │ +3 │ let my_array: Array = [0; 3] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ for_loop_with_static_array.fe:3:40 │ +3 │ let my_array: Array = [0; 3] + │ ^^^^^^ Array: Memory 4 │ my_array[0] = 5 │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__module_const.snap b/crates/analyzer/tests/snapshots/analysis__module_const.snap index bff49a46a8..63ed7680c2 100644 --- a/crates/analyzer/tests/snapshots/analysis__module_const.snap +++ b/crates/analyzer/tests/snapshots/analysis__module_const.snap @@ -38,9 +38,9 @@ note: │ 9 │ ╭ fn bar() -> i32 { 10 │ │ const LOCAL_CONST: i32 = C3 * 2 -11 │ │ let _arr1: Array -12 │ │ let _arr2: Array -13 │ │ let _my_array: MY_ARRAY +11 │ │ let _arr1: Array = [i32(0); { C2 }] +12 │ │ let _arr2: Array = [i32(0); { LOCAL_CONST }] +13 │ │ let _my_array: MY_ARRAY = [true; { C4 }] 14 │ │ return C4 15 │ │ } │ ╰─────^ self: None, params: [] -> i32 @@ -50,11 +50,11 @@ note: │ 10 │ const LOCAL_CONST: i32 = C3 * 2 │ ^^^^^^^^^^^ i32 -11 │ let _arr1: Array +11 │ let _arr1: Array = [i32(0); { C2 }] │ ^^^^^ Array -12 │ let _arr2: Array +12 │ let _arr2: Array = [i32(0); { LOCAL_CONST }] │ ^^^^^ Array -13 │ let _my_array: MY_ARRAY +13 │ let _my_array: MY_ARRAY = [true; { C4 }] │ ^^^^^^^^^ Array note: @@ -70,11 +70,52 @@ note: │ 10 │ const LOCAL_CONST: i32 = C3 * 2 │ ^^^^^^ i32: Value -11 │ let _arr1: Array - │ ^^ i32: Value -12 │ let _arr2: Array - │ ^^^^^^^^^^^ i32: Value -13 │ let _my_array: MY_ARRAY +11 │ let _arr1: Array = [i32(0); { C2 }] + │ ^^ ^ i32: Value + │ │ + │ i32: Value + +note: + ┌─ module_const.fe:11:42 + │ +11 │ let _arr1: Array = [i32(0); { C2 }] + │ ^^^^^^ ^^ i32: Value + │ │ + │ i32: Value + +note: + ┌─ module_const.fe:11:41 + │ +11 │ let _arr1: Array = [i32(0); { C2 }] + │ ^^^^^^^^^^^^^^^^ Array: Memory +12 │ let _arr2: Array = [i32(0); { LOCAL_CONST }] + │ ^^^^^^^^^^^ ^ i32: Value + │ │ + │ i32: Value + +note: + ┌─ module_const.fe:12:51 + │ +12 │ let _arr2: Array = [i32(0); { LOCAL_CONST }] + │ ^^^^^^ ^^^^^^^^^^^ i32: Value + │ │ + │ i32: Value + +note: + ┌─ module_const.fe:12:50 + │ +12 │ let _arr2: Array = [i32(0); { LOCAL_CONST }] + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ Array: Memory +13 │ let _my_array: MY_ARRAY = [true; { C4 }] + │ ^^^^ ^^ i32: Value + │ │ + │ bool: Value + +note: + ┌─ module_const.fe:13:35 + │ +13 │ let _my_array: MY_ARRAY = [true; { C4 }] + │ ^^^^^^^^^^^^^^ Array: Memory 14 │ return C4 │ ^^ i32: Value diff --git a/crates/analyzer/tests/snapshots/analysis__multi_param.snap b/crates/analyzer/tests/snapshots/analysis__multi_param.snap index fe0400f427..ae1cd06ae6 100644 --- a/crates/analyzer/tests/snapshots/analysis__multi_param.snap +++ b/crates/analyzer/tests/snapshots/analysis__multi_param.snap @@ -7,7 +7,7 @@ note: ┌─ multi_param.fe:2:5 │ 2 │ ╭ pub fn bar(x: u256, y: u256, z: u256) -> Array { -3 │ │ let my_array: Array +3 │ │ let my_array: Array = [0; 3] 4 │ │ my_array[0] = x 5 │ │ my_array[1] = y 6 │ │ my_array[2] = z @@ -18,12 +18,22 @@ note: note: ┌─ multi_param.fe:3:13 │ -3 │ let my_array: Array +3 │ let my_array: Array = [0; 3] │ ^^^^^^^^ Array note: - ┌─ multi_param.fe:4:9 + ┌─ multi_param.fe:3:41 + │ +3 │ let my_array: Array = [0; 3] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ multi_param.fe:3:40 │ +3 │ let my_array: Array = [0; 3] + │ ^^^^^^ Array: Memory 4 │ my_array[0] = x │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/analysis__return_array.snap b/crates/analyzer/tests/snapshots/analysis__return_array.snap index 0ea8f1816e..c0e589c937 100644 --- a/crates/analyzer/tests/snapshots/analysis__return_array.snap +++ b/crates/analyzer/tests/snapshots/analysis__return_array.snap @@ -7,7 +7,7 @@ note: ┌─ return_array.fe:2:5 │ 2 │ ╭ pub fn bar(x: u256) -> Array { -3 │ │ let my_array: Array +3 │ │ let my_array: Array = [0; 5] 4 │ │ my_array[3] = x 5 │ │ return my_array 6 │ │ } @@ -16,12 +16,22 @@ note: note: ┌─ return_array.fe:3:13 │ -3 │ let my_array: Array +3 │ let my_array: Array = [0; 5] │ ^^^^^^^^ Array note: - ┌─ return_array.fe:4:9 + ┌─ return_array.fe:3:41 + │ +3 │ let my_array: Array = [0; 5] + │ ^ ^ u256: Value + │ │ + │ u256: Value + +note: + ┌─ return_array.fe:3:40 │ +3 │ let my_array: Array = [0; 5] + │ ^^^^^^ Array: Memory 4 │ my_array[3] = x │ ^^^^^^^^ ^ u256: Value │ │ diff --git a/crates/analyzer/tests/snapshots/errors__invalid_repeat_length.snap b/crates/analyzer/tests/snapshots/errors__invalid_repeat_length.snap new file mode 100644 index 0000000000..737958b5a7 --- /dev/null +++ b/crates/analyzer/tests/snapshots/errors__invalid_repeat_length.snap @@ -0,0 +1,14 @@ +--- +source: crates/analyzer/tests/errors.rs +expression: "error_string(&path, test_files::fixture(path))" + +--- +error: expected a constant u256 value + ┌─ compile_errors/invalid_repeat_length.fe:3:45 + │ +3 │ let my_array: Array = [0; true] + │ ^^^^ Array length + │ + = Note: Array length must be a constant u256 + + diff --git a/crates/analyzer/tests/snapshots/errors__uninit_values.snap b/crates/analyzer/tests/snapshots/errors__uninit_values.snap new file mode 100644 index 0000000000..c982082c48 --- /dev/null +++ b/crates/analyzer/tests/snapshots/errors__uninit_values.snap @@ -0,0 +1,24 @@ +--- +source: crates/analyzer/tests/errors.rs +expression: "error_string(&path, test_files::fixture(path))" + +--- +error: uninitialized variable + ┌─ compile_errors/uninit_values.fe:7:13 + │ +7 │ let my_struct: MyStruct + │ ^^^^^^^^^ struct types must be initialized at declaration site + +error: uninitialized variable + ┌─ compile_errors/uninit_values.fe:8:13 + │ +8 │ let my_array: Array + │ ^^^^^^^^ array types must be initialized at declaration site + +error: uninitialized variable + ┌─ compile_errors/uninit_values.fe:9:13 + │ +9 │ let my_tuple: (u256, bool) + │ ^^^^^^^^ tuple types must be initialized at declaration site + + diff --git a/crates/mir/src/lower/function.rs b/crates/mir/src/lower/function.rs index dd66abc94c..a508867d47 100644 --- a/crates/mir/src/lower/function.rs +++ b/crates/mir/src/lower/function.rs @@ -668,6 +668,22 @@ impl<'db, 'a> BodyLowerHelper<'db, 'a> { self.builder.aggregate_construct(ty, args, expr.into()) } + ast::Expr::Repeat { value, len: _ } => { + let array_type = if let Type::Array(array_type) = self.analyzer_body.expressions + [&expr.id] + .typ + .typ(self.db.upcast()) + { + array_type + } else { + panic!("not an array"); + }; + + let args = vec![self.lower_expr_to_value(value); array_type.size]; + let ty = self.expr_ty(expr); + self.builder.aggregate_construct(ty, args, expr.into()) + } + ast::Expr::Bool(b) => { let imm = self.builder.make_imm_from_bool(*b, ty); self.builder.bind(imm, expr.into()) diff --git a/crates/parser/src/ast.rs b/crates/parser/src/ast.rs index 69b58a4290..1debd7d97f 100644 --- a/crates/parser/src/ast.rs +++ b/crates/parser/src/ast.rs @@ -337,6 +337,10 @@ pub enum Expr { List { elts: Vec>, }, + Repeat { + value: Box>, + len: Box>, + }, Tuple { elts: Vec>, }, @@ -964,6 +968,7 @@ impl fmt::Display for Expr { write!(f, "({})", node_comma_joined(&args.kind)) } Expr::List { elts } => write!(f, "[{}]", node_comma_joined(elts)), + Expr::Repeat { value: elt, len } => write!(f, "[{}; {}]", elt.kind, len.kind), Expr::Tuple { elts } => { if elts.len() == 1 { write!(f, "({},)", elts[0].kind) @@ -1181,6 +1186,7 @@ fn expr_left_binding_power(expr: &Expr) -> u8 { Expr::Subscript { .. } => max_power, Expr::Call { .. } => max_power, Expr::List { .. } => max_power, + Expr::Repeat { .. } => max_power, Expr::Tuple { .. } => max_power, Expr::Bool(_) => max_power, Expr::Name(_) => max_power, @@ -1204,6 +1210,7 @@ fn expr_right_binding_power(expr: &Expr) -> u8 { Expr::Subscript { .. } => max_power, Expr::Call { .. } => max_power, Expr::List { .. } => max_power, + Expr::Repeat { .. } => max_power, Expr::Tuple { .. } => max_power, Expr::Bool(_) => max_power, Expr::Name(_) => max_power, diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index 8ced7ebb61..2dbd6e1c03 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -1,4 +1,4 @@ -use crate::ast::{self, CallArg, Expr, Path}; +use crate::ast::{self, CallArg, Expr, GenericArg, Path}; use crate::node::Node; use crate::{Label, ParseFailed, ParseResult, Parser, Token, TokenKind}; @@ -230,7 +230,7 @@ fn parse_expr_head(par: &mut Parser) -> ParseResult> { unary_op(par, &op, operand) } ParenOpen => parse_group_or_tuple(par), - BracketOpen => parse_list(par), + BracketOpen => parse_list_or_repeat(par), _ => { let tok = par.next()?; par.unexpected_token_error( @@ -297,13 +297,55 @@ fn postfix_binding_power(op: TokenKind) -> Option { } } -/// Parse a square-bracket list expression, eg. `[1, 2, x]` -fn parse_list(par: &mut Parser) -> ParseResult> { +/// Parse a square-bracket list expression, eg. `[1, 2, x]` or `[true; 42]` +fn parse_list_or_repeat(par: &mut Parser) -> ParseResult> { let lbracket = par.assert(TokenKind::BracketOpen); - let elts = parse_expr_list(par, TokenKind::BracketClose, None)?; - let rbracket = par.assert(TokenKind::BracketClose); - let span = lbracket.span + rbracket.span; - Ok(Node::new(Expr::List { elts }, span)) + let elts = parse_expr_list(par, &[TokenKind::BracketClose, TokenKind::Semi], None)?; + + if elts.len() == 1 { + if par.peek() == Some(TokenKind::BracketClose) { + let rbracket = par.assert(TokenKind::BracketClose); + let span = lbracket.span + rbracket.span; + Ok(Node::new(Expr::List { elts }, span)) + } else if par.peek() == Some(TokenKind::Semi) { + par.assert(TokenKind::Semi); + + let len = if par.peek() == Some(TokenKind::BraceOpen) { + // handle `{ ... }` const expression + let brace_open = par.next()?; + let expr = parse_expr(par)?; + if !matches!(par.peek(), Some(TokenKind::BraceClose)) { + par.error(brace_open.span, "missing closing delimiter `}`"); + return Err(ParseFailed); + } + let brace_close = par.assert(TokenKind::BraceClose); + let span = brace_open.span + brace_close.span; + Box::new(Node::new(GenericArg::ConstExpr(expr), span)) + } else { + // handle const expression without braces + let expr = parse_expr(par)?; + let span = expr.span; + Box::new(Node::new(GenericArg::ConstExpr(expr), span)) + }; + + let rbracket = par.assert(TokenKind::BracketClose); + let span = lbracket.span + rbracket.span; + Ok(Node::new( + Expr::Repeat { + value: Box::new(elts[0].clone()), + len, + }, + span, + )) + } else { + par.error(lbracket.span, "expected `]` or `;`"); + Err(ParseFailed) + } + } else { + let rbracket = par.assert(TokenKind::BracketClose); + let span = lbracket.span + rbracket.span; + Ok(Node::new(Expr::List { elts }, span)) + } } /// Parse a paren-wrapped expression, which might turn out to be a tuple @@ -328,7 +370,7 @@ fn parse_group_or_tuple(par: &mut Parser) -> ParseResult> { Comma => { // tuple par.next()?; - let elts = parse_expr_list(par, ParenClose, Some(elem))?; + let elts = parse_expr_list(par, &[ParenClose], Some(elem))?; let rparen = par.expect(ParenClose, "failed to parse tuple expression")?; let span = lparen.span + rparen.span; Ok(Node::new(Expr::Tuple { elts }, span)) @@ -349,7 +391,7 @@ fn parse_group_or_tuple(par: &mut Parser) -> ParseResult> { /// `peek()`ed. fn parse_expr_list( par: &mut Parser, - end_marker: TokenKind, + end_markers: &[TokenKind], head: Option>, ) -> ParseResult>> { let mut elts = vec![]; @@ -358,7 +400,7 @@ fn parse_expr_list( } loop { let next = par.peek_or_err()?; - if next == end_marker { + if end_markers.contains(&next) { break; } elts.push(parse_expr(par)?); @@ -366,7 +408,7 @@ fn parse_expr_list( TokenKind::Comma => { par.next()?; } - tk if tk == end_marker => break, + tk if end_markers.contains(&tk) => break, _ => { let tok = par.next()?; par.unexpected_token_error( diff --git a/crates/parser/tests/cases/parse_ast.rs b/crates/parser/tests/cases/parse_ast.rs index 70d8c59c9a..94f744667c 100644 --- a/crates/parser/tests/cases/parse_ast.rs +++ b/crates/parser/tests/cases/parse_ast.rs @@ -81,6 +81,8 @@ test_parse! { expr_path_call, expressions::parse_expr, "foo::bar::abc1()" } test_parse! { expr_string, expressions::parse_expr, r#""hi \tmom\n""# } test_parse! { expr_list, expressions::parse_expr, "[]" } test_parse! { expr_list2, expressions::parse_expr, "[x, y, z,]" } +test_parse! { expr_repeat, expressions::parse_expr, "[true; 42]" } +test_parse! { expr_repeat2, expressions::parse_expr, "[5 + 4; 26]" } test_parse! { expr_ternary, expressions::parse_expr, "x + 1 if y + 2 else z + 3" } test_parse! { expr_group, expressions::parse_expr, "(1 + 2) * 3" } test_parse! { expr_tuple1, expressions::parse_expr, "(1,)" } diff --git a/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat.snap b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat.snap new file mode 100644 index 0000000000..026de8a85b --- /dev/null +++ b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat.snap @@ -0,0 +1,33 @@ +--- +source: crates/parser/tests/cases/parse_ast.rs +expression: "ast_string(stringify!(expr_repeat), expressions::parse_expr, \"[true; 42]\")" + +--- +Node( + kind: Repeat( + value: Node( + kind: Bool(true), + span: Span( + start: 1, + end: 5, + ), + ), + len: Node( + kind: ConstExpr(Node( + kind: Num("42"), + span: Span( + start: 7, + end: 9, + ), + )), + span: Span( + start: 7, + end: 9, + ), + ), + ), + span: Span( + start: 0, + end: 10, + ), +) diff --git a/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat2.snap b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat2.snap new file mode 100644 index 0000000000..d60b37f045 --- /dev/null +++ b/crates/parser/tests/cases/snapshots/cases__parse_ast__expr_repeat2.snap @@ -0,0 +1,55 @@ +--- +source: crates/parser/tests/cases/parse_ast.rs +expression: "ast_string(stringify!(expr_repeat2), expressions::parse_expr, \"[5 + 4; 26]\")" + +--- +Node( + kind: Repeat( + value: Node( + kind: BinOperation( + left: Node( + kind: Num("5"), + span: Span( + start: 1, + end: 2, + ), + ), + op: Node( + kind: Add, + span: Span( + start: 3, + end: 4, + ), + ), + right: Node( + kind: Num("4"), + span: Span( + start: 5, + end: 6, + ), + ), + ), + span: Span( + start: 1, + end: 6, + ), + ), + len: Node( + kind: ConstExpr(Node( + kind: Num("26"), + span: Span( + start: 8, + end: 10, + ), + )), + span: Span( + start: 8, + end: 10, + ), + ), + ), + span: Span( + start: 0, + end: 11, + ), +) diff --git a/crates/test-files/fixtures/compile_errors/cannot_move2.fe b/crates/test-files/fixtures/compile_errors/cannot_move2.fe index e13377770f..5349b1b048 100644 --- a/crates/test-files/fixtures/compile_errors/cannot_move2.fe +++ b/crates/test-files/fixtures/compile_errors/cannot_move2.fe @@ -1,7 +1,7 @@ contract Foo { pub fn foo() { - let x: Array - let y: Array + let x: Array = [0; 10] + let y: Array = [0; 10] let c: Array = x + y } } diff --git a/crates/test-files/fixtures/compile_errors/duplicate_var_in_child_scope.fe b/crates/test-files/fixtures/compile_errors/duplicate_var_in_child_scope.fe index 58856c3e55..1cb4c016be 100644 --- a/crates/test-files/fixtures/compile_errors/duplicate_var_in_child_scope.fe +++ b/crates/test-files/fixtures/compile_errors/duplicate_var_in_child_scope.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar() { - let my_array: Array + let my_array: Array = [u64(0); 3] let sum: u256 = 0 for i in my_array { let sum: u64 = 0 diff --git a/crates/test-files/fixtures/compile_errors/invalid_repeat_length.fe b/crates/test-files/fixtures/compile_errors/invalid_repeat_length.fe new file mode 100644 index 0000000000..43f3d19c91 --- /dev/null +++ b/crates/test-files/fixtures/compile_errors/invalid_repeat_length.fe @@ -0,0 +1,5 @@ +contract Foo { + pub fn foo() { + let my_array: Array = [0; true] + } +} \ No newline at end of file diff --git a/crates/test-files/fixtures/compile_errors/undefined_type_param.fe b/crates/test-files/fixtures/compile_errors/undefined_type_param.fe index 69bcf0c5be..4cee2bf373 100644 --- a/crates/test-files/fixtures/compile_errors/undefined_type_param.fe +++ b/crates/test-files/fixtures/compile_errors/undefined_type_param.fe @@ -14,7 +14,7 @@ contract Foo { } pub fn c() { - let x: BadField + let x: BadField = BadField(x: 0) x.x = 10 } } diff --git a/crates/test-files/fixtures/compile_errors/uninit_values.fe b/crates/test-files/fixtures/compile_errors/uninit_values.fe new file mode 100644 index 0000000000..12ec154cd3 --- /dev/null +++ b/crates/test-files/fixtures/compile_errors/uninit_values.fe @@ -0,0 +1,11 @@ +struct MyStruct { + x: u256 +} + +contract Foo { + pub fn foo() { + let my_struct: MyStruct + let my_array: Array + let my_tuple: (u256, bool) + } +} \ No newline at end of file diff --git a/crates/test-files/fixtures/features/array_repeat.fe b/crates/test-files/fixtures/features/array_repeat.fe new file mode 100644 index 0000000000..f7c45d7559 --- /dev/null +++ b/crates/test-files/fixtures/features/array_repeat.fe @@ -0,0 +1,14 @@ +contract Foo { + pub fn foo() -> Array { + let my_array: Array = [8; 4] + my_array[1] = 42 + return my_array + } + + pub fn bar() { + let my_array: Array<(u256, u256), 2> = [(1, 0); 2] + my_array[0].item0 = 4 + assert my_array[0].item0 == 4 + assert my_array[1].item0 == 1 + } +} \ No newline at end of file diff --git a/crates/test-files/fixtures/features/aug_assign.fe b/crates/test-files/fixtures/features/aug_assign.fe index da6bbd2e38..e0b728d672 100644 --- a/crates/test-files/fixtures/features/aug_assign.fe +++ b/crates/test-files/fixtures/features/aug_assign.fe @@ -63,7 +63,7 @@ contract Foo { } pub fn add_from_mem(a: u256, b: u256) -> u256 { - let my_array: Array + let my_array: Array = [0; 10] my_array[7] = a my_array[7] += b return my_array[7] diff --git a/crates/test-files/fixtures/features/const_generics.fe b/crates/test-files/fixtures/features/const_generics.fe index b3773c51e1..7d38799d41 100644 --- a/crates/test-files/fixtures/features/const_generics.fe +++ b/crates/test-files/fixtures/features/const_generics.fe @@ -1,48 +1,48 @@ contract Foo { pub fn bar() { # const generics with literal. - let array_lit: Array - let array_lit2: Array + let array_lit: Array = [i32(0); 8] + let array_lit2: Array = [i32(0); 8] # const generics with ternary expression. - let array_ternary: Array + let array_ternary: Array = [i32(0); { 3 if false else 8 }] # const generics with logical expression. - let array_logical_or: Array - let array_logical_and: Array + let array_logical_or: Array = [i32(0); { 8 if (true or false) else 0 }] + let array_logical_and: Array = [i32(0); { 0 if (true and false) else 8 }] # const generics with binary expression. - let array_add: Array - let array_sub: Array - let array_mul: Array - let array_div: Array - let array_mod: Array - let array_pow: Array - let array_shl: Array - let array_shr: Array> 2 }> - let array_bitor: Array - let array_xor: Array - let array_bitand: Array + let array_add: Array = [i32(42); 8] + let array_sub: Array = [i32(26); 8] + let array_mul: Array = [i32(0); 8] + let array_div: Array = [i32(0); 8] + let array_mod: Array = [i32(0); 8] + let array_pow: Array = [i32(0); 8] + let array_shl: Array = [i32(0); 8] + let array_shr: Array> 2 }> = [i32(0); 8] + let array_bitor: Array = [i32(0); 8] + let array_xor: Array = [i32(0); 8] + let array_bitand: Array = [i32(0); 8] # const generics with comparison expression. - let array_eq: Array - let array_ne: Array - let array_lt1: Array - let array_lt2: Array - let array_lte: Array - let array_lte2: Array - let array_gt: Array 0 else 0 }> - let array_gt2: Array 10 else 8 }> - let array_gte: Array= 10 else 8 }> - let array_gte2: Array= 10 else 0 }> + let array_eq: Array = [i32(0); 8] + let array_ne: Array = [i32(0); 8] + let array_lt1: Array = [i32(0); 8] + let array_lt2: Array = [i32(0); 8] + let array_lte: Array = [i32(0); 8] + let array_lte2: Array = [i32(0); 8] + let array_gt: Array 0 else 0 }> = [i32(0); 8] + let array_gt2: Array 10 else 8 }> = [i32(0); 8] + let array_gte: Array= 10 else 8 }> = [i32(0); 8] + let array_gte2: Array= 10 else 0 }> = [i32(0); 8] # const generics with unary expression. - let array_not: Array + let array_not: Array = [i32(0); 8] # const generics with const variable. const DOUBLE_ARRAY_LENGTH: u64 = 16 const TWO: u64 = 2 - let array_with_const: Array + let array_with_const: Array = [i32(0); 8] } } \ No newline at end of file diff --git a/crates/test-files/fixtures/features/const_local.fe b/crates/test-files/fixtures/features/const_local.fe index 1800710820..40b77b7481 100644 --- a/crates/test-files/fixtures/features/const_local.fe +++ b/crates/test-files/fixtures/features/const_local.fe @@ -11,7 +11,7 @@ contract Foo { const C8: bool = false const C9: bool = C8 < C7 # true const C10: u256 = 42 if C9 else 0 # 42 - let _arr: Array + let _arr: Array = [true; { C10 }] return C10 } } diff --git a/crates/test-files/fixtures/features/events.fe b/crates/test-files/fixtures/features/events.fe index 453ac576a6..c08ce2ff94 100644 --- a/crates/test-files/fixtures/features/events.fe +++ b/crates/test-files/fixtures/features/events.fe @@ -35,7 +35,7 @@ contract Foo { } pub fn emit_addresses(ctx: Context, addr1: address, addr2: address) { - let addrs: Array + let addrs: Array = [address(0); 2] addrs[0] = addr1 addrs[1] = addr2 emit Addresses(ctx, addrs) diff --git a/crates/test-files/fixtures/features/external_contract.fe b/crates/test-files/fixtures/features/external_contract.fe index 54a0512960..2d56d87cda 100644 --- a/crates/test-files/fixtures/features/external_contract.fe +++ b/crates/test-files/fixtures/features/external_contract.fe @@ -12,7 +12,7 @@ contract Foo { } pub fn build_array(a: u256, b: u256) -> Array { - let my_array: Array + let my_array: Array = [0; 3] my_array[0] = a my_array[1] = a * b my_array[2] = b diff --git a/crates/test-files/fixtures/features/for_loop_with_break.fe b/crates/test-files/fixtures/features/for_loop_with_break.fe index 25d20b5fb3..8e8079b7dc 100644 --- a/crates/test-files/fixtures/features/for_loop_with_break.fe +++ b/crates/test-files/fixtures/features/for_loop_with_break.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar() -> u256 { - let my_array: Array + let my_array: Array = [0; 3] my_array[0] = 5 my_array[1] = 10 my_array[2] = 15 diff --git a/crates/test-files/fixtures/features/for_loop_with_continue.fe b/crates/test-files/fixtures/features/for_loop_with_continue.fe index b946482371..d2ce17e87d 100644 --- a/crates/test-files/fixtures/features/for_loop_with_continue.fe +++ b/crates/test-files/fixtures/features/for_loop_with_continue.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar() -> u256 { - let my_array: Array + let my_array: Array = [0; 5] my_array[0] = 2 my_array[1] = 3 my_array[2] = 5 diff --git a/crates/test-files/fixtures/features/for_loop_with_static_array.fe b/crates/test-files/fixtures/features/for_loop_with_static_array.fe index 632df0dfa5..6ff378cd83 100644 --- a/crates/test-files/fixtures/features/for_loop_with_static_array.fe +++ b/crates/test-files/fixtures/features/for_loop_with_static_array.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar() -> u256 { - let my_array: Array + let my_array: Array = [0; 3] my_array[0] = 5 my_array[1] = 10 my_array[2] = 15 diff --git a/crates/test-files/fixtures/features/module_const.fe b/crates/test-files/fixtures/features/module_const.fe index 027f74caef..6030b46b5b 100644 --- a/crates/test-files/fixtures/features/module_const.fe +++ b/crates/test-files/fixtures/features/module_const.fe @@ -8,9 +8,9 @@ const C4: i32 = 42 contract Foo { fn bar() -> i32 { const LOCAL_CONST: i32 = C3 * 2 - let _arr1: Array - let _arr2: Array - let _my_array: MY_ARRAY + let _arr1: Array = [i32(0); { C2 }] + let _arr2: Array = [i32(0); { LOCAL_CONST }] + let _my_array: MY_ARRAY = [true; { C4 }] return C4 } } diff --git a/crates/test-files/fixtures/features/multi_param.fe b/crates/test-files/fixtures/features/multi_param.fe index df5cd903b5..5579ebf859 100644 --- a/crates/test-files/fixtures/features/multi_param.fe +++ b/crates/test-files/fixtures/features/multi_param.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar(x: u256, y: u256, z: u256) -> Array { - let my_array: Array + let my_array: Array = [0; 3] my_array[0] = x my_array[1] = y my_array[2] = z diff --git a/crates/test-files/fixtures/features/return_array.fe b/crates/test-files/fixtures/features/return_array.fe index 03bbd33b54..1e9f684424 100644 --- a/crates/test-files/fixtures/features/return_array.fe +++ b/crates/test-files/fixtures/features/return_array.fe @@ -1,6 +1,6 @@ contract Foo { pub fn bar(x: u256) -> Array { - let my_array: Array + let my_array: Array = [0; 5] my_array[3] = x return my_array } diff --git a/crates/test-files/fixtures/stress/data_copying_stress.fe b/crates/test-files/fixtures/stress/data_copying_stress.fe index 0b814aeaec..e8a1d56083 100644 --- a/crates/test-files/fixtures/stress/data_copying_stress.fe +++ b/crates/test-files/fixtures/stress/data_copying_stress.fe @@ -54,7 +54,7 @@ contract Foo { } pub fn assign_my_nums_and_return(self) -> Array { - let my_nums_mem: Array + let my_nums_mem: Array = [0; 5] self.my_nums[0] = 42 self.my_nums[1] = 26 self.my_nums[2] = 0 diff --git a/crates/tests/src/features.rs b/crates/tests/src/features.rs index 88fa33753c..5b754ea985 100644 --- a/crates/tests/src/features.rs +++ b/crates/tests/src/features.rs @@ -2080,3 +2080,18 @@ fn generics() { harness.test_function(&mut executor, "generic_compute", &[], None); }); } + +#[test] +fn array_repeat() { + with_executor(&|mut executor| { + let harness = deploy_contract(&mut executor, "array_repeat.fe", "Foo", &[]); + harness.test_function( + &mut executor, + "foo", + &[], + Some(&uint_array_token(&[8, 42, 8, 8])), + ); + + harness.test_function(&mut executor, "bar", &[], None); + }); +} diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_001.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_001.snap index d17fb3445d..eedfa52178 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__case_001.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_001.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([]) used 143 gas +bar([]) used 2323 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_002.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_002.snap index d50d6b6665..2f4787cfe9 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__case_002.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_002.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([]) used 1020 gas +bar([]) used 1074 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_004.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_004.snap index 2e6ef6f829..5e24537053 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__case_004.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_004.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([]) used 759 gas +bar([]) used 813 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_005.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_005.snap index 3fe69d8bc6..b866edc981 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__case_005.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_005.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([]) used 1658 gas +bar([]) used 1745 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_13.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_13.snap index 0a8343e2a1..3b4b86956c 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__case_13.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_13.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -add_from_mem([Uint(2), Uint(5)]) used 643 gas +add_from_mem([Uint(2), Uint(5)]) used 819 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__events.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__events.snap index 297096f146..142d36c58d 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__events.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__events.snap @@ -1,9 +1,10 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- emit_nums([]) used 1600 gas emit_bases([Address(0x1234000000000000000000000000000000005678)]) used 1676 gas emit_mix([Address(0x1234000000000000000000000000000000005678), Bytes([116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46, 116, 101, 110, 32, 98, 121, 116, 101, 115, 46])]) used 4833 gas -emit_addresses([Address(0x1234000000000000000000000000000000005678), Address(0x9123000000000000000000000000000000004567)]) used 2344 gas +emit_addresses([Address(0x1234000000000000000000000000000000005678), Address(0x9123000000000000000000000000000000004567)]) used 2339 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__external_contract.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__external_contract.snap index 215da3633f..faff46a0a8 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__external_contract.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__external_contract.snap @@ -1,7 +1,8 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", proxy_harness.gas_reporter)" + --- call_emit_event([Address(0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643), Uint(26), FixedArray([Address(0x0000000000000000000000000000000000000000), Address(0x0000000000000000000000000000000000000001), Address(0x0000000000000000000000000000000000000042), Address(0x0000000000000000000000000000000000000003), Address(0x0000000000000000000000000000000000000004)]), String("hello world")]) used 8195 gas -call_build_array([Address(0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643), Uint(26), Uint(42)]) used 1945 gas +call_build_array([Address(0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643), Uint(26), Uint(42)]) used 1978 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__multi_param.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__multi_param.snap index 06d0836468..3ff3fce0d8 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__multi_param.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__multi_param.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([Uint(4), Uint(42), Uint(420)]) used 579 gas +bar([Uint(4), Uint(42), Uint(420)]) used 596 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__return_array.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__return_array.snap index e43f830560..e29e58ad07 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__features__return_array.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__return_array.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/features.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- -bar([Uint(42)]) used 727 gas +bar([Uint(42)]) used 796 gas diff --git a/crates/tests/src/snapshots/fe_compiler_tests__stress__data_copying_stress.snap b/crates/tests/src/snapshots/fe_compiler_tests__stress__data_copying_stress.snap index e3368d1875..daa4e1c0fa 100644 --- a/crates/tests/src/snapshots/fe_compiler_tests__stress__data_copying_stress.snap +++ b/crates/tests/src/snapshots/fe_compiler_tests__stress__data_copying_stress.snap @@ -1,6 +1,7 @@ --- source: crates/tests/src/stress.rs expression: "format!(\"{}\", harness.gas_reporter)" + --- set_my_vals([String("my string"), String("my other string"), Uint(26), Uint(42)]) used 138325 gas emit_my_event([]) used 3694 gas @@ -10,7 +11,7 @@ mutate_and_return([FixedArray([Uint(1), Uint(2), Uint(3), Uint(4), Uint(5), Uint multiple_references_shared_memory([FixedArray([Uint(1), Uint(2), Uint(3), Uint(4), Uint(5), Uint(6), Uint(7), Uint(8), Uint(9), Uint(10)])]) used 680 gas clone_and_return([FixedArray([Uint(1), Uint(2), Uint(3), Uint(4), Uint(5), Uint(6), Uint(7), Uint(8), Uint(9), Uint(10)])]) used 2494 gas clone_mutate_and_return([FixedArray([Uint(1), Uint(2), Uint(3), Uint(4), Uint(5), Uint(6), Uint(7), Uint(8), Uint(9), Uint(10)])]) used 2528 gas -assign_my_nums_and_return([]) used 92449 gas +assign_my_nums_and_return([]) used 92544 gas set_my_addrs([FixedArray([Address(0x0000000000000000000000000000000000000000), Address(0x0000000000000000000000000000000000000001), Address(0x0000000000000000000000000000000000000002)])]) used 47327 gas get_my_second_addr([]) used 468 gas diff --git a/newsfragments/747.feature.md b/newsfragments/747.feature.md new file mode 100644 index 0000000000..4e8830e3b5 --- /dev/null +++ b/newsfragments/747.feature.md @@ -0,0 +1,9 @@ +Added support for repeat expressions (`[VALUE; LENGTH]`). + +e.g. + +``` +let my_array: Array = [bool; 42] +``` + +Also added checks to ensure array and struct types are initialized. These checks are currently performed at the declaration site, but will be loosened in the future.