diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 9de71ee19c4570..6ef2797162482c 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -15,57 +15,58 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ // fixed array if p.tok.kind in [.number, .name] { mut fixed_size := 0 - size_expr := p.expr(0) + mut size_expr := p.expr(0) if p.pref.is_fmt { fixed_size = 987654321 } else { - match size_expr { + match mut size_expr { ast.IntegerLiteral { fixed_size = size_expr.val.int() } ast.Ident { - mut show_non_const_error := false - fixed_size, show_non_const_error = p.check_and_eval_const_val(size_expr) + mut show_non_const_error := true + if mut const_field := p.table.global_scope.find_const('${p.mod}.${size_expr.name}') { + if mut const_field.expr is ast.IntegerLiteral { + fixed_size = const_field.expr.val.int() + show_non_const_error = false + } else { + if mut const_field.expr is ast.InfixExpr { + // QUESTION: this should most likely no be done in the parser, right? + mut t := transformer.new_transformer_with_table(p.table, + p.pref) + folded_expr := t.infix_expr(mut const_field.expr) + + if folded_expr is ast.IntegerLiteral { + fixed_size = folded_expr.val.int() + show_non_const_error = false + } + } + } + } else { + if p.pref.is_fmt { + // for vfmt purposes, pretend the constant does exist + // it may have been defined in another .v file: + fixed_size = 1 + show_non_const_error = false + } + } if show_non_const_error { p.error_with_pos('non-constant array bound `${size_expr.name}`', size_expr.pos) } } ast.InfixExpr { - mut show_non_const_error := false - mut left_val := 1 - mut right_val := 1 - if size_expr.left is ast.Ident { - left_val, show_non_const_error = p.check_and_eval_const_val(size_expr.left) - if show_non_const_error { - p.error_with_pos('non-constant array bound `${size_expr.left.name}`', - size_expr.left.pos) - } - } - if size_expr.right is ast.Ident && !show_non_const_error { - right_val, show_non_const_error = p.check_and_eval_const_val(size_expr.right) - if show_non_const_error { - p.error_with_pos('non-constant array bound `${size_expr.right.name}`', - size_expr.right.pos) - } + mut show_non_const_error := true + mut t := transformer.new_transformer_with_table(p.table, p.pref) + folded_expr := t.infix_expr(mut size_expr) + + if folded_expr is ast.IntegerLiteral { + fixed_size = folded_expr.val.int() + show_non_const_error = false } - match size_expr.op { - .plus { - fixed_size = left_val + right_val - } - .minus { - fixed_size = left_val - right_val - } - .mul { - fixed_size = left_val * right_val - } - .div { - fixed_size = left_val / right_val - } - else { - p.error_with_pos('fixed array size cannot use non-constant value', - size_expr.pos) - } + if show_non_const_error { + p.error_with_pos('fixed array size cannot use non-constant eval value', + size_expr.pos) } } else { @@ -851,29 +852,3 @@ fn (mut p Parser) parse_generic_inst_type(name string) ast.Type { } return p.find_type_or_add_placeholder(name, .v).set_flag(.generic) } - -// return value and show_non_const_error -fn (mut p Parser) check_and_eval_const_val(expr ast.Ident) (int, bool) { - if mut const_field := p.table.global_scope.find_const('${p.mod}.${expr.name}') { - if mut const_field.expr is ast.IntegerLiteral { - return const_field.expr.val.int(), false - } else { - if mut const_field.expr is ast.InfixExpr { - // QUESTION: this should most likely no be done in the parser, right? - mut t := transformer.new_transformer(p.pref) - folded_expr := t.infix_expr(mut const_field.expr) - - if folded_expr is ast.IntegerLiteral { - return folded_expr.val.int(), false - } - } - } - } else { - if p.pref.is_fmt { - // for vfmt purposes, pretend the constant does exist - // it may have been defined in another .v file: - return 1, false - } - } - return 0, true -} diff --git a/vlib/v/tests/fixed_array_const_size_test.v b/vlib/v/tests/fixed_array_const_size_test.v index fe3f385a1535ca..f0e0bdab2075fc 100644 --- a/vlib/v/tests/fixed_array_const_size_test.v +++ b/vlib/v/tests/fixed_array_const_size_test.v @@ -46,8 +46,8 @@ fn test_int_const_used_as_fixed_array_size() { } const ( - rows = 4 - cols = 4 + rows = 2 + cols = 3 ) struct Matrix { @@ -57,5 +57,5 @@ struct Matrix { fn test_infix_const_expr_used_as_fixed_array_size() { mat := Matrix{} println(mat) - assert mat.data.len == 16 + assert mat.data.len == 6 } diff --git a/vlib/v/transformer/transformer.v b/vlib/v/transformer/transformer.v index 144ed4e01d01ab..24574c70a559d2 100644 --- a/vlib/v/transformer/transformer.v +++ b/vlib/v/transformer/transformer.v @@ -695,7 +695,8 @@ pub fn (mut t Transformer) expr(mut node ast.Expr) ast.Expr { } else {} } - }*/ + } + */ else {} } return node @@ -708,9 +709,41 @@ pub fn (mut t Transformer) call_expr(mut node ast.CallExpr) ast.Expr { return node } +fn (mut t Transformer) trans_const_value_to_literal(mut expr ast.Expr) { + mut expr_ := expr + if mut expr_ is ast.Ident { + if mut obj := t.table.global_scope.find_const(expr_.mod + '.' + expr_.name) { + if mut obj.expr is ast.BoolLiteral { + expr = obj.expr + } else if mut obj.expr is ast.IntegerLiteral { + expr = obj.expr + } else if mut obj.expr is ast.FloatLiteral { + expr = obj.expr + } else if mut obj.expr is ast.StringLiteral { + expr = obj.expr + } else if mut obj.expr is ast.InfixExpr { + folded_expr := t.infix_expr(mut obj.expr) + if folded_expr is ast.BoolLiteral { + expr = folded_expr + } else if folded_expr is ast.IntegerLiteral { + expr = folded_expr + } else if folded_expr is ast.FloatLiteral { + expr = folded_expr + } else if folded_expr is ast.StringLiteral { + expr = folded_expr + } + } + } + } +} + pub fn (mut t Transformer) infix_expr(mut node ast.InfixExpr) ast.Expr { node.left = t.expr(mut node.left) node.right = t.expr(mut node.right) + if !t.pref.translated { + t.trans_const_value_to_literal(mut node.left) + t.trans_const_value_to_literal(mut node.right) + } mut pos := node.left.pos() pos.extend(node.pos)