mirror of
https://github.com/vlang/v.git
synced 2025-09-14 06:52:36 +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 {
|
ast.Ident {
|
||||||
mut show_non_const_error := false
|
mut show_non_const_error := false
|
||||||
if mut const_field := p.table.global_scope.find_const('${p.mod}.${size_expr.name}') {
|
fixed_size, show_non_const_error = p.check_and_eval_const_val(size_expr)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if show_non_const_error {
|
if show_non_const_error {
|
||||||
p.error_with_pos('non-constant array bound `${size_expr.name}`',
|
p.error_with_pos('non-constant array bound `${size_expr.name}`',
|
||||||
size_expr.pos)
|
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 {
|
else {
|
||||||
p.error_with_pos('fixed array size cannot use non-constant value',
|
p.error_with_pos('fixed array size cannot use non-constant value',
|
||||||
size_expr.pos())
|
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 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)
|
dump(bb.len)
|
||||||
assert aa.len == 10_000
|
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