From 0986f9001e6147ca363aa5bdd9d0aa4b8a196353 Mon Sep 17 00:00:00 2001 From: Nicolas Dandrimont Date: Sat, 11 May 2013 09:09:34 +0200 Subject: [PATCH] Change macros to be called with separate arguments This provides free argument-length checking for macros. --- hy/cmdline.py | 4 +- hy/core/bootstrap.py | 76 ++++++++++------------------ hy/macros.py | 2 +- tests/macros/test_macro_processor.py | 4 +- tests/resources/tlib.py | 4 +- 5 files changed, 33 insertions(+), 57 deletions(-) diff --git a/hy/cmdline.py b/hy/cmdline.py index 199c454..bdc4eb5 100644 --- a/hy/cmdline.py +++ b/hy/cmdline.py @@ -85,7 +85,7 @@ class HyREPL(code.InteractiveConsole): @macro("koan") -def koan_macro(tree): +def koan_macro(): return HyExpression([HySymbol('print'), HyString(""" Ummon asked the head monk, "What sutra are you lecturing on?" @@ -103,7 +103,7 @@ def koan_macro(tree): @macro("ideas") -def ideas_macro(tree): +def ideas_macro(): return HyExpression([HySymbol('print'), HyString(""" diff --git a/hy/core/bootstrap.py b/hy/core/bootstrap.py index a5685cc..5cf4106 100644 --- a/hy/core/bootstrap.py +++ b/hy/core/bootstrap.py @@ -28,14 +28,13 @@ from hy.models.list import HyList @macro("defn") @macro("defun") -def defn_macro(tree): +def defn_macro(name, *body): return HyExpression([HySymbol("def"), - tree[1], HyExpression([HySymbol("fn")] + tree[2:])]) + name, HyExpression([HySymbol("fn")] + list(body))]) @macro("cond") -def cond_macro(tree): - tree.pop(0) # cond flag +def cond_macro(*tree): it = iter(tree) test, branch = next(it) @@ -50,8 +49,7 @@ def cond_macro(tree): @macro("for") -def for_macro(tree): - tree.pop(0) +def for_macro(*tree): ret = None # for [x iter y iter] ... # -> @@ -59,6 +57,8 @@ def for_macro(tree): # foreach y iter # ... + tree = HyExpression(tree).replace(tree[0]) + it = iter(tree.pop(0)) blocks = list(zip(it, it)) # List for Python 3.x degenerating. @@ -81,10 +81,9 @@ def for_macro(tree): @macro("_>") -def threading_macro(tree): - tree.pop(0) - ret = tree.pop(0) - for node in tree: +def threading_macro(head, *rest): + ret = head + for node in rest: if not isinstance(node, HyExpression): nnode = HyExpression([node]) nnode.replace(node) @@ -95,10 +94,9 @@ def threading_macro(tree): @macro("_>>") -def threading_tail_macro(tree): - tree.pop(0) - ret = tree.pop(0) - for node in tree: +def threading_tail_macro(head, *rest): + ret = head + for node in rest: if not isinstance(node, HyExpression): nnode = HyExpression([node]) nnode.replace(node) @@ -110,31 +108,22 @@ def threading_tail_macro(tree): @macro("car") @macro("first") -def first_macro(tree): - tree.pop(0) # "first" - ret = tree.pop(0) # the list - # assert tree is empty +def first_macro(lst): return HyExpression([HySymbol('get'), - ret, + lst, HyInteger(0)]) @macro("cdr") @macro("rest") -def rest_macro(tree): - tree.pop(0) # "first" - ret = tree.pop(0) # the list - # assert tree is empty +def rest_macro(lst): return HyExpression([HySymbol('slice'), - ret, + lst, HyInteger(1)]) @macro("let") -def let_macro(tree): - tree.pop(0) # "let" - variables = tree.pop(0) - # tree is now the body +def let_macro(variables, *body): expr = HyExpression([HySymbol("fn"), HyList([])]) for var in variables: @@ -145,51 +134,38 @@ def let_macro(tree): expr.append(HyExpression([HySymbol("setf"), var, HySymbol("None")])) - for stmt in tree: - expr.append(stmt) - - return HyExpression([expr]) + return HyExpression([expr + list(body)]) @macro("take") -def take_macro(tree): - tree.pop(0) # "take" - n = tree.pop(0) - ret = tree.pop(0) +def take_macro(n, lst): return HyExpression([HySymbol('slice'), - ret, + lst, HyInteger(0), HyInteger(n)]) @macro("drop") -def drop_macro(tree): - tree.pop(0) # "drop" - n = tree.pop(0) - ret = tree.pop(0) +def drop_macro(n, lst): return HyExpression([HySymbol('slice'), - ret, + lst, HyInteger(n)]) @macro("when") -def when_macro(tree): - tree.pop(0) # "when" - test = tree.pop(0) +def when_macro(test, *body): return HyExpression([ HySymbol('if'), test, - HyExpression([HySymbol("do")]) + tree, + HyExpression([HySymbol("do")] + list(body)), ]) @macro("unless") -def unless_macro(tree): - tree.pop(0) # "unless" - test = tree.pop(0) +def unless_macro(test, *body): return HyExpression([ HySymbol('if'), test, HySymbol('None'), - HyExpression([HySymbol("do")]) + tree, + HyExpression([HySymbol("do")] + list(body)), ]) diff --git a/hy/macros.py b/hy/macros.py index ca35aa6..b58d0ec 100644 --- a/hy/macros.py +++ b/hy/macros.py @@ -44,7 +44,7 @@ def process(tree): if isinstance(fn, HyString): if fn in _hy_macros: m = _hy_macros[fn] - obj = m(ntree) + obj = m(*ntree[1:]) obj.replace(tree) return obj diff --git a/tests/macros/test_macro_processor.py b/tests/macros/test_macro_processor.py index d9d7144..4ffdbfe 100644 --- a/tests/macros/test_macro_processor.py +++ b/tests/macros/test_macro_processor.py @@ -7,9 +7,9 @@ from hy.models.list import HyList @macro("test") -def tmac(tree): +def tmac(*tree): """ Turn an expression into a list """ - return HyList(tree[1:]) + return HyList(tree) def test_preprocessor_simple(): diff --git a/tests/resources/tlib.py b/tests/resources/tlib.py index 3b9e310..7ce0ee5 100644 --- a/tests/resources/tlib.py +++ b/tests/resources/tlib.py @@ -3,5 +3,5 @@ from hy import HyList @macro("qplah") -def tmac(tree): - return HyList(tree[1:]) +def tmac(*tree): + return HyList(tree)