Skip to content

Instantly share code, notes, and snippets.

@larsr
Last active August 29, 2015 14:09
Show Gist options
  • Save larsr/cd9a590cbb34ba36fbe9 to your computer and use it in GitHub Desktop.
Save larsr/cd9a590cbb34ba36fbe9 to your computer and use it in GitHub Desktop.
A python implementation of the MUPL language
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