Skip to content

Commit d26f692

Browse files
committed
Fix allocation of named function variable
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 65ae77d commit d26f692

File tree

11 files changed

+115
-75
lines changed

11 files changed

+115
-75
lines changed

pkg/codegen/codegen.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -441,26 +441,39 @@ func (g *Generator) generateFn(fn *runtime.Fn) string {
441441
astNode := fn.ASTNode()
442442
fnNode := astNode.Sub.(*ast.FnNode)
443443

444-
// Allocate a variable for the function
445-
var fnVar string
446-
if fnNode.Local == nil {
447-
fnVar = g.allocateTempVar()
448-
} else {
449-
// If there's a local binding, use that name
450-
localNode := fnNode.Local.Sub.(*ast.BindingNode)
451-
fnVar = g.allocateLocal(localNode.Name.Name())
452-
}
444+
// Allocate a variable to return the function
445+
fnVar := g.allocateTempVar()
446+
447+
// declare it now to make sure it's in the scope of the caller
448+
// we may add a nested scope to declare the function in to keep a
449+
// scoped variable for the function itelf, if the function is named
450+
g.writef("var %s lang.FnFunc\n", fnVar)
453451

454452
// Push a new scope for the function definition
455453
g.pushVarScope()
456454
defer g.popVarScope()
457455

456+
if fnNode.Local != nil {
457+
// If there's a local binding, use that name
458+
localNode := fnNode.Local.Sub.(*ast.BindingNode)
459+
if fnName := localNode.Name.Name(); fnName != "" {
460+
g.writef("{ // function %s\n", fnName)
461+
defer g.writef("}\n")
462+
463+
namedFnVar := g.allocateLocal(fnName)
464+
defer func() {
465+
g.writef("%s := %s\n", namedFnVar, fnVar)
466+
g.writeAssign("_", namedFnVar) // Prevent unused variable warning
467+
}()
468+
}
469+
}
470+
458471
// If there's only one method and it's not variadic, generate a simple function
459472
if len(fnNode.Methods) == 1 && !fnNode.IsVariadic {
460473
method := fnNode.Methods[0]
461474
methodNode := method.Sub.(*ast.FnMethodNode)
462475

463-
g.writef("%s := lang.NewFnFunc(func(args ...any) any {\n", fnVar)
476+
g.writef("%s = lang.NewFnFunc(func(args ...any) any {\n", fnVar)
464477

465478
g.addImport("fmt") // Import fmt for error formatting
466479
// Check arity
@@ -474,7 +487,7 @@ func (g *Generator) generateFn(fn *runtime.Fn) string {
474487
g.writef("})\n")
475488
} else {
476489
// Multiple arities or variadic - need to dispatch
477-
g.writef("%s := lang.NewFnFunc(func(args ...any) any {\n", fnVar)
490+
g.writef("%s = lang.NewFnFunc(func(args ...any) any {\n", fnVar)
478491
g.writef(" switch len(args) {\n")
479492

480493
// Generate cases for fixed arity methods

pkg/codegen/testdata/codegen/test/fn_recur.go

Lines changed: 51 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/loop_simple.go

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/maybe_class.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/quote_simple.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/the_var.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/throw_simple.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/codegen/testdata/codegen/test/try_advanced.go

Lines changed: 10 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)