try: add support for `finally'
This fixes #75 Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
403be35aa3
commit
fdb6bf944c
@ -235,12 +235,6 @@ class HyASTCompiler(object):
|
|||||||
def compile_try_expression(self, expr):
|
def compile_try_expression(self, expr):
|
||||||
expr.pop(0) # try
|
expr.pop(0) # try
|
||||||
|
|
||||||
if sys.version_info[0] >= 3 and sys.version_info[1] >= 3:
|
|
||||||
# Python 3.3 features a rename of TryExcept to Try.
|
|
||||||
Try = ast.Try
|
|
||||||
else:
|
|
||||||
Try = ast.TryExcept
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body = expr.pop(0)
|
body = expr.pop(0)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -252,17 +246,9 @@ class HyASTCompiler(object):
|
|||||||
expr.start_column)
|
expr.start_column)
|
||||||
|
|
||||||
orelse = []
|
orelse = []
|
||||||
if len(expr) == 0:
|
finalbody = []
|
||||||
# (try) or (try body)
|
|
||||||
handlers = [ast.ExceptHandler(
|
|
||||||
lineno=expr.start_line,
|
|
||||||
col_offset=expr.start_column,
|
|
||||||
type=None,
|
|
||||||
name=None,
|
|
||||||
body=[ast.Pass(lineno=expr.start_line,
|
|
||||||
col_offset=expr.start_column)])]
|
|
||||||
else:
|
|
||||||
handlers = []
|
handlers = []
|
||||||
|
|
||||||
for e in expr:
|
for e in expr:
|
||||||
if not len(e):
|
if not len(e):
|
||||||
raise TypeError("Empty list not allowed in `try'")
|
raise TypeError("Empty list not allowed in `try'")
|
||||||
@ -277,19 +263,67 @@ class HyASTCompiler(object):
|
|||||||
orelse = self._code_branch(self.compile(e[1:]),
|
orelse = self._code_branch(self.compile(e[1:]),
|
||||||
e.start_line,
|
e.start_line,
|
||||||
e.start_column)
|
e.start_column)
|
||||||
|
elif e[0] == HySymbol("finally"):
|
||||||
|
if finalbody:
|
||||||
|
raise TypeError(
|
||||||
|
"`try' cannot have more than one `finally'")
|
||||||
|
else:
|
||||||
|
finalbody = self._code_branch(self.compile(e[1:]),
|
||||||
|
e.start_line,
|
||||||
|
e.start_column)
|
||||||
else:
|
else:
|
||||||
raise TypeError("Unknown expression in `try'")
|
raise TypeError("Unknown expression in `try'")
|
||||||
|
|
||||||
if handlers == []:
|
# Using (else) without (except) is verboten!
|
||||||
|
if orelse and not handlers:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"`try' must have at least `except' or `finally'")
|
"`try' cannot have `else' without `except'")
|
||||||
|
|
||||||
return Try(
|
# (try) or (try BODY)
|
||||||
|
# Generate a default handler for Python >= 3.3 and pypy
|
||||||
|
if not handlers and not finalbody and not orelse:
|
||||||
|
handlers = [ast.ExceptHandler(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
type=None,
|
||||||
|
name=None,
|
||||||
|
body=[ast.Pass(lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column)])]
|
||||||
|
|
||||||
|
if sys.version_info[0] >= 3 and sys.version_info[1] >= 3:
|
||||||
|
# Python 3.3 features a merge of TryExcept+TryFinally into Try.
|
||||||
|
return ast.Try(
|
||||||
lineno=expr.start_line,
|
lineno=expr.start_line,
|
||||||
col_offset=expr.start_column,
|
col_offset=expr.start_column,
|
||||||
body=body,
|
body=body,
|
||||||
handlers=handlers,
|
handlers=handlers,
|
||||||
finalbody=[],
|
orelse=orelse,
|
||||||
|
finalbody=finalbody)
|
||||||
|
|
||||||
|
if finalbody:
|
||||||
|
if handlers:
|
||||||
|
return ast.TryFinally(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
body=[ast.TryExcept(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
handlers=handlers,
|
||||||
|
body=body,
|
||||||
|
orelse=orelse)],
|
||||||
|
finalbody=finalbody)
|
||||||
|
|
||||||
|
return ast.TryFinally(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
body=body,
|
||||||
|
finalbody=finalbody)
|
||||||
|
|
||||||
|
return ast.TryExcept(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
handlers=handlers,
|
||||||
|
body=body,
|
||||||
orelse=orelse)
|
orelse=orelse)
|
||||||
|
|
||||||
@builds("catch")
|
@builds("catch")
|
||||||
|
@ -123,6 +123,11 @@ def test_ast_good_try():
|
|||||||
hy_compile(tokenize("(try 1)"))
|
hy_compile(tokenize("(try 1)"))
|
||||||
hy_compile(tokenize("(try 1 (except) (else 1))"))
|
hy_compile(tokenize("(try 1 (except) (else 1))"))
|
||||||
hy_compile(tokenize("(try 1 (else 1) (except))"))
|
hy_compile(tokenize("(try 1 (else 1) (except))"))
|
||||||
|
hy_compile(tokenize("(try 1 (finally 1) (except))"))
|
||||||
|
hy_compile(tokenize("(try 1 (finally 1))"))
|
||||||
|
hy_compile(tokenize("(try 1 (except) (finally 1))"))
|
||||||
|
hy_compile(tokenize("(try 1 (except) (finally 1) (else 1))"))
|
||||||
|
hy_compile(tokenize("(try 1 (except) (else 1) (finally 1))"))
|
||||||
|
|
||||||
|
|
||||||
def test_ast_bad_try():
|
def test_ast_bad_try():
|
||||||
|
@ -198,6 +198,34 @@
|
|||||||
(setv passed true)))
|
(setv passed true)))
|
||||||
(assert passed))
|
(assert passed))
|
||||||
|
|
||||||
|
|
||||||
|
;; Test (finally)
|
||||||
|
(let [[passed false]]
|
||||||
|
(try
|
||||||
|
(pass)
|
||||||
|
(finally (setv passed true)))
|
||||||
|
(assert passed))
|
||||||
|
|
||||||
|
;; Test (finally) + (raise)
|
||||||
|
(let [[passed false]]
|
||||||
|
(try
|
||||||
|
(raise Exception)
|
||||||
|
(except)
|
||||||
|
(finally (setv passed true)))
|
||||||
|
(assert passed))
|
||||||
|
|
||||||
|
|
||||||
|
;; Test (finally) + (raise) + (else)
|
||||||
|
(let [[passed false]
|
||||||
|
[not-elsed true]]
|
||||||
|
(try
|
||||||
|
(raise Exception)
|
||||||
|
(except)
|
||||||
|
(else (setv not-elsed false))
|
||||||
|
(finally (setv passed true)))
|
||||||
|
(assert passed)
|
||||||
|
(assert not-elsed))
|
||||||
|
|
||||||
(try
|
(try
|
||||||
(raise (KeyError))
|
(raise (KeyError))
|
||||||
(catch [[IOError]] (assert false))
|
(catch [[IOError]] (assert false))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user