Merge pull request #87 from jd/jd/try

compiler: add `else' support in `try'
This commit is contained in:
Julien Danjou 2013-04-09 08:23:41 -07:00
commit 92eaed21e4
4 changed files with 76 additions and 6 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

@ -216,6 +216,7 @@ class HyASTCompiler(object):
expr.start_line,
expr.start_column)
orelse = []
if len(expr) == 0:
# (try) or (try body)
handlers = [ast.ExceptHandler(
@ -226,8 +227,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,
@ -235,7 +255,7 @@ class HyASTCompiler(object):
body=body,
handlers=handlers,
finalbody=[],
orelse=[])
orelse=orelse)
@builds("catch")
@builds("except")

View File

@ -118,8 +118,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():

View File

@ -255,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"