Change macros to be called with separate arguments

This provides free argument-length checking for macros.
This commit is contained in:
Nicolas Dandrimont 2013-05-11 09:09:34 +02:00
parent 74d4937078
commit 0986f9001e
5 changed files with 33 additions and 57 deletions

View File

@ -85,7 +85,7 @@ class HyREPL(code.InteractiveConsole):
@macro("koan") @macro("koan")
def koan_macro(tree): def koan_macro():
return HyExpression([HySymbol('print'), return HyExpression([HySymbol('print'),
HyString(""" HyString("""
Ummon asked the head monk, "What sutra are you lecturing on?" Ummon asked the head monk, "What sutra are you lecturing on?"
@ -103,7 +103,7 @@ def koan_macro(tree):
@macro("ideas") @macro("ideas")
def ideas_macro(tree): def ideas_macro():
return HyExpression([HySymbol('print'), return HyExpression([HySymbol('print'),
HyString(""" HyString("""

View File

@ -28,14 +28,13 @@ from hy.models.list import HyList
@macro("defn") @macro("defn")
@macro("defun") @macro("defun")
def defn_macro(tree): def defn_macro(name, *body):
return HyExpression([HySymbol("def"), return HyExpression([HySymbol("def"),
tree[1], HyExpression([HySymbol("fn")] + tree[2:])]) name, HyExpression([HySymbol("fn")] + list(body))])
@macro("cond") @macro("cond")
def cond_macro(tree): def cond_macro(*tree):
tree.pop(0) # cond flag
it = iter(tree) it = iter(tree)
test, branch = next(it) test, branch = next(it)
@ -50,8 +49,7 @@ def cond_macro(tree):
@macro("for") @macro("for")
def for_macro(tree): def for_macro(*tree):
tree.pop(0)
ret = None ret = None
# for [x iter y iter] ... # for [x iter y iter] ...
# -> # ->
@ -59,6 +57,8 @@ def for_macro(tree):
# foreach y iter # foreach y iter
# ... # ...
tree = HyExpression(tree).replace(tree[0])
it = iter(tree.pop(0)) it = iter(tree.pop(0))
blocks = list(zip(it, it)) # List for Python 3.x degenerating. blocks = list(zip(it, it)) # List for Python 3.x degenerating.
@ -81,10 +81,9 @@ def for_macro(tree):
@macro("_>") @macro("_>")
def threading_macro(tree): def threading_macro(head, *rest):
tree.pop(0) ret = head
ret = tree.pop(0) for node in rest:
for node in tree:
if not isinstance(node, HyExpression): if not isinstance(node, HyExpression):
nnode = HyExpression([node]) nnode = HyExpression([node])
nnode.replace(node) nnode.replace(node)
@ -95,10 +94,9 @@ def threading_macro(tree):
@macro("_>>") @macro("_>>")
def threading_tail_macro(tree): def threading_tail_macro(head, *rest):
tree.pop(0) ret = head
ret = tree.pop(0) for node in rest:
for node in tree:
if not isinstance(node, HyExpression): if not isinstance(node, HyExpression):
nnode = HyExpression([node]) nnode = HyExpression([node])
nnode.replace(node) nnode.replace(node)
@ -110,31 +108,22 @@ def threading_tail_macro(tree):
@macro("car") @macro("car")
@macro("first") @macro("first")
def first_macro(tree): def first_macro(lst):
tree.pop(0) # "first"
ret = tree.pop(0) # the list
# assert tree is empty
return HyExpression([HySymbol('get'), return HyExpression([HySymbol('get'),
ret, lst,
HyInteger(0)]) HyInteger(0)])
@macro("cdr") @macro("cdr")
@macro("rest") @macro("rest")
def rest_macro(tree): def rest_macro(lst):
tree.pop(0) # "first"
ret = tree.pop(0) # the list
# assert tree is empty
return HyExpression([HySymbol('slice'), return HyExpression([HySymbol('slice'),
ret, lst,
HyInteger(1)]) HyInteger(1)])
@macro("let") @macro("let")
def let_macro(tree): def let_macro(variables, *body):
tree.pop(0) # "let"
variables = tree.pop(0)
# tree is now the body
expr = HyExpression([HySymbol("fn"), HyList([])]) expr = HyExpression([HySymbol("fn"), HyList([])])
for var in variables: for var in variables:
@ -145,51 +134,38 @@ def let_macro(tree):
expr.append(HyExpression([HySymbol("setf"), expr.append(HyExpression([HySymbol("setf"),
var, HySymbol("None")])) var, HySymbol("None")]))
for stmt in tree: return HyExpression([expr + list(body)])
expr.append(stmt)
return HyExpression([expr])
@macro("take") @macro("take")
def take_macro(tree): def take_macro(n, lst):
tree.pop(0) # "take"
n = tree.pop(0)
ret = tree.pop(0)
return HyExpression([HySymbol('slice'), return HyExpression([HySymbol('slice'),
ret, lst,
HyInteger(0), HyInteger(0),
HyInteger(n)]) HyInteger(n)])
@macro("drop") @macro("drop")
def drop_macro(tree): def drop_macro(n, lst):
tree.pop(0) # "drop"
n = tree.pop(0)
ret = tree.pop(0)
return HyExpression([HySymbol('slice'), return HyExpression([HySymbol('slice'),
ret, lst,
HyInteger(n)]) HyInteger(n)])
@macro("when") @macro("when")
def when_macro(tree): def when_macro(test, *body):
tree.pop(0) # "when"
test = tree.pop(0)
return HyExpression([ return HyExpression([
HySymbol('if'), HySymbol('if'),
test, test,
HyExpression([HySymbol("do")]) + tree, HyExpression([HySymbol("do")] + list(body)),
]) ])
@macro("unless") @macro("unless")
def unless_macro(tree): def unless_macro(test, *body):
tree.pop(0) # "unless"
test = tree.pop(0)
return HyExpression([ return HyExpression([
HySymbol('if'), HySymbol('if'),
test, test,
HySymbol('None'), HySymbol('None'),
HyExpression([HySymbol("do")]) + tree, HyExpression([HySymbol("do")] + list(body)),
]) ])

View File

@ -44,7 +44,7 @@ def process(tree):
if isinstance(fn, HyString): if isinstance(fn, HyString):
if fn in _hy_macros: if fn in _hy_macros:
m = _hy_macros[fn] m = _hy_macros[fn]
obj = m(ntree) obj = m(*ntree[1:])
obj.replace(tree) obj.replace(tree)
return obj return obj

View File

@ -7,9 +7,9 @@ from hy.models.list import HyList
@macro("test") @macro("test")
def tmac(tree): def tmac(*tree):
""" Turn an expression into a list """ """ Turn an expression into a list """
return HyList(tree[1:]) return HyList(tree)
def test_preprocessor_simple(): def test_preprocessor_simple():

View File

@ -3,5 +3,5 @@ from hy import HyList
@macro("qplah") @macro("qplah")
def tmac(tree): def tmac(*tree):
return HyList(tree[1:]) return HyList(tree)