Skip to content

Instantly share code, notes, and snippets.

@dplepage
Last active December 17, 2015 05:58
Show Gist options
  • Save dplepage/5561346 to your computer and use it in GitHub Desktop.
Save dplepage/5561346 to your computer and use it in GitHub Desktop.
Case classes for Python.Depends on actually.py (< https://gist.github.com/dplepage/5095902 >)
from collections import namedtuple
from actually import ActuallyCalls
class CaseClasses(object):
'''Class that converts all lists/tuples in the class into namedtuple classes.'''
class __metaclass__(type):
def __new__(cls, name, supers, kwargs):
for name, value in kwargs.items():
if isinstance(value, (list, tuple)):
kwargs[name] = namedtuple(name, value)
cls = type.__new__(cls, name, supers, kwargs)
return cls
def Case(val):
'''Inherit from this to actually call a member function by case class name'''
def resolver(**matches):
return matches[type(val).__name__](*val)
return ActuallyCalls(resolver)
import operator
class Exp(CaseClasses):
'''Case classes for expressions'''
Var = ('name',)
Const = ('value',)
Binop = ('op', 'lhs', 'rhs')
binops = {
'+': operator.add,
'-': operator.sub,
'/': operator.div,
'*': operator.mul,
'%': operator.mod,
}
def evaluate(exp, env):
'''Evaluate an expression in an environment'''
class x(Case(exp)):
def Var(name):
return env[name]
def Const(value):
return value
def Binop(op, left, right):
if op not in binops:
raise Exception("Unknown Binop {}".format(op))
return binops[op](evaluate(left, env), evaluate(right, env))
return x
def show(exp):
'''Render an expression as a string'''
class x(Case(exp)):
def Var(name):
return name
def Const(value):
return str(value)
def Binop(op, left, right):
return '({} {} {})'.format(show(left), op, show(right))
return x
e = Exp.Binop('*', Exp.Var('x'), Exp.Binop('+', Exp.Const(1), Exp.Const(3)))
print e
print show(e) # prints (x * (1 + 3))
print evaluate(e, dict(x=5)) # prints 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment