Merge branch 'master' into feature/quoting
This commit is contained in:
commit
a948cf2870
10
NEWS
10
NEWS
@ -1,3 +1,13 @@
|
|||||||
|
Changes from Hy 0.9.4
|
||||||
|
|
||||||
|
[ Syntax Fixes ]
|
||||||
|
|
||||||
|
* `try' now accepts `else': (JD)
|
||||||
|
(try BODY
|
||||||
|
(except [] BODY)
|
||||||
|
(else BODY))
|
||||||
|
|
||||||
|
|
||||||
Changes from Hy 0.9.4
|
Changes from Hy 0.9.4
|
||||||
|
|
||||||
[ Syntax Fixes ]
|
[ Syntax Fixes ]
|
||||||
|
@ -38,7 +38,21 @@ import sys
|
|||||||
|
|
||||||
|
|
||||||
class HyCompileError(HyError):
|
class HyCompileError(HyError):
|
||||||
pass
|
def __init__(self, exception,
|
||||||
|
start_line=0, start_column=0):
|
||||||
|
self.exception = exception
|
||||||
|
self.start_line = start_line
|
||||||
|
self.start_column = start_column
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.start_line == 0:
|
||||||
|
return("Internal Compiler Bug\n⤷ %s: %s"
|
||||||
|
% (self.exception.__class__.__name__,
|
||||||
|
self.exception))
|
||||||
|
return ("Compilation error at line %d, column %d\n%s: %s"
|
||||||
|
% (self.start_line, self.start_column,
|
||||||
|
self.exception.__class__.__name__,
|
||||||
|
self.exception))
|
||||||
|
|
||||||
|
|
||||||
_compile_table = {}
|
_compile_table = {}
|
||||||
@ -111,12 +125,15 @@ class HyASTCompiler(object):
|
|||||||
for _type in _compile_table:
|
for _type in _compile_table:
|
||||||
if type(tree) == _type:
|
if type(tree) == _type:
|
||||||
return _compile_table[_type](self, tree)
|
return _compile_table[_type](self, tree)
|
||||||
|
except HyCompileError:
|
||||||
|
# compile calls compile, so we're going to have multiple raise
|
||||||
|
# nested; so let's re-raise this exception, let's not wrap it in
|
||||||
|
# another HyCompileError!
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = HyCompileError(str(e))
|
raise HyCompileError(exception=e,
|
||||||
err.exception = e
|
start_line=getattr(e, "start_line", 0),
|
||||||
err.start_line = getattr(e, "start_line", None)
|
start_column=getattr(e, "start_column", 0))
|
||||||
err.start_column = getattr(e, "start_column", None)
|
|
||||||
raise err
|
|
||||||
|
|
||||||
raise HyCompileError("Unknown type - `%s'" % (str(type(tree))))
|
raise HyCompileError("Unknown type - `%s'" % (str(type(tree))))
|
||||||
|
|
||||||
@ -183,10 +200,10 @@ class HyASTCompiler(object):
|
|||||||
|
|
||||||
@builds("throw")
|
@builds("throw")
|
||||||
@builds("raise")
|
@builds("raise")
|
||||||
@checkargs(min=1)
|
@checkargs(max=1)
|
||||||
def compile_throw_expression(self, expr):
|
def compile_throw_expression(self, expr):
|
||||||
expr.pop(0)
|
expr.pop(0)
|
||||||
exc = self.compile(expr.pop(0))
|
exc = self.compile(expr.pop(0)) if expr else None
|
||||||
return ast.Raise(
|
return ast.Raise(
|
||||||
lineno=expr.start_line,
|
lineno=expr.start_line,
|
||||||
col_offset=expr.start_column,
|
col_offset=expr.start_column,
|
||||||
@ -215,6 +232,7 @@ class HyASTCompiler(object):
|
|||||||
expr.start_line,
|
expr.start_line,
|
||||||
expr.start_column)
|
expr.start_column)
|
||||||
|
|
||||||
|
orelse = []
|
||||||
if len(expr) == 0:
|
if len(expr) == 0:
|
||||||
# (try) or (try body)
|
# (try) or (try body)
|
||||||
handlers = [ast.ExceptHandler(
|
handlers = [ast.ExceptHandler(
|
||||||
@ -225,8 +243,27 @@ class HyASTCompiler(object):
|
|||||||
body=[ast.Pass(lineno=expr.start_line,
|
body=[ast.Pass(lineno=expr.start_line,
|
||||||
col_offset=expr.start_column)])]
|
col_offset=expr.start_column)])]
|
||||||
else:
|
else:
|
||||||
# (try body except except…)
|
handlers = []
|
||||||
handlers = [self.compile(s) for s in expr]
|
for e in expr:
|
||||||
|
if not len(e):
|
||||||
|
raise TypeError("Empty list not allowed in `try'")
|
||||||
|
|
||||||
|
if e[0] in (HySymbol("except"), HySymbol("catch")):
|
||||||
|
handlers.append(self.compile(e))
|
||||||
|
elif e[0] == HySymbol("else"):
|
||||||
|
if orelse:
|
||||||
|
raise TypeError(
|
||||||
|
"`try' cannot have more than one `else'")
|
||||||
|
else:
|
||||||
|
orelse = self._code_branch(self.compile(e[1:]),
|
||||||
|
e.start_line,
|
||||||
|
e.start_column)
|
||||||
|
else:
|
||||||
|
raise TypeError("Unknown expression in `try'")
|
||||||
|
|
||||||
|
if handlers == []:
|
||||||
|
raise TypeError(
|
||||||
|
"`try' must have at least `except' or `finally'")
|
||||||
|
|
||||||
return Try(
|
return Try(
|
||||||
lineno=expr.start_line,
|
lineno=expr.start_line,
|
||||||
@ -234,17 +271,17 @@ class HyASTCompiler(object):
|
|||||||
body=body,
|
body=body,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
finalbody=[],
|
finalbody=[],
|
||||||
orelse=[])
|
orelse=orelse)
|
||||||
|
|
||||||
@builds("catch")
|
@builds("catch")
|
||||||
@builds("except")
|
@builds("except")
|
||||||
def compile_catch_expression(self, expr):
|
def compile_catch_expression(self, expr):
|
||||||
expr.pop(0) # catch
|
catch = expr.pop(0) # catch
|
||||||
|
|
||||||
try:
|
try:
|
||||||
exceptions = expr.pop(0)
|
exceptions = expr.pop(0)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
exceptions = []
|
exceptions = HyList()
|
||||||
# exceptions catch should be either:
|
# exceptions catch should be either:
|
||||||
# [[list of exceptions]]
|
# [[list of exceptions]]
|
||||||
# or
|
# or
|
||||||
@ -255,8 +292,10 @@ class HyASTCompiler(object):
|
|||||||
# [exception]
|
# [exception]
|
||||||
# or
|
# or
|
||||||
# []
|
# []
|
||||||
|
if not isinstance(exceptions, HyList):
|
||||||
|
raise TypeError("`%s' exceptions list is not a list" % catch)
|
||||||
if len(exceptions) > 2:
|
if len(exceptions) > 2:
|
||||||
raise TypeError("`catch' exceptions list is too long")
|
raise TypeError("`%s' exceptions list is too long" % catch)
|
||||||
|
|
||||||
# [variable [list of exceptions]]
|
# [variable [list of exceptions]]
|
||||||
# let's pop variable and use it as name
|
# let's pop variable and use it as name
|
||||||
@ -294,7 +333,7 @@ class HyASTCompiler(object):
|
|||||||
elif isinstance(exceptions_list, HySymbol):
|
elif isinstance(exceptions_list, HySymbol):
|
||||||
_type = self.compile(exceptions_list)
|
_type = self.compile(exceptions_list)
|
||||||
else:
|
else:
|
||||||
raise TypeError("`catch' needs a valid exception list to catch")
|
raise TypeError("`%s' needs a valid exception list" % catch)
|
||||||
|
|
||||||
body = self._code_branch([self.compile(x) for x in expr],
|
body = self._code_branch([self.compile(x) for x in expr],
|
||||||
expr.start_line,
|
expr.start_line,
|
||||||
|
@ -94,30 +94,40 @@ def test_ast_good_do():
|
|||||||
|
|
||||||
def test_ast_good_throw():
|
def test_ast_good_throw():
|
||||||
"Make sure AST can compile valid throw"
|
"Make sure AST can compile valid throw"
|
||||||
|
hy_compile(tokenize("(throw)"))
|
||||||
hy_compile(tokenize("(throw 1)"))
|
hy_compile(tokenize("(throw 1)"))
|
||||||
|
|
||||||
|
|
||||||
def test_ast_bad_throw():
|
def test_ast_bad_throw():
|
||||||
"Make sure AST can't compile invalid throw"
|
"Make sure AST can't compile invalid throw"
|
||||||
cant_compile("(throw)")
|
cant_compile("(raise 1 2 3)")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_good_raise():
|
def test_ast_good_raise():
|
||||||
"Make sure AST can compile valid raise"
|
"Make sure AST can compile valid raise"
|
||||||
|
hy_compile(tokenize("(raise)"))
|
||||||
hy_compile(tokenize("(raise 1)"))
|
hy_compile(tokenize("(raise 1)"))
|
||||||
|
|
||||||
|
|
||||||
def test_ast_bad_raise():
|
def test_ast_bad_raise():
|
||||||
"Make sure AST can't compile invalid raise"
|
"Make sure AST can't compile invalid raise"
|
||||||
cant_compile("(raise)")
|
cant_compile("(raise 1 2 3)")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_good_try():
|
def test_ast_good_try():
|
||||||
"Make sure AST can compile valid try"
|
"Make sure AST can compile valid try"
|
||||||
hy_compile(tokenize("(try)"))
|
hy_compile(tokenize("(try)"))
|
||||||
hy_compile(tokenize("(try 1)"))
|
hy_compile(tokenize("(try 1)"))
|
||||||
hy_compile(tokenize("(try 1 bla)"))
|
hy_compile(tokenize("(try 1 (except) (else 1))"))
|
||||||
hy_compile(tokenize("(try 1 bla bla)"))
|
hy_compile(tokenize("(try 1 (else 1) (except))"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_ast_bad_try():
|
||||||
|
"Make sure AST can't compile invalid try"
|
||||||
|
cant_compile("(try 1 bla)")
|
||||||
|
cant_compile("(try 1 bla bla)")
|
||||||
|
cant_compile("(try (do) (else 1) (else 2))")
|
||||||
|
cant_compile("(try 1 (else 1))")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_good_catch():
|
def test_ast_good_catch():
|
||||||
@ -134,6 +144,7 @@ def test_ast_good_catch():
|
|||||||
def test_ast_bad_catch():
|
def test_ast_bad_catch():
|
||||||
"Make sure AST can't compile invalid catch"
|
"Make sure AST can't compile invalid catch"
|
||||||
cant_compile("(catch 1)")
|
cant_compile("(catch 1)")
|
||||||
|
cant_compile("(catch \"A\")")
|
||||||
cant_compile("(catch [1 3])")
|
cant_compile("(catch [1 3])")
|
||||||
cant_compile("(catch [x [FooBar] BarBar])")
|
cant_compile("(catch [x [FooBar] BarBar])")
|
||||||
|
|
||||||
|
@ -178,6 +178,26 @@
|
|||||||
|
|
||||||
(try (pass) (except [IOError]) (except))
|
(try (pass) (except [IOError]) (except))
|
||||||
|
|
||||||
|
;; Test correct (raise)
|
||||||
|
(let [[passed false]]
|
||||||
|
(try
|
||||||
|
(try
|
||||||
|
(raise IndexError)
|
||||||
|
(except [IndexError] (raise)))
|
||||||
|
(except [IndexError]
|
||||||
|
(setv passed true)))
|
||||||
|
(assert passed))
|
||||||
|
|
||||||
|
;; Test incorrect (raise)
|
||||||
|
(let [[passed false]]
|
||||||
|
(try
|
||||||
|
(raise)
|
||||||
|
;; Python 2 raises TypeError
|
||||||
|
;; Python 3 raises RuntimeError
|
||||||
|
(except [[TypeError RuntimeError]]
|
||||||
|
(setv passed true)))
|
||||||
|
(assert passed))
|
||||||
|
|
||||||
(try
|
(try
|
||||||
(raise (KeyError))
|
(raise (KeyError))
|
||||||
(catch [[IOError]] (assert false))
|
(catch [[IOError]] (assert false))
|
||||||
@ -235,7 +255,39 @@
|
|||||||
(print foobar42ofthebaz)
|
(print foobar42ofthebaz)
|
||||||
(catch []
|
(catch []
|
||||||
(setv foobar42ofthebaz 42)
|
(setv foobar42ofthebaz 42)
|
||||||
(assert (= foobar42ofthebaz 42)))))
|
(assert (= foobar42ofthebaz 42))))
|
||||||
|
|
||||||
|
(let [[passed false]]
|
||||||
|
(try
|
||||||
|
(try (pass) (except) (else (bla)))
|
||||||
|
(except [NameError] (setv passed true)))
|
||||||
|
(assert passed))
|
||||||
|
|
||||||
|
(let [[x 0]]
|
||||||
|
(try
|
||||||
|
(raise IOError)
|
||||||
|
(except [IOError]
|
||||||
|
(setv x 45))
|
||||||
|
(else (setv x 44)))
|
||||||
|
(assert (= x 45)))
|
||||||
|
|
||||||
|
(let [[x 0]]
|
||||||
|
(try
|
||||||
|
(raise KeyError)
|
||||||
|
(except []
|
||||||
|
(setv x 45))
|
||||||
|
(else (setv x 44)))
|
||||||
|
(assert (= x 45)))
|
||||||
|
|
||||||
|
(let [[x 0]]
|
||||||
|
(try
|
||||||
|
(try
|
||||||
|
(raise KeyError)
|
||||||
|
(except [IOError]
|
||||||
|
(setv x 45))
|
||||||
|
(else (setv x 44)))
|
||||||
|
(except))
|
||||||
|
(assert (= x 0))))
|
||||||
|
|
||||||
(defn test-earmuffs []
|
(defn test-earmuffs []
|
||||||
"NATIVE: Test earmuffs"
|
"NATIVE: Test earmuffs"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user