Skip to content

Commit

Permalink
cgen: fix comptime for method with $method as inherited var (fix #1…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Oct 16, 2024
1 parent 1310781 commit 3e697fe
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 21 deletions.
11 changes: 11 additions & 0 deletions vlib/v/ast/scope.v
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ pub fn (s &Scope) has_inherited_vars() bool {
return false
}

pub fn (s &Scope) is_inherited_var(var_name string) bool {
for _, obj in s.objects {
if obj is Var {
if obj.is_inherited && obj.name == var_name {
return true
}
}
}
return false
}

pub fn (sc &Scope) show(depth int, max_depth int) string {
mut out := ''
mut indent := ''
Expand Down
2 changes: 2 additions & 0 deletions vlib/v/comptime/comptimeinfo.v
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ pub mut:
resolver IResolverType = DummyResolver{}
// symbol table resolver
table &ast.Table = unsafe { nil }
// loop id for loop distinction
comptime_loop_id int
// $for
inside_comptime_for bool
type_map map[string]ast.Type
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ mut:
defer_ifdef string
defer_profile_code string
defer_vars []string
closure_structs []string
str_types []StrType // types that need automatic str() generation
generated_str_fns []StrType // types that already have a str() function
str_fn_names shared []string // remove duplicate function names
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ fn (mut g Gen) push_new_comptime_info() {
comptime_for_method_var: g.comptime.comptime_for_method_var
comptime_for_method: g.comptime.comptime_for_method
comptime_for_method_ret_type: g.comptime.comptime_for_method_ret_type
comptime_loop_id: g.comptime.comptime_loop_id++
}
}

Expand Down
53 changes: 32 additions & 21 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,10 @@ fn (mut g Gen) c_fn_name(node &ast.FnDecl) string {
name = name.replace_each(c_fn_name_escape_seq)
}
}
if node.is_anon && g.comptime.comptime_for_method_var != ''
&& node.scope.is_inherited_var('method') {
name = '${name}_${g.comptime.comptime_loop_id}'
}
if node.language == .c {
name = util.no_dots(name)
} else {
Expand All @@ -571,6 +575,18 @@ fn (mut g Gen) c_fn_name(node &ast.FnDecl) string {

const closure_ctx = '_V_closure_ctx'

fn (mut g Gen) gen_closure_fn_name(node ast.AnonFn) string {
mut fn_name := node.decl.name
if node.decl.generic_names.len > 0 {
fn_name = g.generic_fn_name(g.cur_concrete_types, fn_name)
}
if node.inherited_vars.len > 0 && g.comptime.comptime_for_method_var != ''
&& node.inherited_vars.any(it.name == 'method') {
fn_name += '_${g.comptime.comptime_loop_id}'
}
return fn_name
}

fn (mut g Gen) closure_ctx(node ast.FnDecl) string {
mut fn_name := node.name
if node.generic_names.len > 0 {
Expand All @@ -581,12 +597,7 @@ fn (mut g Gen) closure_ctx(node ast.FnDecl) string {

fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
g.gen_anon_fn_decl(mut node)
mut fn_name := node.decl.name

if node.decl.generic_names.len > 0 {
fn_name = g.generic_fn_name(g.cur_concrete_types, fn_name)
}

fn_name := g.gen_closure_fn_name(node)
if !node.decl.scope.has_inherited_vars() {
g.write(fn_name)
return
Expand Down Expand Up @@ -652,10 +663,7 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
}

fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
mut fn_name := node.decl.name
if node.decl.generic_names.len > 0 {
fn_name = g.generic_fn_name(g.cur_concrete_types, fn_name)
}
mut fn_name := g.gen_closure_fn_name(node)
if node.has_gen[fn_name] {
return
}
Expand All @@ -664,19 +672,22 @@ fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
builder.writeln('/*F*/')
if node.inherited_vars.len > 0 {
ctx_struct := g.closure_ctx(node.decl)
builder.writeln('${ctx_struct} {')
for var in node.inherited_vars {
var_sym := g.table.sym(var.typ)
if var_sym.info is ast.FnType {
sig := g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
c_name(var.name))
builder.writeln('\t' + sig + ';')
} else {
styp := g.typ(var.typ)
builder.writeln('\t${styp} ${c_name(var.name)};')
if ctx_struct !in g.closure_structs {
g.closure_structs << ctx_struct
builder.writeln('${ctx_struct} {')
for var in node.inherited_vars {
var_sym := g.table.sym(var.typ)
if var_sym.info is ast.FnType {
sig := g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
c_name(var.name))
builder.writeln('\t' + sig + ';')
} else {
styp := g.typ(var.typ)
builder.writeln('\t${styp} ${c_name(var.name)};')
}
}
builder.writeln('};\n')
}
builder.writeln('};\n')
}
pos := g.out.len
was_anon_fn := g.anon_fn
Expand Down
22 changes: 22 additions & 0 deletions vlib/v/tests/comptime/comptime_call_method_closure_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
struct Foo {}

fn (f Foo) foo() string {
return 'foo'
}

fn (f Foo) bar() string {
return 'bar'
}

fn test_main() {
f := Foo{}
mut results := []string{}
$for method in Foo.methods {
x := fn [method, f] () string {
return f.$method()
}
results << x()
}
assert results[0] == 'foo'
assert results[1] == 'bar'
}

0 comments on commit 3e697fe

Please sign in to comment.