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:
parent
f762d46c84
commit
c3ee26f15f
@ -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
|
||||
}
|
||||
|
8
vlib/v/checker/tests/comptime_dump_fields_var_test.out
Normal file
8
vlib/v/checker/tests/comptime_dump_fields_var_test.out
Normal 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
|
21
vlib/v/checker/tests/comptime_dump_fields_var_test.vv
Normal file
21
vlib/v/checker/tests/comptime_dump_fields_var_test.vv
Normal 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)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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}*)')
|
||||
|
Loading…
Reference in New Issue
Block a user