1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker,cgen: fix dump when using comptime variable val.${field.name} (#16671)

This commit is contained in:
Felipe Pena 2022-12-14 15:45:28 -03:00 committed by GitHub
parent f762d46c84
commit c3ee26f15f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 8 deletions

View File

@ -183,6 +183,10 @@ fn (mut c Checker) comptime_for(node ast.ComptimeFor) {
c.comptime_fields_type[node.val_var] = node.typ
c.comptime_fields_default_type = field.typ
c.stmts(node.stmts)
unwrapped_expr_type := c.unwrap_generic(field.typ)
tsym := c.table.sym(unwrapped_expr_type)
c.table.dumps[int(unwrapped_expr_type.clear_flag(.optional).clear_flag(.result))] = tsym.cname
}
c.inside_comptime_for_field = false
}

View File

@ -0,0 +1,8 @@
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$field.name: c
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$field.name: d
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$field.name: 1
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$field.name: 0
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$field.name: _VAnonStruct1{
i: 100
}
ok

View File

@ -0,0 +1,21 @@
struct Foo {
a string
b ?string
c int
d ?int
e struct {
i ?int
}
}
fn run[T](val T) {
$for field in T.fields {
dump(val.$(field.name))
}
println('ok')
}
fn test_main() {
foo := Foo{'c', 'd', 1, 0, struct {100}}
run(foo)
}

View File

@ -8,6 +8,15 @@ import v.ast
import v.util
import v.pref
fn (mut g Gen) get_comptime_selector_var_type(node ast.ComptimeSelector) (ast.StructField, string) {
field_name := g.comptime_for_field_value.name
left_sym := g.table.sym(g.unwrap_generic(node.left_type))
field := g.table.find_field_with_embeds(left_sym, field_name) or {
g.error('`${node.left}` has no field named `${field_name}`', node.left.pos())
}
return field, field_name
}
fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
g.expr(node.left)
if node.left_type.is_ptr() {
@ -20,11 +29,7 @@ fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
if node.field_expr.expr is ast.Ident {
if node.field_expr.expr.name == g.comptime_for_field_var
&& node.field_expr.field_name == 'name' {
field_name := g.comptime_for_field_value.name
left_sym := g.table.sym(g.unwrap_generic(node.left_type))
_ := g.table.find_field_with_embeds(left_sym, field_name) or {
g.error('`${node.left}` has no field named `${field_name}`', node.left.pos())
}
_, field_name := g.get_comptime_selector_var_type(node)
g.write(c_name(field_name))
return
}

View File

@ -13,17 +13,35 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
return
}
mut name := node.cname
mut expr_type := node.expr_type
// var.${field.name}
if node.expr is ast.ComptimeSelector {
selector := node.expr as ast.ComptimeSelector
if selector.field_expr is ast.SelectorExpr {
selector_expr := selector.field_expr as ast.SelectorExpr
if selector_expr.expr is ast.Ident {
ident_expr := selector_expr.expr
if ident_expr.name == g.comptime_for_field_var && selector_expr.field_name == 'name' {
field, _ := g.get_comptime_selector_var_type(selector)
name = g.typ(g.unwrap_generic(field.typ.clear_flag(.shared_f).clear_flag(.optional).clear_flag(.result)))
expr_type = field.typ
}
}
}
}
if g.table.sym(node.expr_type).language == .c {
name = name[3..]
}
dump_fn_name := '_v_dump_expr_${name}' +
(if node.expr_type.is_ptr() { '_ptr'.repeat(node.expr_type.nr_muls()) } else { '' })
(if expr_type.is_ptr() { '_ptr'.repeat(expr_type.nr_muls()) } else { '' })
g.write(' ${dump_fn_name}(${ctoslit(fpath)}, ${line}, ${sexpr}, ')
if node.expr_type.has_flag(.shared_f) {
if expr_type.has_flag(.shared_f) {
g.write('&')
g.expr(node.expr)
g.write('->val')
} else if node.expr_type.has_flag(.optional) || node.expr_type.has_flag(.result) {
} else if expr_type.has_flag(.optional) || expr_type.has_flag(.result) {
old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = true
g.write('(*(${name}*)')