From 6e670ec90818c1aea158b9d73f74cbc58f97da93 Mon Sep 17 00:00:00 2001 From: ChAoS_UnItY Date: Tue, 7 Mar 2023 14:52:40 +0800 Subject: [PATCH] v: support interface field compile time reflection (#17503) --- vlib/v/checker/comptime.v | 19 +++++++++++++++--- vlib/v/gen/c/comptime.v | 20 +++++++++++++++---- .../c/testdata/comptime_interface_field.out | 2 ++ .../c/testdata/comptime_interface_field.vv | 10 ++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 vlib/v/gen/c/testdata/comptime_interface_field.out create mode 100644 vlib/v/gen/c/testdata/comptime_interface_field.vv diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index f22902b17..f8709f1f1 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -180,10 +180,23 @@ fn (mut c Checker) comptime_for(node ast.ComptimeFor) { c.error('unknown type `${sym.name}`', node.typ_pos) } if node.kind == .fields { - if sym.kind == .struct_ { - sym_info := sym.info as ast.Struct + if sym.kind in [.struct_, .interface_] { + mut fields := []ast.StructField{} + match sym.info { + ast.Struct { + fields = sym.info.fields.clone() + } + ast.Interface { + fields = sym.info.fields.clone() + } + else { + c.error('comptime field lookup supports only structs and interfaces currently, and ${sym.name} is neither', + node.typ_pos) + return + } + } c.inside_comptime_for_field = true - for field in sym_info.fields { + for field in fields { c.comptime_for_field_value = field c.comptime_for_field_var = node.val_var c.comptime_fields_type[node.val_var] = node.typ diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 8f462df1b..bb5b82710 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -763,12 +763,24 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { } } else if node.kind == .fields { // TODO add fields - if sym.kind == .struct_ { - sym_info := sym.info as ast.Struct - if sym_info.fields.len > 0 { + if sym.kind in [.struct_, .interface_] { + fields := match sym.info { + ast.Struct { + sym.info.fields + } + ast.Interface { + sym.info.fields + } + else { + g.error('comptime field lookup is supported only for structs and interfaces, and ${sym.name} is neither', + node.pos) + []ast.StructField{len: 0} + } + } + if fields.len > 0 { g.writeln('\tFieldData ${node.val_var} = {0};') } - for field in sym_info.fields { + for field in fields { g.push_existing_comptime_values() g.inside_comptime_for_field = true g.comptime_for_field_var = node.val_var diff --git a/vlib/v/gen/c/testdata/comptime_interface_field.out b/vlib/v/gen/c/testdata/comptime_interface_field.out new file mode 100644 index 000000000..759a31c98 --- /dev/null +++ b/vlib/v/gen/c/testdata/comptime_interface_field.out @@ -0,0 +1,2 @@ +name +age diff --git a/vlib/v/gen/c/testdata/comptime_interface_field.vv b/vlib/v/gen/c/testdata/comptime_interface_field.vv new file mode 100644 index 000000000..dfe85ab98 --- /dev/null +++ b/vlib/v/gen/c/testdata/comptime_interface_field.vv @@ -0,0 +1,10 @@ +interface User { + name string + age int +} + +fn main() { + $for field in User.fields { + println(field.name) + } +} -- 2.39.5