@@ -81,11 +81,9 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
8181 g .writef (" ns := lang.FindOrCreateNamespace(lang.NewSymbol(\" %s\" ))\n " , ns .Name ().String ())
8282 g .writef (" _ = ns\n " )
8383
84- // TODO: Generate code to populate the namespace
85- // This will involve:
86- // 1. Iterating through ns.Mappings()
87- // 2. Generating Go code for each var
88- // 3. Creating initialization functions
84+ // 1. Iterate through ns.Mappings()
85+ // 2. Generate Go code for each var
86+ // 3. Create initialization functions
8987 for seq := mappings .Seq (); seq != nil ; seq = seq .Next () {
9088 entry := seq .First ()
9189 name , ok := lang .First (entry ).(* lang.Symbol )
@@ -346,7 +344,6 @@ func (g *Generator) generateFnMethod(methodNode *ast.FnMethodNode, argsVar strin
346344
347345// generateASTNode generates code for an AST node
348346func (g * Generator ) generateASTNode (node * ast.Node ) string {
349- fmt .Printf ("Generating code for AST node: %T %+v\n " , node .Sub , node .Sub )
350347 switch node .Op {
351348 case ast .OpConst :
352349 constNode := node .Sub .(* ast.ConstNode )
@@ -363,42 +360,72 @@ func (g *Generator) generateASTNode(node *ast.Node) string {
363360 return g .generateIf (node )
364361 case ast .OpInvoke :
365362 return g .generateInvoke (node )
363+ case ast .OpVar :
364+ return g .generateVarDeref (node )
365+ case ast .OpRecur :
366+ return g .generateRecur (node )
366367 default :
368+ fmt .Printf ("Generating code for AST node: %T %+v\n " , node .Sub , node .Sub )
367369 panic (fmt .Sprintf ("unsupported AST node type %T" , node .Sub ))
368370 }
369371}
370372
373+ // generateVarDeref generates code for a Var dereference
374+ func (g * Generator ) generateVarDeref (node * ast.Node ) string {
375+ varNode := node .Sub .(* ast.VarNode )
376+
377+ varNamespace := varNode .Var .Namespace ()
378+ varSymbol := varNode .Var .Symbol ()
379+
380+ // generate code to look up the var in the namespace
381+ nsVar := g .allocateVar ("ns" )
382+ g .writef ("%s := lang.FindNamespace(lang.NewSymbol(\" %s\" ))\n " , nsVar , varNamespace .Name ())
383+ // look up the var in the namespace
384+ varId := g .allocateVar ("varId" )
385+ g .writef ("%s := %s.FindInternedVar(lang.NewSymbol(\" %s\" ))\n " , varId , nsVar , varSymbol .Name ())
386+
387+ // if macro, panic with 'can't take value of macro: %v'
388+ g .writef ("if %s.IsMacro() {\n " , varId )
389+ g .writef (" panic(lang.NewIllegalArgumentError(\" can't take value of macro: %v\" ))\n " , varId )
390+ g .writef ("}\n " )
391+ // else, return Get()
392+ resultId := g .allocateVar ("result" )
393+ g .writef ("%s := %s.Get()\n " , resultId , varId )
394+
395+ return resultId
396+ }
397+
371398// generateInvoke generates code for an Invoke node
372399func (g * Generator ) generateInvoke (node * ast.Node ) string {
373400 invokeNode := node .Sub .(* ast.InvokeNode )
374-
401+
375402 // Generate the function expression
376403 fnExpr := g .generateASTNode (invokeNode .Fn )
377-
404+
378405 // Generate the arguments
379406 var argExprs []string
380407 for _ , arg := range invokeNode .Args {
381408 argExprs = append (argExprs , g .generateASTNode (arg ))
382409 }
383-
410+
384411 // Allocate a result variable for the invocation
385412 resultVar := g .allocateVar ("invokeResult" )
386-
413+
387414 // Emit the invocation
388415 if len (argExprs ) == 0 {
389- g .writef ("%s := lang.Invoke (%s)\n " , resultVar , fnExpr )
416+ g .writef ("%s := lang.Apply (%s, nil )\n " , resultVar , fnExpr )
390417 } else {
391- g .writef ("%s := lang.Invoke (%s, %s )\n " , resultVar , fnExpr , strings .Join (argExprs , ", " ))
418+ g .writef ("%s := lang.Apply (%s, []any{%s} )\n " , resultVar , fnExpr , strings .Join (argExprs , ", " ))
392419 }
393-
420+
394421 // Return the result variable
395422 return resultVar
396423}
397424
398425// generateDo generates code for a Do node
399426func (g * Generator ) generateDo (node * ast.Node ) string {
400427 doNode := node .Sub .(* ast.DoNode )
401-
428+
402429 // Emit all statements except the last to g.w
403430 for _ , stmt := range doNode .Statements {
404431 if stmt == nil {
@@ -407,7 +434,7 @@ func (g *Generator) generateDo(node *ast.Node) string {
407434 stmtResult := g .generateASTNode (stmt )
408435 g .writef ("_ = %s\n " , stmtResult ) // Discard intermediate results
409436 }
410-
437+
411438 // Return the final expression
412439 return g .generateASTNode (doNode .Ret )
413440}
@@ -418,7 +445,7 @@ func (g *Generator) generateIf(node *ast.Node) string {
418445
419446 // Allocate result variable
420447 resultVar := g .allocateVar ("ifResult" )
421-
448+
422449 // Emit the if statement to g.w
423450 g .writef ("var %s any\n " , resultVar )
424451 testExpr := g .generateASTNode (ifNode .Test )
@@ -433,7 +460,7 @@ func (g *Generator) generateIf(node *ast.Node) string {
433460 g .writef (" %s = nil\n " , resultVar )
434461 }
435462 g .writef ("}\n " )
436-
463+
437464 // Return the r-value
438465 return resultVar
439466}
@@ -510,8 +537,35 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
510537 g .writef ("%s := %s\n " , varName , initCode )
511538 }
512539
540+ resultId := g .allocateVar ("letResult" )
541+ if isLoop {
542+ g .writef ("var %s any\n " , resultId )
543+ g .writef ("for {\n " )
544+ }
545+
513546 // Return the body expression (r-value)
514- return g .generateASTNode (letNode .Body )
547+ result := g .generateASTNode (letNode .Body )
548+ if isLoop {
549+ g .writef (" %s = %s\n " , resultId , result )
550+ g .writef (" break\n " ) // Break out of the loop after the body
551+ g .writef ("}\n " )
552+ return resultId
553+ } else {
554+ return result
555+ }
556+ }
557+
558+ func (g * Generator ) generateRecur (node * ast.Node ) string {
559+ recurNode := node .Sub .(* ast.RecurNode )
560+
561+ exprs := recurNode .Exprs
562+ for _ , expr := range exprs {
563+ val , err := noRecurEnv .EvalAST (expr )
564+ if err != nil {
565+ return nil , err
566+ }
567+ vals = append (vals , val )
568+ }
515569}
516570
517571////////////////////////////////////////////////////////////////////////////////
0 commit comments