rename sharp macros to tag macros

This commit is contained in:
gilch 2017-06-20 21:48:54 -06:00
parent 20c26a52e4
commit 6cd3201421
10 changed files with 61 additions and 61 deletions

View File

@ -779,19 +779,19 @@ For example,
42 42
defsharp deftag
-------- --------
.. versionadded:: 0.13.0 .. versionadded:: 0.13.0
``defsharp`` defines a sharp macro. A sharp macro is a unary macro that has the ``deftag`` defines a tag macro. A tag macro is a unary macro that has the
same semantics as an ordinary macro defined with ``defmacro``. It is called with same semantics as an ordinary macro defined with ``defmacro``. It is called with
the syntax ``#tag FORM``, where ``tag`` is the name of the macro, and ``FORM`` the syntax ``#tag FORM``, where ``tag`` is the name of the macro, and ``FORM``
is any form. The ``tag`` is often only one character, but it can be any symbol. is any form. The ``tag`` is often only one character, but it can be any symbol.
.. code-block:: clj .. code-block:: clj
=> (defsharp ♣ [expr] `[~expr ~expr]) => (deftag ♣ [expr] `[~expr ~expr])
<function <lambda> at 0x7f76d0271158> <function <lambda> at 0x7f76d0271158>
=> #♣ 5 => #♣ 5
[5, 5] [5, 5]
@ -801,13 +801,13 @@ is any form. The ``tag`` is often only one character, but it can be any symbol.
=> x => x
2 2
In this example, if you used ``(defmacro ♣ ...)`` instead of ``(defsharp In this example, if you used ``(defmacro ♣ ...)`` instead of ``(deftag
♣ ...)``, you would call the macro as ``(♣ 5)`` or ``(♣ (+= x 1))``. ♣ ...)``, you would call the macro as ``(♣ 5)`` or ``(♣ (+= x 1))``.
The syntax for calling sharp macros is similar to that of reader macros a la The syntax for calling tag macros is similar to that of reader macros a la
Common Lisp's ``SET-MACRO-CHARACTER``. In fact, before Hy 0.13.0, sharp macros Common Lisp's ``SET-MACRO-CHARACTER``. In fact, before Hy 0.13.0, tag macros
were called "reader macros", and defined with ``defreader`` rather than were called "reader macros", and defined with ``defreader`` rather than
``defsharp``. True reader macros are not (yet) implemented in Hy. ``deftag``. True reader macros are not (yet) implemented in Hy.
del del
--- ---
@ -1727,7 +1727,7 @@ will be 4 (``1+1 + 1+1``).
.. versionadded:: 0.12.0 .. versionadded:: 0.12.0
The sharp macro ``#@`` can be used as a shorthand for ``with-decorator``. With The tag macro ``#@`` can be used as a shorthand for ``with-decorator``. With
``#@``, the previous example becomes: ``#@``, the previous example becomes:
.. code-block:: clj .. code-block:: clj

View File

