hacking on stuff.

This commit is contained in:
Paul Tagliamonte 2012-12-18 09:11:42 -05:00
parent 94040dfbd3
commit 4f5bc16508
18 changed files with 207 additions and 22 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
*.pyc *.pyc
*swp *swp
*hy*egg* *hy*egg*
.tox
*pycache*

View File

@ -1,11 +1,13 @@
from __future__ import print_function
from hy.lex.tokenize import tokenize from hy.lex.tokenize import tokenize
import imp import imp
def _add_native_methods(mod): def _add_native_methods(mod):
def shim(): def shim():
from hy.lang.bool import HYBool
def _print(*args, **kwargs): def _print(*args, **kwargs):
print " ".join([str(x) for x in args]) print(" ".join([str(x) for x in args]))
def _plus(*args): def _plus(*args):
@ -40,14 +42,67 @@ def _add_native_methods(mod):
return ret return ret
def _eq(*args):
car, cdr = args[0], args[1:]
for arg in cdr:
if arg != car:
return False
return True
def _ne(*args):
seen = set()
for arg in args:
if arg in seen:
return False
seen.add(arg)
return True
def _gt(*args):
arg = args[0]
for i in range(1, len(args)):
if not (args[i - 1] > args[i]):
return False
return True
def _ge(*args):
arg = args[0]
for i in range(1, len(args)):
if not (args[i - 1] >= args[i]):
return False
return True
def _le(*args):
arg = args[0]
for i in range(1, len(args)):
if not (args[i - 1] <= args[i]):
return False
return True
def _lt(*args):
arg = args[0]
for i in range(1, len(args)):
if not (args[i - 1] < args[i]):
return False
return True
natives = { natives = {
"print": _print, "puts": _print,
"+": _plus, "+": _plus,
"-": _subtract, "-": _subtract,
"*": _mult, "*": _mult,
"/": _divide, "/": _divide,
"true": True, "==": _eq,
"false": False ">": _gt,
">=": _ge,
"<": _lt,
"<=": _le,
"!=": _ne
} }
for native in natives: for native in natives:
@ -65,7 +120,7 @@ def forge_module(name, fpath, forest):
def shim(): def shim():
ns = globals() ns = globals()
for tree in _hy_forest: for tree in _hy_forest:
tree.set_namespace(ns) tree.set_namespace(ns, {})
for tree in _hy_forest: for tree in _hy_forest:
tree() tree()

9
hy/lang/bool.py Normal file
View File

@ -0,0 +1,9 @@
from hy.lang.hyobj import HYObject
class HYBool(HYObject):
def __init__(self, val):
self._val = val
def eval(self, *args, **kwargs):
return self._val == True

View File

@ -18,12 +18,18 @@ def _fn(obj):
for i in range(0, len(sig)): for i in range(0, len(sig)):
name = sig[i] name = sig[i]
value = args[i] value = args[i]
obj.namespace[name] = value obj.local_namespace[name] = value
return meth(*args, **kwargs) return meth(*args, **kwargs)
return _ return _
def _kwapply(obj):
fd = obj.get_invocation()
subshell, kwargs = fd['args']
return subshell.eval(**kwargs)
def _import(obj): def _import(obj):
ns = obj.namespace ns = obj.namespace
fd = obj.get_invocation() fd = obj.get_invocation()
@ -37,8 +43,19 @@ def _import(obj):
ns[basename] = mod ns[basename] = mod
def _if(obj):
fd = obj.get_invocation()
args = fd['args']
if args[0].eval():
return args[1].eval()
else:
return args[2].eval()
builtins = { builtins = {
"def": _define, "def": _define,
"fn": _fn, "fn": _fn,
"import": _import "import": _import,
"kwapply": _kwapply,
"if": _if,
} }

View File

@ -5,7 +5,6 @@ from hy.lang.builtins import builtins
class HYExpression(list, HYObject): class HYExpression(list, HYObject):
def __init__(self, nodes): def __init__(self, nodes):
self += nodes self += nodes
self.namespace = globals()
def get_children(self): def get_children(self):
ret = [] ret = []
@ -27,6 +26,7 @@ class HYExpression(list, HYObject):
def eval(self, *args, **kwargs): def eval(self, *args, **kwargs):
fn = self.peek() fn = self.peek()
if fn in builtins: if fn in builtins:
# special-case builtin handling. # special-case builtin handling.
return builtins[fn](self) return builtins[fn](self)
@ -35,4 +35,5 @@ class HYExpression(list, HYObject):
for child in self.get_children(): for child in self.get_children():
things.append(child()) things.append(child())
return self.lookup(fn)(*things) ret = self.lookup(fn)(*things, **kwargs)
return ret

View File

@ -1,8 +1,13 @@
from hy.lang.internals import HYNamespaceCOW
class HYObject(object): class HYObject(object):
def set_namespace(self, ns): def set_namespace(self, ns, ls):
self.namespace = ns self.namespace = ns
nns = HYNamespaceCOW(ls)
self.local_namespace = nns
for c in self.get_children(): for c in self.get_children():
c.set_namespace(ns) c.set_namespace(ns, ls=nns)
def get_children(self): def get_children(self):
return [] return []
@ -12,16 +17,18 @@ class HYObject(object):
def lookup(self, fn): def lookup(self, fn):
callee = None callee = None
if fn in self.local_namespace:
callee = self.local_namespace[fn]
if fn in self.namespace: if callee is None and fn in self.namespace:
callee = self.namespace[fn] callee = self.namespace[fn]
if "." in fn: if callee is None and "." in fn:
lon, short = fn.rsplit(".", 1) lon, short = fn.rsplit(".", 1)
holder = self.lookup(lon) holder = self.lookup(lon)
callee = getattr(holder, short) callee = getattr(holder, short)
if callee: if callee is not None:
return callee return callee
raise Exception("No such symbol: `%s`" % (fn)) raise Exception("No such symbol: `%s`" % (fn))

