mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
parser: fix fixed array with eval const size (#19269)
This commit is contained in:
parent
d04a3e52e3
commit
e6b7eb3a29
2 changed files with 79 additions and 27 deletions
|
@ -25,38 +25,49 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ
|
|||
}
|
||||
ast.Ident {
|
||||
mut show_non_const_error := false
|
||||
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()
|
||||
} 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 {
|
||||
fixed_size = folded_expr.val.int()
|
||||
} else {
|
||||
show_non_const_error = true
|
||||
}
|
||||
} else {
|
||||
show_non_const_error = true
|
||||
}
|
||||
}
|
||||
} 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
|
||||
} else {
|
||||
show_non_const_error = true
|
||||
}
|
||||
}
|
||||
fixed_size, show_non_const_error = p.check_and_eval_const_val(size_expr)
|
||||
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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.error_with_pos('fixed array size cannot use non-constant value',
|
||||
size_expr.pos())
|
||||
|
@ -840,3 +851,29 @@ 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
|
||||
}
|
||||
|
|
|
@ -44,3 +44,18 @@ fn test_int_const_used_as_fixed_array_size() {
|
|||
dump(bb.len)
|
||||
assert aa.len == 10_000
|
||||
}
|
||||
|
||||
const (
|
||||
rows = 4
|
||||
cols = 4
|
||||
)
|
||||
|
||||
struct Matrix {
|
||||
data [rows * cols]int
|
||||
}
|
||||
|
||||
fn test_infix_const_expr_used_as_fixed_array_size() {
|
||||
mat := Matrix{}
|
||||
println(mat)
|
||||
assert mat.data.len == 16
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue