Skip to content

Commit 3144802

Browse files
committed
we now have macros
1 parent 718fa80 commit 3144802

6 files changed

Lines changed: 83 additions & 21 deletions

File tree

pixie/stdlib.lisp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,12 @@
166166
(extend -seq PersistentVector sequence)
167167

168168
(def concat (fn [& args] (transduce cat conj args)))
169+
170+
(def defn (fn [nm & rest] `(def ~nm (fn ~nm ~@rest))))
171+
(set-macro! defn)
172+
173+
(defn defmacro [nm & rest]
174+
`(do (defn ~nm ~@rest)
175+
(set-macro! ~nm)
176+
~nm))
177+
(set-macro! defmacro)

pixie/vm/code.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@
4343

4444
class BaseCode(object.Object):
4545
def __init__(self):
46-
pass
46+
self._is_macro = False
47+
48+
def set_macro(self):
49+
self._is_macro = true
50+
51+
def is_macro(self):
52+
return self._is_macro
4753

4854
def _invoke(self, args):
4955
raise NotImplementedError()
@@ -71,6 +77,7 @@ def type(self):
7177
return MultiArityFn._type
7278

7379
def __init__(self, arities, required_arity=0, rest_fn=None):
80+
BaseCode.__init__(self)
7481
self._arities = arities
7582
self._required_arity = required_arity
7683
self._rest_fn = rest_fn
@@ -188,7 +195,7 @@ def type(self):
188195

189196
class Var(BaseCode):
190197
_type = object.Type(u"Var")
191-
_immutable_fields_ = ["_rev?"]
198+
_immutable_fields_ = ["_rev?", "_is_macro?"]
192199

193200
def type(self):
194201
return Var._type
@@ -214,10 +221,15 @@ def deref(self):
214221
assert val is not undefined, u"Var " + self._name + u" is undefined"
215222
return val
216223

224+
def is_defined(self):
225+
return self._root is not undefined
226+
217227
def _invoke(self, args):
218228
return self.deref().invoke(args)
219229

220230

231+
232+
221233
class Namespace(py_object):
222234
def __init__(self, name):
223235
self._registry = {}
@@ -307,6 +319,7 @@ def type(self):
307319

308320
__immutable_fields__ = ["_rev?"]
309321
def __init__(self, name, protocol):
322+
BaseCode.__init__(self)
310323
self._name = name
311324
self._dict = {}
312325
self._rev = 0

pixie/vm/compiler.py

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,36 @@ def emit(self, ctx):
203203

204204

205205

206-
207-
206+
def resolve_var(ctx, name):
207+
var = code.get_var_if_defined(ctx.ns, name)
208+
if var is None:
209+
var = code.get_var_if_defined(u"pixie.stdlib", name)
210+
return var
211+
212+
def resolve_local(ctx, name):
213+
return ctx.get_local(name)
214+
215+
216+
def is_macro_call(form, ctx):
217+
if rt.seq_QMARK_(form) is true and isinstance(rt.first(form), symbol.Symbol):
218+
name = rt.first(form)._str
219+
if resolve_local(ctx, name):
220+
return None
221+
var = resolve_var(ctx, name)
222+
223+
if var and var.is_defined():
224+
val = var.deref()
225+
if isinstance(val, code.BaseCode) and val.is_macro():
226+
return val
227+
return None
228+
229+
def call_macro(var, form, ctx):
230+
form = rt.next(form)
231+
args = []
232+
while form is not nil:
233+
args.append(rt.first(form))
234+
form = rt.next(form)
235+
return var.invoke(args)
208236

209237
def compile_form(form, ctx):
210238
if rt.instance_QMARK_(form, rt.ISeq.deref()) is true and form is not nil:
@@ -215,12 +243,9 @@ def compile_form(form, ctx):
215243

216244
if isinstance(form, symbol.Symbol):
217245
name = form._str
218-
loc = ctx.get_local(name)
246+
loc = resolve_local(ctx, name)
219247
if loc is None:
220-
var = code.get_var_if_defined(ctx.ns, name)
221-
if var is None:
222-
var = code.get_var_if_defined(u"pixie.stdlib", name)
223-
248+
var = resolve_var(ctx, name)
224249
if var is None:
225250
var = _type_registry.get_by_name(name, None)
226251
if var is not None:
@@ -412,10 +437,10 @@ def compile_if(form, ctx):
412437
ctx.mark(else_lbl)
413438

414439
def compile_def(form, ctx):
415-
form = form.next()
416-
name = form.first()
417-
form = form.next()
418-
val = form.first()
440+
form = rt.next(form)
441+
name = rt.first(form)
442+
form = rt.next(form)
443+
val = rt.first(form)
419444

420445
assert isinstance(name, symbol.Symbol)
421446

@@ -426,12 +451,12 @@ def compile_def(form, ctx):
426451
ctx.sub_sp(1)
427452

428453
def compile_do(form, ctx):
429-
form = form.next()
454+
form = rt.next(form)
430455
assert form is not nil
431456

432457
while True:
433-
compile_form(form.first(), ctx)
434-
form = form.next()
458+
compile_form(rt.first(form), ctx)
459+
form = rt.next(form)
435460

436461
if form is nil:
437462
return
@@ -546,10 +571,15 @@ def compile_loop(form, ctx):
546571
u"let": compile_let,
547572
u"loop": compile_loop}
548573

