From dda291cfb5c39cbd337592aae46dc485363d4449 Mon Sep 17 00:00:00 2001 From: Guillermo Vaya Date: Tue, 16 Jul 2013 14:35:57 +0200 Subject: [PATCH] make assoc accept multiple values, also added a even/odd check for checkargs --- hy/compiler.py | 41 +++++++++++++++++++++------------- tests/native_tests/language.hy | 5 +++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index 2e4e2b7..5b23272 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -318,7 +318,7 @@ def _raise_wrong_args_number(expression, error): len(expression))) -def checkargs(exact=None, min=None, max=None): +def checkargs(exact=None, min=None, max=None, even=None): def _dec(fn): def checker(self, expression): if exact is not None and (len(expression) - 1) != exact: @@ -334,6 +334,11 @@ def checkargs(exact=None, min=None, max=None): _raise_wrong_args_number( expression, "`%%s' needs at most %d arguments, got %%d" % (max)) + + is_even = not((len(expression) - 1) % 2) + if even is not None and is_even!=even: + even_str = "even" if even else "odd" + _raise_wrong_args_number(expression, "`%%s' needs an %s number of arguments, got %%d" % (even_str)) return fn(self, expression) @@ -1130,25 +1135,31 @@ class HyASTCompiler(object): ctx=ast.Load()) @builds("assoc") - @checkargs(3) + @checkargs(min=3, even=False) def compile_assoc_expression(self, expr): expr.pop(0) # assoc # (assoc foo bar baz) => foo[bar] = baz target = self.compile(expr.pop(0)) - key = self.compile(expr.pop(0)) - val = self.compile(expr.pop(0)) + ret = target + while expr != []: + key = self.compile(expr.pop(0)) + try: + val = self.compile(expr.pop(0)) + except IndexError: + raise HyCompileError("Key {key} has no value to associate".format(key)) - return target + key + val + ast.Assign( - lineno=expr.start_line, - col_offset=expr.start_column, - targets=[ - ast.Subscript( - lineno=expr.start_line, - col_offset=expr.start_column, - value=target.force_expr, - slice=ast.Index(value=key.force_expr), - ctx=ast.Store())], - value=val.force_expr) + ret += key + val + ast.Assign( + lineno=expr.start_line, + col_offset=expr.start_column, + targets=[ + ast.Subscript( + lineno=expr.start_line, + col_offset=expr.start_column, + value=target.force_expr, + slice=ast.Index(value=key.force_expr), + ctx=ast.Store())], + value=val.force_expr) + return ret @builds("with_decorator") @checkargs(min=1) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index fa55e27..be2393c 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -348,6 +348,11 @@ (assoc vals "two" "three") (assert (= (get vals "two") "three"))) +(defn test-multiassoc [] + "NATIVE: test assoc multiple values" + (setv vals {"one" "two"}) + (assoc vals "two" "three" "four" "five") + (assert (and (= (get vals "two") "three") (= (get vals "four") "five")))) (defn test-pass [] "NATIVE: Test pass worksish"