Revision 7
Added by Willibald K. over 8 years ago
UlyssesType.java | ||
---|---|---|
1 |
/**
|
|
2 |
*
|
|
3 |
* OOAS Compiler
|
|
4 |
*
|
|
5 |
* Copyright 2015, AIT Austrian Institute of Technology.
|
|
6 |
* This code is based on the C# Version of the OOAS Compiler, which is
|
|
7 |
* copyright 2015 by the Institute of Software Technology, Graz University
|
|
8 |
* of Technology with portions copyright by the AIT Austrian Institute of
|
|
9 |
* Technology. All rights reserved.
|
|
10 |
*
|
|
11 |
* SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
|
|
12 |
*
|
|
13 |
* If you modify the file please update the list of contributors below to in-
|
|
14 |
* clude your name. Please also stick to the coding convention of using TABs
|
|
15 |
* to do the basic (block-level) indentation and spaces for anything after
|
|
16 |
* that. (Enable the display of special chars and it should be pretty obvious
|
|
17 |
* what this means.) Also, remove all trailing whitespace.
|
|
18 |
*
|
|
19 |
* Contributors:
|
|
20 |
* Willibald Krenn (AIT)
|
|
21 |
* Stephan Zimmerer (AIT)
|
|
22 |
* Markus Demetz (AIT)
|
|
23 |
* Christoph Czurda (AIT)
|
|
24 |
*
|
|
25 |
*/
|
|
1 |
/** |
|
2 |
* |
|
3 |
* OOAS Compiler |
|
4 |
* |
|
5 |
* Copyright 2015, AIT Austrian Institute of Technology. |
|
6 |
* This code is based on the C# Version of the OOAS Compiler, which is |
|
7 |
* copyright 2015 by the Institute of Software Technology, Graz University |
|
8 |
* of Technology with portions copyright by the AIT Austrian Institute of |
|
9 |
* Technology. All rights reserved. |
|
10 |
* |
|
11 |
* SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED. |
|
12 |
* |
|
13 |
* If you modify the file please update the list of contributors below to in- |
|
14 |
* clude your name. Please also stick to the coding convention of using TABs |
|
15 |
* to do the basic (block-level) indentation and spaces for anything after |
|
16 |
* that. (Enable the display of special chars and it should be pretty obvious |
|
17 |
* what this means.) Also, remove all trailing whitespace. |
|
18 |
* |
|
19 |
* Contributors: |
|
20 |
* Willibald Krenn (AIT) |
|
21 |
* Stephan Zimmerer (AIT) |
|
22 |
* Markus Demetz (AIT) |
|
23 |
* Christoph Czurda (AIT) |
|
24 |
* |
|
25 |
*/ |
|
26 | 26 |
|
27 | 27 |
|
28 |
package org.momut.ooas.ast.types; |
|
29 |
|
|
30 |
import java.util.Iterator; |
|
28 |
package org.momut.ooas.ast.types; |
|
31 | 29 |
|
30 |
import java.util.Iterator; |
|
31 |
|
|
32 | 32 |
import org.momut.ooas.ast.AstNode; |
33 | 33 |
import org.momut.ooas.ast.AstNodeTypeEnum; |
34 | 34 |
import org.momut.ooas.ast.IAst; |
... | ... | |
37 | 37 |
import org.momut.ooas.utils.exceptions.ArgumentException; |
38 | 38 |
import org.momut.ooas.utils.exceptions.NotImplementedException; |
39 | 39 |
import org.momut.ooas.utils.exceptions.OoasCompilerRuntimeException; |
40 |
|
|
41 |
public abstract class UlyssesType extends AstNode implements IAst |
|
42 |
{ |
|
43 |
private String m_origAnonName; |
|
44 |
protected TypeKind m_kind; |
|
45 |
protected TypeIdentifier m_identifier; |
|
46 |
protected int m_hash; |
|
47 |
// protected long TimeStamp = DateTime.Now.Ticks; |
|
48 |
|
|
49 |
|
|
50 |
public TypeKind kind() { return m_kind; } |
|
51 |
|
|
52 |
public TypeIdentifier identifier() { |
|
53 |
synchronized(this) { |
|
54 |
if (m_identifier == null) |
|
55 |
SetupAnonymousName(); |
|
56 |
} |
|
57 |
return m_identifier; |
|
58 |
} |
|
59 |
|
|
60 |
public boolean isAnonymousType() { |
|
61 |
final String anonName = AnonymousName(); |
|
62 |
if (!m_origAnonName.equals(anonName)) |
|
63 |
throw new OoasCompilerRuntimeException("Internal Error: Anonymous Name changed from '%s' to '%s'.", m_origAnonName, anonName); |
|
64 |
return anonName.equals(m_identifier.tokenText()); |
|
65 |
} |
|
66 |
|
|
67 |
protected UlyssesType(TypeKind aKind, TypeIdentifier anIdentifier) |
|
68 |
{ |
|
69 |
m_kind = aKind; |
|
70 |
m_identifier = anIdentifier; |
|
71 |
m_hash = aKind.toString().hashCode(); //Enum.GetName(typeof(TypeKind), aKind).GetHashCode(); |
|
72 |
} |
|
73 |
|
|
74 |
@Override |
|
75 |
public /*override*/ String toString() |
|
76 |
{ |
|
77 |
return identifier().tokenText(); |
|
78 |
} |
|
79 |
|
|
80 |
public /*virtual*/ String AnonymousName() |
|
81 |
{ |
|
82 |
throw new NotImplementedException(); |
|
83 |
} |
|
84 |
|
|
85 |
|
|
86 |
public void SetTypeIdentifier(TypeIdentifier anId) |
|
87 |
{ |
|
88 |
m_identifier = anId; |
|
89 |
} |
|
90 |
|
|
91 |
public void SetupAnonymousName() |
|
92 |
{ |
|
93 |
if (m_identifier == null) |
|
94 |
{ |
|
95 |
final String anonymousName = this.AnonymousName(); |
|
96 |
m_identifier = new TypeIdentifier(anonymousName, this, null); |
|
97 |
m_origAnonName = anonymousName; |
|
98 |
} |
|
99 |
} |
|
100 |
|
|
101 |
|
|
102 |
@Override |
|
103 |
public AstNodeTypeEnum nodeType() { return AstNodeTypeEnum.type; } |
|
104 |
|
|
105 |
@Override |
|
106 |
public void Accept(IAstVisitor visitor) |
|
107 |
{ |
|
108 |
throw new NotImplementedException(); |
|
109 |
} |
|
110 |
|
|
111 |
|
|
112 |
|
|
113 |
public boolean IsNumeric() |
|
114 |
{ |
|
115 |
final Object o = this; |
|
116 |
return (m_kind == TypeKind.IntType) || |
|
117 |
(m_kind == TypeKind.FloatType) || |
|
118 |
(m_kind == TypeKind.EnumeratedType && o instanceof ValuedEnumType); |
|
119 |
} |
|
120 |
|
|
121 |
public boolean IsQualitative() |
|
122 |
{ |
|
123 |
return (m_kind == TypeKind.QrType); |
|
124 |
} |
|
125 |
|
|
126 |
/** |
|
127 |
* returns the number of unique values of the type (2 for bool, etc..) |
|
128 |
*/ |
|
129 |
public int valueCount() { |
|
130 |
throw new NotImplementedException(); // must be overridden by child |
|
131 |
} |
|
132 |
|
|
133 |
public static String High(UlyssesType atype) |
|
134 |
{ |
|
135 |
switch (atype.kind()) |
|
136 |
{ |
|
137 |
case BoolType: |
|
138 |
return "1"; |
|
139 |
case EnumeratedType: |
|
140 |
return Integer.toString((((EnumType)atype).listOfEnumSymbols().size() - 1)); |
|
141 |
case IntType: |
|
142 |
return Integer.toString(((IntType)atype).rangeHigh()); |
|
143 |
case FloatType: |
|
144 |
return Double.toString(((FloatType)atype).high()); |
|
145 |
// case TypeKind.QrType: |
|
146 |
// return (((QrType)atype).landmarks.Count - 1).ToString(); |
|
147 |
default: |
|
148 |
throw new NotImplementedException(); |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
public static String Low(UlyssesType atype) |
|
153 |
{ |
|
154 |
switch (atype.kind()) |
|
155 |
{ |
|
156 |
case BoolType: |
|
157 |
return "0"; |
|
158 |
case EnumeratedType: |
|
159 |
return "0"; |
|
160 |
case IntType: |
|
161 |
return Integer.toString(((IntType)atype).rangeLow()); |
|
162 |
case FloatType: |
|
163 |
return Double.toString(((FloatType)atype).low()); |
|
164 |
// case TypeKind.QrType: |
|
165 |
// return "0"; |
|
166 |
default: |
|
167 |
throw new NotImplementedException(); |
|
168 |
} |
|
169 |
} |
|
170 |
|
|
171 |
|
|
172 |
/// <summary> |
|
173 |
/// Returns a cover for two types (if possible). |
|
174 |
/// note the cover type for two ints, floats, etc. will have max/min values |
|
175 |
/// that reflect the maximum of the two operands. |
|
176 |
/// </summary> |
|
177 |
|
|
178 |
public static UlyssesType CoverType(UlyssesType type1, UlyssesType type2) |
|
179 |
{ |
|
180 |
/*first some sanity checks*/ |
|
181 |
if (type1 == null) |
|
182 |
throw new ArgumentException("type1 null"); |
|
183 |
if (type2 == null) |
|
184 |
throw new ArgumentException("type2 null"); |
|
185 |
|
|
186 |
if (type1.kind() == TypeKind.OpaqueType) |
|
187 |
throw new ArgumentException("type1 opaque type"); |
|
188 |
if (type2.kind() == TypeKind.OpaqueType) |
|
189 |
throw new ArgumentException("type2 opaque type"); |
|
190 |
|
|
191 |
if (type1 == type2) |
|
192 |
return type1; |
|
193 |
if (UlyssesType.TypeEqual(type1, type2)) |
|
194 |
return type1; |
|
195 |
|
|
196 |
final TypeKind tk1 = type1.kind(); |
|
197 |
final TypeKind tk2 = type2.kind(); |
|
198 |
|
|
199 |
|
|
200 |
|
|
201 |
if (tk1 != tk2) |
|
202 |
{ |
|
203 |
// the only notion we support here is int->float and valenum -> int |
|
204 |
if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType) |
|
205 |
&& (tk1 == TypeKind.FloatType || tk2 == TypeKind.FloatType)) |
|
206 |
{ |
|
207 |
final IntType aInt = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2; |
|
208 |
final FloatType aFloat = tk1 == TypeKind.IntType ? (FloatType)type2 : (FloatType)type1; |
|
209 |
|
|
210 |
final double low = aInt.rangeLow() < aFloat.low() ? (double)aInt.rangeLow() : aFloat.low(); |
|
211 |
final double high = aInt.rangeHigh() < aFloat.high() ? aFloat.high() : (double)aInt.rangeHigh(); |
|
212 |
final double precision = aFloat.precision() > 1 ? 1.0 : aFloat.precision(); |
|
213 |
|
|
214 |
return new FloatType(low, high, precision, null); |
|
215 |
|
|
216 |
} |
|
217 |
else if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType) |
|
218 |
&& (tk1 == TypeKind.EnumeratedType || tk2 == TypeKind.EnumeratedType)) |
|
219 |
{ |
|
220 |
final IntType intt1 = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2; |
|
221 |
final EnumType anEnum = tk1 == TypeKind.IntType ? (EnumType)type2 : (EnumType)type1; |
|
222 |
|
|
223 |
if (anEnum instanceof ValuedEnumType) |
|
224 |
{ |
|
225 |
final IntType intt2 = ((ValuedEnumType)anEnum).getIntType(); |
|
226 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
|
227 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
|
228 |
return new IntType(low, high, null); |
|
229 |
} |
|
230 |
else |
|
231 |
return null; |
|
232 |
} |
|
233 |
else if (tk1 == TypeKind.Any || tk2 == TypeKind.Any) |
|
234 |
{ |
|
235 |
final AnyType freeVar = tk1 == TypeKind.Any ? (AnyType)type1 : (AnyType)type2; |
|
236 |
final UlyssesType fixedType = tk1 == TypeKind.Any ? type2 : type1; |
|
237 |
final UlyssesType newcover = freeVar.VariableIdentifier().type().kind() == TypeKind.Any |
|
238 |
? fixedType : CoverType(fixedType, freeVar.VariableIdentifier().type()); |
|
239 |
freeVar.VariableIdentifier().SetType(newcover); |
|
240 |
return newcover; |
|
241 |
} |
|
242 |
else if (tk1 == TypeKind.OoActionSystemType && tk2 == TypeKind.Null) |
|
243 |
{ |
|
244 |
return type1; |
|
245 |
} |
|
246 |
else if (tk2 == TypeKind.OoActionSystemType && tk1 == TypeKind.Null) |
|
247 |
{ |
|
248 |
return type2; |
|
249 |
} |
|
250 |
|
|
251 |
else |
|
252 |
return null; |
|
253 |
} |
|
254 |
else |
|
255 |
{ |
|
256 |
switch (tk1) |
|
257 |
{ |
|
258 |
case Any: |
|
259 |
return type1; |
|
260 |
|
|
261 |
case IntType: |
|
262 |
final IntType intt1 = (IntType)type1; |
|
263 |
final IntType intt2 = (IntType)type2; |
|
264 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
|
265 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
|
266 |
return new IntType(low, high, null); |
|
267 |
case BoolType: |
|
268 |
return type1; |
|
269 |
case FloatType: |
|
270 |
final FloatType floatt1 = (FloatType)type1; |
|
271 |
final FloatType floatt2 = (FloatType)type2; |
|
272 |
final double flow = floatt1.low() < floatt2.low() ? floatt1.low() : floatt2.low(); |
|
273 |
final double fhigh = floatt1.high() > floatt2.high() ? floatt1.high() : floatt2.high(); |
|
274 |
final double fprec = floatt1.precision() < floatt2.precision() ? floatt1.precision() : floatt2.precision(); |
|
275 |
return new FloatType(flow, fhigh, fprec, null); |
|
276 |
case EnumeratedType: |
|
277 |
return null; |
|
278 |
case ListType: |
|
279 |
final ListType listt1 = (ListType)type1; |
|
280 |
final ListType listt2 = (ListType)type2; |
|
281 |
int maxelems = listt1.maxNumberOfElements() > listt2.maxNumberOfElements() ? |
|
282 |
listt1.maxNumberOfElements() : listt2.maxNumberOfElements(); |
|
283 |
// empty lists lack type, so take the other one |
|
284 |
if ((listt1.innerType().kind() == TypeKind.Null) && (listt2.innerType().kind() != TypeKind.Null)) |
|
285 |
return listt2; |
|
286 |
else if ((listt2.innerType().kind() == TypeKind.Null) && (listt1.innerType().kind() != TypeKind.Null)) |
|
287 |
return listt1; |
|
288 |
else if (listt1.innerType().kind() == TypeKind.Null && listt2.innerType().kind() == TypeKind.Null) |
|
289 |
return listt1; |
|
290 |
else |
|
291 |
{ |
|
292 |
final UlyssesType subtype = UlyssesType.CoverType(listt1.innerType(), listt2.innerType()); |
|
293 |
if (subtype != null) |
|
294 |
return new ListType(subtype, maxelems, null); |
|
295 |
else |
|
296 |
return null; |
|
297 |
} |
|
298 |
case MapType: |
|
299 |
final MapType mapt1 = (MapType)type1; |
|
300 |
final MapType mapt2 = (MapType)type2; |
|
301 |
// empty maps lack type, so take the other one. |
|
302 |
if ((mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null) |
|
303 |
&& (mapt2.fromType().kind() != TypeKind.Null && mapt2.toType().kind() != TypeKind.Null)) |
|
304 |
return mapt2; |
|
305 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
|
306 |
&& (mapt1.fromType().kind() != TypeKind.Null && mapt1.toType().kind() != TypeKind.Null)) |
|
307 |
return mapt1; |
|
308 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
|
309 |
&& (mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null)) |
|
310 |
return mapt1; |
|
311 |
else |
|
312 |
{ |
|
313 |
final UlyssesType sub1 = UlyssesType.CoverType(mapt1.fromType(), mapt2.fromType()); |
|
314 |
final UlyssesType sub2 = UlyssesType.CoverType(mapt2.toType(), mapt2.toType()); |
|
315 |
maxelems = mapt1.maxNumberOfElements() > mapt2.maxNumberOfElements() ? |
|
316 |
mapt1.maxNumberOfElements() : mapt2.maxNumberOfElements(); |
|
317 |
if (sub1 != null && sub2 != null) |
|
318 |
return new MapType(sub1, sub2, maxelems, null); |
|
319 |
else |
|
320 |
return null; |
|
321 |
} |
|
322 |
case QrType: |
|
323 |
return null; /*if refs are equal, we do not reach this statement! see above..*/ |
|
324 |
case TupleType: |
|
325 |
final TupleType tuplet1 = (TupleType)type1; |
|
326 |
final TupleType tuplet2 = (TupleType)type2; |
|
327 |
final TupleType result = new TupleType(null); |
|
328 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
329 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
330 |
while (innert1.hasNext()) |
|
331 |
{ |
|
332 |
final UlyssesType newinner = UlyssesType.CoverType(innert1.next(), innert2.next()); |
|
333 |
if (newinner == null) |
|
334 |
return null; |
|
335 |
result.AddType(newinner); |
|
336 |
} |
|
337 |
return result; |
|
338 |
case OoActionSystemType: |
|
339 |
if (type1.kind() == TypeKind.Null && type2.kind() != TypeKind.Null) |
|
340 |
return type2; |
|
341 |
else if (type2.kind() == TypeKind.Null && type1.kind() != TypeKind.Null) |
|
342 |
return type1; |
|
343 |
else if (type1.kind() == TypeKind.Null && type2.kind() == TypeKind.Null) |
|
344 |
return type2; |
|
345 |
else if (type1 == type2) // ref equals! |
|
346 |
return type1; |
|
347 |
else |
|
348 |
return ClassBaseType((OoActionSystemType)type1, (OoActionSystemType)type2); |
|
349 |
case OpaqueType: |
|
350 |
assert(false); |
|
351 |
return null; |
|
352 |
default: |
|
353 |
throw new NotImplementedException(); |
|
354 |
} |
|
355 |
} |
|
356 |
} |
|
357 |
|
|
358 |
private static UlyssesType ClassBaseType(OoActionSystemType type1, OoActionSystemType type2) |
|
359 |
{ |
|
360 |
// this is rather inefficient.. should be done differently |
|
361 |
final OoActionSystemType typea = type1; |
|
362 |
final OoActionSystemType typeb = type2; |
|
363 |
OoActionSystemType basea = type1; |
|
364 |
OoActionSystemType baseb = type2; |
|
365 |
while (basea != null) |
|
366 |
{ |
|
367 |
if (basea == typeb) // ref equals |
|
368 |
return basea; |
|
369 |
basea = basea.baseType(); |
|
370 |
} |
|
371 |
while (baseb != null) |
|
372 |
{ |
|
373 |
if (baseb == typea) // ref equals |
|
374 |
return baseb; |
|
375 |
baseb = baseb.baseType(); |
|
376 |
} |
|
377 |
return null; |
|
378 |
} |
|
379 |
|
|
380 |
public static boolean FirstTypeLessRange(UlyssesType type1, UlyssesType type2) |
|
381 |
{ |
|
382 |
final TypeKind tk1 = type1.kind(); |
|
383 |
final TypeKind tk2 = type2.kind(); |
|
384 |
|
|
385 |
if (tk1 != tk2) |
|
386 |
throw new ArgumentException("Types need to be equal"); |
|
387 |
|
|
388 |
switch (tk1) |
|
389 |
{ |
|
390 |
case Any: |
|
391 |
return false; |
|
392 |
case IntType: |
|
393 |
final IntType Int1 = (IntType)type1; |
|
394 |
final IntType Int2 = (IntType)type2; |
|
395 |
return Int1.rangeLow() > Int2.rangeLow() || |
|
396 |
Int1.rangeHigh() < Int2.rangeHigh(); |
|
397 |
case BoolType: |
|
398 |
return false; |
|
399 |
case FloatType: |
|
400 |
final FloatType Float1 = (FloatType)type1; |
|
401 |
final FloatType Float2 = (FloatType)type2; |
|
402 |
return Float1.low() > Float2.low() |
|
403 |
|| Float1.high() < Float2.high() |
|
404 |
|| Float1.precision() > Float2.precision(); |
|
405 |
case EnumeratedType: |
|
406 |
return false; |
|
407 |
case ListType: |
|
408 |
final ListType listt1 = (ListType)type1; |
|
409 |
final ListType listt2 = (ListType)type2; |
|
410 |
return (listt1.maxNumberOfElements() < listt2.maxNumberOfElements()) || |
|
411 |
UlyssesType.FirstTypeLessRange(listt1.innerType(), listt2.innerType()); |
|
412 |
case MapType: |
|
413 |
final MapType mapt1 = (MapType)type1; |
|
414 |
final MapType mapt2 = (MapType)type2; |
|
415 |
return (mapt1.maxNumberOfElements() < mapt2.maxNumberOfElements()) || |
|
416 |
UlyssesType.FirstTypeLessRange(mapt1.fromType(), mapt2.fromType()) || |
|
417 |
UlyssesType.FirstTypeLessRange(mapt1.toType(), mapt2.toType()); |
|
418 |
case QrType: |
|
419 |
return false; |
|
420 |
case TupleType: |
|
421 |
final TupleType tuplet1 = (TupleType)type1; |
|
422 |
final TupleType tuplet2 = (TupleType)type2; |
|
423 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
424 |
return false; |
|
425 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
426 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
427 |
while (innert1.hasNext()) |
|
428 |
{ |
|
429 |
if (UlyssesType.FirstTypeLessRange(innert1.next(), innert2.next())) |
|
430 |
return true; |
|
431 |
} |
|
432 |
return false; |
|
433 |
case OoActionSystemType: |
|
434 |
return false; |
|
435 |
case OpaqueType: |
|
436 |
assert(false); |
|
437 |
return false; |
|
438 |
default: |
|
439 |
throw new NotImplementedException(); |
|
440 |
} |
|
441 |
} |
|
442 |
|
|
443 |
public static boolean TypeEqualByKind(UlyssesType type1, UlyssesType type2) |
|
444 |
{ |
|
445 |
if ((type1 == null) || (type2 == null)) |
|
446 |
return false; |
|
447 |
|
|
448 |
final TypeKind tk1 = type1.kind(); |
|
449 |
final TypeKind tk2 = type2.kind(); |
|
450 |
|
|
451 |
// if of different kind, then return false.. |
|
452 |
if (tk1 != tk2) |
|
453 |
return false; |
|
454 |
|
|
455 |
// if same kind, make a rigorous check |
|
456 |
switch (tk1) |
|
457 |
{ |
|
458 |
case Any: |
|
459 |
return true; |
|
460 |
|
|
461 |
case IntType: |
|
462 |
case BoolType: |
|
463 |
case FloatType: |
|
464 |
return true; |
|
465 |
case EnumeratedType: |
|
466 |
return type1 == type2; // ref equals |
|
467 |
case ListType: |
|
468 |
final ListType listt1 = (ListType)type1; |
|
469 |
final ListType listt2 = (ListType)type2; |
|
470 |
return UlyssesType.TypeEqualByKind(listt1.innerType(), listt2.innerType()); |
|
471 |
case MapType: |
|
472 |
final MapType mapt1 = (MapType)type1; |
|
473 |
final MapType mapt2 = (MapType)type2; |
|
474 |
return UlyssesType.TypeEqualByKind(mapt1.fromType(), mapt2.fromType()) && |
|
475 |
UlyssesType.TypeEqualByKind(mapt1.toType(), mapt2.toType()); |
|
476 |
case QrType: |
|
477 |
final QrType qr1 = (QrType)type1; |
|
478 |
final QrType qr2 = (QrType)type2; |
|
479 |
return qr1 == qr2; // ref equals |
|
480 |
case TupleType: |
|
481 |
final TupleType tuplet1 = (TupleType)type1; |
|
482 |
final TupleType tuplet2 = (TupleType)type2; |
|
483 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
484 |
return false; |
|
485 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
486 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
487 |
while (innert1.hasNext()) |
|
488 |
{ |
|
489 |
if (!UlyssesType.TypeEqualByKind(innert1.next(), innert2.next())) |
|
490 |
return false; |
|
491 |
} |
|
492 |
return true; |
|
493 |
case OoActionSystemType: |
|
494 |
return type1 == type2; // ref equ. |
|
495 |
case OpaqueType: |
|
496 |
assert(false); |
|
497 |
return false; |
|
498 |
default: |
|
499 |
throw new NotImplementedException(); |
|
500 |
} |
|
501 |
} |
|
502 |
|
|
503 |
|
|
504 |
public static boolean TypeEqual(UlyssesType type1, UlyssesType type2) |
|
505 |
{ |
|
506 |
// this will also work with opaque types... |
|
507 |
while (type1 instanceof OpaqueType) |
|
508 |
type1 = ((OpaqueType)type1).resolvedType(); |
|
509 |
while (type2 instanceof OpaqueType) |
|
510 |
type2 = ((OpaqueType)type2).resolvedType(); |
|
511 |
|
|
512 |
if ((type1 == null) || (type2 == null)) |
|
513 |
return false; |
|
514 |
|
|
515 |
final TypeKind tk1 = type1.kind(); |
|
516 |
final TypeKind tk2 = type2.kind(); |
|
517 |
|
|
518 |
// if of different kind, then return false.. |
|
519 |
if (tk1 != tk2) |
|
520 |
return false; |
|
521 |
|
|
522 |
// if same kind, make a rigorous check |
|
523 |
switch (tk1) |
|
524 |
{ |
|
525 |
case IntType: |
|
526 |
final IntType intt1 = (IntType)type1; |
|
527 |
final IntType intt2 = (IntType)type2; |
|
528 |
return intt1.rangeLow() == intt2.rangeLow() && |
|
529 |
intt1.rangeHigh() == intt2.rangeHigh(); |
|
530 |
case BoolType: |
|
531 |
return true; |
|
532 |
case FloatType: |
|
533 |
final FloatType floatt1 = (FloatType)type1; |
|
534 |
final FloatType floatt2 = (FloatType)type2; |
|
535 |
return floatt1.low() == floatt2.low() && |
|
536 |
floatt1.high() == floatt2.high() && |
|
537 |
floatt1.precision() == floatt2.precision(); |
|
538 |
case EnumeratedType: |
|
539 |
return type1 == type2; // ref equ |
|
540 |
case ListType: |
|
541 |
final ListType listt1 = (ListType)type1; |
|
542 |
final ListType listt2 = (ListType)type2; |
|
543 |
// an empty list can be of any type.. |
|
544 |
/*if ((listt1.innerType.kind == TypeKind.Null) || (listt2.innerType.kind == TypeKind.Null)) |
|
545 |
return true; |
|
546 |
else*/ |
|
547 |
return UlyssesType.TypeEqual(listt1.innerType(), listt2.innerType()) && |
|
548 |
listt1.maxNumberOfElements() == listt2.maxNumberOfElements(); // need this because of covertype |
|
549 |
case MapType: |
|
550 |
final MapType mapt1 = (MapType)type1; |
|
551 |
final MapType mapt2 = (MapType)type2; |
|
552 |
return UlyssesType.TypeEqual(mapt1.fromType(), mapt2.fromType()) && |
|
553 |
UlyssesType.TypeEqual(mapt1.toType(), mapt2.toType()) && |
|
554 |
mapt1.maxNumberOfElements() == mapt2.maxNumberOfElements(); // need this because of covertype |
|
555 |
case QrType: |
|
556 |
final QrType qr1 = (QrType)type1; |
|
557 |
final QrType qr2 = (QrType)type2; |
|
558 |
return qr1 == qr2; // ref equ. |
|
559 |
case TupleType: |
|
560 |
final TupleType tuplet1 = (TupleType)type1; |
|
561 |
final TupleType tuplet2 = (TupleType)type2; |
|
562 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
563 |
return false; |
|
564 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
565 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
566 |
while (innert1.hasNext()) |
|
567 |
{ |
|
568 |
if (!UlyssesType.TypeEqual(innert1.next(), innert2.next())) |
|
569 |
return false; |
|
570 |
} |
|
571 |
return true; |
|
572 |
case OoActionSystemType: |
|
573 |
return type1 == type2; // ref equ. // || Covariance((OoActionSystemType)type1, (OoActionSystemType)type2); |
|
574 |
case OpaqueType: |
|
575 |
assert(false); |
|
576 |
return false; |
|
577 |
case Null: |
|
578 |
case Any: |
|
579 |
return true; |
|
580 |
default: |
|
581 |
throw new NotImplementedException(); |
|
582 |
} |
|
583 |
} |
|
584 |
|
|
585 |
/// <summary> |
|
586 |
/// checks if type 2 is a desc. of type 1 |
|
587 |
/// </summary> |
|
588 |
public static boolean Covariance(OoActionSystemType ooActionSystemType, OoActionSystemType ooActionSystemType_2) |
|
589 |
{ |
|
590 |
// check if type 2 is a desc. of type 1 |
|
591 |
while (ooActionSystemType != ooActionSystemType_2 && ooActionSystemType_2.baseType() != null) // ref equ. |
|
592 |
ooActionSystemType_2 = ooActionSystemType_2.baseType(); |
|
593 |
|
|
594 |
return ooActionSystemType == ooActionSystemType_2; // ref equ. |
|
595 |
} |
|
596 |
} |
|
40 |
|
|
41 |
public abstract class UlyssesType extends AstNode implements IAst |
|
42 |
{ |
|
43 |
private String m_origAnonName; |
|
44 |
protected TypeKind m_kind; |
|
45 |
protected TypeIdentifier m_identifier; |
|
46 |
protected int m_hash; |
|
47 |
// protected long TimeStamp = DateTime.Now.Ticks; |
|
48 |
|
|
49 |
|
|
50 |
public TypeKind kind() { return m_kind; } |
|
51 |
|
|
52 |
public TypeIdentifier identifier() { |
|
53 |
synchronized(this) { |
|
54 |
if (m_identifier == null) |
|
55 |
SetupAnonymousName(); |
|
56 |
} |
|
57 |
return m_identifier; |
|
58 |
} |
|
59 |
|
|
60 |
public boolean isAnonymousType() { |
|
61 |
final String anonName = AnonymousName(); |
|
62 |
if (!m_origAnonName.equals(anonName)) |
|
63 |
throw new OoasCompilerRuntimeException("Internal Error: Anonymous Name changed from '%s' to '%s'.", m_origAnonName, anonName); |
|
64 |
return anonName.equals(m_identifier.tokenText()); |
|
65 |
} |
|
66 |
|
|
67 |
protected UlyssesType(TypeKind aKind, TypeIdentifier anIdentifier) |
|
68 |
{ |
|
69 |
m_kind = aKind; |
|
70 |
m_identifier = anIdentifier; |
|
71 |
m_hash = aKind.toString().hashCode(); //Enum.GetName(typeof(TypeKind), aKind).GetHashCode(); |
|
72 |
} |
|
73 |
|
|
74 |
@Override |
|
75 |
public /*override*/ String toString() |
|
76 |
{ |
|
77 |
return identifier().tokenText(); |
|
78 |
} |
|
79 |
|
|
80 |
public /*virtual*/ String AnonymousName() |
|
81 |
{ |
|
82 |
throw new NotImplementedException(); |
|
83 |
} |
|
84 |
|
|
85 |
|
|
86 |
public void SetTypeIdentifier(TypeIdentifier anId) |
|
87 |
{ |
|
88 |
m_identifier = anId; |
|
89 |
} |
|
90 |
|
|
91 |
public void SetupAnonymousName() |
|
92 |
{ |
|
93 |
if (m_identifier == null) |
|
94 |
{ |
|
95 |
final String anonymousName = this.AnonymousName(); |
|
96 |
m_identifier = new TypeIdentifier(anonymousName, this, null); |
|
97 |
m_origAnonName = anonymousName; |
|
98 |
} |
|
99 |
} |
|
100 |
|
|
101 |
|
|
102 |
@Override |
|
103 |
public AstNodeTypeEnum nodeType() { return AstNodeTypeEnum.type; } |
|
104 |
|
|
105 |
@Override |
|
106 |
public void Accept(IAstVisitor visitor) |
|
107 |
{ |
|
108 |
throw new NotImplementedException(); |
|
109 |
} |
|
110 |
|
|
111 |
|
|
112 |
|
|
113 |
public boolean IsNumeric() |
|
114 |
{ |
|
115 |
final Object o = this; |
|
116 |
return (m_kind == TypeKind.IntType) || |
|
117 |
(m_kind == TypeKind.FloatType) || |
|
118 |
(m_kind == TypeKind.EnumeratedType && o instanceof ValuedEnumType); |
|
119 |
} |
|
120 |
|
|
121 |
public boolean IsQualitative() |
|
122 |
{ |
|
123 |
return (m_kind == TypeKind.QrType); |
|
124 |
} |
|
125 |
|
|
126 |
/** |
|
127 |
* returns the number of unique values of the type (2 for bool, etc..) |
|
128 |
*/ |
|
129 |
public int valueCount() { |
|
130 |
throw new NotImplementedException(); // must be overridden by child |
|
131 |
} |
|
132 |
|
|
133 |
public static String High(UlyssesType atype) |
|
134 |
{ |
|
135 |
switch (atype.kind()) |
|
136 |
{ |
|
137 |
case BoolType: |
|
138 |
return "1"; |
|
139 |
case EnumeratedType: |
|
140 |
return Integer.toString((((EnumType)atype).listOfEnumSymbols().size() - 1)); |
|
141 |
case IntType: |
|
142 |
return Integer.toString(((IntType)atype).rangeHigh()); |
|
143 |
case FloatType: |
|
144 |
return Double.toString(((FloatType)atype).high()); |
|
145 |
// case TypeKind.QrType: |
|
146 |
// return (((QrType)atype).landmarks.Count - 1).ToString(); |
|
147 |
default: |
|
148 |
throw new NotImplementedException(); |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
public static String Low(UlyssesType atype) |
|
153 |
{ |
|
154 |
switch (atype.kind()) |
|
155 |
{ |
|
156 |
case BoolType: |
|
157 |
return "0"; |
|
158 |
case EnumeratedType: |
|
159 |
return "0"; |
|
160 |
case IntType: |
|
161 |
return Integer.toString(((IntType)atype).rangeLow()); |
|
162 |
case FloatType: |
|
163 |
return Double.toString(((FloatType)atype).low()); |
|
164 |
// case TypeKind.QrType: |
|
165 |
// return "0"; |
|
166 |
default: |
|
167 |
throw new NotImplementedException(); |
|
168 |
} |
|
169 |
} |
|
170 |
|
|
171 |
|
|
172 |
/// <summary> |
|
173 |
/// Returns a cover for two types (if possible). |
|
174 |
/// note the cover type for two ints, floats, etc. will have max/min values |
|
175 |
/// that reflect the maximum of the two operands. |
|
176 |
/// </summary> |
|
177 |
|
|
178 |
public static UlyssesType CoverType(UlyssesType type1, UlyssesType type2) |
|
179 |
{ |
|
180 |
/*first some sanity checks*/ |
|
181 |
if (type1 == null) |
|
182 |
throw new ArgumentException("type1 null"); |
|
183 |
if (type2 == null) |
|
184 |
throw new ArgumentException("type2 null"); |
|
185 |
|
|
186 |
if (type1.kind() == TypeKind.OpaqueType) |
|
187 |
throw new ArgumentException("type1 opaque type"); |
|
188 |
if (type2.kind() == TypeKind.OpaqueType) |
|
189 |
throw new ArgumentException("type2 opaque type"); |
|
190 |
|
|
191 |
if (type1 == type2) |
|
192 |
return type1; |
|
193 |
if (UlyssesType.TypeEqual(type1, type2)) |
|
194 |
return type1; |
|
195 |
|
|
196 |
final TypeKind tk1 = type1.kind(); |
|
197 |
final TypeKind tk2 = type2.kind(); |
|
198 |
|
|
199 |
|
|
200 |
|
|
201 |
if (tk1 != tk2) |
|
202 |
{ |
|
203 |
// the only notion we support here is int->float and valenum -> int |
|
204 |
if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType) |
|
205 |
&& (tk1 == TypeKind.FloatType || tk2 == TypeKind.FloatType)) |
|
206 |
{ |
|
207 |
final IntType aInt = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2; |
|
208 |
final FloatType aFloat = tk1 == TypeKind.IntType ? (FloatType)type2 : (FloatType)type1; |
|
209 |
|
|
210 |
final double low = aInt.rangeLow() < aFloat.low() ? (double)aInt.rangeLow() : aFloat.low(); |
|
211 |
final double high = aInt.rangeHigh() < aFloat.high() ? aFloat.high() : (double)aInt.rangeHigh(); |
|
212 |
final double precision = aFloat.precision() > 1 ? 1.0 : aFloat.precision(); |
|
213 |
|
|
214 |
return new FloatType(low, high, precision, null); |
|
215 |
|
|
216 |
} |
|
217 |
else if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType) |
|
218 |
&& (tk1 == TypeKind.EnumeratedType || tk2 == TypeKind.EnumeratedType)) |
|
219 |
{ |
|
220 |
final IntType intt1 = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2; |
|
221 |
final EnumType anEnum = tk1 == TypeKind.IntType ? (EnumType)type2 : (EnumType)type1; |
|
222 |
|
|
223 |
if (anEnum instanceof ValuedEnumType) |
|
224 |
{ |
|
225 |
final IntType intt2 = ((ValuedEnumType)anEnum).getIntType(); |
|
226 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
|
227 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
|
228 |
return new IntType(low, high, null); |
|
229 |
} |
|
230 |
else |
|
231 |
return null; |
|
232 |
} |
|
233 |
else if (tk1 == TypeKind.Any || tk2 == TypeKind.Any) |
|
234 |
{ |
|
235 |
final AnyType freeVar = tk1 == TypeKind.Any ? (AnyType)type1 : (AnyType)type2; |
|
236 |
final UlyssesType fixedType = tk1 == TypeKind.Any ? type2 : type1; |
|
237 |
final UlyssesType newcover = freeVar.VariableIdentifier().type().kind() == TypeKind.Any |
|
238 |
? fixedType : CoverType(fixedType, freeVar.VariableIdentifier().type()); |
|
239 |
freeVar.VariableIdentifier().SetType(newcover); |
|
240 |
return newcover; |
|
241 |
} |
|
242 |
else if (tk1 == TypeKind.OoActionSystemType && tk2 == TypeKind.Null) |
|
243 |
{ |
|
244 |
return type1; |
|
245 |
} |
|
246 |
else if (tk2 == TypeKind.OoActionSystemType && tk1 == TypeKind.Null) |
|
247 |
{ |
|
248 |
return type2; |
|
249 |
} |
|
250 |
|
|
251 |
else |
|
252 |
return null; |
|
253 |
} |
|
254 |
else |
|
255 |
{ |
|
256 |
switch (tk1) |
|
257 |
{ |
|
258 |
case Any: |
|
259 |
return type1; |
|
260 |
|
|
261 |
case IntType: |
|
262 |
final IntType intt1 = (IntType)type1; |
|
263 |
final IntType intt2 = (IntType)type2; |
|
264 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
|
265 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
|
266 |
return new IntType(low, high, null); |
|
267 |
case BoolType: |
|
268 |
return type1; |
|
269 |
case FloatType: |
|
270 |
final FloatType floatt1 = (FloatType)type1; |
|
271 |
final FloatType floatt2 = (FloatType)type2; |
|
272 |
final double flow = floatt1.low() < floatt2.low() ? floatt1.low() : floatt2.low(); |
|
273 |
final double fhigh = floatt1.high() > floatt2.high() ? floatt1.high() : floatt2.high(); |
|
274 |
final double fprec = floatt1.precision() < floatt2.precision() ? floatt1.precision() : floatt2.precision(); |
|
275 |
return new FloatType(flow, fhigh, fprec, null); |
|
276 |
case EnumeratedType: |
|
277 |
return null; |
|
278 |
case ListType: |
|
279 |
final ListType listt1 = (ListType)type1; |
|
280 |
final ListType listt2 = (ListType)type2; |
|
281 |
int maxelems = listt1.maxNumberOfElements() > listt2.maxNumberOfElements() ? |
|
282 |
listt1.maxNumberOfElements() : listt2.maxNumberOfElements(); |
|
283 |
// empty lists lack type, so take the other one |
|
284 |
if ((listt1.innerType().kind() == TypeKind.Null) && (listt2.innerType().kind() != TypeKind.Null)) |
|
285 |
return listt2; |
|
286 |
else if ((listt2.innerType().kind() == TypeKind.Null) && (listt1.innerType().kind() != TypeKind.Null)) |
|
287 |
return listt1; |
|
288 |
else if (listt1.innerType().kind() == TypeKind.Null && listt2.innerType().kind() == TypeKind.Null) |
|
289 |
return listt1; |
|
290 |
else |
|
291 |
{ |
|
292 |
final UlyssesType subtype = UlyssesType.CoverType(listt1.innerType(), listt2.innerType()); |
|
293 |
if (subtype != null) |
|
294 |
return new ListType(subtype, maxelems, null); |
|
295 |
else |
|
296 |
return null; |
|
297 |
} |
|
298 |
case MapType: |
|
299 |
final MapType mapt1 = (MapType)type1; |
|
300 |
final MapType mapt2 = (MapType)type2; |
|
301 |
// empty maps lack type, so take the other one. |
|
302 |
if ((mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null) |
|
303 |
&& (mapt2.fromType().kind() != TypeKind.Null && mapt2.toType().kind() != TypeKind.Null)) |
|
304 |
return mapt2; |
|
305 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
|
306 |
&& (mapt1.fromType().kind() != TypeKind.Null && mapt1.toType().kind() != TypeKind.Null)) |
|
307 |
return mapt1; |
|
308 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
|
309 |
&& (mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null)) |
|
310 |
return mapt1; |
|
311 |
else |
|
312 |
{ |
|
313 |
final UlyssesType sub1 = UlyssesType.CoverType(mapt1.fromType(), mapt2.fromType()); |
|
314 |
final UlyssesType sub2 = UlyssesType.CoverType(mapt2.toType(), mapt2.toType()); |
|
315 |
maxelems = mapt1.maxNumberOfElements() > mapt2.maxNumberOfElements() ? |
|
316 |
mapt1.maxNumberOfElements() : mapt2.maxNumberOfElements(); |
|
317 |
if (sub1 != null && sub2 != null) |
|
318 |
return new MapType(sub1, sub2, maxelems, null); |
|
319 |
else |
|
320 |
return null; |
|
321 |
} |
|
322 |
case QrType: |
|
323 |
return null; /*if refs are equal, we do not reach this statement! see above..*/ |
|
324 |
case TupleType: |
|
325 |
final TupleType tuplet1 = (TupleType)type1; |
|
326 |
final TupleType tuplet2 = (TupleType)type2; |
|
327 |
final TupleType result = new TupleType(null); |
|
328 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
329 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
330 |
while (innert1.hasNext()) |
|
331 |
{ |
|
332 |
final UlyssesType newinner = UlyssesType.CoverType(innert1.next(), innert2.next()); |
|
333 |
if (newinner == null) |
|
334 |
return null; |
|
335 |
result.AddType(newinner); |
|
336 |
} |
|
337 |
return result; |
|
338 |
case OoActionSystemType: |
|
339 |
if (type1.kind() == TypeKind.Null && type2.kind() != TypeKind.Null) |
|
340 |
return type2; |
|
341 |
else if (type2.kind() == TypeKind.Null && type1.kind() != TypeKind.Null) |
|
342 |
return type1; |
|
343 |
else if (type1.kind() == TypeKind.Null && type2.kind() == TypeKind.Null) |
|
344 |
return type2; |
|
345 |
else if (type1 == type2) // ref equals! |
|
346 |
return type1; |
|
347 |
else |
|
348 |
return ClassBaseType((OoActionSystemType)type1, (OoActionSystemType)type2); |
|
349 |
case OpaqueType: |
|
350 |
assert(false); |
|
351 |
return null; |
|
352 |
default: |
|
353 |
throw new NotImplementedException(); |
|
354 |
} |
|
355 |
} |
|
356 |
} |
|
357 |
|
|
358 |
private static UlyssesType ClassBaseType(OoActionSystemType type1, OoActionSystemType type2) |
|
359 |
{ |
|
360 |
// this is rather inefficient.. should be done differently |
|
361 |
final OoActionSystemType typea = type1; |
|
362 |
final OoActionSystemType typeb = type2; |
|
363 |
OoActionSystemType basea = type1; |
|
364 |
OoActionSystemType baseb = type2; |
|
365 |
while (basea != null) |
|
366 |
{ |
|
367 |
if (basea == typeb) // ref equals |
|
368 |
return basea; |
|
369 |
basea = basea.baseType(); |
|
370 |
} |
|
371 |
while (baseb != null) |
|
372 |
{ |
|
373 |
if (baseb == typea) // ref equals |
|
374 |
return baseb; |
|
375 |
baseb = baseb.baseType(); |
|
376 |
} |
|
377 |
return null; |
|
378 |
} |
|
379 |
|
|
380 |
public static boolean FirstTypeLessRange(UlyssesType type1, UlyssesType type2) |
|
381 |
{ |
|
382 |
final TypeKind tk1 = type1.kind(); |
|
383 |
final TypeKind tk2 = type2.kind(); |
|
384 |
|
|
385 |
if (tk1 != tk2) |
|
386 |
throw new ArgumentException("Types need to be equal"); |
|
387 |
|
|
388 |
switch (tk1) |
|
389 |
{ |
|
390 |
case Any: |
|
391 |
return false; |
|
392 |
case IntType: |
|
393 |
final IntType Int1 = (IntType)type1; |
|
394 |
final IntType Int2 = (IntType)type2; |
|
395 |
return Int1.rangeLow() > Int2.rangeLow() || |
|
396 |
Int1.rangeHigh() < Int2.rangeHigh(); |
|
397 |
case BoolType: |
|
398 |
return false; |
|
399 |
case FloatType: |
|
400 |
final FloatType Float1 = (FloatType)type1; |
|
401 |
final FloatType Float2 = (FloatType)type2; |
|
402 |
return Float1.low() > Float2.low() |
|
403 |
|| Float1.high() < Float2.high() |
|
404 |
|| Float1.precision() > Float2.precision(); |
|
405 |
case EnumeratedType: |
|
406 |
return false; |
|
407 |
case ListType: |
|
408 |
final ListType listt1 = (ListType)type1; |
|
409 |
final ListType listt2 = (ListType)type2; |
|
410 |
return (listt1.maxNumberOfElements() < listt2.maxNumberOfElements()) || |
|
411 |
UlyssesType.FirstTypeLessRange(listt1.innerType(), listt2.innerType()); |
|
412 |
case MapType: |
|
413 |
final MapType mapt1 = (MapType)type1; |
|
414 |
final MapType mapt2 = (MapType)type2; |
|
415 |
return (mapt1.maxNumberOfElements() < mapt2.maxNumberOfElements()) || |
|
416 |
UlyssesType.FirstTypeLessRange(mapt1.fromType(), mapt2.fromType()) || |
|
417 |
UlyssesType.FirstTypeLessRange(mapt1.toType(), mapt2.toType()); |
|
418 |
case QrType: |
|
419 |
return false; |
|
420 |
case TupleType: |
|
421 |
final TupleType tuplet1 = (TupleType)type1; |
|
422 |
final TupleType tuplet2 = (TupleType)type2; |
|
423 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
424 |
return false; |
|
425 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
426 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
427 |
while (innert1.hasNext()) |
|
428 |
{ |
|
429 |
if (UlyssesType.FirstTypeLessRange(innert1.next(), innert2.next())) |
|
430 |
return true; |
|
431 |
} |
|
432 |
return false; |
|
433 |
case OoActionSystemType: |
|
434 |
return false; |
|
435 |
case OpaqueType: |
|
436 |
assert(false); |
|
437 |
return false; |
|
438 |
default: |
|
439 |
throw new NotImplementedException(); |
|
440 |
} |
|
441 |
} |
|
442 |
|
|
443 |
public static boolean TypeEqualByKind(UlyssesType type1, UlyssesType type2) |
|
444 |
{ |
|
445 |
if ((type1 == null) || (type2 == null)) |
|
446 |
return false; |
|
447 |
|
|
448 |
final TypeKind tk1 = type1.kind(); |
|
449 |
final TypeKind tk2 = type2.kind(); |
|
450 |
|
|
451 |
// if of different kind, then return false.. |
|
452 |
if (tk1 != tk2) |
|
453 |
return false; |
|
454 |
|
|
455 |
// if same kind, make a rigorous check |
|
456 |
switch (tk1) |
|
457 |
{ |
|
458 |
case Any: |
|
459 |
return true; |
|
460 |
|
|
461 |
case IntType: |
|
462 |
case BoolType: |
|
463 |
case FloatType: |
|
464 |
return true; |
|
465 |
case EnumeratedType: |
|
466 |
return type1 == type2; // ref equals |
|
467 |
case ListType: |
|
468 |
final ListType listt1 = (ListType)type1; |
|
469 |
final ListType listt2 = (ListType)type2; |
|
470 |
return UlyssesType.TypeEqualByKind(listt1.innerType(), listt2.innerType()); |
|
471 |
case MapType: |
|
472 |
final MapType mapt1 = (MapType)type1; |
|
473 |
final MapType mapt2 = (MapType)type2; |
|
474 |
return UlyssesType.TypeEqualByKind(mapt1.fromType(), mapt2.fromType()) && |
|
475 |
UlyssesType.TypeEqualByKind(mapt1.toType(), mapt2.toType()); |
|
476 |
case QrType: |
|
477 |
final QrType qr1 = (QrType)type1; |
|
478 |
final QrType qr2 = (QrType)type2; |
|
479 |
return qr1 == qr2; // ref equals |
|
480 |
case TupleType: |
|
481 |
final TupleType tuplet1 = (TupleType)type1; |
|
482 |
final TupleType tuplet2 = (TupleType)type2; |
|
483 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
484 |
return false; |
|
485 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
486 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
487 |
while (innert1.hasNext()) |
|
488 |
{ |
|
489 |
if (!UlyssesType.TypeEqualByKind(innert1.next(), innert2.next())) |
|
490 |
return false; |
|
491 |
} |
|
492 |
return true; |
|
493 |
case OoActionSystemType: |
|
494 |
return type1 == type2; // ref equ. |
|
495 |
case OpaqueType: |
|
496 |
assert(false); |
|
497 |
return false; |
|
498 |
default: |
|
499 |
throw new NotImplementedException(); |
|
500 |
} |
|
501 |
} |
|
502 |
|
|
503 |
|
|
504 |
public static boolean TypeEqual(UlyssesType type1, UlyssesType type2) |
|
505 |
{ |
|
506 |
// this will also work with opaque types... |
|
507 |
while (type1 instanceof OpaqueType) |
|
508 |
type1 = ((OpaqueType)type1).resolvedType(); |
|
509 |
while (type2 instanceof OpaqueType) |
|
510 |
type2 = ((OpaqueType)type2).resolvedType(); |
|
511 |
|
|
512 |
if ((type1 == null) || (type2 == null)) |
|
513 |
return false; |
|
514 |
|
|
515 |
final TypeKind tk1 = type1.kind(); |
|
516 |
final TypeKind tk2 = type2.kind(); |
|
517 |
|
|
518 |
// if of different kind, then return false.. |
|
519 |
if (tk1 != tk2) |
|
520 |
return false; |
|
521 |
|
|
522 |
// if same kind, make a rigorous check |
|
523 |
switch (tk1) |
|
524 |
{ |
|
525 |
case IntType: |
|
526 |
final IntType intt1 = (IntType)type1; |
|
527 |
final IntType intt2 = (IntType)type2; |
|
528 |
return intt1.rangeLow() == intt2.rangeLow() && |
|
529 |
intt1.rangeHigh() == intt2.rangeHigh(); |
|
530 |
case BoolType: |
|
531 |
return true; |
|
532 |
case FloatType: |
|
533 |
final FloatType floatt1 = (FloatType)type1; |
|
534 |
final FloatType floatt2 = (FloatType)type2; |
|
535 |
return floatt1.low() == floatt2.low() && |
|
536 |
floatt1.high() == floatt2.high() && |
|
537 |
floatt1.precision() == floatt2.precision(); |
|
538 |
case EnumeratedType: |
|
539 |
return type1 == type2; // ref equ |
|
540 |
case ListType: |
|
541 |
final ListType listt1 = (ListType)type1; |
|
542 |
final ListType listt2 = (ListType)type2; |
|
543 |
// an empty list can be of any type.. |
|
544 |
/*if ((listt1.innerType.kind == TypeKind.Null) || (listt2.innerType.kind == TypeKind.Null)) |
|
545 |
return true; |
|
546 |
else*/ |
|
547 |
return UlyssesType.TypeEqual(listt1.innerType(), listt2.innerType()) && |
|
548 |
listt1.maxNumberOfElements() == listt2.maxNumberOfElements(); // need this because of covertype |
|
549 |
case MapType: |
|
550 |
final MapType mapt1 = (MapType)type1; |
|
551 |
final MapType mapt2 = (MapType)type2; |
|
552 |
return UlyssesType.TypeEqual(mapt1.fromType(), mapt2.fromType()) && |
|
553 |
UlyssesType.TypeEqual(mapt1.toType(), mapt2.toType()) && |
|
554 |
mapt1.maxNumberOfElements() == mapt2.maxNumberOfElements(); // need this because of covertype |
|
555 |
case QrType: |
|
556 |
final QrType qr1 = (QrType)type1; |
|
557 |
final QrType qr2 = (QrType)type2; |
|
558 |
return qr1 == qr2; // ref equ. |
|
559 |
case TupleType: |
|
560 |
final TupleType tuplet1 = (TupleType)type1; |
|
561 |
final TupleType tuplet2 = (TupleType)type2; |
|
562 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size()) |
|
563 |
return false; |
|
564 |
final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator(); |
|
565 |
final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator(); |
|
566 |
while (innert1.hasNext()) |
|
567 |
{ |
|
568 |
if (!UlyssesType.TypeEqual(innert1.next(), innert2.next())) |
|
569 |
return false; |
|
570 |
} |
|
571 |
return true; |
|
572 |
case OoActionSystemType: |
|
573 |
return type1 == type2; // ref equ. // || Covariance((OoActionSystemType)type1, (OoActionSystemType)type2); |
|
574 |
case OpaqueType: |
|
575 |
assert(false); |
|
576 |
return false; |
|
577 |
case Null: |
|
578 |
case Any: |
|
579 |
return true; |
|
580 |
default: |
|
581 |
throw new NotImplementedException(); |
|
582 |
} |
|
583 |
} |
|
584 |
|
|
585 |
/// <summary> |
|
586 |
/// checks if type 2 is a desc. of type 1 |
|
587 |
/// </summary> |
|
588 |
public static boolean Covariance(OoActionSystemType ooActionSystemType, OoActionSystemType ooActionSystemType_2) |
|
589 |
{ |
|
590 |
// check if type 2 is a desc. of type 1 |
|
591 |
while (ooActionSystemType != ooActionSystemType_2 && ooActionSystemType_2.baseType() != null) // ref equ. |
|
592 |
ooActionSystemType_2 = ooActionSystemType_2.baseType(); |
|
593 |
|
|
594 |
return ooActionSystemType == ooActionSystemType_2; // ref equ. |
|
595 |
} |
|
596 |
} |
Also available in: Unified diff
changing java, cpp, hpp files to unix line endings