Skip to content

Commit e09b70e

Browse files
committed
Fix closure codegen
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 997cd6b commit e09b70e

File tree

2 files changed

+110
-30
lines changed

2 files changed

+110
-30
lines changed

pkg/codegen/codegen.go

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,15 @@ func New(w io.Writer) *Generator {
7777

7878
// Generate takes a namespace and generates Go code that populates the same namespace
7979
func (g *Generator) Generate(ns *lang.Namespace) error {
80-
// TODO: Implement namespace-based code generation
81-
// For now, just stub it out
82-
var buf bytes.Buffer
83-
g.w = &buf
84-
85-
g.writef("func init() {\n")
80+
// Buffer for the vars and namespace setup
81+
var varsBuf bytes.Buffer
82+
g.w = &varsBuf
8683

8784
g.writef(" ns := lang.FindOrCreateNamespace(lang.NewSymbol(%#v))\n", ns.Name().String())
8885
g.writef(" _ = ns\n")
8986

9087
// 1. Iterate through ns.Mappings()
91-
// 2. Generate Go code for each var
92-
// 3. Create initialization functions
88+
// 2. Generate Go code for each var (this discovers lifted values)
9389
mappings := ns.Mappings()
9490
for seq := mappings.Seq(); seq != nil; seq = seq.Next() {
9591
entry := seq.First()
@@ -112,15 +108,13 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
112108
}
113109
}
114110

115-
g.writef("}\n")
116-
117-
// Prepare the final source
118-
sourceBytes := []byte(g.header()) // Package declaration and imports
111+
// Now construct the complete init function
112+
var initBuf bytes.Buffer
113+
initBuf.WriteString("func init() {\n")
119114

120-
// Generate lifted values block if any
115+
// Generate lifted values at the beginning of init() if any
121116
if len(g.liftedValues) > 0 {
122-
var liftedBuf bytes.Buffer
123-
liftedBuf.WriteString("\n// Closed-over values\nvar (\n")
117+
initBuf.WriteString(" // Closed-over values\n")
124118

125119
// Sort by variable name for deterministic output
126120
var sortedLifted []*liftedValue
@@ -131,17 +125,30 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
131125
return sortedLifted[i].varName < sortedLifted[j].varName
132126
})
133127

134-
// Generate each lifted value
128+
// Generate code for each lifted value
129+
// Use a temporary buffer to capture any initialization code
130+
var liftedBuf bytes.Buffer
131+
g.w = &liftedBuf
132+
135133
for _, lifted := range sortedLifted {
134+
// Generate the value - this will write any needed initialization
136135
valueCode := g.generateValue(lifted.value)
137-
liftedBuf.WriteString(fmt.Sprintf(" %s = %s\n",
138-
lifted.varName, valueCode))
136+
// Declare the lifted variable with the final value
137+
g.writef(" var %s = %s\n", lifted.varName, valueCode)
139138
}
140-
liftedBuf.WriteString(")\n\n")
141-
sourceBytes = append(sourceBytes, liftedBuf.Bytes()...)
139+
140+
// Write the lifted values code to init
141+
initBuf.Write(liftedBuf.Bytes())
142+
initBuf.WriteString("\n")
142143
}
143144

144-
sourceBytes = append(sourceBytes, buf.Bytes()...) // The init function
145+
// Add the vars code after the lifted values
146+
initBuf.Write(varsBuf.Bytes())
147+
initBuf.WriteString("}\n")
148+
149+
// Prepare the final source
150+
sourceBytes := []byte(g.header()) // Package declaration and imports
151+
sourceBytes = append(sourceBytes, initBuf.Bytes()...) // The complete init function
145152

146153
// Format the generated code
147154
formatted, err := format.Source(sourceBytes)

pkg/codegen/testdata/codegen/test/fn_closure.go

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

0 commit comments

Comments
 (0)