From 426d34288f37c61182c7c0ef054a127dfbd83c6d Mon Sep 17 00:00:00 2001 From: Foxboron Date: Tue, 31 Dec 2013 02:06:51 +0100 Subject: [PATCH] Added docs and one small bug fix in defreader --- docs/language/api.rst | 19 +++++++++++ docs/language/index.rst | 1 + docs/language/readermacros.rst | 61 ++++++++++++++++++++++++++++++++++ hy/compiler.py | 2 +- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/language/readermacros.rst diff --git a/docs/language/api.rst b/docs/language/api.rst index aff6745..4e70b7d 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -397,6 +397,25 @@ So ``g!a`` would become ``(gensym "a")``. Section :ref:`using-gensym` +defreader +--------- + +.. versionadded:: 0.9.12 + +`defreader` defines a reader macro, enabling you to restructure or +modify syntax. + +.. code-block:: clj + + => (defreader ^ [expr] (print expr)) + => #^(1 2 3 4) + (1 2 3 4) + => #^"Hello" + "Hello" + +.. seealso:: + + Section :ref:`Reader Macros ` del --- diff --git a/docs/language/index.rst b/docs/language/index.rst index 5132647..4721eb3 100644 --- a/docs/language/index.rst +++ b/docs/language/index.rst @@ -11,3 +11,4 @@ Contents: api core internals + readermacros diff --git a/docs/language/readermacros.rst b/docs/language/readermacros.rst new file mode 100644 index 0000000..0c05d9c --- /dev/null +++ b/docs/language/readermacros.rst @@ -0,0 +1,61 @@ +.. _reader-macros: + +.. highlight:: clj + +============= +Reader Macros +============= + +Reader macros gives LISP the power to modify and alter syntax on the fly. +You don't want polish notation? A reader macro can easily do just that. Want +Clojure's way of having a regex? Reader macros can also do this easily. + + +Syntax +====== + +:: + + => (defreader ^ [expr] (print expr)) + => #^(1 2 3 4) + (1 2 3 4) + => #^"Hello" + "Hello" + => #^1+2+3+4+3+2 + 1+2+3+4+3+2 + + +Implementation +============== + +Hy uses ``defreader`` to define the reader symbol, and ``#`` as the dispatch +character. ``#`` expands into ``(dispatch_reader_macro ...)`` where the symbol +and expression is quoted, and then passed along to the correct function:: + + => (defreader ^ ...) + => #^() + ;=> (dispatch_reader_macro '^ '()) + + +``defreader`` takes a single character as symbol name for the reader macro, +anything longer will return an error. Implementation wise, ``defreader`` +expands into a lambda covered with a decorator, this decorater saves the +lambda in a dict with its module name and symbol. + +:: + + => (defreader ^ [expr] (print expr)) + ;=> (with_decorator (hy.macros.reader ^) (fn [expr] (print expr))) + + +Anything passed along is quoted, thus given to the function defined. + +:: + + => #^"Hello" + "Hello" + +.. warning:: + Because of a limitation in Hy's lexer and parser, reader macros can't + redefine defined syntax such as ``()[]{}``. This will most likely be + adressed in the future. diff --git a/hy/compiler.py b/hy/compiler.py index 9a3b710..8b34a9d 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1866,7 +1866,7 @@ class HyASTCompiler(object): expression.pop(0) name = expression.pop(0) NOT_READERS = [":", "&"] - if name in NOT_READERS: + if name in NOT_READERS or len(name) > 1: raise NameError("%s can't be used as a macro reader symbol" % name) if not isinstance(name, HySymbol): raise HyTypeError(name,