Skip to content

Commit 5e35f1e

Browse files
committed
Add name binding for named fns
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 2b39e6a commit 5e35f1e

File tree

4 files changed

+110
-9
lines changed

4 files changed

+110
-9
lines changed

pkg/codegen/codegen.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,14 @@ func (g *Generator) generateFn(fn *runtime.Fn) string {
266266
fnNode := astNode.Sub.(*ast.FnNode)
267267

268268
// Allocate a variable for the function
269-
fnVar := g.allocateTempVar()
269+
var fnVar string
270+
if fnNode.Local == nil {
271+
fnVar = g.allocateTempVar()
272+
} else {
273+
// If there's a local binding, use that name
274+
localNode := fnNode.Local.Sub.(*ast.BindingNode)
275+
fnVar = g.allocateLocal(localNode.Name.Name())
276+
}
270277

271278
// Push a new scope for the function definition
272279
g.pushVarScope()
@@ -385,7 +392,6 @@ func (g *Generator) generateASTNode(node *ast.Node) string {
385392
// OpMap
386393
// OpLetFn
387394
// OpGo
388-
// OpHostInterop
389395
// OpMaybeHostForm
390396
// OpCase
391397
// OpTheVar
@@ -433,6 +439,8 @@ func (g *Generator) generateASTNode(node *ast.Node) string {
433439
return g.generateFn(runtime.NewFn(node, nil))
434440
case ast.OpHostCall:
435441
return g.generateHostCall(node)
442+
case ast.OpHostInterop:
443+
return g.generateHostInterop(node)
436444
default:
437445
fmt.Printf("Generating code for AST node: %T %+v\n", node.Sub, node.Sub)
438446
panic(fmt.Sprintf("unsupported AST node type %T", node.Sub))
@@ -615,7 +623,7 @@ func (g *Generator) generateRecur(node *ast.Node) string {
615623
// This prevents issues with bindings that reference each other
616624
tempVars := make([]string, len(recurNode.Exprs))
617625
for i, expr := range recurNode.Exprs {
618-
tempVar := g.allocateLocal(fmt.Sprintf("recurTemp%d", i))
626+
tempVar := g.allocateTempVar()
619627
tempVars[i] = tempVar
620628
exprCode := g.generateASTNode(expr)
621629
g.writef("var %s any = %s\n", tempVar, exprCode)
@@ -852,6 +860,32 @@ func (g *Generator) generateHostCall(node *ast.Node) string {
852860
return resultId
853861
}
854862

863+
func (g *Generator) generateHostInterop(node *ast.Node) string {
864+
hostInteropNode := node.Sub.(*ast.HostInteropNode)
865+
866+
tgtId := g.generateASTNode(hostInteropNode.Target)
867+
868+
mOrF := hostInteropNode.MOrF.Name()
869+
mOrFId := g.allocateTempVar()
870+
g.writef("%s, ok := lang.FieldOrMethod(%s, %q)\n", mOrFId, tgtId, mOrF)
871+
g.writef("if !ok {\n")
872+
g.writef(" panic(lang.NewIllegalArgumentError(fmt.Sprintf(\"no such field or method on %%T: %%s\", %s, %q)))\n", tgtId, mOrF)
873+
g.writef("}\n")
874+
875+
g.addImport("reflect")
876+
877+
resultId := g.allocateTempVar()
878+
g.writef("var %s any\n", resultId)
879+
g.writef("switch reflect.TypeOf(%s).Kind() {\n", mOrFId)
880+
g.writef("case reflect.Func:\n")
881+
g.writef(" %s = lang.Apply(%s, nil)\n", resultId, mOrFId)
882+
g.writef("default:\n")
883+
g.writef(" %s = %s\n", resultId, mOrFId)
884+
g.writef("}\n")
885+
886+
return resultId
887+
}
888+
855889
////////////////////////////////////////////////////////////////////////////////
856890

857891
func (g *Generator) addImport(pkg string) {

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

Lines changed: 1 addition & 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.glj

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
(catch go/any e
1414
e)))) ; should be the exception, not "outer"
1515

16+
(defn catch-binding-scope-2 []
17+
(let [e "outer"]
18+
(try
19+
(throw "test")
20+
(catch go/any e
21+
e))
22+
e)) ; should be "outer", not the exception
23+
1624
(defn finally-with-return []
1725
(try
1826
42
@@ -30,6 +38,11 @@
3038
nil
3139
(throw "catch-binding-scope failed"))
3240

41+
;; Test that catch binding does not affect outer scope
42+
(if (= (catch-binding-scope-2) "outer")
43+
nil
44+
(throw "catch-binding-scope-2 failed"))
45+
3346
;; Test that finally doesn't affect return value
3447
(if (= (finally-with-return) 42)
3548
nil

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

Lines changed: 59 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)