compiler: add else' support in
try'
This is a bit tricky, since we'll also have to support `finally' in the end, I've introduced an Else statement on my own to be able to recognize it. This fixes #74 Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
48d5a0abc0
commit
f8131d3c36
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
|
||||
|
||||
[ Syntax Fixes ]
|
||||
|
@ -199,6 +199,7 @@ class HyASTCompiler(object):
|
||||
expr.start_line,
|
||||
expr.start_column)
|
||||
|
||||
orelse = []
|
||||
if len(expr) == 0:
|
||||
# (try) or (try body)
|
||||
handlers = [ast.ExceptHandler(
|
||||
@ -209,8 +210,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,
|
||||
@ -218,7 +238,7 @@ class HyASTCompiler(object):
|
||||
body=body,
|
||||
handlers=handlers,
|
||||
finalbody=[],
|
||||
orelse=[])
|
||||
orelse=orelse)
|
||||
|
||||
@builds("catch")
|
||||
@builds("except")
|
||||
|
@ -116,8 +116,16 @@ 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():
|
||||
|
@ -235,7 +235,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"
|
||||
|
Loading…
Reference in New Issue
Block a user