Skip to content

Commit c859148

Browse files
committed
Implement codegen for letfn
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent d909179 commit c859148

4 files changed

Lines changed: 732 additions & 256 deletions

File tree

pkg/runtime/codegen.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,8 +984,7 @@ func (g *Generator) generateASTNode(node *ast.Node) (res string) {
984984
case ast.OpDef:
985985
return g.generateDef(node)
986986
case ast.OpLetFn:
987-
fmt.Println("LetFn not yet implemented; returning nil")
988-
return "nil"
987+
return g.generateLetFn(node)
989988
case ast.OpGo:
990989
return g.generateGo(node)
991990
case ast.OpSetBang:
@@ -1294,6 +1293,42 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
12941293
return resultId
12951294
}
12961295

1296+
func (g *Generator) generateLetFn(node *ast.Node) string {
1297+
letFnNode := node.Sub.(*ast.LetFnNode)
1298+
1299+
resultId := g.allocateTempVar()
1300+
g.writef("var %s any\n", resultId)
1301+
1302+
// Push a new variable scope for the letfn bindings
1303+
g.writef("{ // letfn\n")
1304+
g.pushVarScope()
1305+
defer func() {
1306+
g.popVarScope()
1307+
g.writef("} // end letfn\n")
1308+
}()
1309+
1310+
// Emit bindings directly to g.w
1311+
for _, binding := range letFnNode.Bindings {
1312+
bindingNode := binding.Sub.(*ast.BindingNode)
1313+
name := bindingNode.Name
1314+
fn := bindingNode.Init
1315+
1316+
// Allocate a Go variable for the Clojure name
1317+
g.writef("// letfn binding \"%s\"\n", name)
1318+
varName := g.allocateLocal(name.Name())
1319+
// declare the variable now to allow for recursion
1320+
g.writef("var %s lang.FnFunc\n", varName)
1321+
fnVar := g.generateASTNode(fn)
1322+
g.writeAssign(varName, fnVar)
1323+
g.writeAssign("_", varName) // Prevent unused variable warning
1324+
}
1325+
1326+
// Return the body expression (r-value)
1327+
result := g.generateASTNode(letFnNode.Body)
1328+
g.writeAssign(resultId, result)
1329+
return resultId
1330+
}
1331+
12971332
func (g *Generator) generateRecur(node *ast.Node) string {
12981333
recurNode := node.Sub.(*ast.RecurNode)
12991334

0 commit comments

Comments
 (0)