View File

@ -5,9 +5,7 @@ import imp
import os import os
def _hy_import_file(fd): def _hy_import_file(fd, name):
name = 'hython file'
m = forge_module( m = forge_module(
name, name,
fd, fd,
@ -34,8 +32,11 @@ class MetaImporter(object):
def load_module(self, name): def load_module(self, name):
if name not in sys.modules: if name not in sys.modules:
sys.modules[name] = None sys.modules[name] = None
sys.modules[name] = _hy_import_file(self.path) mod = _hy_import_file(self.path, name)
sys.modules[name].__loader__ = self mod.__file__ = self.path
mod.__name__ = name
mod.__loader__ = self
sys.modules[name] = mod
return sys.modules[name] return sys.modules[name]

20
hy/lang/internals.py Normal file
View File

@ -0,0 +1,20 @@
#
class HYNamespaceCOW(object):
def __init__(self, inmutable_copy):
self._inmute = inmutable_copy
self._mute = {}
def __contains__(self, key):
if key in self._mute:
return True
return key in self._inmute
def __getitem__(self, key):
if key in self._mute:
return self._mute[key]
return self._inmute[key]
def __setitem__(self, key, value):
self._mute[key] = value

View File

@ -7,4 +7,9 @@ class HYMap(dict, HYObject):
self[node] = nodes[node] self[node] = nodes[node]
def get_children(self): def get_children(self):
return self.keys() + self.values() ret = []
for v in self.keys():
ret.append(v)
for v in self.values():
ret.append(v)
return ret

View File

@ -3,4 +3,10 @@ from hy.lang.hyobj import HYObject
class HYNumber(int, HYObject): class HYNumber(int, HYObject):
def __init__(self, number): def __init__(self, number):
if isinstance(number, HYObject):
number = number.eval()
number = int(number)
self = number self = number
def eval(self, *args, **kwargs):
return int(self)

View File

@ -6,4 +6,5 @@ class HYSymbol(HYString):
self += string self += string
def eval(self, *args, **kwargs): def eval(self, *args, **kwargs):
return self.lookup(self) obj = self.lookup(self)
return obj

View File

@ -5,6 +5,7 @@ from hy.lang.symbol import HYSymbol
from hy.lang.number import HYNumber from hy.lang.number import HYNumber
from hy.lex.machine import Machine from hy.lex.machine import Machine
from hy.lang.list import HYList from hy.lang.list import HYList
from hy.lang.bool import HYBool
from hy.lang.map import HYMap from hy.lang.map import HYMap
@ -12,6 +13,11 @@ WHITESPACE = [" ", "\t", "\n", "\r"]
def _resolve_atom(value): def _resolve_atom(value):
if value == "true":
return HYBool(True)
elif value == "false":
return HYBool(False)
if value.isdigit(): if value.isdigit():
return HYNumber(value) return HYNumber(value)
return HYSymbol(value) return HYSymbol(value)

View File

@ -2,7 +2,10 @@
from setuptools import setup from setuptools import setup
long_description = open('README.md', 'r').read() long_description = """This thing does stuff and
things with other things until things looks like other
things. """
appname = "hy" appname = "hy"
version = "0.6.0" version = "0.6.0"

4
tests/lang/foo.hy Normal file
View File

@ -0,0 +1,4 @@
; vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2 filetype=lisp
(def square (fn [arg]
(* arg arg)))

10
tests/lang/kwargs.hy Normal file
View File

@ -0,0 +1,10 @@
; vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2 filetype=lisp
(import ["tests.lang.test_kwargs"])
(def kiwi (fn []
(kwapply (tests.lang.test_kwargs.shim "one" "two") {
"three" "three"
"four" "four"
})
))

13
tests/lang/test_import.py Normal file
View File

@ -0,0 +1,13 @@
import hy.lang.importer
import tests.lang.foo
def square(x):
return x * x
def test_squares_properly():
assert tests.lang.foo.square
assert tests.lang.foo.square(2) == 4
for x in range(0, 10):
tests.lang.foo.square(x)

18
tests/lang/test_kwargs.py Normal file
View File

@ -0,0 +1,18 @@
import hy.lang.importer
def shim(*args, **kwargs):
return {"a": args,
"k": kwargs}
def test_kwargs_proper():
import tests.lang.kwargs
val = tests.lang.kwargs.kiwi()
assert val == {
"a": ('one', 'two'),
"k": {
"three": "three",
"four": "four"
}
}

7
tox.ini Normal file
View File

@ -0,0 +1,7 @@
# content of: tox.ini , put in same dir as setup.py
[tox]
envlist = py27,pypy,py32,py33
# jython -- jython fails?
[testenv]
commands = nosetests
deps = nose