@ -582,13 +582,13 @@ elements, so by the time program started executing, it actually reads:
(+ 1 2 3) (+ 1 2 3)
Sometimes it's nice to be able to call a one-parameter macro without Sometimes it's nice to be able to call a one-parameter macro without
parentheses. Sharp macros allow this. The name of a sharp macro is typically parentheses. Tag macros allow this. The name of a tag macro is typically
one character long, but since Hy operates well with Unicode, we aren't running one character long, but since Hy operates well with Unicode, we aren't running
out of characters that soon: out of characters that soon:
.. code-block:: clj .. code-block:: clj
=> (defsharp ↻ [code] => (deftag ↻ [code]
... (setv op (last code) params (list (butlast code))) ... (setv op (last code) params (list (butlast code)))
... `(~op ~@params)) ... `(~op ~@params))
=> #↻(1 2 3 +) => #↻(1 2 3 +)

View File

@ -13,7 +13,7 @@ from hy.lex.parser import hy_symbol_mangle
import hy.macros import hy.macros
from hy._compat import ( from hy._compat import (
str_type, bytes_type, long_type, PY3, PY34, PY35, raise_empty) str_type, bytes_type, long_type, PY3, PY34, PY35, raise_empty)
from hy.macros import require, macroexpand, sharp_macroexpand from hy.macros import require, macroexpand, tag_macroexpand
import hy.importer import hy.importer
import traceback import traceback
@ -2465,20 +2465,20 @@ class HyASTCompiler(object):
return ret return ret
@builds("defsharp") @builds("deftag")
@checkargs(min=2) @checkargs(min=2)
def compile_sharp_macro(self, expression): def compile_tag_macro(self, expression):
expression.pop(0) expression.pop(0)
name = expression.pop(0) name = expression.pop(0)
if name == ":" or name == "&": if name == ":" or name == "&":
raise NameError("%s can't be used as a sharp macro name" % name) raise NameError("%s can't be used as a tag macro name" % name)
if not isinstance(name, HySymbol) and not isinstance(name, HyString): if not isinstance(name, HySymbol) and not isinstance(name, HyString):
raise HyTypeError(name, raise HyTypeError(name,
("received a `%s' instead of a symbol " ("received a `%s' instead of a symbol "
"for sharp macro name" % type(name).__name__)) "for tag macro name" % type(name).__name__))
name = HyString(name).replace(name) name = HyString(name).replace(name)
new_expression = HyExpression([ new_expression = HyExpression([
HyExpression([HySymbol("hy.macros.sharp"), name]), HyExpression([HySymbol("hy.macros.tag"), name]),
HyExpression([HySymbol("fn")] + expression), HyExpression([HySymbol("fn")] + expression),
]).replace(expression) ]).replace(expression)
@ -2486,19 +2486,19 @@ class HyASTCompiler(object):
return ret return ret
@builds("dispatch_sharp_macro") @builds("dispatch_tag_macro")
@checkargs(exact=2) @checkargs(exact=2)
def compile_dispatch_sharp_macro(self, expression): def compile_dispatch_tag_macro(self, expression):
expression.pop(0) # dispatch-sharp-macro expression.pop(0) # dispatch-tag-macro
tag = expression.pop(0) tag = expression.pop(0)
if not type(tag) == HyString: if not type(tag) == HyString:
raise HyTypeError( raise HyTypeError(
tag, tag,
"Trying to expand a sharp macro using `{0}' instead " "Trying to expand a tag macro using `{0}' instead "
"of string".format(type(tag).__name__), "of string".format(type(tag).__name__),
) )
tag = HyString(hy_symbol_mangle(str(tag))).replace(tag) tag = HyString(hy_symbol_mangle(str(tag))).replace(tag)
expr = sharp_macroexpand(tag, expression.pop(0), self) expr = tag_macroexpand(tag, expression.pop(0), self)
return self.compile(expr) return self.compile(expr)
@builds("eval_and_compile") @builds("eval_and_compile")

View File

@ -40,11 +40,11 @@ class Completer(object):
builtins.__dict__, builtins.__dict__,
hy.macros._hy_macros[None], hy.macros._hy_macros[None],
namespace] namespace]
self.sharp_path = [hy.macros._hy_sharp[None]] self.tag_path = [hy.macros._hy_tag[None]]
if '__name__' in namespace: if '__name__' in namespace:
module_name = namespace['__name__'] module_name = namespace['__name__']
self.path.append(hy.macros._hy_macros[module_name]) self.path.append(hy.macros._hy_macros[module_name])
self.sharp_path.append(hy.macros._hy_sharp[module_name]) self.tag_path.append(hy.macros._hy_tag[module_name])
def attr_matches(self, text): def attr_matches(self, text):
# Borrowed from IPython's completer # Borrowed from IPython's completer
@ -81,10 +81,10 @@ class Completer(object):
matches.append(k) matches.append(k)
return matches return matches
def sharp_matches(self, text): def tag_matches(self, text):
text = text[1:] text = text[1:]
matches = [] matches = []
for p in self.sharp_path: for p in self.tag_path:
for k in p.keys(): for k in p.keys():
if isinstance(k, string_types): if isinstance(k, string_types):
if k.startswith(text): if k.startswith(text):
@ -93,7 +93,7 @@ class Completer(object):
def complete(self, text, state): def complete(self, text, state):
if text.startswith("#"): if text.startswith("#"):
matches = self.sharp_matches(text) matches = self.tag_matches(text)
elif "." in text: elif "." in text:
matches = self.attr_matches(text) matches = self.attr_matches(text)
else: else:

