Implemented &key and added tests

This commit is contained in:
James King 2013-04-18 22:27:38 -04:00
parent 263d7af0fc
commit 1080a457b1
3 changed files with 39 additions and 17 deletions

View File

@ -189,11 +189,12 @@ class HyASTCompiler(object):
return ret
def _parse_lambda_list(self, exprs):
""" Return FunctionDef parameter values from lambda list."""
exprs.reverse()
args = []
keywords = []
defaults = []
varargs = None
kwargs = {}
kwargs = None
lambda_keyword = None
while exprs:
@ -227,25 +228,30 @@ class HyASTCompiler(object):
varargs = str(expr)
elif lambda_keyword == "&key":
if type(expr) != HyDict:
raise TypeError("FOOBAR")
raise TypeError("There can only be one &key "
"argument")
else:
if len(keywords) > 0:
if len(defaults) > 0:
raise HyCompileError("There can only be "
"one &key argument")
keywords = [ast.keyword(arg=ast_str(k),
value=self.compile(v),
lineno=expr.start_line,
col_offset=expr.start_column)
for k, v in expr.items()]
# As you can see, Python has a funny way of
# defining keyword arguments.
for k in expr.keys():
args.append(k)
for v in expr.values():
defaults.append(self.compile(v))
elif lambda_keyword == "&optional":
# not implemented yet.
pass
elif lambda_keyword == "&kwargs":
if kwargs:
raise HyCompileError("There can only be one "
"&kwargs argument")
kwargs = str(expr)
if not kwargs:
kwargs = None
return args, keywords, varargs, kwargs
return args, defaults, varargs, kwargs
@builds(list)
def compile_raw_list(self, entries):
@ -1103,7 +1109,7 @@ class HyASTCompiler(object):
expression.start_line,
expression.start_column)
args, keywords, stararg, kwargs = self._parse_lambda_list(sig)
args, defaults, stararg, kwargs = self._parse_lambda_list(sig)
ret = ast.FunctionDef(
name=name,
@ -1120,8 +1126,8 @@ class HyASTCompiler(object):
vararg=stararg,
kwarg=kwargs,
kwonlyargs=[],
kw_defaults=keywords,
defaults=[]),
kw_defaults=[],
defaults=defaults),
body=body,
decorator_list=[])

View File

@ -334,14 +334,25 @@ def test_ast_tuple():
assert type(code) == ast.Tuple
def test_lambda_list_keywords():
def test_lambda_list_keywords_rest():
""" Ensure we can compile functions with lambda list keywords."""
hy_compile(tokenize("(fn (x &rest xs) (print xs))"))
cant_compile("(fn (x &rest xs &rest ys) (print xs))")
def test_lambda_list_keywords_optional():
""" Ensure we can compile functions with &optional."""
hy_compile(tokenize("(fn (x &optional (foo True)) foo)"))
def test_lambda_list_keywords_key():
""" Ensure we can compile functions with &key."""
hy_compile(tokenize("(fn (x &key {foo True}) (list x foo))"))
cant_compile("(fn (x &key {bar \"baz\"} &key {foo 42}) (list x bar foo))")
def test_lambda_list_keywords_kwargs():
""" Ensure we can compile functions with &kwargs."""
hy_compile(tokenize("(fn (x &kwargs kw) (list x kw))"))
cant_compile("(fn (x &kwargs xs &kwargs ys) (list x xs ys))")
def test_lambda_list_keywords_mixed():
""" Ensure we can mix them up."""
hy_compile(tokenize("(fn (x &rest xs &kwargs kw) (list x xs kw))"))
cant_compile("(fn (x &rest xs &key {bar \"baz\"}))")
def test_ast_unicode_strings():
"""Ensure we handle unicode strings correctly"""

View File

@ -616,3 +616,8 @@
(assert (= (dirname "/some/path") "/some"))
(assert (= op.dirname dirname))
(assert (= dn dirname)))
(defn test-lambda-keyword-lists []
"NATIVE: test lambda keyword lists"
(defn foo (x &rest xs &kwargs kw) [x xs kw])
(assert (= (foo 10 20 30) [10, (20, 30), {}])))