Skip to content

Commit efbe959

Browse files
committed
UUID fixes, codegen fixes
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent dc9cb21 commit efbe959

File tree

21 files changed

+87086
-142
lines changed

21 files changed

+87086
-142
lines changed

pkg/codegen/codegen.go

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
9191

9292
// add lang import
9393
g.addImport("github.com/glojurelang/glojure/pkg/lang")
94+
g.addImport("fmt") // for error formatting
95+
g.writef("// reference fmt to avoid unused import error\n")
96+
g.writef("_ = fmt.Printf\n")
9497

9598
g.writef(" ns := lang.FindOrCreateNamespace(lang.NewSymbol(%#v))\n", ns.Name().String())
9699
g.writef(" _ = ns\n")
@@ -157,9 +160,14 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
157160

158161
for _, lifted := range sortedLifted {
159162
// Generate the value - this will write any needed initialization
163+
g.writef("var %s any\n", lifted.varName)
164+
g.pushVarScope()
165+
g.writef("{\n")
160166
valueCode := g.generateValue(lifted.value)
161167
// Declare the lifted variable with the final value
162-
g.writef(" var %s = %s\n", lifted.varName, valueCode)
168+
g.writef("%s = %s\n", lifted.varName, valueCode)
169+
g.writef("}\n")
170+
g.popVarScope()
163171
}
164172

165173
// Write the lifted values code to init
@@ -180,7 +188,7 @@ func (g *Generator) Generate(ns *lang.Namespace) error {
180188
if err != nil {
181189
// If formatting fails, write the unformatted code with the error
182190
g.originalWriter.Write(sourceBytes)
183-
return fmt.Errorf("formatting failed: %w\n\nGenerated code:\n%s", err, string(sourceBytes))
191+
return fmt.Errorf("formatting failed: %w\n", err)
184192
}
185193

186194
// Write formatted code to the original writer
@@ -541,12 +549,14 @@ func (g *Generator) generateSetValue(s lang.IPersistentSet) string {
541549
if idx > 0 {
542550
buf.WriteString(", ")
543551
}
552+
idx++
544553
element := seq.First()
545554
elementVar := g.generateValue(element)
546555
buf.WriteString(elementVar)
547556
}
548557

549558
buf.WriteString(")")
559+
550560
return buf.String()
551561
}
552562

@@ -593,7 +603,6 @@ func (g *Generator) generateFn(fn *runtime.Fn) string {
593603

594604
g.writef("%s = lang.NewFnFunc(func(args ...any) any {\n", fnVar)
595605

596-
g.addImport("fmt") // Import fmt for error formatting
597606
// Check arity
598607
g.writef(" if len(args) != %d {\n", methodNode.FixedArity)
599608
g.writef(" panic(lang.NewIllegalArgumentError(\"wrong number of arguments (\" + fmt.Sprint(len(args)) + \")\"))\n")
@@ -667,6 +676,7 @@ func (g *Generator) generateFnMethod(methodNode *ast.FnMethodNode, argsVar strin
667676
if i < methodNode.FixedArity {
668677
// Regular parameter
669678
g.writef("%s := %s[%d]\n", paramVar, argsVar, i)
679+
g.writeAssign("_", paramVar) // Prevent unused variable warning
670680
paramVars[i] = paramVar
671681
} else {
672682
// Variadic parameter - collect rest args
@@ -869,8 +879,15 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
869879
letNode := node.Sub.(*ast.LetNode)
870880

871881
// Push a new variable scope for the let bindings
882+
resultId := g.allocateTempVar()
883+
g.writef("var %s any\n", resultId)
884+
885+
g.writef("{ // let\n")
872886
g.pushVarScope()
873-
defer g.popVarScope()
887+
defer func() {
888+
g.popVarScope()
889+
g.writef("} // end let\n")
890+
}()
874891

875892
// Collect binding variable names for recur context if this is a loop
876893
var bindingVars []string
@@ -885,10 +902,11 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
885902
init := bindingNode.Init
886903

887904
// Allocate a Go variable for the Clojure name
888-
varName := g.allocateLocal(name)
905+
g.writef("// let binding \"%s\"\n", name)
889906

890907
// Generate initialization code
891908
initCode := g.generateASTNode(init)
909+
varName := g.allocateLocal(name)
892910
g.writef("var %s any = %s\n", varName, initCode)
893911
g.writeAssign("_", varName) // Prevent unused variable warning
894912

@@ -898,13 +916,11 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
898916
}
899917
}
900918

901-
resultId := g.allocateTempVar()
902919
if isLoop {
903920
// Push recur context for this loop
904921
g.pushRecurContext(letNode.LoopID, bindingVars, false)
905922
defer g.popRecurContext()
906923

907-
g.writef("var %s any\n", resultId)
908924
g.writef("for {\n")
909925
}
910926

@@ -914,10 +930,10 @@ func (g *Generator) generateLet(node *ast.Node, isLoop bool) string {
914930
g.writeAssign(resultId, result)
915931
g.writef(" break\n") // Break out of the loop after the body
916932
g.writef("}\n")
917-
return resultId
918933
} else {
919-
return result
934+
g.writeAssign(resultId, result)
920935
}
936+
return resultId
921937
}
922938