View File

@ -230,7 +230,7 @@
(sys.exit ~retval)))) (sys.exit ~retval))))
(defsharp @ [expr] (deftag @ [expr]
(setv decorators (cut expr None -1) (setv decorators (cut expr None -1)
fndef (get expr -1)) fndef (get expr -1))
`(with-decorator ~@decorators ~fndef)) `(with-decorator ~@decorators ~fndef))

View File

@ -204,7 +204,7 @@ def hash_other(p):
st = p[0].getstr()[1:] st = p[0].getstr()[1:]
str_object = HyString(st) str_object = HyString(st)
expr = p[1] expr = p[1]
return HyExpression([HySymbol("dispatch_sharp_macro"), str_object, expr]) return HyExpression([HySymbol("dispatch_tag_macro"), str_object, expr])
@pg.production("set : HLCURLY list_contents RCURLY") @pg.production("set : HLCURLY list_contents RCURLY")

View File

@ -18,7 +18,7 @@ EXTRA_MACROS = [
] ]
_hy_macros = defaultdict(dict) _hy_macros = defaultdict(dict)
_hy_sharp = defaultdict(dict) _hy_tag = defaultdict(dict)
def macro(name): def macro(name):
@ -50,8 +50,8 @@ def macro(name):
return _ return _
def sharp(name): def tag(name):
"""Decorator to define a sharp macro called `name`. """Decorator to define a tag macro called `name`.
This stores the macro `name` in the namespace for the module where it is This stores the macro `name` in the namespace for the module where it is
defined. defined.
@ -59,14 +59,14 @@ def sharp(name):
If the module where it is defined is in `hy.core`, then the macro is stored If the module where it is defined is in `hy.core`, then the macro is stored
in the default `None` namespace. in the default `None` namespace.
This function is called from the `defsharp` special form in the compiler. This function is called from the `deftag` special form in the compiler.
""" """
def _(fn): def _(fn):
module_name = fn.__module__ module_name = fn.__module__
if module_name.startswith("hy.core"): if module_name.startswith("hy.core"):
module_name = None module_name = None
_hy_sharp[module_name][name] = fn _hy_tag[module_name][name] = fn
return fn return fn
return _ return _
@ -90,7 +90,7 @@ def require(source_module, target_module,
if prefix: if prefix:
prefix += "." prefix += "."
for d in _hy_macros, _hy_sharp: for d in _hy_macros, _hy_tag:
for name, macro in d[source_module].items(): for name, macro in d[source_module].items():
seen_names.add(name) seen_names.add(name)
if all_macros: if all_macros:
@ -210,19 +210,19 @@ def macroexpand_1(tree, compiler):
return tree return tree
def sharp_macroexpand(tag, tree, compiler): def tag_macroexpand(tag, tree, compiler):
"""Expand the sharp macro "tag" with argument `tree`.""" """Expand the tag macro "tag" with argument `tree`."""
load_macros(compiler.module_name) load_macros(compiler.module_name)
sharp_macro = _hy_sharp[compiler.module_name].get(tag) tag_macro = _hy_tag[compiler.module_name].get(tag)
if sharp_macro is None: if tag_macro is None:
try: try:
sharp_macro = _hy_sharp[None][tag] tag_macro = _hy_tag[None][tag]
except KeyError: except KeyError:
raise HyTypeError( raise HyTypeError(
tag, tag,
"`{0}' is not a defined sharp macro.".format(tag) "`{0}' is not a defined tag macro.".format(tag)
) )
expr = sharp_macro(tree) expr = tag_macro(tree)
return replace_hy_obj(wrap_value(expr), tree) return replace_hy_obj(wrap_value(expr), tree)

View File

@ -7,10 +7,10 @@ from hy.compiler import HyTypeError, HyASTCompiler
from hy.lex import tokenize from hy.lex import tokenize
def test_sharp_macro_error(): def test_tag_macro_error():
"""Check if we get correct error with wrong dispatch character""" """Check if we get correct error with wrong dispatch character"""
try: try:
macroexpand(tokenize("(dispatch_sharp_macro '- '())")[0], macroexpand(tokenize("(dispatch_tag_macro '- '())")[0],
HyASTCompiler(__name__)) HyASTCompiler(__name__))
except HyTypeError as e: except HyTypeError as e:
assert "with the character `-`" in str(e) assert "with the character `-`" in str(e)

View File

@ -5,34 +5,34 @@
(import [functools [wraps]]) (import [functools [wraps]])
(defn test-sharp-macro [] (defn test-tag-macro []
"Test a basic sharp macro" "Test a basic tag macro"
(defsharp ^ [expr] (deftag ^ [expr]
expr) expr)
(assert (= #^"works" "works"))) (assert (= #^"works" "works")))
(defn test-sharp-macro-expr [] (defn test-tag-macro-expr []
"Test basic exprs like lists and arrays" "Test basic exprs like lists and arrays"
(defsharp n [expr] (deftag n [expr]
(get expr 1)) (get expr 1))
(assert (= #n[1 2] 2)) (assert (= #n[1 2] 2))
(assert (= #n(1 2) 2))) (assert (= #n(1 2) 2)))
(defn test-sharp-macro-override [] (defn test-tag-macro-override []
"Test if we can override function symbols" "Test if we can override function symbols"
(defsharp + [n] (deftag + [n]
(+ n 1)) (+ n 1))
(assert (= #+2 3))) (assert (= #+2 3)))
(defn test-sharp-macros-macros [] (defn test-tag-macros-macros []
"Test if defsharp is actually a macro" "Test if deftag is actually a macro"
(defsharp t [expr] (deftag t [expr]
`(, ~@expr)) `(, ~@expr))
(def a #t[1 2 3]) (def a #t[1 2 3])
@ -41,16 +41,16 @@
(assert (= (, 1 2 3) a))) (assert (= (, 1 2 3) a)))
(defn test-sharp-macro-string-name [] (defn test-tag-macro-string-name []
"Test if defsharp accepts a string as a macro name." "Test if deftag accepts a string as a macro name."
(defsharp "." [expr] (deftag "." [expr]
expr) expr)
(assert (= #."works" "works"))) (assert (= #."works" "works")))
(defn test-builtin-decorator-sharp [] (defn test-builtin-decorator-tag []
(defn increment-arguments [func] (defn increment-arguments [func]
"Increments each argument passed to the decorated function." "Increments each argument passed to the decorated function."
((wraps func) ((wraps func)
@ -72,7 +72,7 @@
(assert (= "foo" (. foo --name--))) (assert (= "foo" (. foo --name--)))
(assert (= "Bar." (. foo --doc--))) (assert (= "Bar." (. foo --doc--)))
;; We can use the #@ sharp macro to apply more than one decorator ;; We can use the #@ tag macro to apply more than one decorator
#@(increment-arguments #@(increment-arguments
increment-arguments increment-arguments
(defn double-foo [&rest args &kwargs kwargs] (defn double-foo [&rest args &kwargs kwargs]

View File

@ -303,10 +303,10 @@ def test_complex():
assert entry == HySymbol("j") assert entry == HySymbol("j")
def test_sharp_macro(): def test_tag_macro():
"""Ensure sharp macros are handled properly""" """Ensure tag macros are handled properly"""
entry = tokenize("#^()") entry = tokenize("#^()")
assert entry[0][0] == HySymbol("dispatch_sharp_macro") assert entry[0][0] == HySymbol("dispatch_tag_macro")
assert entry[0][1] == HyString("^") assert entry[0][1] == HyString("^")
assert len(entry[0]) == 3 assert len(entry[0]) == 3