Teach apply about symbol mangling
apply now mangles strings and keywords according to the Hy mangling rules (by using the same function, now imported from hy.lex.parser). With this change, if the dict passed to apply has keywords, strings or quoted symbols, they'll get mangled, to turn them into proper keys. This only works for the cases where the keys are directly in the apply params. A previously deffed dict, or key through a variable will not be mangled. This closes #219. Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
parent
b1f497ae72
commit
26f342d580
@ -115,8 +115,10 @@ it appends it as the last argument. The following code demonstrates this:
|
||||
apply
|
||||
-----
|
||||
|
||||
``apply`` is used to apply an optional list of arguments and an optional
|
||||
dictionary of kwargs to a function.
|
||||
``apply`` is used to apply an optional list of arguments and an
|
||||
optional dictionary of kwargs to a function. The symbol mangling
|
||||
transformations will be applied to all keys in the dictionary of
|
||||
kwargs, provided the dictionary and its keys are defined in-place.
|
||||
|
||||
Usage: ``(apply fn-name [args] [kwargs])``
|
||||
|
||||
@ -142,6 +144,8 @@ Examples:
|
||||
(apply total-purchase [] {"price" 10 "amount" 15 "vat" 1.05})
|
||||
;=> 165.375
|
||||
|
||||
(apply total-purchase [] {:price 10 :amount 15 :vat 1.05})
|
||||
;=> 165.375
|
||||
|
||||
and
|
||||
---
|
||||
|
@ -38,6 +38,8 @@ from hy.models.cons import HyCons
|
||||
|
||||
from hy.errors import HyCompileError, HyTypeError
|
||||
|
||||
from hy.lex.parser import hy_symbol_mangle
|
||||
|
||||
import hy.macros
|
||||
from hy._compat import (
|
||||
str_type, long_type, PY27, PY33, PY3, PY34, PY35, raise_empty)
|
||||
@ -1640,7 +1642,21 @@ class HyASTCompiler(object):
|
||||
ret = stargs + ret
|
||||
|
||||
if expr:
|
||||
kwargs = self.compile(expr.pop(0))
|
||||
kwargs = expr.pop(0)
|
||||
if isinstance(kwargs, HyDict):
|
||||
new_kwargs = []
|
||||
for k, v in kwargs.items():
|
||||
if isinstance(k, HySymbol):
|
||||
pass
|
||||
elif isinstance(k, HyString):
|
||||
k = HyString(hy_symbol_mangle(str_type(k))).replace(k)
|
||||
elif isinstance(k, HyKeyword):
|
||||
sym = hy_symbol_mangle(str_type(k)[2:])
|
||||
k = HyString(sym).replace(k)
|
||||
new_kwargs += [k, v]
|
||||
kwargs = HyDict(new_kwargs).replace(kwargs)
|
||||
|
||||
kwargs = self.compile(kwargs)
|
||||
if PY35:
|
||||
kwargs_expr = kwargs.force_expr
|
||||
ret.expr.keywords.append(
|
||||
|
@ -45,6 +45,22 @@ pg = ParserGenerator(
|
||||
)
|
||||
|
||||
|
||||
def hy_symbol_mangle(p):
|
||||
if p.startswith("*") and p.endswith("*") and p not in ("*", "**"):
|
||||
p = p[1:-1].upper()
|
||||
|
||||
if "-" in p and p != "-":
|
||||
p = p.replace("-", "_")
|
||||
|
||||
if p.endswith("?") and p != "?":
|
||||
p = "is_%s" % (p[:-1])
|
||||
|
||||
if p.endswith("!") and p != "!":
|
||||
p = "%s_bang" % (p[:-1])
|
||||
|
||||
return p
|
||||
|
||||
|
||||
def set_boundaries(fun):
|
||||
@wraps(fun)
|
||||
def wrapped(p):
|
||||
@ -297,22 +313,7 @@ def t_identifier(p):
|
||||
if obj.startswith(":"):
|
||||
return HyKeyword(obj)
|
||||
|
||||
def mangle(p):
|
||||
if p.startswith("*") and p.endswith("*") and p not in ("*", "**"):
|
||||
p = p[1:-1].upper()
|
||||
|
||||
if "-" in p and p != "-":
|
||||
p = p.replace("-", "_")
|
||||
|
||||
if p.endswith("?") and p != "?":
|
||||
p = "is_%s" % (p[:-1])
|
||||
|
||||
if p.endswith("!") and p != "!":
|
||||
p = "%s_bang" % (p[:-1])
|
||||
|
||||
return p
|
||||
|
||||
obj = ".".join([mangle(part) for part in obj.split(".")])
|
||||
obj = ".".join([hy_symbol_mangle(part) for part in obj.split(".")])
|
||||
|
||||
return HySymbol(obj)
|
||||
|
||||
|
@ -309,7 +309,10 @@
|
||||
(assert (= (apply sumit [] {"a" 1 "b" 1 "c" 2}) 4))
|
||||
(assert (= (apply sumit ((fn [] [1 1])) {"c" 1}) 3))
|
||||
(defn noargs [] [1 2 3])
|
||||
(assert (= (apply noargs) [1 2 3])))
|
||||
(assert (= (apply noargs) [1 2 3]))
|
||||
(defn sumit-mangle [an-a a-b a-c a-d] (+ an-a a-b a-c a-d))
|
||||
(def Z "a_d")
|
||||
(assert (= (apply sumit-mangle [] {"an-a" 1 :a-b 2 'a-c 3 Z 4}) 10)))
|
||||
|
||||
|
||||
(defn test-apply-with-methods []
|
||||
|
Loading…
Reference in New Issue
Block a user