Move logic from macroexpand_1 to macroexpand
By ending macro-expansion immediately when appropriate, this change fixes a bug arising from the fact that NaN != NaN.
This commit is contained in:
parent
026316ebef
commit
c1a487cdf7
1
NEWS.rst
1
NEWS.rst
@ -42,6 +42,7 @@ Bug Fixes
|
||||
* Fixed a case where `->` and `->>` duplicated an argument
|
||||
* Fixed bugs that caused `defclass` to drop statements or crash
|
||||
* Fixed a REPL crash caused by illegle unicode escape string inputs
|
||||
* `NaN` can no longer create an infinite loop during macro-expansion
|
||||
|
||||
Misc. Improvements
|
||||
----------------------------
|
||||
|
25
hy/macros.py
25
hy/macros.py
@ -156,24 +156,16 @@ def make_empty_fn_copy(fn):
|
||||
return empty_fn
|
||||
|
||||
|
||||
def macroexpand(tree, compiler):
|
||||
def macroexpand(tree, compiler, once=False):
|
||||
"""Expand the toplevel macros for the `tree`.
|
||||
|
||||
Load the macros from the given `module_name`, then expand the (top-level)
|
||||
macros in `tree` until it stops changing.
|
||||
macros in `tree` until we no longer can.
|
||||
|
||||
"""
|
||||
load_macros(compiler.module_name)
|
||||
old = None
|
||||
while old != tree:
|
||||
old = tree
|
||||
tree = macroexpand_1(tree, compiler)
|
||||
return tree
|
||||
while True:
|
||||
|
||||
|
||||
def macroexpand_1(tree, compiler):
|
||||
"""Expand the toplevel macro from `tree` once, in the context of
|
||||
`module_name`."""
|
||||
if not isinstance(tree, HyExpression) or tree == []:
|
||||
return tree
|
||||
|
||||
@ -207,7 +199,16 @@ def macroexpand_1(tree, compiler):
|
||||
except Exception as e:
|
||||
msg = "expanding `" + str(tree[0]) + "': " + repr(e)
|
||||
raise HyMacroExpansionError(tree, msg)
|
||||
return replace_hy_obj(obj, tree)
|
||||
tree = replace_hy_obj(obj, tree)
|
||||
|
||||
if once:
|
||||
return tree
|
||||
|
||||
|
||||
def macroexpand_1(tree, compiler):
|
||||
"""Expand the toplevel macro from `tree` once, in the context of
|
||||
`compiler`."""
|
||||
return macroexpand(tree, compiler, once=True)
|
||||
|
||||
|
||||
def tag_macroexpand(tag, tree, compiler):
|
||||
|
@ -5,7 +5,7 @@
|
||||
from hy.macros import macro, macroexpand
|
||||
from hy.lex import tokenize
|
||||
|
||||
from hy.models import HyString, HyList, HySymbol, HyExpression
|
||||
from hy.models import HyString, HyList, HySymbol, HyExpression, HyFloat
|
||||
from hy.errors import HyMacroExpansionError
|
||||
|
||||
from hy.compiler import HyASTCompiler
|
||||
@ -53,3 +53,12 @@ def test_preprocessor_exceptions():
|
||||
except HyMacroExpansionError as e:
|
||||
assert "_hy_anon_fn_" not in str(e)
|
||||
assert "TypeError" not in str(e)
|
||||
|
||||
|
||||
def test_macroexpand_nan():
|
||||
# https://github.com/hylang/hy/issues/1574
|
||||
import math
|
||||
NaN = float('nan')
|
||||
x = macroexpand(HyFloat(NaN), HyASTCompiler(__name__))
|
||||
assert type(x) is HyFloat
|
||||
assert math.isnan(x)
|
||||
|
Loading…
x
Reference in New Issue
Block a user