Last active
August 29, 2015 14:09
-
-
Save larsr/cd9a590cbb34ba36fbe9 to your computer and use it in GitHub Desktop.
A python implementation of the MUPL language
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class term(object): | |
def __init__(self,**args): | |
for k in self.vals: | |
self.__setattr__(k,args[k]) | |
def __str__(self): | |
return self.__class__.__name__+"("+(", ".join([k+'='+str(self.__getattribute__(k)) for k in self.vals]))+")" | |
class const(term): vals = ['val'] | |
class add(term): vals = ['e1', 'e2'] | |
class let(term): vals = ['name','exp', 'body'] | |
class var(term): vals = ['name'] | |
class ifgt(term): vals = ['e1', 'e2','thn','els'] | |
class fun(term): vals = ['name','param', 'body'] | |
class closure(term): vals = ['funexp', 'env'] | |
class call(term): vals = ['fun', 'arg'] | |
class pair(term): vals = ['e1', 'e2'] | |
class ispair(term): vals = ['exp'] | |
class fst(term): vals = ['exp'] | |
class snd(term): vals = ['exp'] | |
def addvar(var, val, env): return dict(env.items()+[(var,val)]) | |
def eval_exp(e, env = {}): | |
c = e.__class__ | |
if c == const: | |
return e | |
elif c == add: | |
return const(val=eval_exp(e.e1, env).val + eval_exp(e.e2, env).val) | |
elif c == let: | |
env2 = addvar(e.name, eval_exp(e.exp, env), env) | |
return eval_exp(e.body, env2) | |
elif c == var: | |
return env[e.name] | |
elif c == ifgt: | |
b = eval_exp(e.e1, env).val > eval_exp(e.e2, env).val | |
return eval_exp(e.thn if b else e.els, env) | |
elif c == fun: | |
return closure(funexp=e, env=env) | |
elif c == closure: | |
return e | |
elif c == call: | |
a = eval_exp(e.arg, env) | |
clos = eval_exp(e.fun, env) | |
fenv = addvar(clos.funexp.name, clos, clos.env) | |
fenv = addvar(clos.funexp.param, a, fenv) | |
return eval_exp(clos.funexp.body, fenv) | |
elif c == pair: | |
return pair(e1=eval_exp(e.e1, env), e2=eval_exp(e.e2, env)) | |
elif c == ispair: | |
if eval_exp(e.exp, env).__class__ == pair: | |
return const(val=1) | |
else: | |
return const(val=0) | |
elif c == fst: | |
return eval_exp(e.exp, env).e1 | |
elif c == snd: | |
return eval_exp(e.exp, env).e2 | |
print eval_exp(add(e1=const(val=123), e2=const(val=321))) | |
print eval_exp(ifgt(e1=const(val=3),e2=const(val=2), thn=const(val=3), els=const(val=4))) | |
print eval_exp(ifgt(e1=const(val=1),e2=const(val=2), thn=const(val=3), els=const(val=4))) | |
print eval_exp(add(e1=var(name="x"), e2=var(name="x")),{"x":const(val=32)}) | |
print eval_exp(let(name="x",exp=const(val=123), body=add(e1=var(name="x"), e2=var(name="x")))) | |
print eval_exp(call(fun=fun(name="f", param="x", body=add(e1=const(val=1), e2=var(name="x"))),arg=const(val=3))) | |
### Example | |
# map '+1' on list [1,2,3] | |
map=fun(name="map", param="f", body= | |
fun(name="mapf", param="L", body= | |
ifgt(e1=ispair(exp=var(name="L")),e2=const(val=0), | |
thn=pair(e1=call(fun=var(name="f"), arg=fst(exp=var(name="L"))), | |
e2=call(fun=var(name="mapf"), arg=snd(exp=var(name="L")))), | |
els=const(val=0)))) | |
test=pair(e1=const(val=1),e2=pair(e1=const(val=2),e2=pair(e1=const(val=3),e2=const(val=0)))) | |
inc=fun(name="inc", param="x", body=add(e1=const(val=1), e2=var(name="x"))) | |
print eval_exp(call(fun=call(fun=map, arg=inc), arg=test)) | |
# | |
### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment