]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/unification/Unification.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.runtime / src / org / simantics / scl / runtime / unification / Unification.java
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/unification/Unification.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/unification/Unification.java
new file mode 100644 (file)
index 0000000..679af1f
--- /dev/null
@@ -0,0 +1,106 @@
+package org.simantics.scl.runtime.unification;
+
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.scl.runtime.tuple.Tuple;
+import org.simantics.scl.runtime.tuple.Tuple0;
+
+
+public class Unification {
+    public static Object canonical(Object a) {
+        if(a instanceof UVar) {
+            UVar ua = (UVar)a;
+            if(ua.bound)
+                return ua.ref = canonical(ua.ref);
+            else
+                return a;
+        }
+        return a;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static void unify(Object a, Object b) {
+        a = canonical(a);
+        b = canonical(b);
+        if(a == b)
+            return;
+        if(a instanceof UVar) {
+            ((UVar)a).setRef(b);
+            return;
+        }
+        if(b instanceof UVar) {
+            ((UVar)b).setRef(a);
+            return;
+        }
+        if(a instanceof UPending) {
+            ((UPending)a).checkAgains(b);
+            return;
+        }
+        if(b instanceof UPending) {
+            ((UPending)b).checkAgains(a);
+            return;
+        }
+        if(a instanceof UCons) {
+            UCons ua = (UCons)a;
+            if(b instanceof UCons) {
+                UCons ub = (UCons)b;
+                if(ua.tag.id != ub.tag.id)
+                    throw new RuntimeUnificationException();
+                unifyTuple(ua.components, ub.components);
+                ua.components = ub.components;
+            }
+            else {
+                Object bComponents = ua.tag.destructor.apply(b);
+                unifyTuple(ua.components, bComponents);
+                ua.components = bComponents;
+            }
+        }
+        else {
+            if(b instanceof UCons) {
+                UCons ub = (UCons)b;
+                Object aComponents = ub.tag.destructor.apply(a);
+                unifyTuple(aComponents, ub.components);
+                ub.components = aComponents;
+            }
+            else {
+                if(a == null ? b != null : !a.equals(b))
+                    throw new RuntimeUnificationException();
+            }
+        }
+    }
+    
+    public static void unifyTuple(Object a, Object b) {
+        if(a instanceof Tuple) {
+            Tuple ta = (Tuple)a;
+            Tuple tb = (Tuple)b;
+            int length = ta.length();
+            for(int i=0;i<length;++i)
+                unify(ta.get(i), tb.get(i));
+        }
+        else {
+            unify(a, b);
+        }
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static Object extractWithDefault(Function def, Object uni) {
+        if(uni instanceof UVar) {
+            UVar var = (UVar)uni;
+            if(var.bound)
+                return var.ref = extractWithDefault(def, var.ref);
+            else {
+                var.bound = true;
+                return var.ref = def.apply(Tuple0.INSTANCE);
+            }
+        }
+        else if(uni instanceof UCons) {
+            UCons cons = (UCons)uni;
+            return cons.tag.constructor.apply(cons.components);
+        }
+        else if(uni instanceof UPending) {
+            UPending pending = (UPending)uni;
+            return pending.force();
+        }
+        else
+            return uni;
+    }
+}