Add &optional arguments.

Python doesn't really have that concept, so make them clash with &key arguments.
This commit is contained in:
Nicolas Dandrimont 2013-05-08 20:56:16 +02:00
parent 5dbf6c6ca9
commit 4e3f842972
3 changed files with 26 additions and 4 deletions

View File

@ -402,6 +402,9 @@ class HyASTCompiler(object):
if expr == "&rest" and lambda_keyword is None: if expr == "&rest" and lambda_keyword is None:
lambda_keyword = expr lambda_keyword = expr
elif expr == "&optional": elif expr == "&optional":
if len(defaults) > 0:
raise HyCompileError("There can only be &optional "
"arguments or one &key argument")
lambda_keyword = expr lambda_keyword = expr
elif expr == "&key": elif expr == "&key":
lambda_keyword = expr lambda_keyword = expr
@ -427,8 +430,8 @@ class HyASTCompiler(object):
"argument") "argument")
else: else:
if len(defaults) > 0: if len(defaults) > 0:
raise HyCompileError("There can only be " raise HyCompileError("There can only be &optional "
"one &key argument") "arguments or one &key argument")
# As you can see, Python has a funny way of # As you can see, Python has a funny way of
# defining keyword arguments. # defining keyword arguments.
for k, v in expr.items(): for k, v in expr.items():
@ -436,8 +439,17 @@ class HyASTCompiler(object):
ret += self.compile(v) ret += self.compile(v)
defaults.append(ret.force_expr) defaults.append(ret.force_expr)
elif lambda_keyword == "&optional": elif lambda_keyword == "&optional":
# not implemented yet. if isinstance(expr, HyList):
pass 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": elif lambda_keyword == "&kwargs":
if kwargs: if kwargs:
raise HyCompileError("There can only be one " raise HyCompileError("There can only be one "

View File

@ -353,6 +353,8 @@ def test_ast_non_kwapplyable():
def test_ast_lambda_lists(): def test_ast_lambda_lists():
"""Ensure the compiler chokes on invalid lambda-lists""" """Ensure the compiler chokes on invalid lambda-lists"""
cant_compile('(fn [&key {"a" b} &key {"foo" bar}] [a foo])') 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(): def test_ast_print():

View File

@ -645,6 +645,14 @@
(assert (= (kwapply (foo) {"b" 42}) [None 42]))) (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 [] (defn test-quoted-hoistable []
"NATIVE: test quoted hoistable" "NATIVE: test quoted hoistable"
(setf f (quote (if true true true))) (setf f (quote (if true true true)))