923939
func (g *Generator) generateRecur(node *ast.Node) string {
@@ -1135,10 +1151,37 @@ func (g *Generator) generateSet(node *ast.Node) string {
11351151
return setId
11361152
}
11371153

1154+
var (
1155+
// TODO: fix all these invalid imports
1156+
expectedInvalidImports = map[string]bool{
1157+
"ExceptionInfo": true,
1158+
"LinkedBlockingQueue": true,
1159+
"glojure.lang.LineNumberingPushbackReader": true,
1160+
"glojure.lang": true,
1161+
"java.io.InputStreamReader": true,
1162+
"java.io.StringReader": true,
1163+
"java.util.concurrent.CountDownLatch": true,
1164+
"java.util.concurrent": true,
1165+
}
1166+
)
1167+
11381168
func (g *Generator) generateMaybeClass(node *ast.Node) string {
11391169
sym := node.Sub.(*ast.MaybeClassNode).Class.(*lang.Symbol)
11401170
pkg := sym.FullName()
11411171

1172+
v, ok := pkgmap.Get(sym.FullName())
1173+
// special-case for reflect.Types
1174+
//
1175+
// NB: we're allowing references to exports of packages that aren't in the package map
1176+
// This implies a difference in behavior, where the interpreter would fail while
1177+
// the compiled code would succeed, because the import will cause the go toolchain
1178+
// to pull in the package.
1179+
if ok {
1180+
if t, ok := v.(reflect.Type); ok {
1181+
return g.getTypeString(t)
1182+
}
1183+
}
1184+
11421185
// find last dot in the package name
11431186
dotIndex := strings.LastIndex(pkg, ".")
11441187
if dotIndex == -1 {
@@ -1152,6 +1195,12 @@ func (g *Generator) generateMaybeClass(node *ast.Node) string {
11521195
exportedName := pkg[dotIndex+1:]
11531196

11541197
packageName := pkgmap.UnmungePkg(mungedPkgName)
1198+
1199+
if _, ok := expectedInvalidImports[packageName]; ok {
1200+
// TODO: fix all these invalid imports
1201+
fmt.Println("Warning: skipping invalid import:", packageName)
1202+
return "nil"
1203+
}
11551204
alias := g.addImportWithAlias(packageName)
11561205

11571206
return alias + "." + exportedName
@@ -1269,6 +1318,10 @@ func (g *Generator) addImport(pkg string) {
12691318
}
12701319

12711320
func (g *Generator) addImportWithAlias(pkg string) string {
1321+
if pkg == "glojure.lang.LineNumberingPushbackReader" {
1322+
panic("glojure.lang.LineNumberingPushbackReader is not a valid Go package")
1323+
}
1324+
12721325
// Check if the package is already imported
12731326
if alias, ok := g.imports[pkg]; ok {
12741327
return alias // Return existing alias

pkg/codegen/testdata/codegen/test/const_keyword.go

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

pkg/codegen/testdata/codegen/test/const_number.go

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

pkg/codegen/testdata/codegen/test/const_string.go

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

0 commit comments

Comments
 (0)