aboutsummaryrefslogtreecommitdiff
path: root/python/mal_types.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mal_types.py')
-rw-r--r--python/mal_types.py251
1 files changed, 32 insertions, 219 deletions
diff --git a/python/mal_types.py b/python/mal_types.py
index 401a03b..15e4b6b 100644
--- a/python/mal_types.py
+++ b/python/mal_types.py
@@ -1,71 +1,17 @@
-import copy
-from itertools import chain
-
# General functions
-def _pr_str(obj, print_readably=True):
- _r = print_readably
- if list_Q(obj):
- return "(" + " ".join(map(lambda e: _pr_str(e,_r), obj)) + ")"
- elif vector_Q(obj):
- return "[" + " ".join(map(lambda e: _pr_str(e,_r), obj)) + "]"
- elif hash_map_Q(obj):
- ret = []
- for k in obj.keys():
- ret.extend((_pr_str(k), _pr_str(obj[k],_r)))
- return "{" + " ".join(ret) + "}"
- elif string_Q(obj):
- if print_readably:
- return '"' + obj.encode('unicode_escape').replace('"', '\\"') + '"'
- else:
- return obj
- elif nil_Q(obj):
- return "nil"
- elif true_Q(obj):
- return "true"
- elif false_Q(obj):
- return "false"
- elif atom_Q(obj):
- return "(atom " + _pr_str(obj.val,_r) + ")"
- else:
- return obj.__str__()
-
-def pr_str(*args):
- return " ".join(map(lambda exp: _pr_str(exp, True), args))
-
-def do_str(*args):
- return "".join(map(lambda exp: _pr_str(exp, False), args))
-
-def prn(*args):
- print " ".join(map(lambda exp: _pr_str(exp, True), args))
- return None
-
-def println(*args):
- line = " ".join(map(lambda exp: _pr_str(exp, False), args))
- print line.replace('\\n', '\n')
- return None
-
-def with_meta(obj, meta):
- new_obj = copy.copy(obj)
- new_obj.__meta__ = meta
- return new_obj
-
-def meta(obj):
- if hasattr(obj, "__meta__"): return obj.__meta__
- else: return None
-
-def equal_Q(a, b):
+def _equal_Q(a, b):
ota, otb = type(a), type(b)
- if not (ota == otb or (sequential_Q(a) and sequential_Q(b))):
+ if not (ota == otb or (_sequential_Q(a) and _sequential_Q(b))):
return False;
- if symbol_Q(a):
+ if _symbol_Q(a):
return a == b
- elif list_Q(a) or vector_Q(a):
+ elif _list_Q(a) or _vector_Q(a):
if len(a) != len(b): return False
for i in range(len(a)):
- if not equal_Q(a[i], b[i]): return False
+ if not _equal_Q(a[i], b[i]): return False
return True
- elif hash_map_Q(a):
+ elif _hash_map_Q(a):
akeys = a.keys()
akeys.sort()
bkeys = b.keys()
@@ -78,70 +24,26 @@ def equal_Q(a, b):
else:
return a == b
-# nil, true, false
-def nil_Q(exp): return exp is None
-def true_Q(exp): return exp is True
-def false_Q(exp): return exp is False
-def string_Q(exp): return type(exp) in [str, unicode]
+def _sequential_Q(seq): return _list_Q(seq) or _vector_Q(seq)
-# numbers
-int_plus = lambda a,b: a+b
-int_minus = lambda a,b: a-b
-int_multiply = lambda a,b: a*b
-int_divide = lambda a,b: a/b
-int_lt = lambda a,b: a<b
-int_lte = lambda a,b: a<=b
-int_gt = lambda a,b: a>b
-int_gte = lambda a,b: a>=b
+# Scalars
+def _nil_Q(exp): return exp is None
+def _true_Q(exp): return exp is True
+def _false_Q(exp): return exp is False
+def _string_Q(exp): return type(exp) in [str, unicode]
-# symbols
+# Symbols
class Symbol(str): pass
-def new_symbol(str): return Symbol(str)
-def symbol_Q(exp): return type(exp) == Symbol
+def _symbol(str): return Symbol(str)
+def _symbol_Q(exp): return type(exp) == Symbol
-
-# functions
-def new_function(func, exp, env, params):
+# Functions
+def _function(Eval, Env, exp, env, params):
def f(*args):
- return func(exp, Env(env, params, args))
+ return Eval(exp, Env(env, params, args))
f.__meta__ = {"exp": exp, "env": env, "params": params}
return f
-def function_Q(f): return type(f) == type(function_Q)
-
-# hash maps
-class Hash_Map(dict): pass
-def new_hash_map(*key_vals):
- hm = Hash_Map()
- for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1]
- return hm
-def hash_map_Q(exp): return type(exp) == Hash_Map
-
-def assoc(src_hm, *key_vals):
- hm = copy.copy(src_hm)
- for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1]
- return hm
-
-def dissoc(src_hm, *keys):
- hm = copy.copy(src_hm)
- for key in keys: del hm[key]
- return hm
-
-def get(hm, key):
- if key in hm:
- return hm[key]
- else:
- return None
-
-def contains_Q(hm, key): return key in hm
-
-def keys(hm): return new_list(*hm.keys())
-
-def vals(hm): return new_list(*hm.values())
-
-
-# errors/exceptions
-def throw(exc): raise Exception(exc)
-
+def _function_Q(f): return type(f) == type(function_Q)
# lists
class List(list):
@@ -151,8 +53,8 @@ class List(list):
elif i >= len(self): return None
else: return list.__getitem__(self, i)
def __getslice__(self, *a): return List(list.__getslice__(self, *a))
-def new_list(*vals): return List(vals)
-def list_Q(exp): return type(exp) == List
+def _list(*vals): return List(vals)
+def _list_Q(exp): return type(exp) == List
# vectors
@@ -163,109 +65,20 @@ class Vector(list):
elif i >= len(self): return None
else: return list.__getitem__(self, i)
def __getslice__(self, *a): return Vector(list.__getslice__(self, *a))
-def new_vector(*vals): return Vector(vals)
-def vector_Q(exp): return type(exp) == Vector
+def _vector(*vals): return Vector(vals)
+def _vector_Q(exp): return type(exp) == Vector
+# Hash maps
+class Hash_Map(dict): pass
+def _hash_map(*key_vals):
+ hm = Hash_Map()
+ for i in range(0,len(key_vals),2): hm[key_vals[i]] = key_vals[i+1]
+ return hm
+def _hash_map_Q(exp): return type(exp) == Hash_Map
# atoms
class Atom(object):
def __init__(self, val):
self.val = val
-def new_atom(val): return Atom(val)
-def atom_Q(exp): return type(exp) == Atom
-def deref(atm): return atm.val
-def reset_BANG(atm,val):
- atm.val = val
- return atm.val
-def swap_BANG(atm,f,*args):
- atm.val = f(atm.val,*args)
- return atm.val
-
-
-
-# Sequence operations
-def sequential_Q(seq): return list_Q(seq) or vector_Q(seq)
-
-def coll_Q(coll): return sequential_Q(coll) or hash_map_Q(coll)
-
-def cons(x, seq): return List([x]) + List(seq)
-
-def nth(lst, idx): return lst[idx]
-
-def count(lst): return len(lst)
-
-def empty_Q(lst): return len(lst) == 0
-
-def concat(*lsts): return List(chain(*lsts))
-
-# retains metadata
-def conj(lst, *args):
- if list_Q(lst):
- new_lst = List(list(reversed(list(args))) + lst)
- else:
- new_lst = Vector(lst + list(args))
- if hasattr(lst, "__meta__"):
- new_lst.__meta__ = lst.__meta__
- return new_lst
-
-def first(lst): return lst[0]
-
-def rest(lst): return List(lst[1:])
-
-def apply(f, *args):
- return f(*(list(args[0:-1])+args[-1]))
-
-def mapf(f, lst):
- return List(map(f, lst))
-
-
-# Environment
-
-class Env():
- def __init__(self, outer=None, binds=None, exprs=None):
- self.data = {}
- self.outer = outer or None
-
- if binds:
- for i in range(len(binds)):
- if binds[i] == "&":
- self.data[binds[i+1]] = exprs[i:]
- break
- else:
- self.data[binds[i]] = exprs[i]
-
- def find(self, key):
- if key in self.data: return self
- elif self.outer: return self.outer.find(key)
- else: return None
-
- def set(self, key, value):
- self.data[key] = value
- return value
-
- def get(self, key):
- env = self.find(key)
- if not env: raise Exception("'" + key + "' not found")
- return env.data[key]
-
-types_ns = {
- 'pr-str': pr_str, 'str': do_str, 'prn': prn, 'println': println,
- 'with-meta': with_meta, 'meta': meta,
- '=': equal_Q,
- 'nil?': nil_Q, 'true?': true_Q, 'false?': false_Q,
- 'symbol?': symbol_Q,
- '<': int_lt, '<=': int_lte, '>': int_gt, '>=': int_gte,
- '+': int_plus, '-': int_minus, '*': int_multiply, '/': int_divide,
- 'hash-map': new_hash_map, 'map?': hash_map_Q,
- 'assoc': assoc, 'dissoc': dissoc, 'get': get,
- 'contains?': contains_Q, 'keys': keys, 'vals': vals,
- 'throw': throw,
- 'list': new_list, 'list?': list_Q,
- 'vector': new_vector, 'vector?': vector_Q,
- 'atom': new_atom, 'atom?': atom_Q, 'deref': deref,
- 'reset!': reset_BANG, 'swap!': swap_BANG,
- 'sequential?': sequential_Q,
- 'cons': cons, 'nth': nth, 'count': count, 'empty?': empty_Q,
- 'concat': concat, "conj": conj, "first": first, "rest": rest,
- 'apply': apply, 'map': mapf}
-
+def _atom(val): return Atom(val)
+def _atom_Q(exp): return type(exp) == Atom