Merge branch 'master' into feature/quoting

This commit is contained in:
Paul R. Tagliamonte 2013-04-09 19:50:25 -04:00
commit a948cf2870
4 changed files with 132 additions and 20 deletions

10
NEWS
View File

@ -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
[ Syntax Fixes ]

View File

@ -38,7 +38,21 @@ import sys
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 = {}
@ -111,12 +125,15 @@ class HyASTCompiler(object):
for _type in _compile_table:
if type(tree) == _type:
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:
err = HyCompileError(str(e))
err.exception = e
err.start_line = getattr(e, "start_line", None)
err.start_column = getattr(e, "start_column", None)
raise err
raise HyCompileError(exception=e,
start_line=getattr(e, "start_line", 0),
start_column=getattr(e, "start_column", 0))
raise HyCompileError("Unknown type - `%s'" % (str(type(tree))))
@ -183,10 +200,10 @@ class HyASTCompiler(object):
@builds("throw")
@builds("raise")
@checkargs(min=1)
@checkargs(max=1)
def compile_throw_expression(self, expr):
expr.pop(0)
exc = self.compile(expr.pop(0))
exc = self.compile(expr.pop(0)) if expr else None
return ast.Raise(
lineno=expr.start_line,
col_offset=expr.start_column,
@ -215,6 +232,7 @@ class HyASTCompiler(object):
expr.start_line,
expr.start_column)
orelse = []
if len(expr) == 0:
# (try) or (try body)
handlers = [ast.ExceptHandler(
@ -225,8 +243,27 @@ class HyASTCompiler(object):
body=[ast.Pass(lineno=expr.start_line,
col_offset=expr.start_column)])]
else:
# (try body except except…)
handlers = [self.compile(s) for s in expr]
handlers = []
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(
lineno=expr.start_line,
@ -234,17 +271,17 @@ class HyASTCompiler(object):
body=body,
handlers=handlers,
finalbody=[],
orelse=[])
orelse=orelse)
@builds("catch")
@builds("except")
def compile_catch_expression(self, expr):
expr.pop(0) # catch
catch = expr.pop(0) # catch
try:
exceptions = expr.pop(0)
except IndexError:
exceptions = []
exceptions = HyList()
# exceptions catch should be either:
# [[list of exceptions]]
# or
@ -255,8 +292,10 @@ class HyASTCompiler(object):
# [exception]
# or
# []
if not isinstance(exceptions, HyList):
raise TypeError("`%s' exceptions list is not a list" % catch)
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]]
# let's pop variable and use it as name
@ -294,7 +333,7 @@ class HyASTCompiler(object):
elif isinstance(exceptions_list, HySymbol):
_type = self.compile(exceptions_list)
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],
expr.start_line,

View File

@ -94,30 +94,40 @@ def test_ast_good_do():
def test_ast_good_throw():
"Make sure AST can compile valid throw"
hy_compile(tokenize("(throw)"))
hy_compile(tokenize("(throw 1)"))
def test_ast_bad_throw():
"Make sure AST can't compile invalid throw"
cant_compile("(throw)")
cant_compile("(raise 1 2 3)")
def test_ast_good_raise():
"Make sure AST can compile valid raise"
hy_compile(tokenize("(raise)"))
hy_compile(tokenize("(raise 1)"))
def test_ast_bad_raise():
"Make sure AST can't compile invalid raise"
cant_compile("(raise)")
cant_compile("(raise 1 2 3)")
def test_ast_good_try():
"Make sure AST can compile valid try"
hy_compile(tokenize("(try)"))
hy_compile(tokenize("(try 1)"))
hy_compile(tokenize("(try 1 bla)"))
hy_compile(tokenize("(try 1 bla bla)"))
hy_compile(tokenize("(try 1 (except) (else 1))"))
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():
@ -134,6 +144,7 @@ def test_ast_good_catch():
def test_ast_bad_catch():
"Make sure AST can't compile invalid catch"
cant_compile("(catch 1)")
cant_compile("(catch \"A\")")
cant_compile("(catch [1 3])")
cant_compile("(catch [x [FooBar] BarBar])")

View File

@ -178,6 +178,26 @@
(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
(raise (KeyError))
(catch [[IOError]] (assert false))
@ -235,7 +255,39 @@
(print foobar42ofthebaz)
(catch []
(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 []
"NATIVE: Test earmuffs"