python一个简单的lisp实
#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