mirror of
https://github.com/kanaka/mal.git
synced 2024-11-14 00:09:01 +03:00
ea81a8087b
- types: low-level mapping to the implementation language. - core: functions on types that are exposed directly to mal. - printer: implementation called by pr-str, str, prn, println. - env: the environment implementation - Also, unindent all TCO while loops so that the diff of step4 and step5 are minimized.
160 lines
3.6 KiB
Python
160 lines
3.6 KiB
Python
import copy
|
|
from itertools import chain
|
|
|
|
import mal_types as types
|
|
from mal_types import List, Vector
|
|
import printer
|
|
|
|
# Errors/Exceptions
|
|
def throw(exc): raise Exception(exc)
|
|
|
|
|
|
# String functions
|
|
def pr_str(*args):
|
|
return " ".join(map(lambda exp: printer._pr_str(exp, True), args))
|
|
|
|
def do_str(*args):
|
|
return "".join(map(lambda exp: printer._pr_str(exp, False), args))
|
|
|
|
def prn(*args):
|
|
print " ".join(map(lambda exp: printer._pr_str(exp, True), args))
|
|
return None
|
|
|
|
def println(*args):
|
|
line = " ".join(map(lambda exp: printer._pr_str(exp, False), args))
|
|
print line.replace('\\n', '\n')
|
|
return None
|
|
|
|
|
|
# Hash map functions
|
|
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 types._list(*hm.keys())
|
|
|
|
def vals(hm): return types._list(*hm.values())
|
|
|
|
|
|
# Sequence functions
|
|
def coll_Q(coll): return sequential_Q(coll) or hash_map_Q(coll)
|
|
|
|
def cons(x, seq): return List([x]) + List(seq)
|
|
|
|
def concat(*lsts): return List(chain(*lsts))
|
|
|
|
def nth(lst, idx): return lst[idx]
|
|
|
|
def first(lst): return lst[0]
|
|
|
|
def rest(lst): return List(lst[1:])
|
|
|
|
def empty_Q(lst): return len(lst) == 0
|
|
|
|
def count(lst): return len(lst)
|
|
|
|
# retains metadata
|
|
def conj(lst, *args):
|
|
if types._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 apply(f, *args): return f(*(list(args[0:-1])+args[-1]))
|
|
|
|
def mapf(f, lst): return List(map(f, lst))
|
|
|
|
|
|
# Metadata functions
|
|
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
|
|
|
|
|
|
# Atoms functions
|
|
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
|
|
|
|
|
|
ns = {
|
|
'=': types._equal_Q,
|
|
'throw': throw,
|
|
'nil?': types._nil_Q,
|
|
'true?': types._true_Q,
|
|
'false?': types._false_Q,
|
|
'symbol': types._symbol,
|
|
'symbol?': types._symbol_Q,
|
|
'pr-str': pr_str,
|
|
'str': do_str,
|
|
'prn': prn,
|
|
'println': println,
|
|
'<': lambda a,b: a<b,
|
|
'<=': lambda a,b: a<=b,
|
|
'>': lambda a,b: a>b,
|
|
'>=': lambda a,b: a>=b,
|
|
'+': lambda a,b: a+b,
|
|
'-': lambda a,b: a-b,
|
|
'*': lambda a,b: a*b,
|
|
'/': lambda a,b: a/b,
|
|
|
|
'list': types._list,
|
|
'list?': types._list_Q,
|
|
'vector': types._vector,
|
|
'vector?': types._vector_Q,
|
|
'hash-map': types._hash_map,
|
|
'map?': types._hash_map_Q,
|
|
'assoc': assoc,
|
|
'dissoc': dissoc,
|
|
'get': get,
|
|
'contains?': contains_Q,
|
|
'keys': keys,
|
|
'vals': vals,
|
|
|
|
'sequential?': types._sequential_Q,
|
|
'cons': cons,
|
|
'concat': concat,
|
|
'nth': nth,
|
|
'first': first,
|
|
'rest': rest,
|
|
'empty?': empty_Q,
|
|
'count': count,
|
|
'conj': conj,
|
|
'apply': apply,
|
|
'map': mapf,
|
|
|
|
'with-meta': with_meta,
|
|
'meta': meta,
|
|
'atom': types._atom,
|
|
'atom?': types._atom_Q,
|
|
'deref': deref,
|
|
'reset!': reset_BANG,
|
|
'swap!': swap_BANG}
|
|
|