diff --git a/data2.py b/data2.py
new file mode 100644
index 0000000..bfe099e
--- /dev/null
+++ b/data2.py
@@ -0,0 +1,408 @@
+
+#encoding: utf-8
+
+import os.path
+import signal
+from copy import copy
+import shelve
+
+DBFILE = os.path.expanduser("~/.config/pylambda.vars")
+varnames = "xyztspqfgabcdehijklmnoruvwABCDEFGHIJKLMNOPQRSTUVWXYZ"
+DEBUG = 0
+
+vars = dict()
+N = 0
+
+if DEBUG:
+ def debug(s):
+ print "| " +s
+else:
+ def debug(s):
+ pass
+
+def d_show(obj):
+ return "[%d] %s" % (obj.n, str(obj))
+
+class Set(object):
+ def __init__(self,*elems):
+ self._list = list(elems)
+
+ def __in__(self,obj):
+ return str(obj) in map(str,self._list)
+
+ def add(self,obj):
+ if not str(obj) in map(str,self._list):
+ self._list.append(obj)
+
+ def sub(self,obj):
+ if str(obj) in map(str,self._list):
+ self._list = [x for x in self._list if str(x) != str(obj)]
+
+ def __add__(self,set):
+ new = Set(*self._list)
+ for i in set:
+ new.add(i)
+ return new
+
+ def __sub__(self,set):
+ new = Set(*self._list)
+ for i in set:
+ new.sub(i)
+ return new
+
+ def __mul__(self,set):
+ r = Set()
+ for i in self._list:
+ if i in set:
+ r.add(i)
+ return r
+
+ def __iter__(self):
+ return iter(self._list)
+
+ def __repr__(self):
+ return "<Set: %s>" % map(str,self._list)
+
+def catch_signal(signum,frame):
+ raise RuntimeError, "User interrupt."
+
+def merge(d1,d2):
+ t = copy(d1)
+ for k in d2:
+ t[k] = d2[k]
+ return t
+
+def typeof(var):
+ v = var
+ while isinstance(v,Var) and not isinstance(v,Const):
+ try:
+ v = vars[v.name]
+ except KeyError:
+ return 'UnboundVar'
+ if isinstance(v,Const):
+ return 'Const'
+ elif isinstance(v,Lambda):
+ return 'Lambda'
+ elif isinstance(v,Assignment):
+ return 'Assignment'
+ elif isinstance(v,Comma):
+ return 'Comma-Expr'
+ elif isinstance(v,Expr):
+ return 'Expr'
+
+def set_old_value(data):
+ global vars
+ vars['%'] = data
+
+def multy_lambda(arglist,expr):
+ "Return Lambda(arglist[0],Lambda(arglist[1],...Lambda(arglist[n],expr))..)."
+ if len(arglist) == 1:
+ return Lambda(Var(arglist[0]),expr)
+ else:
+ return Lambda(Var(arglist[0]),multy_lambda(arglist[1:],expr))
+
+def lambda_pow(var,expr,const):
+ "Returns right part of (\var.expr^{n})"
+ if const == 0:
+ return var
+ else:
+ f = lambda_pow(var,expr,const-1)
+ return expr.subst(var,f)
+
+def first_var(excl_list=[]):
+ n = 0
+ while varnames[n] in map(str,excl_list):
+ n = n+1
+ return varnames[n]
+
+def nextvar(old):
+ if old.count("'") < 3:
+ n = old + "'"
+ else:
+ o = old[0]
+ i = (varnames.index(o)+1)%len(varnames)
+ n = varnames[i]
+ return n
+
+def FV(obj):
+ return obj.FV()
+
+def V(obj):
+ return obj.V()
+
+def Clos(obj):
+ fv = FV(obj)
+ l = obj
+ for v in fv:
+ l = Lambda(v,l)
+ return l
+
+def CV(obj):
+ return V(obj) - FV(obj)
+
+def rename_off(obj,excl):
+ old = copy(obj)
+ old_e = Set(*excl._list)
+ for v in CV(obj):
+ nv = first_var(excl + FV(obj))
+ obj = obj.rename(v,Var(nv))
+ excl.add(Var(nv))
+ debug("%s: renaming off %s => %s" % (d_show(old),old_e,d_show(obj)))
+ return obj
+
+def alpha(obj,app,excl_vars=Set()):
+ vs = V(app)
+ return rename_off(obj,vs+excl_vars)
+
+class Term(object):
+ def setnumber(self):
+ global N
+ N += 1
+ self.n = N
+
+class Var(Term):
+ def __init__(self,name):
+ self.name = name
+ self.setnumber()
+
+ def __repr__(self):
+ return "<Var: %s>" % self.name
+
+ def __str__(self):
+ return self.name
+
+ def FV(self):
+ return Set(self)
+
+ def V(self):
+ return Set(self)
+
+ def subst(self,old,new):
+ if str(self) == str(old):
+ return new
+ else:
+ return copy(self)
+
+ def rename(self,old,new):
+ if str(self) == str(old):
+ return new
+ else:
+ return self
+
+ def eval(self,excl_vars=Set()):
+ return self.eval_vars(excl_vars)
+
+ def eval_vars(self,excl_vars=Set()):
+ global vars
+ if self.name in vars:
+ return vars[self.name]
+ else:
+ return self
+
+class Const(Term):
+ def __init__(self,value):
+ self.value = value
+ self.setnumber()
+
+ def __repr__(self):
+ return "<Const: %s>" % self.value
+
+ def __str__(self):
+ return str(self.value)
+
+ def FV(self):
+ return Set()
+
+ def V(self):
+ return Set()
+
+ def subst(self,old,new):
+ return self
+
+ def rename(self,old,new):
+ return self
+
+ def eval(self,excl_vars=Set()):
+ return self
+
+ def eval_vars(self,excl_vars=Set()):
+ return self
+
+class Lambda(Term):
+ def __init__(self,var,expr):
+ self.var = var
+ self.expr = expr
+ self.setnumber()
+
+ def __repr__(self):
+ return "<Lambda: %s. %s>" % (self.var,self.expr)
+
+ def __str__(self):
+ return "(λ%s.%s)" % (str(self.var),str(self.expr))
+
+ def FV(self):
+ return FV(self.expr) - Set(self.var)
+
+ def V(self):
+ return V(self.expr) + Set(self.var)
+
+ def subst(self,old,new):
+ if str(old) != str(self.var) and not new in FV(self):
+ l = Lambda(self.var,self.expr.subst(old,new))
+ else:
+ l = copy(self)
+ return l
+
+ def rename(self,old,new):
+ if str(old) != str(self.var):
+ l = Lambda(self.var,self.expr.rename(old,new))
+ else:
+ l = Lambda(new,self.expr.rename(old,new))
+ return l
+
+ def eval(self,excl_vars=Set()):
+ return Lambda(self.var,self.expr.eval(excl_vars + Set(self.var)))
+
+ def eval_vars(self,excl_vars=Set()):
+ return Lambda(self.var, self.expr.eval_vars(excl_vars + Set(self.var)))
+
+ def apply(self,expr,excl_vars=Set()):
+ old = copy(self)
+ self = alpha(self,expr,excl_vars)
+ r = self.expr.subst(self.var,expr)
+ debug("Apply: <%s> @ <%s> => %s" % (self,expr,r))
+ return r
+
+
+class Expr(Term):
+ def __init__(self,op,a1,a2):
+ self.op = op
+ self.a1 = a1
+ self.a2 = a2
+ self.setnumber()
+# debug("[%d] New Expr: %s" % d_show(self))
+
+ def __repr__(self):
+ return "<Expr: %s %s %s>" % (self.a1,self.op,self.a2)
+
+ def __str__(self):
+ if self.op == '@':
+ return "(%s %s)" % (str(self.a1),str(self.a2))
+ else:
+ return "(%s%s%s)" % (str(self.a1),self.op,str(self.a2))
+
+ def FV(self):
+ return FV(self.a1) + FV(self.a2)
+
+ def V(self):
+ return V(self.a1) + V(self.a2)
+
+ def subst(self,old,new):
+ a = self.a1.subst(old,new)
+ b = self.a2.subst(old,new)
+ return Expr(self.op,a,b)
+
+ def rename(self,old,new):
+ a = self.a1.rename(old,new)
+ b = self.a2.rename(old,new)
+ return Expr(self.op,a,b)
+
+ def eval(self,excl_vars=Set()):
+ self = self.eval_vars()
+ if type(self) != Expr:
+ return self
+# debug("[%d] A1 = %s" % (self.n,self.a1))
+ a = self.a1.eval(excl_vars)
+ b = rename_off(self.a2,V(a)+excl_vars)
+# debug("[%d] A = %s" % (self.n,a))
+ if self.op=='@' and type(a)==Lambda:
+ e = a.apply(b,excl_vars)
+ elif self.op=='!' and type(a)==Lambda and type(b)==Const:
+ e = Lambda(a.var, lambda_pow(a.var,a.expr,b.value))
+ else:
+ e = Expr(self.op,a,b)
+ debug("[%d] Eval: %s" % (self.n,e))
+ return e
+
+ def eval_vars(self,excl_vars=Set()):
+ global vars
+ b = self.a2.eval_vars(excl_vars)
+ a = self.a1.eval_vars(excl_vars + V(b))
+ e = Expr(self.op,a,b)
+ if e.op == '@' and type(a)==Lambda:
+ return a.apply(b,excl_vars)
+ if type(e.a1)==Const and type(e.a2)==Const:
+ if e.op=='+':
+ return Const(e.a1.value + e.a2.value)
+ if e.op=='-':
+ return Const(e.a1.value - e.a2.value)
+ if e.op=='*':
+ return Const(e.a1.value * e.a2.value)
+ if e.op=='/':
+ return Const(e.a1.value / e.a2.value)
+ if e.op=='^':
+ return Const(e.a1.value ** e.a2.value)
+# debug("[%d] Eval_vars: %s" % (self.n,e))
+ return e
+
+class Assignment(Term):
+ "Assignment, as in x = 5"
+ def __init__(self,var,expr):
+ self.var = var
+ self.expr = expr
+ self.setnumber()
+ vars[str(var)] = expr
+
+ def __repr__(self):
+ return "<Assignment: %s = %s>" % (self.var,self.expr)
+
+ def __str__(self):
+ return "%s = %s" % (self.var,self.expr)
+
+ def eval(self,excl_vars=Set()):
+ return self
+
+class Comma(Term):
+ "Variable substitution expression, as in: 'sqr z, z=5'."
+ def __init__(self,expr,assign):
+ self.expr = expr
+ self.assign = assign
+ self.setnumber()
+
+ def __str__(self):
+ return "%s, %s" % (self.expr.show(),self.assign.show())
+
+ def subst(self,old,new):
+ e = self.expr.subst(old,new)
+ return Comma(e,self.assign)
+
+ def eval(self,excl_vars=Set()):
+ return self.expr.subst(self.assign.var,self.assign.expr).eval()
+
+def save():
+ global vars
+ d = shelve.open(DBFILE)
+ tmp = copy(vars)
+ del vars['%']
+ d["vars"] = tmp
+ d.close()
+
+def load():
+ global vars
+ try:
+ old = copy(vars['%'])
+ except KeyError:
+ old = Const(0)
+ d = shelve.open(DBFILE)
+ t = d["vars"]
+ vars = merge(vars,t)
+ d.close()
+ vars['%'] = old
+
+def show_var(name):
+ global vars
+ return "%s = %s" % (name,vars[name])
+
+def show_vars():
+ global vars
+ print ", ".join(map(show_var,vars.keys()))