Add mangle
and unmangle
as core functions
This commit is contained in:
parent
ebc9bda7ee
commit
85968e70dd
@ -12,5 +12,5 @@ import hy.importer # NOQA
|
||||
# we import for side-effects.
|
||||
|
||||
|
||||
from hy.core.language import read, read_str # NOQA
|
||||
from hy.core.language import read, read_str, mangle, unmangle # NOQA
|
||||
from hy.importer import hy_eval as eval # NOQA
|
||||
|
@ -16,7 +16,7 @@ import astor.code_gen
|
||||
import hy
|
||||
|
||||
from hy.lex import LexException, PrematureEndOfInput
|
||||
from hy.lex.parser import hy_symbol_mangle
|
||||
from hy.lex.parser import mangle
|
||||
from hy.compiler import HyTypeError
|
||||
from hy.importer import (hy_eval, import_buffer_to_module,
|
||||
import_file_to_ast, import_file_to_hst,
|
||||
@ -64,11 +64,11 @@ class HyREPL(code.InteractiveConsole):
|
||||
self.output_fn = output_fn
|
||||
else:
|
||||
if "." in output_fn:
|
||||
parts = [hy_symbol_mangle(x) for x in output_fn.split(".")]
|
||||
parts = [mangle(x) for x in output_fn.split(".")]
|
||||
module, f = '.'.join(parts[:-1]), parts[-1]
|
||||
self.output_fn = getattr(importlib.import_module(module), f)
|
||||
else:
|
||||
self.output_fn = __builtins__[hy_symbol_mangle(output_fn)]
|
||||
self.output_fn = __builtins__[mangle(output_fn)]
|
||||
|
||||
code.InteractiveConsole.__init__(self, locals=locals,
|
||||
filename=filename)
|
||||
|
@ -8,7 +8,7 @@ from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
|
||||
HyDict, HyCons, wrap_value)
|
||||
from hy.errors import HyCompileError, HyTypeError
|
||||
|
||||
from hy.lex.parser import hy_symbol_mangle
|
||||
from hy.lex.parser import mangle
|
||||
|
||||
import hy.macros
|
||||
from hy._compat import (
|
||||
@ -70,7 +70,7 @@ if PY35:
|
||||
def ast_str(x, piecewise=False):
|
||||
if piecewise:
|
||||
return ".".join(ast_str(s) if s else "" for s in x.split("."))
|
||||
x = hy_symbol_mangle(str_type(x))
|
||||
x = mangle(x)
|
||||
return x if PY3 else x.encode('UTF8')
|
||||
|
||||
|
||||
@ -2109,7 +2109,7 @@ class HyASTCompiler(object):
|
||||
"Trying to expand a tag macro using `{0}' instead "
|
||||
"of string".format(type(tag).__name__),
|
||||
)
|
||||
tag = HyString(hy_symbol_mangle(str(tag))).replace(tag)
|
||||
tag = HyString(mangle(tag)).replace(tag)
|
||||
expr = tag_macroexpand(tag, expression.pop(0), self)
|
||||
return self.compile(expr)
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
[functools [partial]]
|
||||
[collections [OrderedDict]]
|
||||
[hy.macros [macroexpand :as mexpand]]
|
||||
[hy.lex.parser [hy-symbol-mangle]]
|
||||
[hy.compiler [HyASTCompiler]])
|
||||
|
||||
(defn walk [inner outer form]
|
||||
@ -258,7 +257,7 @@ Arguments without a header are under None.
|
||||
(= head 'defclass) (self.handle-defclass)
|
||||
(= head 'quasiquote) (self.+quote)
|
||||
;; must be checked last!
|
||||
(in (hy-symbol-mangle (string head)) special-forms) (self.handle-special-form)
|
||||
(in (mangle head) special-forms) (self.handle-special-form)
|
||||
;; Not a special form. Traverse it like a coll
|
||||
(self.handle-coll)))
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
(import [hy._compat [long-type]]) ; long for python2, int for python3
|
||||
(import [hy.models [HyCons HySymbol HyKeyword]])
|
||||
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
|
||||
(import [hy.lex.parser [mangle unmangle]])
|
||||
(import [hy.compiler [HyASTCompiler spoof-positions]])
|
||||
(import [hy.importer [hy-eval :as eval]])
|
||||
|
||||
@ -495,7 +496,7 @@ Even objects with the __name__ magic will work."
|
||||
filter flatten float? fraction gensym group-by identity inc input instance?
|
||||
integer integer? integer-char? interleave interpose islice iterable?
|
||||
iterate iterator? juxt keyword keyword? last list* macroexpand
|
||||
macroexpand-1 map merge-with multicombinations name neg? none? nth
|
||||
macroexpand-1 mangle map merge-with multicombinations name neg? none? nth
|
||||
numeric? odd? partition permutations pos? product range read read-str
|
||||
remove repeat repeatedly rest reduce second some string string? symbol?
|
||||
take take-nth take-while xor tee zero? zip zip-longest])
|
||||
take take-nth take-while unmangle xor tee zero? zip zip-longest])
|
||||
|
@ -13,7 +13,6 @@
|
||||
The result of the first call is cached."
|
||||
(global _cache)
|
||||
(if (is _cache None) (do
|
||||
(setv unmangle (. sys.modules ["hy.lex.parser"] hy_symbol_unmangle))
|
||||
(setv _cache (frozenset (map unmangle (+
|
||||
hy.core.language.EXPORTS
|
||||
hy.core.shadow.EXPORTS
|
||||
|
@ -25,9 +25,14 @@ pg = ParserGenerator(
|
||||
|
||||
mangle_delim = 'Δ' if PY3 else 'X'
|
||||
|
||||
def hy_symbol_mangle(s):
|
||||
def mangle(s):
|
||||
"""Stringify the argument and convert it to a valid Python identifier
|
||||
according to Hy's mangling rules."""
|
||||
|
||||
assert s
|
||||
|
||||
s = str_type(s)
|
||||
|
||||
s = s.replace("-", "_")
|
||||
s2 = s.lstrip('_')
|
||||
leading_underscores = '_' * (len(s) - len(s2))
|
||||
@ -53,8 +58,11 @@ def hy_symbol_mangle(s):
|
||||
return s
|
||||
|
||||
|
||||
def hy_symbol_unmangle(s):
|
||||
# hy_symbol_mangle is one-way, so this won't round-trip.
|
||||
def unmangle(s):
|
||||
"""Stringify the argument and try to convert it to a pretty unmangled
|
||||
form. This may not round-trip, because different Hy symbol names can
|
||||
mangle to the same Python identifier."""
|
||||
|
||||
s = str_type(s)
|
||||
|
||||
s2 = s.lstrip('_')
|
||||
|
16
hy/macros.py
16
hy/macros.py
@ -5,7 +5,7 @@
|
||||
from hy._compat import PY3
|
||||
import hy.inspect
|
||||
from hy.models import replace_hy_obj, HyExpression, HySymbol
|
||||
from hy.lex.parser import hy_symbol_mangle
|
||||
from hy.lex.parser import mangle
|
||||
from hy._compat import str_type
|
||||
|
||||
from hy.errors import HyTypeError, HyMacroExpansionError
|
||||
@ -36,7 +36,7 @@ def macro(name):
|
||||
This function is called from the `defmacro` special form in the compiler.
|
||||
|
||||
"""
|
||||
name = hy_symbol_mangle(name)
|
||||
name = mangle(name)
|
||||
def _(fn):
|
||||
fn.__name__ = '({})'.format(name)
|
||||
try:
|
||||
@ -67,14 +67,14 @@ def tag(name):
|
||||
|
||||
"""
|
||||
def _(fn):
|
||||
_name = hy_symbol_mangle('#{}'.format(name))
|
||||
_name = mangle('#{}'.format(name))
|
||||
if not PY3:
|
||||
_name = _name.encode('UTF-8')
|
||||
fn.__name__ = _name
|
||||
module_name = fn.__module__
|
||||
if module_name.startswith("hy.core"):
|
||||
module_name = None
|
||||
_hy_tag[module_name][hy_symbol_mangle(name)] = fn
|
||||
_hy_tag[module_name][mangle(name)] = fn
|
||||
|
||||
return fn
|
||||
return _
|
||||
@ -97,15 +97,15 @@ def require(source_module, target_module,
|
||||
seen_names = set()
|
||||
if prefix:
|
||||
prefix += "."
|
||||
assignments = {hy_symbol_mangle(str_type(k)): v for k, v in assignments.items()}
|
||||
assignments = {mangle(str_type(k)): v for k, v in assignments.items()}
|
||||
|
||||
for d in _hy_macros, _hy_tag:
|
||||
for name, macro in d[source_module].items():
|
||||
seen_names.add(name)
|
||||
if all_macros:
|
||||
d[target_module][hy_symbol_mangle(prefix + name)] = macro
|
||||
d[target_module][mangle(prefix + name)] = macro
|
||||
elif name in assignments:
|
||||
d[target_module][hy_symbol_mangle(prefix + assignments[name])] = macro
|
||||
d[target_module][mangle(prefix + assignments[name])] = macro
|
||||
|
||||
if not all_macros:
|
||||
unseen = frozenset(assignments.keys()).difference(seen_names)
|
||||
@ -187,7 +187,7 @@ def macroexpand_1(tree, compiler):
|
||||
opts = {}
|
||||
|
||||
if isinstance(fn, HySymbol):
|
||||
fn = hy_symbol_mangle(str_type(fn))
|
||||
fn = mangle(str_type(fn))
|
||||
m = _hy_macros[compiler.module_name].get(fn)
|
||||
if m is None:
|
||||
m = _hy_macros[None].get(fn)
|
||||
|
@ -178,3 +178,12 @@
|
||||
(setv ~sym 10)
|
||||
[foo? is_foo])))
|
||||
(assert (= out [10 10])))
|
||||
|
||||
|
||||
(defn test-functions []
|
||||
(for [[a b] [
|
||||
["---ab-cd?" "___is_ab_cd"]
|
||||
["if" "hyx_if"]
|
||||
["⚘-⚘" (if PY3 "hyx_ΔflowerΔ_ΔflowerΔ" "hyx_XflowerX_XflowerX")]]]
|
||||
(assert (= (mangle a) b))
|
||||
(assert (= (unmangle b) a))))
|
||||
|
@ -3,7 +3,6 @@
|
||||
;; license. See the LICENSE.
|
||||
|
||||
(import [hy.errors [HyTypeError]])
|
||||
(import [hy.lex.parser [hy-symbol-mangle]])
|
||||
|
||||
(defmacro rev [&rest body]
|
||||
"Execute the `body` statements in reverse"
|
||||
@ -164,8 +163,8 @@
|
||||
(setv s1 (to_source _ast1))
|
||||
(setv s2 (to_source _ast2))
|
||||
;; and make sure there is something new that starts with _;G|
|
||||
(assert (in (hy-symbol-mangle "_;G|") s1))
|
||||
(assert (in (hy-symbol-mangle "_;G|") s2))
|
||||
(assert (in (mangle "_;G|") s1))
|
||||
(assert (in (mangle "_;G|") s2))
|
||||
;; but make sure the two don't match each other
|
||||
(assert (not (= s1 s2))))
|
||||
|
||||
@ -189,8 +188,8 @@
|
||||
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
||||
(setv s1 (to_source _ast1))
|
||||
(setv s2 (to_source _ast2))
|
||||
(assert (in (hy-symbol-mangle "_;a|") s1))
|
||||
(assert (in (hy-symbol-mangle "_;a|") s2))
|
||||
(assert (in (mangle "_;a|") s1))
|
||||
(assert (in (mangle "_;a|") s2))
|
||||
(assert (not (= s1 s2))))
|
||||
|
||||
(defn test-defmacro-g! []
|
||||
|
Loading…
Reference in New Issue
Block a user