From f5754b404e24d7621a4e0f9bf604788848285e1e Mon Sep 17 00:00:00 2001 From: Guillermo Vaya Date: Wed, 24 Jul 2013 00:25:48 +0200 Subject: [PATCH] Define kwapply as a macro Define apply if python3 Added apply tests --- hy/compiler.py | 36 ++++++++++++++++++++++++---------- hy/core/language.hy | 4 ++-- hy/core/macros.hy | 13 ++++++++++++ tests/native_tests/language.hy | 17 +++++++++++++++- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index f14c79f..a1ef47d 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1255,19 +1255,35 @@ class HyASTCompiler(object): return ret - @builds("kwapply") - @checkargs(2) - def compile_kwapply_expression(self, expr): - expr.pop(0) # kwapply - call = self.compile(expr.pop(0)) - kwargs = self.compile(expr.pop(0)) + # apply only needs to be defined for python3 + if sys.version_info[0] >= 3: + @builds("apply") + @checkargs(min=2, max=3) + def compile_apply_expression(self, expr): + expr.pop(0) # apply + call = self.compile(expr.pop(0)) + call = ast.Call(func=call.expr, + args=[], + keywords=[], + starargs=None, + kwargs=None, + lineno=expr.start_line, + col_offset=expr.start_column) + ret = call - if type(call.expr) != ast.Call: - raise HyTypeError(expr, "kwapplying a non-call") + #add star args if any + stargs = expr.pop(0) + if stargs is not None: + stargs = self.compile(stargs) + call.starargs = stargs.force_expr + ret = stargs + ret - call.expr.kwargs = kwargs.force_expr + if expr != []: + kwargs = self.compile(expr.pop(0)) + call.kwargs = kwargs.force_expr + ret = kwargs + ret - return kwargs + call + return ret @builds("not") @builds("~") diff --git a/hy/core/language.hy b/hy/core/language.hy index a96b25d..7574dc0 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -213,8 +213,8 @@ (= n 0)) (def *exports* ["cycle" "dec" "distinct" "drop" "drop_while" "empty?" - "even?" "filter" "float?" "inc" - "instance?" "integer?" "iterable?" "iterate" "iterator?" "neg?" + "even?" "filter" "float?" "inc" "instance?" "integer?" + "iterable?" "iterate" "iterator?" "neg?" "none?" "nth" "numeric?" "odd?" "pos?" "remove" "repeat" "repeatedly" "second" "string?" "take" "take_nth" "take_while" "zero?"]) diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 17792f9..9498b87 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -25,6 +25,7 @@ ;;; These macros form the hy language ;;; They are automatically required in every module, except inside hy.core +(import [functools [reduce]]) (defmacro for [args &rest body] "shorthand for nested foreach loops: @@ -116,3 +117,15 @@ ;; TODO: this needs some gensym love `(foreach [_hy_yield_from_x ~iterable] (yield _hy_yield_from_x))) + +(defmacro kwapply [call kwargs] + "Use a dictionary as keyword arguments" + (let [[-fun (car call)] + [-args (cdr call)] + [-okwargs kwargs]] + (while (= -fun "kwapply") ;; join any further kw + (setv -okwargs (+ (car (cdr -args)) -okwargs)) + (setv -fun (car (car -args))) + (setv -args (cdr (car -args)))) + + `(apply ~-fun [~@-args] ~-okwargs))) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index d19ca17..4bf35d5 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -152,8 +152,23 @@ (assert (= (kwapply (kwtest) {"one" "two"}) {"one" "two"})) (setv mydict {"one" "three"}) (assert (= (kwapply (kwtest) mydict) mydict)) - (assert (= (kwapply (kwtest) ((fn [] {"one" "two"}))) {"one" "two"}))) + (assert (= (kwapply (kwtest) ((fn [] {"one" "two"}))) {"one" "two"})) + (assert (= (kwapply + (kwapply + (kwapply + (kwapply (kwtest) {"x" 4}) + {"x" 8}) + {"x" (- 3 2) "y" 2}) + {"y" 5 "z" 3}) + {"x" 1 "y" 5 "z" 3}))) +(defn test-apply [] + "NATIVE: test working with args and functions" + (defn sumit [a b c] (+ a b c)) + (assert (= (apply sumit [1] {"b" 2 "c" 3}) 6)) + (assert (= (apply sumit [1 2 2]) 5)) + (assert (= (apply sumit [] {"a" 1 "b" 1 "c" 2}) 4)) + (assert (= (apply sumit ((fn [] [1 1])) {"c" 1}) 3))) (defn test-dotted [] "NATIVE: test dotted invocation"