1 package org.simantics.scl.compiler.internal.elaboration.subsumption;
\r
3 import java.util.ArrayList;
\r
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
6 import org.simantics.scl.compiler.internal.types.effects.EffectIdMap;
\r
7 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
\r
8 import org.simantics.scl.compiler.types.TMetaVar;
\r
9 import org.simantics.scl.compiler.types.Type;
\r
10 import org.simantics.scl.compiler.types.exceptions.UnificationException;
\r
15 int constLowerBound = EffectIdMap.MIN;
\r
16 int constUpperBound = EffectIdMap.MAX;
\r
17 int upperApprox = EffectIdMap.MAX;
\r
20 ArrayList<Var> simpleLowerBounds = new ArrayList<Var>();
\r
21 ArrayList<Var> simpleUpperBounds = new ArrayList<Var>();
\r
22 ArrayList<VUnion> complexLowerBounds = new ArrayList<VUnion>();
\r
23 ArrayList<VUnion> complexUpperBounds = new ArrayList<VUnion>();
\r
28 public Var(TMetaVar original, String name, SubSolver solver) {
\r
29 this.original = original;
\r
31 this.solver = solver;
\r
38 solver.dirtyQueue.add(this);
\r
43 * Adds a constant constraint
\r
45 public void addUpperBound(int c) {
\r
46 c &= constUpperBound;
\r
47 if(c != constUpperBound) {
\r
48 if((c & constLowerBound) != constLowerBound) {
\r
49 solver.errorLog.log(solver.globalLoc, "Subsumption failed: " +
\r
50 solver.effectIds.toType(constLowerBound) + " is not a subtype of " +
\r
51 solver.effectIds.toType(c)
\r
55 constUpperBound = c;
\r
56 for(int i=0;i<complexUpperBounds.size();++i) {
\r
57 VUnion u = complexUpperBounds.get(i);
\r
59 if(u.con == 0 && u.vars.size() == 1) {
\r
60 removeComplexUpperBound(i);
\r
62 addUpperBound(u.vars.get(0));
\r
69 public void addLowerBound(int c) {
\r
70 if((c | constUpperBound) != constUpperBound) {
\r
71 solver.errorLog.log(solver.globalLoc, "Subsumption failed: " +
\r
72 solver.effectIds.toType(c) + " is not a subtype of " +
\r
73 solver.effectIds.toType(constUpperBound)
\r
77 constLowerBound |= c;
\r
81 private void removeComplexUpperBound(int i) {
\r
82 VUnion u = complexUpperBounds.get(i);
\r
83 int lastId = complexUpperBounds.size()-1;
\r
84 VUnion last = complexUpperBounds.remove(lastId);
\r
86 complexUpperBounds.set(i, last);
\r
87 for(Var v : u.vars) {
\r
88 v.complexLowerBounds.remove(u);
\r
94 * Adds a simple variable constraint
\r
96 public void addUpperBound(Var var) {
\r
99 if(simpleUpperBounds.size() < var.simpleLowerBounds.size()) {
\r
100 if(simpleUpperBounds.contains(var))
\r
104 if(var.simpleLowerBounds.contains(this))
\r
108 for(int i=0;i<complexUpperBounds.size();++i)
\r
109 if(complexUpperBounds.get(i).vars.contains(var)) {
\r
110 removeComplexUpperBound(i);
\r
114 simpleUpperBounds.add(var);
\r
115 var.simpleLowerBounds.add(this);
\r
122 * Adds a complex constraint
\r
124 public void addUpperBound(VUnion u) {
\r
125 if(u.vars.isEmpty()) {
\r
126 addUpperBound(u.con);
\r
129 if(u.vars.contains(this))
\r
131 for(Var v : u.vars)
\r
132 if(simpleUpperBounds.contains(v))
\r
134 u.con &= constUpperBound;
\r
135 if(u.con == constUpperBound)
\r
137 if(u.con == 0 && u.vars.size() == 1)
\r
138 addUpperBound(u.vars.get(0));
\r
141 complexUpperBounds.add(u);
\r
143 for(Var v : u.vars)
\r
144 v.complexLowerBounds.add(u);
\r
146 // TODO compare complex upper bounds together
\r
149 public void replaceWith(int con) {
\r
150 // Check that replacement is sound
\r
151 if(SCLCompilerConfiguration.DEBUG) {
\r
152 if((con&constLowerBound) != constLowerBound)
\r
153 throw new InternalCompilerError();
\r
154 if((con|constUpperBound) != constUpperBound)
\r
155 throw new InternalCompilerError();
\r
158 // Remove the variable and unify original TMetaVar
\r
159 solver.vars.remove(original);
\r
161 Type type = solver.effectIds.toType(con);
\r
162 if(SubSolver.DEBUG)
\r
163 System.out.println(original.toString(solver.tuc) + " := " + type.toString(solver.tuc));
\r
164 original.setRef(type);
\r
165 } catch (UnificationException e) {
\r
166 throw new InternalCompilerError();
\r
169 // Propagate change to lower and upper bounds
\r
170 for(Var v : simpleUpperBounds) {
\r
171 v.simpleLowerBounds.remove(this);
\r
172 v.addLowerBound(con);
\r
175 for(Var v : simpleLowerBounds) {
\r
176 v.simpleUpperBounds.remove(this);
\r
177 v.addUpperBound(con);
\r
180 for(VUnion u : complexUpperBounds) {
\r
183 if(u.vars.size() == 1) {
\r
184 Var uv = u.vars.get(0);
\r
185 uv.constLowerBound |= ~u.con;
\r
186 uv.complexLowerBounds.remove(u);
\r
190 for(Var uv : u.vars)
\r
194 for(VUnion u : complexLowerBounds) {
\r
196 u.vars.remove(this);
\r
198 u.con &= u.low.constUpperBound;
\r
199 if(u.vars.isEmpty()) {
\r
200 u.low.complexUpperBounds.remove(u);
\r
201 u.low.addUpperBound(u.con);
\r
203 else if(u.vars.size() == 1 && u.con == 0) {
\r
204 u.low.complexUpperBounds.remove(u);
\r
205 u.low.addUpperBound(u.vars.get(0));
\r
210 public void replaceDownwards(Var var) {
\r
211 // Remove the variable and unify original TMetaVar
\r
212 solver.vars.remove(original);
\r
214 if(SubSolver.DEBUG)
\r
215 System.out.println(original.toString(solver.tuc) + " := " + var.original.toString(solver.tuc));
\r
216 original.setRef(var.original);
\r
217 } catch (UnificationException e) {
\r
218 throw new InternalCompilerError();
\r
221 // Remove downwards dependencies
\r
222 if(constLowerBound != 0)
\r
223 throw new InternalCompilerError();
\r
224 for(Var v : simpleLowerBounds)
\r
225 v.simpleUpperBounds.remove(this);
\r
226 if(!complexLowerBounds.isEmpty())
\r
227 throw new InternalCompilerError();
\r
230 // Propagate change to upper bounds
\r
231 var.addUpperBound(constUpperBound);
\r
232 for(Var v : simpleUpperBounds) {
\r
233 v.simpleLowerBounds.remove(this);
\r
234 var.addUpperBound(v);
\r
236 for(VUnion u : complexUpperBounds) {
\r
237 var.addUpperBound(u);
\r
241 public void replaceUpwards(Var var) {
\r
242 // Remove the variable and unify original TMetaVar
\r
243 solver.vars.remove(original);
\r
245 if(SubSolver.DEBUG)
\r
246 System.out.println(original.toString(solver.tuc) + " := " + var.original.toString(solver.tuc));
\r
247 original.setRef(var.original);
\r
248 } catch (UnificationException e) {
\r
249 throw new InternalCompilerError();
\r
252 // Remove upwards dependencies
\r
253 if(constUpperBound != EffectIdMap.MAX)
\r
254 throw new InternalCompilerError();
\r
255 for(Var v : simpleUpperBounds)
\r
256 v.simpleLowerBounds.remove(this);
\r
257 if(!complexUpperBounds.isEmpty())
\r
258 throw new InternalCompilerError();
\r
261 // Propagate change to lower bounds
\r
262 var.addLowerBound(constLowerBound);
\r
263 for(Var v : simpleLowerBounds) {
\r
264 v.simpleUpperBounds.remove(this);
\r
266 v.addUpperBound(var);
\r
268 for(VUnion u : complexLowerBounds) {
\r
269 u.vars.remove(this);
\r
270 if(u.low != null) {
\r
271 u.low.markDirty();
\r
272 if(u.vars.isEmpty() && u.con == 0) {
\r
273 u.low.complexUpperBounds.remove(u);
\r
274 u.low.addUpperBound(var);
\r
282 public boolean isFree() {
\r
283 return constLowerBound == EffectIdMap.MIN &&
\r
284 constUpperBound == EffectIdMap.MAX &&
\r
285 simpleLowerBounds.isEmpty() &&
\r
286 simpleUpperBounds.isEmpty() &&
\r
287 complexLowerBounds.isEmpty() &&
\r
288 complexUpperBounds.isEmpty();
\r