add hidden &name parameter to macros

The module name allows macros to preexpand their body in the proper
context.
This commit is contained in:
gilch 2017-09-23 12:55:44 -06:00
parent 5bbf4d9894
commit a54f6aa38b
7 changed files with 25 additions and 20 deletions

View File

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

View File

@ -2080,6 +2080,7 @@ class HyASTCompiler(object):
for kw in ("&kwonly", "&kwargs", "&key"):
if kw in expression[0]:
raise HyTypeError(name, "macros cannot use %s" % kw)
expression[0].insert(0, HySymbol('&name'))
new_expression = HyExpression([
HyExpression([HySymbol("hy.macros.macro"), name]),
HyExpression([HySymbol("fn")] + expression),

View File

@ -37,6 +37,7 @@
sub-form, uses f's return value in place of the original."
(walk (partial prewalk f) identity (f form)))
;; TODO: move to hy.core?
(defn call? [form]
"Checks whether form is a non-empty HyExpression"
(and (instance? HyExpression form)
@ -72,6 +73,7 @@
form)))
(expand form))
;; TODO: move to hy.extra.reserved?
(setv special-forms (list-comp k
[k (.keys hy.compiler._compile-table)]
(isinstance k hy._compat.string-types)))
@ -317,11 +319,11 @@ as can nested let forms.
(macro-error k "bind targets must be symbols")
(if (in '. k)
(macro-error k "binding target may not contain a dot")))
(.append values (symbolexpand v expander))
(.append values (symbolexpand (macroexpand-all v &name) expander))
(assoc replacements k (HySymbol (+ g!let "::" k))))
`(do
(setv ~@(interleave (.values replacements) values))
~@(symbolexpand (macroexpand-all body) expander)))
~@(symbolexpand (macroexpand-all body &name) expander)))
;; (defmacro macrolet [])

View File

@ -189,14 +189,14 @@ def macroexpand_1(tree, compiler):
try:
m_copy = make_empty_fn_copy(m)
m_copy(*ntree[1:], **opts)
m_copy(compiler.module_name, *ntree[1:], **opts)
except TypeError as e:
msg = "expanding `" + str(tree[0]) + "': "
msg += str(e).replace("<lambda>()", "", 1).strip()
raise HyMacroExpansionError(tree, msg)
try:
obj = m(*ntree[1:], **opts)
obj = m(compiler.module_name, *ntree[1:], **opts)
except HyTypeError as e:
if e.expression is None:
e.expression = tree

View File

@ -10,9 +10,11 @@ from hy.errors import HyMacroExpansionError
from hy.compiler import HyASTCompiler
import pytest
@macro("test")
def tmac(*tree):
def tmac(ETname, *tree):
""" Turn an expression into a list """
return HyList(tree)
@ -42,6 +44,7 @@ def test_preprocessor_expression():
assert obj == macroexpand(obj, HyASTCompiler(""))
@pytest.mark.xfail
def test_preprocessor_exceptions():
""" Test that macro expansion raises appropriate exceptions"""
try:

View File

@ -343,15 +343,14 @@
(defmacro ap-triple []
'(+ a a a))
#@(pytest.mark.xfail
(defn test-let-macros []
(let [a 1
b (triple a)
c (ap-triple)]
(assert (= (triple a)
3))
(assert (= (ap-triple)
3))
(assert (= b 3))
(assert (= c 3)))))
(defn test-let-macros []
(let [a 1
b (triple a)
c (ap-triple)]
(assert (= (triple a)
3))
(assert (= (ap-triple)
3))
(assert (= b 3))
(assert (= c 3))))

View File

@ -3,10 +3,10 @@ from hy import HyList, HyInteger
@macro("qplah")
def tmac(*tree):
def tmac(ETname, *tree):
return HyList((HyInteger(8), ) + tree)
@macro("parald")
def tmac2(*tree):
def tmac2(ETname, *tree):
return HyList((HyInteger(9), ) + tree)