Merge branch 'master' into bugfix/paultag/fix-try-except

This commit is contained in:
Paul Tagliamonte 2013-05-08 20:22:51 -04:00
commit 98134e7396
4 changed files with 69 additions and 5 deletions

View File

@ -193,9 +193,13 @@ class Result(object):
This is useful when we want to use the stored expression in a
statement context (for instance in a code branch).
We drop ast.Names if they are appended to statements, as they
can't have any side effect. "Bare" names still get converted to
statements.
If there is no expression context, return an empty result.
"""
if self.expr:
if self.expr and not (isinstance(self.expr, ast.Name) and self.stmts):
return Result() + ast.Expr(lineno=self.expr.lineno,
col_offset=self.expr.col_offset,
value=self.expr)
@ -402,6 +406,9 @@ class HyASTCompiler(object):
if expr == "&rest" and lambda_keyword is None:
lambda_keyword = expr
elif expr == "&optional":
if len(defaults) > 0:
raise HyCompileError("There can only be &optional "
"arguments or one &key argument")
lambda_keyword = expr
elif expr == "&key":
lambda_keyword = expr
@ -427,8 +434,8 @@ class HyASTCompiler(object):
"argument")
else:
if len(defaults) > 0:
raise HyCompileError("There can only be "
"one &key argument")
raise HyCompileError("There can only be &optional "
"arguments or one &key argument")
# As you can see, Python has a funny way of
# defining keyword arguments.
for k, v in expr.items():
@ -436,8 +443,17 @@ class HyASTCompiler(object):
ret += self.compile(v)
defaults.append(ret.force_expr)
elif lambda_keyword == "&optional":
# not implemented yet.
pass
if isinstance(expr, HyList):
if not len(expr) == 2:
raise TypeError("optional args should be bare names "
"or 2-item lists")
k, v = expr
else:
k = expr
v = HySymbol("None").replace(k)
args.append(k)
ret += self.compile(v)
defaults.append(ret.force_expr)
elif lambda_keyword == "&kwargs":
if kwargs:
raise HyCompileError("There can only be one "

View File

@ -352,6 +352,13 @@ def test_ast_non_kwapplyable():
pass
def test_ast_lambda_lists():
"""Ensure the compiler chokes on invalid lambda-lists"""
cant_compile('(fn [&key {"a" b} &key {"foo" bar}] [a foo])')
cant_compile('(fn [&optional a &key {"foo" bar}] [a foo])')
cant_compile('(fn [&optional [a b c]] a)')
def test_ast_print():
code = hy_compile(tokenize("(print \"foo\")")).body[0]

View File

@ -1,4 +1,5 @@
# Copyright (c) 2013 Julien Danjou <julien@danjou.info>
# Copyright (c) 2013 Nicolas Dandrimont <nicolas.dandrimont@crans.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@ -29,6 +30,7 @@ else:
from hy.models.expression import HyExpression
from hy.models.list import HyList
from hy.models.symbol import HySymbol
from hy.compiler import HyASTCompiler
@ -63,3 +65,26 @@ class HyASTCompilerTest(unittest.TestCase):
self.assertIsInstance(stmt.body[0], ast.Pass)
self.assertIsInstance(ret.expr, ast.Name)
def test_compiler_bare_names(self):
"""
Check that the compiler doesn't drop bare names from code branches
"""
ret = self.c.compile(self._make_expression(HySymbol("do"),
HySymbol("a"),
HySymbol("b"),
HySymbol("c")))
# We expect two statements and a final expr.
self.assertEqual(len(ret.stmts), 2)
stmt = ret.stmts[0]
self.assertIsInstance(stmt, ast.Expr)
self.assertIsInstance(stmt.value, ast.Name)
self.assertEqual(stmt.value.id, "a")
stmt = ret.stmts[1]
self.assertIsInstance(stmt, ast.Expr)
self.assertIsInstance(stmt.value, ast.Name)
self.assertEqual(stmt.value.id, "b")
expr = ret.expr
self.assertIsInstance(expr, ast.Name)
self.assertEqual(expr.id, "c")

View File

@ -637,6 +637,22 @@
(assert (= (foo 10 20 30) [10 (, 20 30) {}])))
(defn test-key-arguments []
"NATIVE: test &key function arguments"
(defn foo [&key {"a" None "b" 1}] [a b])
(assert (= (foo) [None 1]))
(assert (= (kwapply (foo) {"a" 2}) [2 1]))
(assert (= (kwapply (foo) {"b" 42}) [None 42])))
(defn test-optional-arguments []
"NATIVE: test &optional function arguments"
(defn foo [a b &optional c [d 42]] [a b c d])
(assert (= (foo 1 2) [1 2 None 42]))
(assert (= (foo 1 2 3) [1 2 3 42]))
(assert (= (foo 1 2 3 4) [1 2 3 4])))
(defn test-quoted-hoistable []
"NATIVE: test quoted hoistable"
(setf f (quote (if true true true)))