diff --git a/AUTHORS b/AUTHORS index 93fedd2..7ba5488 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,10 @@ -Paul R. Tagliamonte +Code contributors: + + - Paul R. Tagliamonte + +I'd also like to thank the following people: + + - Kragen Sitaker: + Major thanks goes to Kragen on helping me work through some of the + namespacing crap. I think the majority of the approach taken now + with expressions' eval bits is his doing in one way or another. diff --git a/bin/hython b/bin/hython new file mode 100755 index 0000000..3444340 --- /dev/null +++ b/bin/hython @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +from hy.lang.importer import _hy_import_file +import sys + +mod = _hy_import_file(sys.argv[1], '') diff --git a/hy/compiler/modfaker.py b/hy/compiler/modfaker.py index ba4ce52..74e7fb6 100644 --- a/hy/compiler/modfaker.py +++ b/hy/compiler/modfaker.py @@ -120,7 +120,7 @@ def forge_module(name, fpath, forest): def shim(): ns = globals() for tree in _hy_forest: - tree.set_namespace(ns, {}) + tree.set_namespace(ns) for tree in _hy_forest: tree() diff --git a/hy/lang/bool.py b/hy/lang/bool.py index de080c4..78a37ee 100644 --- a/hy/lang/bool.py +++ b/hy/lang/bool.py @@ -5,5 +5,5 @@ class HYBool(HYObject): def __init__(self, val): self._val = val - def eval(self, *args, **kwargs): + def eval(self, lns, *args, **kwargs): return self._val == True diff --git a/hy/lang/builtins.py b/hy/lang/builtins.py index 218797b..8ddf1b2 100644 --- a/hy/lang/builtins.py +++ b/hy/lang/builtins.py @@ -1,37 +1,40 @@ # import sys +from hy.lang.internals import HYNamespaceCOW -def _define(obj): +def _define(obj, lns): fd = obj.get_invocation() args = fd['args'] obj.namespace[args[0]] = args[1]() -def _fn(obj): +def _fn(obj, lns): fd = obj.get_invocation() args = fd['args'] sig = args[0] meth = args[1] def _(*args, **kwargs): + l = lns.clone() + m = meth.copy() for i in range(0, len(sig)): name = sig[i] value = args[i] - meth.local_namespace[name] = value + l[name] = value - ret = meth(*args, **kwargs) + ret = m.eval(l, *args, **kwargs) return ret return _ -def _kwapply(obj): +def _kwapply(obj, lns): fd = obj.get_invocation() subshell, kwargs = fd['args'] - return subshell.eval(**kwargs) + return subshell.eval(lns.clone(), **kwargs) -def _import(obj): +def _import(obj, lns): ns = obj.namespace fd = obj.get_invocation() args = fd['args'] @@ -44,13 +47,13 @@ def _import(obj): ns[basename] = mod -def _if(obj): +def _if(obj, lns): fd = obj.get_invocation() args = fd['args'] - if args[0].eval(): - return args[1].eval() + if args[0].eval(lns.clone()): + return args[1].eval(lns.clone()) else: - return args[2].eval() + return args[2].eval(lns.clone()) builtins = { diff --git a/hy/lang/expression.py b/hy/lang/expression.py index 65eba36..6a63981 100644 --- a/hy/lang/expression.py +++ b/hy/lang/expression.py @@ -2,7 +2,7 @@ from hy.lang.hyobj import HYObject from hy.lang.builtins import builtins -class HYExpression(list, HYObject): +class HYExpression(HYObject, list): def __init__(self, nodes): self += nodes @@ -24,17 +24,17 @@ class HYExpression(list, HYObject): def peek(self): return self.get_invocation()['function'] - def eval(self, *args, **kwargs): + def eval(self, lns, *args, **kwargs): fn = self.peek() if fn in builtins: # special-case builtin handling. - return builtins[fn](self) + return builtins[fn](self, lns) things = [] for child in self.get_children(): c = child.copy() - things.append(c()) + things.append(c.eval(lns.clone())) - ret = self.lookup(fn)(*things, **kwargs) + ret = self.lookup(lns, fn)(*things, **kwargs) return ret diff --git a/hy/lang/hyobj.py b/hy/lang/hyobj.py index a04d216..0ed1327 100644 --- a/hy/lang/hyobj.py +++ b/hy/lang/hyobj.py @@ -1,44 +1,38 @@ from hy.lang.internals import HYNamespaceCOW class HYObject(object): - def set_namespace(self, ns, ls): + def set_namespace(self, ns): self.namespace = ns - nns = HYNamespaceCOW(ls) - self.local_namespace = nns - for c in self.get_children(): - c.set_namespace(ns, nns) + c.set_namespace(ns) def get_children(self): return [] def __call__(self, *args, **kwargs): - return self.eval(*args, **kwargs) + ns = HYNamespaceCOW({}) # Each invocation needs it's own ns + return self.eval(ns, *args, **kwargs) - def lookup(self, fn): - callee = None - if fn in self.local_namespace: - callee = self.local_namespace[fn] + def lookup(self, lns, fn): + if fn in lns: + return lns[fn] - elif callee is None and fn in self.namespace: - callee = self.namespace[fn] + if fn in self.namespace: + return self.namespace[fn] - elif callee is None and "." in fn: + if "." in fn: lon, short = fn.rsplit(".", 1) - holder = self.lookup(lon) - callee = getattr(holder, short) - - if callee is not None: - return callee + holder = self.lookup(lns, lon) + return getattr(holder, short) raise Exception("No such symbol: `%s`" % (fn)) - def eval(self, *args, **kwargs): + def eval(self, lns, *args, **kwargs): for node in self.get_children(): - node.eval(*args, **kwargs) + node.eval(lns, *args, **kwargs) return self def copy(self): new = type(self)(self) - new.set_namespace(self.namespace, self.local_namespace) + new.set_namespace(self.namespace) return new diff --git a/hy/lang/internals.py b/hy/lang/internals.py index 4a29178..289fa43 100644 --- a/hy/lang/internals.py +++ b/hy/lang/internals.py @@ -18,3 +18,6 @@ class HYNamespaceCOW(object): def __setitem__(self, key, value): self._mute[key] = value + + def clone(self): + return HYNamespaceCOW(self) diff --git a/hy/lang/list.py b/hy/lang/list.py index 90775ed..264ab3f 100644 --- a/hy/lang/list.py +++ b/hy/lang/list.py @@ -1,7 +1,7 @@ from hy.lang.hyobj import HYObject -class HYList(list, HYObject): +class HYList(HYObject, list): def __init__(self, nodes): self += nodes diff --git a/hy/lang/number.py b/hy/lang/number.py index e852d71..348e094 100644 --- a/hy/lang/number.py +++ b/hy/lang/number.py @@ -3,10 +3,8 @@ from hy.lang.hyobj import HYObject class HYNumber(HYObject, int): def __new__(cls, number, *args, **kwargs): - if isinstance(number, HYObject): - number = number.eval() number = int(number) return super(HYNumber, cls).__new__(cls, number) - def eval(self, *args, **kwargs): + def eval(self, lns, *args, **kwargs): return int(self) diff --git a/hy/lang/symbol.py b/hy/lang/symbol.py index 729d129..dca8919 100644 --- a/hy/lang/symbol.py +++ b/hy/lang/symbol.py @@ -5,6 +5,6 @@ class HYSymbol(HYString): def __init__(self, string): self += string - def eval(self, *args, **kwargs): - obj = self.lookup(self) + def eval(self, lns, *args, **kwargs): + obj = self.lookup(lns, self) return obj