]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/unification/Unification.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.runtime / src / org / simantics / scl / runtime / unification / Unification.java
1 package org.simantics.scl.runtime.unification;
2
3 import org.simantics.scl.runtime.function.Function;
4 import org.simantics.scl.runtime.tuple.Tuple;
5 import org.simantics.scl.runtime.tuple.Tuple0;
6
7
8 public class Unification {
9     public static Object canonical(Object a) {
10         if(a instanceof UVar) {
11             UVar ua = (UVar)a;
12             if(ua.bound)
13                 return ua.ref = canonical(ua.ref);
14             else
15                 return a;
16         }
17         return a;
18     }
19     
20     @SuppressWarnings("unchecked")
21     public static void unify(Object a, Object b) {
22         a = canonical(a);
23         b = canonical(b);
24         if(a == b)
25             return;
26         if(a instanceof UVar) {
27             ((UVar)a).setRef(b);
28             return;
29         }
30         if(b instanceof UVar) {
31             ((UVar)b).setRef(a);
32             return;
33         }
34         if(a instanceof UPending) {
35             ((UPending)a).checkAgains(b);
36             return;
37         }
38         if(b instanceof UPending) {
39             ((UPending)b).checkAgains(a);
40             return;
41         }
42         if(a instanceof UCons) {
43             UCons ua = (UCons)a;
44             if(b instanceof UCons) {
45                 UCons ub = (UCons)b;
46                 if(ua.tag.id != ub.tag.id)
47                     throw new RuntimeUnificationException();
48                 unifyTuple(ua.components, ub.components);
49                 ua.components = ub.components;
50             }
51             else {
52                 Object bComponents = ua.tag.destructor.apply(b);
53                 unifyTuple(ua.components, bComponents);
54                 ua.components = bComponents;
55             }
56         }
57         else {
58             if(b instanceof UCons) {
59                 UCons ub = (UCons)b;
60                 Object aComponents = ub.tag.destructor.apply(a);
61                 unifyTuple(aComponents, ub.components);
62                 ub.components = aComponents;
63             }
64             else {
65                 if(a == null ? b != null : !a.equals(b))
66                     throw new RuntimeUnificationException();
67             }
68         }
69     }
70     
71     public static void unifyTuple(Object a, Object b) {
72         if(a instanceof Tuple) {
73             Tuple ta = (Tuple)a;
74             Tuple tb = (Tuple)b;
75             int length = ta.length();
76             for(int i=0;i<length;++i)
77                 unify(ta.get(i), tb.get(i));
78         }
79         else {
80             unify(a, b);
81         }
82     }
83     
84     @SuppressWarnings({ "rawtypes", "unchecked" })
85     public static Object extractWithDefault(Function def, Object uni) {
86         if(uni instanceof UVar) {
87             UVar var = (UVar)uni;
88             if(var.bound)
89                 return var.ref = extractWithDefault(def, var.ref);
90             else {
91                 var.bound = true;
92                 return var.ref = def.apply(Tuple0.INSTANCE);
93             }
94         }
95         else if(uni instanceof UCons) {
96             UCons cons = (UCons)uni;
97             return cons.tag.constructor.apply(cons.components);
98         }
99         else if(uni instanceof UPending) {
100             UPending pending = (UPending)uni;
101             return pending.force();
102         }
103         else
104             return uni;
105     }
106 }