574+
549575
def compile_cons(form, ctx):
550576
if isinstance(form.first(), symbol.Symbol) and form.first()._str in builtins:
551577
return builtins[form.first()._str](form, ctx)
552578

579+
macro = is_macro_call(form, ctx)
580+
if macro:
581+
return compile_cons(call_macro(macro, form, ctx), ctx)
582+
553583
cnt = 0
554584
ctc = ctx.can_tail_call
555585
while form is not nil:

pixie/vm/protocols.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from pixie.vm.object import Object, Type, _type_registry
3-
from pixie.vm.code import BaseCode, PolymorphicFn, wrap_fn, as_var, defprotocol, extend, Protocol
3+
from pixie.vm.code import BaseCode, PolymorphicFn, wrap_fn, as_var, defprotocol, extend, Protocol, Var
44
from types import MethodType
55
from pixie.vm.primitives import true, false, nil
66
import pixie.vm.numbers as numbers
@@ -205,3 +205,9 @@ def eq(a, b):
205205
return true
206206
else:
207207
return rt._eq(a, b)
208+
209+
@as_var("set-macro!")
210+
def set_macro(f):
211+
assert isinstance(f, BaseCode)
212+
f.set_macro()
213+
return f

pixie/vm/reader.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ def syntax_quote(self, form):
171171
ret = rt.list(SEQ, rt.cons(CONCAT, self.expand_list(rt.seq(form))))
172172
else:
173173
ret = rt.list(QUOTE, form)
174-
print rt._str(ret)._str
175174
return ret
176175

177176
def expand_list(self, form):

target.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ def entry_point(foo=None):
6868

6969
return 0
7070

71+
@wrap_fn
72+
def bootstrap():
73+
import pixie.vm.rt as rt
74+
from pixie.vm.string import String
75+
rt.load_file(String(u"pixie/stdlib.lisp"))
76+
77+
7178
from rpython.rtyper.lltypesystem import lltype
7279
from rpython.jit.metainterp import warmspot
7380

@@ -132,8 +139,6 @@ def target(*args):
132139
print rpython.config.translationoption.get_combined_translation_config()
133140

134141
if __name__ == "__main__":
135-
import pixie.vm.rt as rt
136-
from pixie.vm.string import String
137-
rt.load_file(String(u"pixie/stdlib.lisp"))
138142
#run_debug(sys.argv)
143+
with_stacklets(bootstrap)
139144
entry_point()

0 commit comments

Comments
 (0)