         return bind( t1, null, t2, changes )
 
 # unification!
+unify = (expr1,expr2,changes=[]) ->
+    success = true
+    expr1 = if expr1 instanceof Tin then expr1 else parse(expr1)
+    expr2 = if expr2 instanceof Tin then expr2 else parse(expr2)
+    success = _unify(expr1.node,expr1.varlist,expr2.node,expr2.varlist,changes)
+    if success == false
+        return null
+    else
+        return [expr1,expr2]
 _unify = (n1,v1,n2,v2,changes=[]) ->
     return true if n1 == undefined and n2 == undefined
     return true if n1 == null and n2 == null

                return false if not _unify(n1[idx],v1,n2[idx],v2, changes)
    return true

unify = (expr1,expr2,changes=[]) ->
    success = true
    expr1 = if expr1 instanceof Tin then expr1 else parse(expr1)
    expr2 = if expr2 instanceof Tin then expr2 else parse(expr2)
    success = _unify(expr1.node,expr1.varlist,expr2.node,expr2.varlist,changes)
    if success == false
        return null
    else
        return [expr1,expr2]

rollback = (changes) ->
    for change in changes
        change()

    unparse: () ->
        unboxit @node

#Before an object can be processed it must be "boxed" this consits of
#1. Wrapping all value types in objects so they can be referenced
#2. Converting all objects to arrays and flagging them as objects so they can be reconstructed
#       Objects must be converted to arrays because order matters in unification and an object's keys have no defined order
#       Objects are converted to arrays whos elements are sorted by object key name
boxit = (elem,tinlist) ->
    if elem instanceof Variable
        tinlist?[elem.name] =  new Tin( elem.name, null, null )
