diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index f881f48761..2b4d9a3349 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -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 } diff --git a/vlib/v/checker/tests/comptime_dump_fields_var_test.out b/vlib/v/checker/tests/comptime_dump_fields_var_test.out new file mode 100644 index 0000000000..ce67fd3b2c --- /dev/null +++ b/vlib/v/checker/tests/comptime_dump_fields_var_test.out @@ -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 \ No newline at end of file diff --git a/vlib/v/checker/tests/comptime_dump_fields_var_test.vv b/vlib/v/checker/tests/comptime_dump_fields_var_test.vv new file mode 100644 index 0000000000..a1ae524cba --- /dev/null +++ b/vlib/v/checker/tests/comptime_dump_fields_var_test.vv @@ -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) +} diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 71ba57d60d..ae770a91fe 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -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 } diff --git a/vlib/v/gen/c/dumpexpr.v b/vlib/v/gen/c/dumpexpr.v index d7030c228f..2852a99f7d 100644 --- a/vlib/v/gen/c/dumpexpr.v +++ b/vlib/v/gen/c/dumpexpr.v @@ -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}*)')