Skip to content

Commit 9e97862

Browse files
committed
Support for maybe-class (package export references)
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 00b9514 commit 9e97862

9 files changed

Lines changed: 94 additions & 12 deletions

File tree

pkg/codegen/codegen.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/glojurelang/glojure/pkg/ast"
1111
"github.com/glojurelang/glojure/pkg/lang"
12+
"github.com/glojurelang/glojure/pkg/pkgmap"
1213
"github.com/glojurelang/glojure/pkg/runtime"
1314
)
1415

@@ -35,7 +36,7 @@ type Generator struct {
3536
varScopes []varScope // stack of variable scopes
3637
recurStack []recurContext // stack of recur contexts for nested loops
3738

38-
imports map[string]bool // set of imported packages to avoid duplicates
39+
imports map[string]string // set of imported packages with their aliases
3940
}
4041

4142
// New creates a new code generator
@@ -45,7 +46,7 @@ func New(w io.Writer) *Generator {
4546
w: w,
4647
varScopes: []varScope{{nextNum: 0, names: make(map[string]string)}},
4748
recurStack: []recurContext{},
48-
imports: make(map[string]bool),
49+
imports: make(map[string]string),
4950
}
5051
}
5152

@@ -111,6 +112,7 @@ func (g *Generator) generateVar(nsVariableName string, name *lang.Symbol, vr *la
111112
g.pushVarScope()
112113
defer g.popVarScope()
113114

115+
fmt.Printf("Generating var: %s\n", name.String())
114116
g.writef("// %s\n", name.String())
115117
g.writef("{\n")
116118
defer g.writef("}\n")
@@ -151,6 +153,9 @@ func (g *Generator) generateValue(value any) string {
151153
return g.generateMapValue(v)
152154
case *lang.Vector:
153155
return g.generateVectorValue(v)
156+
case *lang.SubVector:
157+
// XXX TODO: handle sub-vectors
158+
return fmt.Sprintf("%#v", "subvector not implemented yet")
154159
case lang.Keyword:
155160
if ns := v.Namespace(); ns != "" {
156161
return fmt.Sprintf("lang.NewKeyword(\"%s/%s\")", ns, v.Name())
@@ -341,7 +346,6 @@ func (g *Generator) generateASTNode(node *ast.Node) string {
341346
switch node.Op {
342347
// OpDef
343348
// OpSetBang
344-
// OpMaybeClass
345349
// OpFn
346350
// OpMap
347351
// OpSet
@@ -387,6 +391,8 @@ func (g *Generator) generateASTNode(node *ast.Node) string {
387391
return g.generateGoBuiltin(node)
388392
case ast.OpWithMeta:
389393
return g.generateWithMeta(node)
394+
case ast.OpMaybeClass:
395+
return g.generateMaybeClass(node)
390396
default:
391397
fmt.Printf("Generating code for AST node: %T %+v\n", node.Sub, node.Sub)
392398
panic(fmt.Sprintf("unsupported AST node type %T", node.Sub))
@@ -797,10 +803,44 @@ func (g *Generator) generateMap(node *ast.Node) string {
797803
return mapId
798804
}
799805

806+
func (g *Generator) generateMaybeClass(node *ast.Node) string {
807+
sym := node.Sub.(*ast.MaybeClassNode).Class.(*lang.Symbol)
808+
pkg := sym.FullName()
809+
810+
// find last dot in the package name
811+
dotIndex := strings.LastIndex(pkg, ".")
812+
if dotIndex == -1 {
813+
panic(fmt.Sprintf("invalid package reference: %s", pkg))
814+
}
815+
mungedPkgName := pkg[:dotIndex]
816+
exportedName := pkg[dotIndex+1:]
817+
818+
packageName := pkgmap.UnmungePkg(mungedPkgName)
819+
alias := g.addImportWithAlias(packageName)
820+
821+
return alias + "." + exportedName
822+
}
823+
800824
////////////////////////////////////////////////////////////////////////////////
801825

802826
func (g *Generator) addImport(pkg string) {
803-
g.imports[pkg] = true
827+
parts := strings.Split(pkg, "/")
828+
alias := parts[len(parts)-1]
829+
g.imports[pkg] = alias
830+
}
831+
832+
func (g *Generator) addImportWithAlias(pkg string) string {
833+
// Check if the package is already imported
834+
if alias, ok := g.imports[pkg]; ok {
835+
return alias // Return existing alias
836+
}
837+
// Generate a new alias based on the last part of the package name
838+
parts := strings.Split(pkg, "/")
839+
// Use the last part of the package name and current import count
840+
alias := fmt.Sprintf("%s%d", parts[len(parts)-1], len(g.imports))
841+
g.imports[pkg] = alias // Store the alias for this package
842+
843+
return alias
804844
}
805845

806846
func (g *Generator) header() string {
@@ -812,8 +852,8 @@ import (
812852
"github.com/glojurelang/glojure/pkg/lang"
813853
`
814854

815-
for pkg := range g.imports {
816-
header += fmt.Sprintf(" \"%s\"\n", pkg)
855+
for pkg, alias := range g.imports {
856+
header += fmt.Sprintf(" %s \"%s\"\n", alias, pkg)
817857
}
818858

819859
header += ")\n"

pkg/codegen/codegengotest/codegengo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ func TestGeneratedGo(t *testing.T) {
7373

7474
expected := meta.ValAt(lang.NewKeyword("expected-output"))
7575
expectedThrow := meta.ValAt(lang.NewKeyword("expected-throw"))
76-
fmt.Println("META:", meta)
7776
if lang.IsNil(expected) && lang.IsNil(expectedThrow) {
7877
t.Fatalf("no :expected-output or :expected-throw metadata for %s/-main", nsName)
7978
}
@@ -93,6 +92,7 @@ func TestGeneratedGo(t *testing.T) {
9392
// Run -main and check the result
9493
result := mainVar.Invoke()
9594
if !lang.Equals(result, expected) {
95+
fmt.Printf("Result of %s/-main: %+v (%T)\n", nsName, result, result)
9696
t.Errorf("%s/-main returned %v, expected %v", nsName, result, expected)
9797
}
9898
})

pkg/codegen/testdata/codegen/test/loop_simple.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.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(ns codegen.test.maybe-class)
2+
3+
(defn ^{:expected-output ["1" "2" "3"]} -main []
4+
(vec (strings.Split "1,2,3" ",")))

pkg/codegen/testdata/codegen/test/maybe_class.go

Lines changed: 38 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/throw_simple.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.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_basic.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/with_meta.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.

0 commit comments

Comments
 (0)