-
Notifications
You must be signed in to change notification settings - Fork 372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify tag macros #1971
Simplify tag macros #1971
Conversation
def274e
to
1934fd1
Compare
oh heck the mad man went ahead and did it. I'll take a look soon hopefully. this looks pretty promising though. |
Right, the |
By the way, I first tried having a tag macro named |
tangentially affects #1970 need to test this
makes sense and since it's only relevant in
agreed, i think I like this syntax better any ways |
Would it be worthwhile to add a ;; backwards compat
(defmacro deftag [name &rest forms]
`(defmacro ~(+ "#" (str name)) ~@forms)) I'm also looking into if there's a way to hack up the parser so that we wouldn't need to string-quote tags for |
My philosophy is that backwards-compatibility features before the release of 1.0 are premature. I'm not sure that
I wouldn't recommend it. It will complicate the lexer considerably for an edge case. |
Alternatively, we could single-quote a tag name a la (require [hy.extra.anaphoric ['#%]])
(defmacro '#x [x] x) Here's a patch that would allow this for require, you'd have to do something similar for defmacro (and/or factor stuff out into model_patterns): diff --git a/hy/compiler.py b/hy/compiler.py
index c7224c44..01ce10d5 100755
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -1134,12 +1134,19 @@ class HyASTCompiler(object):
expr, op=ops[root](), operand=operand.force_expr)
def _importlike(*name_types):
- name = some(lambda x: isinstance(x, name_types) and "." not in x)
+ _symn = some(lambda x: isinstance(x, HySymbol) and "." not in x)
+ _symt = some(lambda x: isinstance(x, HySymbol) and (x[0] == "#" or "." not in x))
+ _tname = _symn | pexpr(sym("quote") + _symt)
return [many(
SYM |
- brackets(SYM, sym(":as"), name) |
+ brackets(SYM, sym(":as"), _symn) |
brackets(SYM, brackets(many(
- name + maybe(sym(":as") + name)))))]
+ _tname + maybe(sym(":as") + _tname)))))]
+
+ @staticmethod
+ def _unquote_required(kids):
+ for pair in kids:
+ yield map(lambda x: x[0] if isinstance(x, HyExpression) else x, pair)
@special("import", _importlike(HySymbol))
@special("require", _importlike(HySymbol, HyString))
@@ -1167,7 +1174,7 @@ class HyASTCompiler(object):
raise self._syntax_error(star,
"* in an import name list must be on its own")
else:
- assignments = [(k, v or k) for k, v in kids]
+ assignments = [(k, v or k) for k, v in self._unquote_required(kids)]
ast_module = ast_str(module, piecewise=True)
diff --git a/hy/lex/parser.py b/hy/lex/parser.py
index 6121125a..a2e74e47 100755
--- a/hy/lex/parser.py
+++ b/hy/lex/parser.py
@@ -17,7 +17,7 @@ from .lexer import lexer
from .exceptions import LexException, PrematureEndOfInput
-pg = ParserGenerator([rule.name for rule in lexer.rules] + ['$end'])
+pg = ParserGenerator([rule.name for rule in lexer.rules] + ['$end'], [('nonassoc', ['HASHOTHER'])])
def set_boundaries(fun):
@@ -112,6 +112,12 @@ def term_discard(state, p):
return p[2]
+@pg.production("term : QUOTE HASHOTHER")
+@set_boundaries
+def term_quote_hash(state, p):
+ return HyExpression([HySymbol("quote"), HySymbol(p[1].value)])
+
+
@pg.production("term : QUOTE term")
@set_quote_boundaries
def term_quote(state, p):
Note that using a straight quote will quote the tag name, but a quasiquote will quote a tag term. I think this can be considered a feature and not a bug. |
But then you wouldn't be able to use non-identifier characters in tag macros. |
I'm not sure I follow. How would one even use a tag macro with non-identifier characters? |
So it does. Sorry. I was probably remembering the old days when tag macros had to be only 1 character long, so you could name them nearly anything, like I'm still not entirely enthusiastic about using a quote form in place of a string literal, but I guess that's a matter of taste. |
I'm still getting the |
I haven't run my patch through any of the tests; it's also not a complete patch, just a proof-of-concept since the I have a mild preference for the quoting since it feels more lisp-y to me (importing a specific symbol vs naming with a string) but I'm happy with either direction. |
If it's going to be that big of a change to the core compiler code it may be worth going with string literals for now and making quoting it's own pr. That way we can focus on the removal of the concept of |
1934fd1
to
2d08185
Compare
Okay, the doc changes are in now. |
2d08185
to
a6e38cb
Compare
I'm noticing that this also lets us define non identifier tag macros which leads to weird behavior. |
You actually can call them, if you use mangled names. This is similar to the issue of how Python allows |
a6e38cb
to
e7125d5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a remaining reference to deftag
in docs/style-guide.rst
.
Are the changes in tests/native_tests/language.hy
related to tag macros or just refactoring while you were in the file?
@@ -403,6 +401,7 @@ in expansions." | |||
(assert (= "This is the local version of `nonlocal-test-macro` returning 3!" | |||
#test-module-tag-2 3))) | |||
|
|||
#@(pytest.mark.xfail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did this test start failing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the commit message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think I disagree with the (xfailed) assertion on line 447, but I'll make a separate issue for that.
e7125d5
to
0d05603
Compare
Removed.
The ones in their own commit, at the beginning of this PR, are just refactoring while I was in the file. |
0d05603
to
e95cdf3
Compare
It was passing when it shouldn't have because of mangling issues.
A tag-macro call is now syntactic sugar to call a macro on one argument when the macro's name starts with "#".
Such periods conflict with the use of periods for separating parts of a qualified `require`.
`#@` isn't always available at runtime, which leads to intermittent test failures.
e95cdf3
to
68264b2
Compare
I've reconstrued tag macros as macros whose names begin with "#", which you can call with special syntax. This simplifies a lot of internals and should remove various inconsistencies in the behavior of tag macros. To support this,
defmacro
andrequire
allow macros to be named with string literals instead of symbols.deftag
and#doc
are unnecessary and have been removed.I haven't updated the docs or NEWS yet. Tell me what you think.