mirror of
https://github.com/vlang/v.git
synced 2025-09-17 11:26:17 -04:00
checker: cleanup the const variable evaluate for fixed array fields of structs (#20503)
This commit is contained in:
parent
fe669f8ce1
commit
cfd8915782
@ -247,9 +247,13 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
|||||||
node.elem_type = elem_type
|
node.elem_type = elem_type
|
||||||
} else if node.is_fixed && node.exprs.len == 1 && node.elem_type != ast.void_type {
|
} else if node.is_fixed && node.exprs.len == 1 && node.elem_type != ast.void_type {
|
||||||
// `[50]u8`
|
// `[50]u8`
|
||||||
mut init_expr := node.exprs[0]
|
sym := c.table.sym(node.typ)
|
||||||
node.typ = c.eval_array_fixed_sizes(mut init_expr, 0, node.elem_type)
|
if sym.info !is ast.ArrayFixed
|
||||||
node.elem_type = (c.table.sym(node.typ).info as ast.ArrayFixed).elem_type
|
|| c.array_fixed_has_unresolved_size(sym.info as ast.ArrayFixed) {
|
||||||
|
mut size_expr := node.exprs[0]
|
||||||
|
node.typ = c.eval_array_fixed_sizes(mut size_expr, 0, node.elem_type)
|
||||||
|
node.elem_type = (c.table.sym(node.typ).info as ast.ArrayFixed).elem_type
|
||||||
|
}
|
||||||
if node.has_init {
|
if node.has_init {
|
||||||
c.check_array_init_default_expr(mut node)
|
c.check_array_init_default_expr(mut node)
|
||||||
}
|
}
|
||||||
@ -381,6 +385,26 @@ fn (mut c Checker) eval_array_fixed_sizes(mut size_expr ast.Expr, size int, elem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) array_fixed_has_unresolved_size(info &ast.ArrayFixed) bool {
|
||||||
|
if info.size <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
mut elem_type := info.elem_type
|
||||||
|
mut elem_sym := c.table.sym(elem_type)
|
||||||
|
for {
|
||||||
|
if mut elem_sym.info is ast.ArrayFixed {
|
||||||
|
if elem_sym.info.size <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
elem_type = elem_sym.info.elem_type
|
||||||
|
elem_sym = c.table.sym(elem_type)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||||
// `map = {}`
|
// `map = {}`
|
||||||
if node.keys.len == 0 && node.vals.len == 0 && node.typ == 0 {
|
if node.keys.len == 0 && node.vals.len == 0 && node.typ == 0 {
|
||||||
|
@ -5,7 +5,6 @@ module checker
|
|||||||
import v.ast
|
import v.ast
|
||||||
import v.util
|
import v.util
|
||||||
import v.token
|
import v.token
|
||||||
import v.transformer
|
|
||||||
|
|
||||||
fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
@ -57,56 +56,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||||||
// Evaluate the size of the unresolved fixed array
|
// Evaluate the size of the unresolved fixed array
|
||||||
for mut field in node.fields {
|
for mut field in node.fields {
|
||||||
sym := c.table.sym(field.typ)
|
sym := c.table.sym(field.typ)
|
||||||
if sym.kind == .array_fixed {
|
if sym.info is ast.ArrayFixed && c.array_fixed_has_unresolved_size(sym.info) {
|
||||||
info := sym.info as ast.ArrayFixed
|
mut size_expr := unsafe { sym.info.size_expr }
|
||||||
if info.size > 0 {
|
field.typ = c.eval_array_fixed_sizes(mut size_expr, 0, sym.info.elem_type)
|
||||||
continue
|
|
||||||
}
|
|
||||||
mut fixed_size := 0
|
|
||||||
match info.size_expr {
|
|
||||||
ast.Ident {
|
|
||||||
if mut const_field := c.table.global_scope.find_const('${c.mod}.${info.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 {
|
|
||||||
mut t := transformer.new_transformer_with_table(c.table,
|
|
||||||
c.pref)
|
|
||||||
folded_expr := t.infix_expr(mut const_field.expr)
|
|
||||||
if folded_expr is ast.IntegerLiteral {
|
|
||||||
fixed_size = folded_expr.val.int()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if fixed_size <= 0 {
|
|
||||||
c.error('non-constant array bound `${info.size_expr.name}`',
|
|
||||||
info.size_expr.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast.InfixExpr {
|
|
||||||
mut t := transformer.new_transformer_with_table(c.table, c.pref)
|
|
||||||
mut size_expr := unsafe { &info.size_expr }
|
|
||||||
folded_expr := t.infix_expr(mut size_expr)
|
|
||||||
|
|
||||||
if folded_expr is ast.IntegerLiteral {
|
|
||||||
fixed_size = folded_expr.val.int()
|
|
||||||
}
|
|
||||||
if fixed_size <= 0 {
|
|
||||||
c.error('fixed array size cannot use non-constant eval value',
|
|
||||||
info.size_expr.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
if fixed_size <= 0 {
|
|
||||||
c.error('fixed size cannot be zero or negative', info.size_expr.pos())
|
|
||||||
}
|
|
||||||
idx := c.table.find_or_register_array_fixed(info.elem_type, fixed_size,
|
|
||||||
info.size_expr, false)
|
|
||||||
if info.elem_type.has_flag(.generic) {
|
|
||||||
field.typ = ast.new_type(idx).set_flag(.generic)
|
|
||||||
} else {
|
|
||||||
field.typ = ast.new_type(idx)
|
|
||||||
}
|
|
||||||
for mut symfield in struct_sym.info.fields {
|
for mut symfield in struct_sym.info.fields {
|
||||||
if symfield.name == field.name {
|
if symfield.name == field.name {
|
||||||
symfield.typ = field.typ
|
symfield.typ = field.typ
|
||||||
|
@ -9,21 +9,24 @@ fn test_consant_array_size() {
|
|||||||
b = [1, 2]!
|
b = [1, 2]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for 19593
|
||||||
// test const was declared below struct fixed array fields declaration
|
// test const was declared below struct fixed array fields declaration
|
||||||
struct Foo {
|
struct Foo {
|
||||||
posts [max_posts_count]int
|
arr [width][2][width + 1]f64
|
||||||
}
|
}
|
||||||
|
|
||||||
const max_posts_count = 5
|
|
||||||
|
|
||||||
fn test_const_below_at_struct_fixed_array_fields() {
|
fn test_const_below_at_struct_fixed_array_fields() {
|
||||||
foo := Foo{}
|
foo := Foo{}
|
||||||
assert foo.posts == [0, 0, 0, 0, 0]!
|
assert foo.arr.len == 2
|
||||||
|
assert foo.arr[0].len == 2
|
||||||
|
assert foo.arr[0][0].len == 3
|
||||||
|
assert foo.arr == [[[0.0, 0.0, 0.0]!, [0.0, 0.0, 0.0]!]!,
|
||||||
|
[[0.0, 0.0, 0.0]!, [0.0, 0.0, 0.0]!]!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
// for issue 20311
|
// for issue 20311
|
||||||
// When using a static variable to define a fixed array size,
|
// when using a const variable to define a fixed array size,
|
||||||
// if the static variable is defined below or in another module, the size value will not be calculated correctly.
|
// if the const variable is defined below or in another module, the size value will not be calculated correctly.
|
||||||
fn test_const_below_at_fixed_array() {
|
fn test_const_below_at_fixed_array() {
|
||||||
arr := [width][2][width + 1]f64{}
|
arr := [width][2][width + 1]f64{}
|
||||||
assert arr.len == 2
|
assert arr.len == 2
|
||||||
@ -33,5 +36,6 @@ fn test_const_below_at_fixed_array() {
|
|||||||
[0.0, 0.0, 0.0]!]!]!
|
[0.0, 0.0, 0.0]!]!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not move this definition; it must be below `fn test_const_below_at_fixed_array()`.
|
// do not move this definition,
|
||||||
|
// it must be below `struct Foo {...}` and `fn test_const_below_at_fixed_array()`.
|
||||||
const width = 2
|
const width = 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user