#coding=utf-8
import types,sys
import operator as op
from functools import reduce
from inspect import getargspec
##########################
def quote(code):
return code
def atom(code):
if type(code) is list and code != []:
return []
return True
def eq(car, cdr):
if car==cdr:
return True
return []
def noteq(car, cdr):
if car != cdr:
return True
return []
def and2(car, cdr):#用lisp实现一个and吧
if car!=[] and cdr!=[]:
return True
return []
def car(code):
if code == [] or code == '':#fix map func error
return []
return code[0]
def cdr(code):
return code[1:]
def cons(arg1, arg2):
res = [arg1]
res.extend(arg2);
return res
def cond(code):pass
def define():pass
def fun():pass
def fun_seq():pass
class S(str):pass
#extra
def lt(car, cdr):#<
if car < cdr:
return True
return []
def gt(car, cdr):#>
if car > cdr:
return True
return []
def mul(*args):#*
return reduce(op.mul, args)
def div(*args):#/
return reduce(op.div, args)
def sub(*args):#-
return reduce(op.sub, args)
def add(*args):#+
return reduce(op.add, args)
def mod(car, cdr):#%
return car % cdr
def show(code):
print( code)
return code
def seti(key, val):
pass
# def yf():
# pass
# def yd():
# pass
def nexti(sq, n):
if not hasattr(sq, '__next__'):
sq = iter(sq)
while n:
if n == 1:
return next(sq)
next(sq)
n = n - 1
def use(pg, _as=None):
try:
mod = __import__(pg)
return mod, _as
except Exception as e:
print('<No this Package: '+ str(e) +'>')
return None, None
def attr(obj, prop):
return getattr(obj, prop)
###############################
class Env(dict):
def __init__(self, outer, params=None, args=None):
params = params if params else []
args = args if args else []
#for currying
for i in range(len(args),len(params)):
args.append([])
#end
self.update(zip(params,args))#
self.outer = outer
def find(self, key):
ks = key.split('.')
if len(ks) > 1:
if ks[0] in self:
for k in ks[1:]:
ks[0] = getattr(self[ks[0]], k)
return ks[0]
return self.outer[key]
else:
if key in self:
return self[key]
return self.outer.find(key)
def seti(self, key,value):
if key in self:
self[key] = value
else:
self.outer.seti(key,value)
#############################
lisp_env = {'quote':quote,'_':quote,'atom':atom,'eq':eq,'car':car, \
'cdr':cdr,'cons':cons,'cond':cond,'define':define,'fun':fun, \
'lt':lt,'mul':mul,'sub':sub,'gt':gt,'div':div,'mod':mod, \
'add':add,'noteq':noteq,'and2':and2, 'next':next, 'nexti':nexti, \
'show':show, 'seti':seti, 'True':True, 'False':False, \
'use':use, 'attr':attr }#
############################
def run(code,env):
# print '===code===', code, '======'
# print '===env===', env, '======'
# print '===outer===', env.outer, '======'
#return S('val'),变量
if type(code) is S:
try:
return env.find(code)
except:
print( '<Undefined variable %s...>' % code, '')
raise RuntimeError
#常量
#for empty list and no list
elif code==[] or type(code) is not list:
return code
#设置变量的值
elif code[0] is seti:
if type(code[1]) is not S:
print ("<Can't assign a value to %s...>" % code[1], '')
raise RuntimeError
try:
key = env.seti(code[1], run(code[2], env))
return env.find(code[1])
except:
print( "<Can't variable %s...>" % code[1], '')
raise RuntimeError
#变量引用,for quote exp
elif code[0] is quote:
return code[0](*code[1:])
#特别函数,for def, fun, let
elif code[0] is define:
env[ code[1]] = run(code[2],env)
# if code[1] == 'inner' or code[1]=='E':
# print '--define--', code[1], code[2], env
return env[ code[1]]
#执行function体
elif code[0] is fun_seq:
last = None
codelen = len(code[1:]) - 1
for i, c in enumerate(code[1:]):
res = run(c, env)
if i == codelen:
last = res
return last
elif code[0] is fun:
# if code[1] and code[1][-1] == 'ident' or code[1] and code[1][-1] == '__outer__':
# print '--eval--', env
if len(code[1]) == 0:
return lambda *args: run([fun_seq]+code[2:], Env(env, ['args'], [list(args)]))
if type(code[1]) is S:
return lambda *args: run( [fun_seq]+code[2:], Env(env, [code[1]], [list(args)]))
return lambda *args: run([fun_seq]+code[2:], Env(env, code[1], list(args)))#name,value
#条件,for cond, [cond [p1,e1],[p2,e2],...]
elif code[0] is cond:
for c in code[1:]:
if run(c[0], env):
res = [run(ii, env) for ii in c[1:]]
return res[-1]
elif code[0] is use:
mod, _as = None,None
if len(code) > 2:
mod, _as = use(code[1], code[2])
else:
mod, _as = use(code[1])
if not mod:
raise RuntimeError
if _as:
env[_as] = mod
else:
env[code[1]] = mod
return env[_as] if _as else env[code[1]]
#[S]
elif type(code[0]) is S and len(code) == 1:
try:
return run(env.find(code[0]), env)
except:
print( '<Undefined variable %s...>' % code[0], '')
raise RuntimeError
else:
exps = [ run(exp, env) for exp in code]
f = exps.pop(0)
if not (type(f) is types.FunctionType) and not (type(f) is types.BuiltinFunctionType) and not f is type:
return [f]+exps
try:
#print f, exps
return f(*exps)
except TypeError as e:#pass arg for next(), if not a iterator
print ('<StopIteration!>')
raise RuntimeError
#//python/5409