Add special exception and handling for wrapper errors
This commit is contained in:
parent
4ae4baac2a
commit
9e62903d8a
@ -207,6 +207,15 @@ class HySyntaxError(HyLanguageError, SyntaxError):
|
|||||||
"""Error during the Lexing of a Hython expression."""
|
"""Error during the Lexing of a Hython expression."""
|
||||||
|
|
||||||
|
|
||||||
|
class HyWrapperError(HyError, TypeError):
|
||||||
|
"""Errors caused by language model object wrapping.
|
||||||
|
|
||||||
|
These can be caused by improper user-level use of a macro, so they're
|
||||||
|
not really "internal". If they arise due to anything else, they're an
|
||||||
|
internal/compiler problem, though.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _module_filter_name(module_name):
|
def _module_filter_name(module_name):
|
||||||
try:
|
try:
|
||||||
compiler_loader = pkgutil.get_loader(module_name)
|
compiler_loader = pkgutil.get_loader(module_name)
|
||||||
|
@ -342,10 +342,10 @@ def macroexpand(tree, module, compiler=None, once=False):
|
|||||||
with macro_exceptions(module, tree, compiler):
|
with macro_exceptions(module, tree, compiler):
|
||||||
obj = m(module.__name__, *tree[1:], **opts)
|
obj = m(module.__name__, *tree[1:], **opts)
|
||||||
|
|
||||||
if isinstance(obj, HyExpression):
|
if isinstance(obj, HyExpression):
|
||||||
obj.module = inspect.getmodule(m)
|
obj.module = inspect.getmodule(m)
|
||||||
|
|
||||||
tree = replace_hy_obj(obj, tree)
|
tree = replace_hy_obj(obj, tree)
|
||||||
|
|
||||||
if once:
|
if once:
|
||||||
break
|
break
|
||||||
|
@ -7,6 +7,7 @@ from contextlib import contextmanager
|
|||||||
from math import isnan, isinf
|
from math import isnan, isinf
|
||||||
from hy import _initialize_env_var
|
from hy import _initialize_env_var
|
||||||
from hy._compat import PY3, str_type, bytes_type, long_type, string_types
|
from hy._compat import PY3, str_type, bytes_type, long_type, string_types
|
||||||
|
from hy.errors import HyWrapperError
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from clint.textui import colored
|
from clint.textui import colored
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ def wrap_value(x):
|
|||||||
|
|
||||||
new = _wrappers.get(type(x), lambda y: y)(x)
|
new = _wrappers.get(type(x), lambda y: y)(x)
|
||||||
if not isinstance(new, HyObject):
|
if not isinstance(new, HyObject):
|
||||||
raise TypeError("Don't know how to wrap {!r}: {!r}".format(type(x), x))
|
raise HyWrapperError("Don't know how to wrap {!r}: {!r}".format(type(x), x))
|
||||||
if isinstance(x, HyObject):
|
if isinstance(x, HyObject):
|
||||||
new = new.replace(x, recursive=False)
|
new = new.replace(x, recursive=False)
|
||||||
if not hasattr(new, "start_column"):
|
if not hasattr(new, "start_column"):
|
||||||
|
@ -162,8 +162,8 @@
|
|||||||
")
|
")
|
||||||
;; expand the macro twice, should use a different
|
;; expand the macro twice, should use a different
|
||||||
;; gensym each time
|
;; gensym each time
|
||||||
(setv _ast1 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast1 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv _ast2 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast2 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv s1 (to_source _ast1))
|
(setv s1 (to_source _ast1))
|
||||||
(setv s2 (to_source _ast2))
|
(setv s2 (to_source _ast2))
|
||||||
;; and make sure there is something new that starts with _;G|
|
;; and make sure there is something new that starts with _;G|
|
||||||
@ -189,8 +189,8 @@
|
|||||||
")
|
")
|
||||||
;; expand the macro twice, should use a different
|
;; expand the macro twice, should use a different
|
||||||
;; gensym each time
|
;; gensym each time
|
||||||
(setv _ast1 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast1 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv _ast2 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast2 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv s1 (to_source _ast1))
|
(setv s1 (to_source _ast1))
|
||||||
(setv s2 (to_source _ast2))
|
(setv s2 (to_source _ast2))
|
||||||
(assert (in (mangle "_;a|") s1))
|
(assert (in (mangle "_;a|") s1))
|
||||||
@ -213,8 +213,8 @@
|
|||||||
")
|
")
|
||||||
;; expand the macro twice, should use a different
|
;; expand the macro twice, should use a different
|
||||||
;; gensym each time
|
;; gensym each time
|
||||||
(setv _ast1 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast1 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv _ast2 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast2 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv s1 (to_source _ast1))
|
(setv s1 (to_source _ast1))
|
||||||
(setv s2 (to_source _ast2))
|
(setv s2 (to_source _ast2))
|
||||||
(assert (in (mangle "_;res|") s1))
|
(assert (in (mangle "_;res|") s1))
|
||||||
@ -224,7 +224,7 @@
|
|||||||
;; defmacro/g! didn't like numbers initially because they
|
;; defmacro/g! didn't like numbers initially because they
|
||||||
;; don't have a startswith method and blew up during expansion
|
;; don't have a startswith method and blew up during expansion
|
||||||
(setv macro2 "(defmacro/g! two-point-zero [] `(+ (float 1) 1.0))")
|
(setv macro2 "(defmacro/g! two-point-zero [] `(+ (float 1) 1.0))")
|
||||||
(assert (hy-compile (hy-parse macro2) "foo")))
|
(assert (hy-compile (hy-parse macro2) __name__)))
|
||||||
|
|
||||||
(defn test-defmacro! []
|
(defn test-defmacro! []
|
||||||
;; defmacro! must do everything defmacro/g! can
|
;; defmacro! must do everything defmacro/g! can
|
||||||
@ -243,8 +243,8 @@
|
|||||||
")
|
")
|
||||||
;; expand the macro twice, should use a different
|
;; expand the macro twice, should use a different
|
||||||
;; gensym each time
|
;; gensym each time
|
||||||
(setv _ast1 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast1 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv _ast2 (hy-compile (hy-parse macro1) "foo"))
|
(setv _ast2 (hy-compile (hy-parse macro1) __name__))
|
||||||
(setv s1 (to_source _ast1))
|
(setv s1 (to_source _ast1))
|
||||||
(setv s2 (to_source _ast2))
|
(setv s2 (to_source _ast2))
|
||||||
(assert (in (mangle "_;res|") s1))
|
(assert (in (mangle "_;res|") s1))
|
||||||
@ -254,7 +254,7 @@
|
|||||||
;; defmacro/g! didn't like numbers initially because they
|
;; defmacro/g! didn't like numbers initially because they
|
||||||
;; don't have a startswith method and blew up during expansion
|
;; don't have a startswith method and blew up during expansion
|
||||||
(setv macro2 "(defmacro! two-point-zero [] `(+ (float 1) 1.0))")
|
(setv macro2 "(defmacro! two-point-zero [] `(+ (float 1) 1.0))")
|
||||||
(assert (hy-compile (hy-parse macro2) "foo"))
|
(assert (hy-compile (hy-parse macro2) __name__))
|
||||||
|
|
||||||
(defmacro! foo! [o!foo] `(do ~g!foo ~g!foo))
|
(defmacro! foo! [o!foo] `(do ~g!foo ~g!foo))
|
||||||
;; test that o! becomes g!
|
;; test that o! becomes g!
|
||||||
@ -507,4 +507,13 @@ in expansions."
|
|||||||
(assert (= (cut expected 0 -1) (cut output 0 -1)))
|
(assert (= (cut expected 0 -1) (cut output 0 -1)))
|
||||||
(assert (or (= (get expected -1) (get output -1))
|
(assert (or (= (get expected -1) (get output -1))
|
||||||
;; Handle PyPy's peculiarities
|
;; Handle PyPy's peculiarities
|
||||||
(= (.replace (get expected -1) "global " "") (get output -1)))))
|
(= (.replace (get expected -1) "global " "") (get output -1))))
|
||||||
|
|
||||||
|
|
||||||
|
;; This should throw a `HyWrapperError` that gets turned into a
|
||||||
|
;; `HyMacroExpansionError`.
|
||||||
|
(with [excinfo (pytest.raises HyMacroExpansionError)]
|
||||||
|
(eval '(do (defmacro wrap-error-test []
|
||||||
|
(fn []))
|
||||||
|
(wrap-error-test))))
|
||||||
|
(assert (in "HyWrapperError" (str excinfo.value))))
|
||||||
|
Loading…
Reference in New Issue
Block a user