]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TMetaVar.java
Added missing parts from SVN org.simantics.root project.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TMetaVar.java
1 package org.simantics.scl.compiler.types;
2
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
5
6 import java.util.ArrayList;
7
8 import org.simantics.scl.compiler.environment.Environment;
9 import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
10 import org.simantics.scl.compiler.internal.types.ast.TVarAst;
11 import org.simantics.scl.compiler.internal.types.ast.TypeAst;
12 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
13 import org.simantics.scl.compiler.types.exceptions.UnificationException;
14 import org.simantics.scl.compiler.types.kinds.KMetaVar;
15 import org.simantics.scl.compiler.types.kinds.Kind;
16 import org.simantics.scl.compiler.types.kinds.Kinds;
17 import org.simantics.scl.compiler.types.util.Polarity;
18 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
19
20
21
22 /**
23  * A meta-variable, a type that is currently unknown. This class
24  * should occur only during type inference. Method removeMetaVars
25  * can be used to remove all instances of TMetaVar from the type.
26  * 
27  * @author Hannu Niemistö
28  */
29 public class TMetaVar extends Type {
30     public static final TMetaVar[] EMPTY_ARRAY = new TMetaVar[0];
31     
32     Type ref = null;
33     Polarity polarity = Polarity.NO_POLARITY;
34     private Kind kind;
35     
36     TMetaVar(Kind kind) {
37         this.kind = kind;
38     }
39     
40     TMetaVar(Kind kind, Polarity polarity) {
41         this.kind = kind;
42         this.polarity = polarity;
43     }
44     
45     public Kind getKind() {
46         if(kind instanceof KMetaVar)
47             kind = Kinds.canonical(kind);
48         return kind;        
49     }
50     
51     @Override
52     public Type replace(TVar var, Type replacement) {
53         if(ref == null)
54             return this;
55         else {
56             Type newRef = ref.replace(var, replacement);
57             if(newRef != ref)
58                 return newRef;
59             else
60                 // We could also return newRef here, but in this way
61                 // we don't have to copy so many parent types.
62                 return this;
63         }
64     }
65
66     @Override
67     public TypeAst toTypeAst(TypeUnparsingContext context) {
68         if(ref == null)
69             return new TVarAst(/*polarity.getSymbol() +*/ context.getName(this));
70         else
71             return ref.toTypeAst(context);
72     }
73     
74     @Override
75     public int hashCode() {
76         if(ref == null)
77             return System.identityHashCode(this);
78         else
79             return ref.hashCode();
80     }
81     
82     @Override
83     public void updateHashCode(TypeHashCodeContext context) {
84         if(ref == null)
85             context.append(System.identityHashCode(this));
86         else
87             ref.updateHashCode(context);
88     }
89
90     @Override
91     public void collectFreeVars(ArrayList<TVar> vars) {
92         if(ref != null)
93             ref.collectFreeVars(vars);
94     }
95     
96     @Override
97     public void collectMetaVars(ArrayList<TMetaVar> vars) {
98         if(ref == null)
99             vars.add(this);
100         else
101             ref.collectMetaVars(vars);
102     }
103     
104     @Override
105     public void collectMetaVars(THashSet<TMetaVar> vars) {
106         if(ref == null)
107             vars.add(this);
108         else
109             ref.collectMetaVars(vars);
110     }
111     
112     @Override
113     public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
114         if(ref != null)
115             ref.collectEffectMetaVars(vars);
116     }
117
118     public void setRef(Type a) throws UnificationException {
119         a = Types.weakCanonical(a);
120         if(a.contains(this))
121             throw new UnificationException(this, a);
122         ref = a;
123         if(polarity != Polarity.NO_POLARITY)
124             a.addPolarity(polarity);
125     }
126     
127     public Type getRef() {
128         return ref;
129     }
130     
131     @Override
132     public boolean contains(TMetaVar other) {
133         if(ref == null)
134             return this == other;
135         else
136             return ref.contains(other);
137     }
138     
139     @Override
140     public Type convertMetaVarsToVars() {
141         if(ref == null) {
142             if(kind == Kinds.EFFECT && !polarity.isNegative())
143                 ref = Types.NO_EFFECTS;
144             else
145                 ref = Types.var(getKind());
146             return ref;
147         }
148         else
149             return ref.convertMetaVarsToVars();
150     }
151
152     @Override
153     public boolean isGround() {
154         if(ref == null)
155             return false;
156         else
157             return ref.isGround();
158     }
159
160         public Kind inferKind(Environment context) throws KindUnificationException {
161             return Kinds.metaVar();
162     }
163
164     @Override
165     public boolean containsMetaVars() {
166         if(ref == null)
167             return true;
168         else
169             return ref.containsMetaVars();
170     }
171
172     @Override
173     public void toName(TypeUnparsingContext context, StringBuilder b) {
174         if(ref != null)
175             ref.toName(context, b);
176         else
177             b.append(context.getName(this));
178     }
179     
180     @Override
181     public int getClassId() {
182         return METAVAR_ID;
183     }
184  
185     @Override
186     public boolean isMaximal() {
187         return ref != null && ref.isMaximal(); 
188     }
189     
190     @Override
191     public boolean isMinimal() {
192         return ref != null && ref.isMinimal();
193     }
194
195     @Override
196     public void addPolarity(Polarity polarity) {        
197         if(ref != null)
198             ref.addPolarity(polarity);
199         else
200             this.polarity = this.polarity.add(polarity);
201     }
202
203     public Polarity getPolarity() {
204         return polarity;
205     }
206     
207     @Override
208     public void collectConcreteEffects(ArrayList<TCon> concreteEffects) {
209         if(ref != null)
210             ref.collectConcreteEffects(concreteEffects);
211     }
212
213     @Override
214     public Type head() {
215         if(ref != null)
216             return ref.head();
217         else
218             return this;
219     }
220
221     @Override
222     public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
223         if(ref != null)
224             return ref.copySkeleton(metaVarMap);
225         else {
226             TMetaVar result = metaVarMap.get(this);
227             if(result == null) {
228                 result = new TMetaVar(kind, polarity);
229                 metaVarMap.put(this, result);
230             }
231             return result;
232         }
233     }
234 }