Skip to content

Commit f1f46e9

Browse files
committed
Add codegen for def
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent a1a3bda commit f1f46e9

7 files changed

Lines changed: 161 additions & 37 deletions

File tree

pkg/runtime/codegen.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -982,16 +982,15 @@ func (g *Generator) generateFnMethod(methodNode *ast.FnMethodNode, argsVar strin
982982
func (g *Generator) generateASTNode(node *ast.Node) (res string) {
983983
switch node.Op {
984984
case ast.OpDef:
985-
fmt.Println("Def not yet implemented; returning nil")
986-
return "nil"
987-
case ast.OpSetBang:
988-
return g.generateSetBang(node)
985+
return g.generateDef(node)
989986
case ast.OpLetFn:
990987
fmt.Println("LetFn not yet implemented; returning nil")
991988
return "nil"
992989
case ast.OpGo:
993990
fmt.Println("Go not yet implemented; returning nil")
994991
return "nil"
992+
case ast.OpSetBang:
993+
return g.generateSetBang(node)
995994
case ast.OpCase:
996995
return g.generateCase(node)
997996
case ast.OpTry:
@@ -1050,6 +1049,31 @@ func (g *Generator) generateASTNode(node *ast.Node) (res string) {
10501049
}
10511050
}
10521051

1052+
func (g *Generator) generateDef(node *ast.Node) string {
1053+
defNode := node.Sub.(*ast.DefNode)
1054+
init := defNode.Init
1055+
vr := defNode.Var
1056+
meta := defNode.Meta
1057+
1058+
vrVar := g.allocVarVar(vr.Namespace().Name().String(), vr.Symbol().String())
1059+
if !lang.IsNil(meta) {
1060+
metaVar := g.generateASTNode(meta)
1061+
g.writef("%s.SetMeta(%s.(lang.IPersistentMap))\n", vrVar, metaVar)
1062+
// SetDynamic if dynamic kw true in meta
1063+
g.writef("if runtime.RT.BooleanCast(lang.Get(%s, lang.KWDynamic)) {\n", metaVar)
1064+
g.writef("\t%s.SetDynamic()\n", vrVar)
1065+
g.writef("}\n")
1066+
}
1067+
1068+
if lang.IsNil(init) {
1069+
return vrVar // No initialization
1070+
}
1071+
initVar := g.generateASTNode(init)
1072+
g.writef("%s.BindRoot(%s)\n", vrVar, initVar)
1073+
1074+
return vrVar
1075+
}
1076+
10531077
// generateVarDeref generates code for a Var dereference
10541078
func (g *Generator) generateVarDeref(node *ast.Node) string {
10551079
varNode := node.Sub.(*ast.VarNode)

pkg/runtime/environment.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,6 @@ func (env *environment) DefVar(sym *lang.Symbol, val interface{}) *lang.Var {
114114
return v
115115
}
116116

117-
func (env *environment) DefineMacro(name string, fn lang.IFn) {
118-
vr := env.DefVar(lang.NewSymbol(name), fn)
119-
vr.SetMacro()
120-
}
121-
122117
func (env *environment) lookup(sym *lang.Symbol) (res interface{}, ok bool) {
123118
v, ok := env.scope.lookup(sym)
124119
if ok {

pkg/runtime/evalast.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -125,34 +125,29 @@ func (env *environment) EvalAST(x interface{}) (ret interface{}, err error) {
125125
func (env *environment) EvalASTDef(n *ast.Node) (interface{}, error) {
126126
defNode := n.Sub.(*ast.DefNode)
127127
init := defNode.Init
128-
if lang.IsNil(init) {
129-
return defNode.Var, nil
130-
}
131-
132-
initVal, err := env.EvalAST(init)
133-
if err != nil {
134-
return nil, err
135-
}
136-
sym := defNode.Name
137-
138-
// evaluate symbol metadata if present
128+
vr := defNode.Var
139129
meta := defNode.Meta
140130
if !lang.IsNil(meta) {
141131
metaVal, err := env.EvalAST(meta)
142132
if err != nil {
143133
return nil, err
144134
}
145-
s, err := lang.WithMeta(sym, metaVal.(lang.IPersistentMap))
146-
if err != nil {
147-
return nil, err
135+
vr.SetMeta(metaVal.(lang.IPersistentMap))
136+
// set dynamic if :dynamic true in meta
137+
if RT.BooleanCast(lang.Get(vr.Meta(), lang.KWDynamic)) {
138+
vr.SetDynamic()
148139
}
149-
sym = s.(*lang.Symbol)
140+
}
141+
if lang.IsNil(init) {
142+
return defNode.Var, nil
150143
}
151144

152-
vr := env.DefVar(sym, initVal)
153-
if RT.BooleanCast(lang.Get(vr.Meta(), lang.KWDynamic)) {
154-
vr.SetDynamic()
145+
initVal, err := env.EvalAST(init)
146+
if err != nil {
147+
return nil, err
155148
}
149+
vr.BindRoot(initVal)
150+
156151
return vr, nil
157152
}
158153

pkg/runtime/testdata/codegen/test/core/load.go.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,7 @@ func LoadNS() {
12731273
sym_with_DASH_bindings := lang.NewSymbol("with-bindings")
12741274
sym_with_DASH_bindings_STAR_ := lang.NewSymbol("with-bindings*")
12751275
sym_with_DASH_in_DASH_str := lang.NewSymbol("with-in-str")
1276+
sym_with_DASH_init := lang.NewSymbol("with-init")
12761277
sym_with_DASH_loading_DASH_context := lang.NewSymbol("with-loading-context")
12771278
sym_with_DASH_local_DASH_vars := lang.NewSymbol("with-local-vars")
12781279
sym_with_DASH_meta := lang.NewSymbol("with-meta")
@@ -2790,6 +2791,8 @@ func LoadNS() {
27902791
var_glojure_DOT_core_with_DASH_bindings_STAR_ := lang.InternVarName(sym_glojure_DOT_core, sym_with_DASH_bindings_STAR_)
27912792
// var glojure.core/with-in-str
27922793
var_glojure_DOT_core_with_DASH_in_DASH_str := lang.InternVarName(sym_glojure_DOT_core, sym_with_DASH_in_DASH_str)
2794+
// var glojure.core/with-init
2795+
var_glojure_DOT_core_with_DASH_init := lang.InternVarName(sym_glojure_DOT_core, sym_with_DASH_init)
27932796
// var glojure.core/with-loading-context
27942797
var_glojure_DOT_core_with_DASH_loading_DASH_context := lang.InternVarName(sym_glojure_DOT_core, sym_with_DASH_loading_DASH_context)
27952798
// var glojure.core/with-local-vars
@@ -8053,6 +8056,14 @@ func LoadNS() {
80538056
var_glojure_DOT_core_when_DASH_not.SetMeta(tmp0.Meta().(lang.IPersistentMap))
80548057
}
80558058
}
8059+
// with-init
8060+
{
8061+
tmp0 := sym_with_DASH_init.WithMeta(lang.NewMap(kw_file, "codegen/test/def_simple.glj", kw_line, int(7), kw_column, int(8), kw_end_DASH_line, int(7), kw_end_DASH_column, int(16), kw_ns, lang.FindOrCreateNamespace(sym_glojure_DOT_core))).(*lang.Symbol)
8062+
var_glojure_DOT_core_with_DASH_init = ns.InternWithValue(tmp0, int64(42), true)
8063+
if tmp0.Meta() != nil {
8064+
var_glojure_DOT_core_with_DASH_init.SetMeta(tmp0.Meta().(lang.IPersistentMap))
8065+
}
8066+
}
80568067
// with-meta
80578068
{
80588069
tmp0 := sym_with_DASH_meta.WithMeta(lang.NewMap(kw_arglists, lang.NewList(lang.NewVector(sym_obj, sym_m)), kw_doc, "Returns an object of the same type and value as obj, with\n map m as its metadata.", kw_static, true, kw_file, "glojure/core.glj", kw_added, "1.0", kw_ns, lang.FindOrCreateNamespace(sym_glojure_DOT_core), kw_end_DASH_column, int(10), kw_column, int(2), kw_line, int(211), kw_end_DASH_line, int(216))).(*lang.Symbol)
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
(ns codegen.test.def-simple)
22

3-
(def foo)
3+
(defn deftest [val]
4+
(def no-init)
5+
(def with-init val))
6+
7+
(defn
8+
^{:expected-output ["Unbound: #'codegen.test.def-simple/no-init" 42]}
9+
-main []
10+
(deftest 42)
11+
[(str (deref #'no-init)) with-init])

pkg/runtime/testdata/codegen/test/def_simple/load.go.out

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,113 @@ func checkArityGTE(args []any, min int) {
3434

3535
// LoadNS initializes the namespace "codegen.test.def-simple"
3636
func LoadNS() {
37+
sym__DASH_main := lang.NewSymbol("-main")
3738
sym_codegen_DOT_test_DOT_def_DASH_simple := lang.NewSymbol("codegen.test.def-simple")
38-
sym_foo := lang.NewSymbol("foo")
39-
// var codegen.test.def-simple/foo
40-
var_codegen_DOT_test_DOT_def_DASH_simple_foo := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym_foo)
39+
sym_deftest := lang.NewSymbol("deftest")
40+
sym_deref := lang.NewSymbol("deref")
41+
sym_glojure_DOT_core := lang.NewSymbol("glojure.core")
42+
sym_no_DASH_init := lang.NewSymbol("no-init")
43+
sym_str := lang.NewSymbol("str")
44+
sym_val := lang.NewSymbol("val")
45+
sym_with_DASH_init := lang.NewSymbol("with-init")
46+
kw_arglists := lang.NewKeyword("arglists")
47+
kw_column := lang.NewKeyword("column")
48+
kw_end_DASH_column := lang.NewKeyword("end-column")
49+
kw_end_DASH_line := lang.NewKeyword("end-line")
50+
kw_expected_DASH_output := lang.NewKeyword("expected-output")
51+
kw_file := lang.NewKeyword("file")
52+
kw_line := lang.NewKeyword("line")
53+
kw_ns := lang.NewKeyword("ns")
54+
kw_rettag := lang.NewKeyword("rettag")
55+
// var codegen.test.def-simple/-main
56+
var_codegen_DOT_test_DOT_def_DASH_simple__DASH_main := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym__DASH_main)
57+
// var codegen.test.def-simple/deftest
58+
var_codegen_DOT_test_DOT_def_DASH_simple_deftest := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym_deftest)
59+
// var codegen.test.def-simple/no-init
60+
var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym_no_DASH_init)
61+
// var codegen.test.def-simple/with-init
62+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym_with_DASH_init)
63+
// var glojure.core/deref
64+
var_glojure_DOT_core_deref := lang.InternVarName(sym_glojure_DOT_core, sym_deref)
65+
// var glojure.core/str
66+
var_glojure_DOT_core_str := lang.InternVarName(sym_glojure_DOT_core, sym_str)
4167
// reference fmt to avoid unused import error
4268
_ = fmt.Printf
4369
// reference reflect to avoid unused import error
4470
_ = reflect.TypeOf
4571
ns := lang.FindOrCreateNamespace(sym_codegen_DOT_test_DOT_def_DASH_simple)
4672
_ = ns
47-
// foo
73+
// deftest
4874
{
49-
tmp0 := sym_foo.WithMeta(lang.NewMap()).(*lang.Symbol)
50-
var_codegen_DOT_test_DOT_def_DASH_simple_foo = ns.Intern(tmp0)
75+
tmp0 := sym_deftest.WithMeta(lang.NewMap(kw_file, "codegen/test/def_simple.glj", kw_line, int(3), kw_column, int(7), kw_end_DASH_line, int(3), kw_end_DASH_column, int(13), kw_arglists, lang.NewList(lang.NewVector(sym_val)), kw_ns, lang.FindOrCreateNamespace(sym_codegen_DOT_test_DOT_def_DASH_simple))).(*lang.Symbol)
76+
var tmp1 lang.FnFunc
77+
tmp1 = lang.NewFnFunc(func(args ...any) any {
78+
checkArity(args, 1)
79+
v2 := args[0]
80+
_ = v2
81+
tmp3 := lang.NewMap(kw_file, "codegen/test/def_simple.glj", kw_line, int(4), kw_column, int(8), kw_end_DASH_line, int(4), kw_end_DASH_column, int(14))
82+
var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init.SetMeta(tmp3.(lang.IPersistentMap))
83+
if runtime.RT.BooleanCast(lang.Get(tmp3, lang.KWDynamic)) {
84+
var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init.SetDynamic()
85+
}
86+
_ = var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init
87+
tmp4 := lang.NewMap(kw_file, "codegen/test/def_simple.glj", kw_line, int(5), kw_column, int(8), kw_end_DASH_line, int(5), kw_end_DASH_column, int(16))
88+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init.SetMeta(tmp4.(lang.IPersistentMap))
89+
if runtime.RT.BooleanCast(lang.Get(tmp4, lang.KWDynamic)) {
90+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init.SetDynamic()
91+
}
92+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init.BindRoot(v2)
93+
return var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init
94+
})
95+
tmp1 = tmp1.WithMeta(lang.NewMap(kw_rettag, nil)).(lang.FnFunc)
96+
var_codegen_DOT_test_DOT_def_DASH_simple_deftest = ns.InternWithValue(tmp0, tmp1, true)
5197
if tmp0.Meta() != nil {
52-
var_codegen_DOT_test_DOT_def_DASH_simple_foo.SetMeta(tmp0.Meta().(lang.IPersistentMap))
98+
var_codegen_DOT_test_DOT_def_DASH_simple_deftest.SetMeta(tmp0.Meta().(lang.IPersistentMap))
99+
}
100+
}
101+
// no-init
102+
{
103+
tmp0 := sym_no_DASH_init.WithMeta(lang.NewMap()).(*lang.Symbol)
104+
var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init = ns.Intern(tmp0)
105+
if tmp0.Meta() != nil {
106+
var_codegen_DOT_test_DOT_def_DASH_simple_no_DASH_init.SetMeta(tmp0.Meta().(lang.IPersistentMap))
107+
}
108+
}
109+
// with-init
110+
{
111+
tmp0 := sym_with_DASH_init.WithMeta(lang.NewMap()).(*lang.Symbol)
112+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init = ns.Intern(tmp0)
113+
if tmp0.Meta() != nil {
114+
var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init.SetMeta(tmp0.Meta().(lang.IPersistentMap))
115+
}
116+
}
117+
// -main
118+
{
119+
tmp0 := sym__DASH_main.WithMeta(lang.NewMap(kw_expected_DASH_output, lang.NewVector("Unbound: #'codegen.test.def-simple/no-init", int64(42)), kw_file, "codegen/test/def_simple.glj", kw_line, int(8), kw_column, int(3), kw_end_DASH_line, int(9), kw_end_DASH_column, int(7), kw_arglists, lang.NewList(lang.NewVector()), kw_ns, lang.FindOrCreateNamespace(sym_codegen_DOT_test_DOT_def_DASH_simple))).(*lang.Symbol)
120+
var tmp1 lang.FnFunc
121+
tmp1 = lang.NewFnFunc(func(args ...any) any {
122+
checkArity(args, 0)
123+
tmp2 := checkDerefVar(var_codegen_DOT_test_DOT_def_DASH_simple_deftest)
124+
tmp3 := lang.Apply(tmp2, []any{int64(42)})
125+
_ = tmp3
126+
tmp4 := checkDerefVar(var_glojure_DOT_core_str)
127+
tmp5 := checkDerefVar(var_glojure_DOT_core_deref)
128+
tmp6 := lang.InternVarName(sym_codegen_DOT_test_DOT_def_DASH_simple, sym_no_DASH_init)
129+
tmp7 := lang.Apply(tmp5, []any{tmp6})
130+
tmp8 := lang.Apply(tmp4, []any{tmp7})
131+
tmp9 := checkDerefVar(var_codegen_DOT_test_DOT_def_DASH_simple_with_DASH_init)
132+
tmp10 := lang.NewVector(tmp8, tmp9)
133+
tmp11 := lang.NewMap(kw_file, "codegen/test/def_simple.glj", kw_line, int(11), kw_column, int(3), kw_end_DASH_line, int(11), kw_end_DASH_column, int(37))
134+
tmp12, err := lang.WithMeta(tmp10, tmp11.(lang.IPersistentMap))
135+
if err != nil {
136+
panic(err)
137+
}
138+
return tmp12
139+
})
140+
tmp1 = tmp1.WithMeta(lang.NewMap(kw_rettag, nil)).(lang.FnFunc)
141+
var_codegen_DOT_test_DOT_def_DASH_simple__DASH_main = ns.InternWithValue(tmp0, tmp1, true)
142+
if tmp0.Meta() != nil {
143+
var_codegen_DOT_test_DOT_def_DASH_simple__DASH_main.SetMeta(tmp0.Meta().(lang.IPersistentMap))
53144
}
54145
}
55146
}

pkg/runtime/testdata/codegen/test/fn_recur/load.go.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func LoadNS() {
106106
_ = v7
107107
v8 := args[2]
108108
_ = v8
109-
recur_loop_1617:
109+
recur_loop_1619:
110110
var tmp9 any
111111
tmp10 := checkDerefVar(var_glojure_DOT_core__EQ_)
112112
tmp11 := lang.Apply(tmp10, []any{v8, v2})
@@ -123,7 +123,7 @@ func LoadNS() {
123123
v6 = tmp12
124124
v7 = tmp13
125125
v8 = tmp16
126-
goto recur_loop_1617
126+
goto recur_loop_1619
127127
}
128128
return tmp9
129129
})

0 commit comments

Comments
 (0)