root / trunk / compiler / ooasCompiler / src / org / momut / ooas / ast / types / Type.java @ 10
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 |
|
27 |
|
28 |
package org.momut.ooas.ast.types; |
29 |
|
30 |
import java.util.Iterator; |
31 |
|
32 |
import org.momut.ooas.ast.AstNode; |
33 |
import org.momut.ooas.ast.AstNodeTypeEnum; |
34 |
import org.momut.ooas.ast.IAst; |
35 |
import org.momut.ooas.ast.IAstVisitor; |
36 |
import org.momut.ooas.ast.identifiers.TypeIdentifier; |
37 |
import org.momut.ooas.utils.exceptions.ArgumentException; |
38 |
import org.momut.ooas.utils.exceptions.NotImplementedException; |
39 |
import org.momut.ooas.utils.exceptions.OoasCompilerRuntimeException; |
40 |
|
41 |
public abstract class Type 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 Type(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 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 |
/**
|
122 |
* returns the number of unique values of the type (2 for bool, etc..)
|
123 |
*/
|
124 |
public int valueCount() { |
125 |
throw new NotImplementedException(); // must be overridden by child |
126 |
} |
127 |
|
128 |
public static String High(Type atype) |
129 |
{ |
130 |
switch (atype.kind())
|
131 |
{ |
132 |
case BoolType:
|
133 |
return "1"; |
134 |
case EnumeratedType:
|
135 |
return Integer.toString((((EnumType)atype).listOfEnumSymbols().size() - 1)); |
136 |
case IntType:
|
137 |
return Integer.toString(((IntType)atype).rangeHigh()); |
138 |
case FloatType:
|
139 |
return Double.toString(((FloatType)atype).high()); |
140 |
default:
|
141 |
throw new NotImplementedException(); |
142 |
} |
143 |
} |
144 |
|
145 |
public static String Low(Type atype) |
146 |
{ |
147 |
switch (atype.kind())
|
148 |
{ |
149 |
case BoolType:
|
150 |
return "0"; |
151 |
case EnumeratedType:
|
152 |
return "0"; |
153 |
case IntType:
|
154 |
return Integer.toString(((IntType)atype).rangeLow()); |
155 |
case FloatType:
|
156 |
return Double.toString(((FloatType)atype).low()); |
157 |
// case TypeKind.QrType:
|
158 |
// return "0";
|
159 |
default:
|
160 |
throw new NotImplementedException(); |
161 |
} |
162 |
} |
163 |
|
164 |
|
165 |
/// <summary>
|
166 |
/// Returns a cover for two types (if possible).
|
167 |
/// note the cover type for two ints, floats, etc. will have max/min values
|
168 |
/// that reflect the maximum of the two operands.
|
169 |
/// </summary>
|
170 |
|
171 |
public static Type CoverType(Type type1, Type type2) |
172 |
{ |
173 |
/*first some sanity checks*/
|
174 |
if (type1 == null) |
175 |
throw new ArgumentException("type1 null"); |
176 |
if (type2 == null) |
177 |
throw new ArgumentException("type2 null"); |
178 |
|
179 |
if (type1.kind() == TypeKind.OpaqueType)
|
180 |
throw new ArgumentException("type1 opaque type"); |
181 |
if (type2.kind() == TypeKind.OpaqueType)
|
182 |
throw new ArgumentException("type2 opaque type"); |
183 |
|
184 |
if (type1 == type2)
|
185 |
return type1;
|
186 |
if (Type.TypeEqual(type1, type2)) |
187 |
return type1;
|
188 |
|
189 |
final TypeKind tk1 = type1.kind();
|
190 |
final TypeKind tk2 = type2.kind();
|
191 |
|
192 |
|
193 |
|
194 |
if (tk1 != tk2)
|
195 |
{ |
196 |
// the only notion we support here is int->float and valenum -> int
|
197 |
if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType)
|
198 |
&& (tk1 == TypeKind.FloatType || tk2 == TypeKind.FloatType)) |
199 |
{ |
200 |
final IntType aInt = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2;
|
201 |
final FloatType aFloat = tk1 == TypeKind.IntType ? (FloatType)type2 : (FloatType)type1;
|
202 |
|
203 |
final double low = aInt.rangeLow() < aFloat.low() ? (double)aInt.rangeLow() : aFloat.low(); |
204 |
final double high = aInt.rangeHigh() < aFloat.high() ? aFloat.high() : (double)aInt.rangeHigh(); |
205 |
final double precision = aFloat.precision() > 1 ? 1.0 : aFloat.precision(); |
206 |
|
207 |
return new FloatType(low, high, precision, null); |
208 |
|
209 |
} |
210 |
else if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType) |
211 |
&& (tk1 == TypeKind.EnumeratedType || tk2 == TypeKind.EnumeratedType)) |
212 |
{ |
213 |
final IntType intt1 = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2;
|
214 |
final EnumType anEnum = tk1 == TypeKind.IntType ? (EnumType)type2 : (EnumType)type1;
|
215 |
|
216 |
if (anEnum instanceof ValuedEnumType) |
217 |
{ |
218 |
final IntType intt2 = ((ValuedEnumType)anEnum).getIntType();
|
219 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
220 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
221 |
return new IntType(low, high, null); |
222 |
} |
223 |
else
|
224 |
return null; |
225 |
} |
226 |
else if (tk1 == TypeKind.Any || tk2 == TypeKind.Any) |
227 |
{ |
228 |
final AnyType freeVar = tk1 == TypeKind.Any ? (AnyType)type1 : (AnyType)type2;
|
229 |
final Type fixedType = tk1 == TypeKind.Any ? type2 : type1; |
230 |
final Type newcover = freeVar.VariableIdentifier().type().kind() == TypeKind.Any |
231 |
? fixedType : CoverType(fixedType, freeVar.VariableIdentifier().type()); |
232 |
freeVar.VariableIdentifier().SetType(newcover); |
233 |
return newcover;
|
234 |
} |
235 |
else if (tk1 == TypeKind.OoActionSystemType && tk2 == TypeKind.Null) |
236 |
{ |
237 |
return type1;
|
238 |
} |
239 |
else if (tk2 == TypeKind.OoActionSystemType && tk1 == TypeKind.Null) |
240 |
{ |
241 |
return type2;
|
242 |
} |
243 |
|
244 |
else
|
245 |
return null; |
246 |
} |
247 |
else
|
248 |
{ |
249 |
switch (tk1)
|
250 |
{ |
251 |
case Any:
|
252 |
return type1;
|
253 |
|
254 |
case IntType:
|
255 |
final IntType intt1 = (IntType)type1;
|
256 |
final IntType intt2 = (IntType)type2;
|
257 |
final int low = intt1.rangeLow() < intt2.rangeLow() ? intt1.rangeLow() : intt2.rangeLow(); |
258 |
final int high = intt1.rangeHigh() > intt2.rangeHigh() ? intt1.rangeHigh() : intt2.rangeHigh(); |
259 |
return new IntType(low, high, null); |
260 |
case BoolType:
|
261 |
return type1;
|
262 |
case FloatType:
|
263 |
final FloatType floatt1 = (FloatType)type1;
|
264 |
final FloatType floatt2 = (FloatType)type2;
|
265 |
final double flow = floatt1.low() < floatt2.low() ? floatt1.low() : floatt2.low(); |
266 |
final double fhigh = floatt1.high() > floatt2.high() ? floatt1.high() : floatt2.high(); |
267 |
final double fprec = floatt1.precision() < floatt2.precision() ? floatt1.precision() : floatt2.precision(); |
268 |
return new FloatType(flow, fhigh, fprec, null); |
269 |
case EnumeratedType:
|
270 |
return null; |
271 |
case ListType:
|
272 |
final ListType listt1 = (ListType)type1;
|
273 |
final ListType listt2 = (ListType)type2;
|
274 |
// empty lists lack type, so take the other one
|
275 |
if ((listt1.innerType().kind() == TypeKind.Null) && (listt2.innerType().kind() != TypeKind.Null))
|
276 |
return listt2;
|
277 |
else if ((listt2.innerType().kind() == TypeKind.Null) && (listt1.innerType().kind() != TypeKind.Null)) |
278 |
return listt1;
|
279 |
else if (listt1.innerType().kind() == TypeKind.Null && listt2.innerType().kind() == TypeKind.Null) |
280 |
return listt1;
|
281 |
else
|
282 |
{ |
283 |
/**
|
284 |
* A cover type of a list must not change the size of the inner type. Mostly what is
|
285 |
* allowed to change is the list length.
|
286 |
*/
|
287 |
Type subtype = listt1.innerType();
|
288 |
final boolean castAllowed = TypeEqual(listt1.innerType(), listt2.innerType()) |
289 |
|| ( (listt1.innerType().kind() == TypeKind.OoActionSystemType) |
290 |
&& (subtype = Type.CoverType(listt1.innerType(), listt2.innerType())) != null); |
291 |
if (castAllowed){
|
292 |
final int maxelems = listt1.maxNumberOfElements() > listt2.maxNumberOfElements() |
293 |
? listt1.maxNumberOfElements() |
294 |
: listt2.maxNumberOfElements(); |
295 |
return new ListType(subtype, maxelems, null); |
296 |
} else
|
297 |
return null; |
298 |
|
299 |
// // The code blow allowed for bit-size changes of the inner type and is considered too
|
300 |
// // liberal. If a deep cast is necessary, the user might want to do a fold operation
|
301 |
// // instead..
|
302 |
// final Type subtype = Type.CoverType(listt1.innerType(), listt2.innerType());
|
303 |
// if (subtype != null)
|
304 |
// return new ListType(subtype, maxelems, null);
|
305 |
// else
|
306 |
// return null;
|
307 |
} |
308 |
case MapType:
|
309 |
final MapType mapt1 = (MapType)type1;
|
310 |
final MapType mapt2 = (MapType)type2;
|
311 |
// empty maps lack type, so take the other one.
|
312 |
if ((mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null)
|
313 |
&& (mapt2.fromType().kind() != TypeKind.Null && mapt2.toType().kind() != TypeKind.Null)) |
314 |
return mapt2;
|
315 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
316 |
&& (mapt1.fromType().kind() != TypeKind.Null && mapt1.toType().kind() != TypeKind.Null)) |
317 |
return mapt1;
|
318 |
else if ((mapt2.fromType().kind() == TypeKind.Null && mapt2.toType().kind() == TypeKind.Null) |
319 |
&& (mapt1.fromType().kind() == TypeKind.Null && mapt1.toType().kind() == TypeKind.Null)) |
320 |
return mapt1;
|
321 |
else
|
322 |
{ |
323 |
final Type sub1 = Type.CoverType(mapt1.fromType(), mapt2.fromType()); |
324 |
final Type sub2 = Type.CoverType(mapt2.toType(), mapt2.toType()); |
325 |
final int maxelems = mapt1.maxNumberOfElements() > mapt2.maxNumberOfElements() ? |
326 |
mapt1.maxNumberOfElements() : mapt2.maxNumberOfElements(); |
327 |
if (sub1 != null && sub2 != null) |
328 |
return new MapType(sub1, sub2, maxelems, null); |
329 |
else
|
330 |
return null; |
331 |
} |
332 |
case TupleType:
|
333 |
final TupleType tuplet1 = (TupleType)type1;
|
334 |
final TupleType tuplet2 = (TupleType)type2;
|
335 |
final TupleType result = new TupleType(null); |
336 |
final Iterator<Type> innert1 = tuplet1.innerTypes().iterator(); |
337 |
final Iterator<Type> innert2 = tuplet2.innerTypes().iterator(); |
338 |
while (innert1.hasNext())
|
339 |
{ |
340 |
final Type newinner = Type.CoverType(innert1.next(), innert2.next()); |
341 |
if (newinner == null) |
342 |
return null; |
343 |
result.AddType(newinner); |
344 |
} |
345 |
return result;
|
346 |
case OoActionSystemType:
|
347 |
if (type1.kind() == TypeKind.Null && type2.kind() != TypeKind.Null)
|
348 |
return type2;
|
349 |
else if (type2.kind() == TypeKind.Null && type1.kind() != TypeKind.Null) |
350 |
return type1;
|
351 |
else if (type1.kind() == TypeKind.Null && type2.kind() == TypeKind.Null) |
352 |
return type2;
|
353 |
else if (type1 == type2) // ref equals! |
354 |
return type1;
|
355 |
else
|
356 |
return ClassBaseType((OoActionSystemType)type1, (OoActionSystemType)type2);
|
357 |
case OpaqueType:
|
358 |
assert(false); |
359 |
return null; |
360 |
default:
|
361 |
throw new NotImplementedException(); |
362 |
} |
363 |
} |
364 |
} |
365 |
|
366 |
private static Type ClassBaseType(OoActionSystemType type1, OoActionSystemType type2) |
367 |
{ |
368 |
// this is rather inefficient.. should be done differently
|
369 |
final OoActionSystemType typea = type1;
|
370 |
final OoActionSystemType typeb = type2;
|
371 |
OoActionSystemType basea = type1; |
372 |
OoActionSystemType baseb = type2; |
373 |
while (basea != null) |
374 |
{ |
375 |
if (basea == typeb) // ref equals |
376 |
return basea;
|
377 |
basea = basea.baseType(); |
378 |
} |
379 |
while (baseb != null) |
380 |
{ |
381 |
if (baseb == typea) // ref equals |
382 |
return baseb;
|
383 |
baseb = baseb.baseType(); |
384 |
} |
385 |
return null; |
386 |
} |
387 |
|
388 |
public static boolean FirstTypeLessRange(Type type1, Type type2) |
389 |
{ |
390 |
final TypeKind tk1 = type1.kind();
|
391 |
final TypeKind tk2 = type2.kind();
|
392 |
|
393 |
if (tk1 != tk2)
|
394 |
throw new ArgumentException("Types need to be equal"); |
395 |
|
396 |
switch (tk1)
|
397 |
{ |
398 |
case Any:
|
399 |
return false; |
400 |
case IntType:
|
401 |
final IntType Int1 = (IntType)type1;
|
402 |
final IntType Int2 = (IntType)type2;
|
403 |
return Int1.rangeLow() > Int2.rangeLow() ||
|
404 |
Int1.rangeHigh() < Int2.rangeHigh(); |
405 |
case BoolType:
|
406 |
return false; |
407 |
case FloatType:
|
408 |
final FloatType Float1 = (FloatType)type1;
|
409 |
final FloatType Float2 = (FloatType)type2;
|
410 |
return Float1.low() > Float2.low()
|
411 |
|| Float1.high() < Float2.high() |
412 |
|| Float1.precision() > Float2.precision(); |
413 |
case EnumeratedType:
|
414 |
return false; |
415 |
case ListType:
|
416 |
final ListType listt1 = (ListType)type1;
|
417 |
final ListType listt2 = (ListType)type2;
|
418 |
return (listt1.maxNumberOfElements() < listt2.maxNumberOfElements()) ||
|
419 |
Type.FirstTypeLessRange(listt1.innerType(), listt2.innerType());
|
420 |
case MapType:
|
421 |
final MapType mapt1 = (MapType)type1;
|
422 |
final MapType mapt2 = (MapType)type2;
|
423 |
return (mapt1.maxNumberOfElements() < mapt2.maxNumberOfElements()) ||
|
424 |
Type.FirstTypeLessRange(mapt1.fromType(), mapt2.fromType()) ||
|
425 |
Type.FirstTypeLessRange(mapt1.toType(), mapt2.toType());
|
426 |
case TupleType:
|
427 |
final TupleType tuplet1 = (TupleType)type1;
|
428 |
final TupleType tuplet2 = (TupleType)type2;
|
429 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size())
|
430 |
return false; |
431 |
final Iterator<Type> innert1 = tuplet1.innerTypes().iterator(); |
432 |
final Iterator<Type> innert2 = tuplet2.innerTypes().iterator(); |
433 |
while (innert1.hasNext())
|
434 |
{ |
435 |
if (Type.FirstTypeLessRange(innert1.next(), innert2.next())) |
436 |
return true; |
437 |
} |
438 |
return false; |
439 |
case OoActionSystemType:
|
440 |
return false; |
441 |
case OpaqueType:
|
442 |
assert(false); |
443 |
return false; |
444 |
default:
|
445 |
throw new NotImplementedException(); |
446 |
} |
447 |
} |
448 |
|
449 |
public static boolean TypeEqualByKind(Type type1, Type type2) |
450 |
{ |
451 |
if ((type1 == null) || (type2 == null)) |
452 |
return false; |
453 |
|
454 |
final TypeKind tk1 = type1.kind();
|
455 |
final TypeKind tk2 = type2.kind();
|
456 |
|
457 |
// if of different kind, then return false..
|
458 |
if (tk1 != tk2)
|
459 |
return false; |
460 |
|
461 |
// if same kind, make a rigorous check
|
462 |
switch (tk1)
|
463 |
{ |
464 |
case Any:
|
465 |
return true; |
466 |
|
467 |
case IntType:
|
468 |
case BoolType:
|
469 |
case FloatType:
|
470 |
return true; |
471 |
case EnumeratedType:
|
472 |
return type1 == type2; // ref equals |
473 |
case ListType:
|
474 |
final ListType listt1 = (ListType)type1;
|
475 |
final ListType listt2 = (ListType)type2;
|
476 |
return Type.TypeEqualByKind(listt1.innerType(), listt2.innerType()); |
477 |
case MapType:
|
478 |
final MapType mapt1 = (MapType)type1;
|
479 |
final MapType mapt2 = (MapType)type2;
|
480 |
return Type.TypeEqualByKind(mapt1.fromType(), mapt2.fromType()) && |
481 |
Type.TypeEqualByKind(mapt1.toType(), mapt2.toType());
|
482 |
case TupleType:
|
483 |
final TupleType tuplet1 = (TupleType)type1;
|
484 |
final TupleType tuplet2 = (TupleType)type2;
|
485 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size())
|
486 |
return false; |
487 |
final Iterator<Type> innert1 = tuplet1.innerTypes().iterator(); |
488 |
final Iterator<Type> innert2 = tuplet2.innerTypes().iterator(); |
489 |
while (innert1.hasNext())
|
490 |
{ |
491 |
if (!Type.TypeEqualByKind(innert1.next(), innert2.next())) |
492 |
return false; |
493 |
} |
494 |
return true; |
495 |
case OoActionSystemType:
|
496 |
return type1 == type2; // ref equ. |
497 |
case OpaqueType:
|
498 |
assert(false); |
499 |
return false; |
500 |
default:
|
501 |
throw new NotImplementedException(); |
502 |
} |
503 |
} |
504 |
|
505 |
|
506 |
public static boolean TypeEqual(Type type1, Type type2) |
507 |
{ |
508 |
// this will also work with opaque types...
|
509 |
while (type1 instanceof OpaqueType) |
510 |
type1 = ((OpaqueType)type1).resolvedType(); |
511 |
while (type2 instanceof OpaqueType) |
512 |
type2 = ((OpaqueType)type2).resolvedType(); |
513 |
|
514 |
if ((type1 == null) || (type2 == null)) |
515 |
return false; |
516 |
|
517 |
final TypeKind tk1 = type1.kind();
|
518 |
final TypeKind tk2 = type2.kind();
|
519 |
|
520 |
// if of different kind, then return false..
|
521 |
if (tk1 != tk2)
|
522 |
return false; |
523 |
|
524 |
// if same kind, make a rigorous check
|
525 |
switch (tk1)
|
526 |
{ |
527 |
case IntType:
|
528 |
final IntType intt1 = (IntType)type1;
|
529 |
final IntType intt2 = (IntType)type2;
|
530 |
return intt1.rangeLow() == intt2.rangeLow() &&
|
531 |
intt1.rangeHigh() == intt2.rangeHigh(); |
532 |
case BoolType:
|
533 |
return true; |
534 |
case FloatType:
|
535 |
final FloatType floatt1 = (FloatType)type1;
|
536 |
final FloatType floatt2 = (FloatType)type2;
|
537 |
return floatt1.low() == floatt2.low() &&
|
538 |
floatt1.high() == floatt2.high() && |
539 |
floatt1.precision() == floatt2.precision(); |
540 |
case EnumeratedType:
|
541 |
return type1 == type2; // ref equ |
542 |
case ListType:
|
543 |
final ListType listt1 = (ListType)type1;
|
544 |
final ListType listt2 = (ListType)type2;
|
545 |
// an empty list can be of any type..
|
546 |
/*if ((listt1.innerType.kind == TypeKind.Null) || (listt2.innerType.kind == TypeKind.Null))
|
547 |
return true;
|
548 |
else*/
|
549 |
return Type.TypeEqual(listt1.innerType(), listt2.innerType()) && |
550 |
listt1.maxNumberOfElements() == listt2.maxNumberOfElements(); // need this because of covertype
|
551 |
case MapType:
|
552 |
final MapType mapt1 = (MapType)type1;
|
553 |
final MapType mapt2 = (MapType)type2;
|
554 |
return Type.TypeEqual(mapt1.fromType(), mapt2.fromType()) && |
555 |
Type.TypeEqual(mapt1.toType(), mapt2.toType()) &&
|
556 |
mapt1.maxNumberOfElements() == mapt2.maxNumberOfElements(); // need this because of covertype
|
557 |
case TupleType:
|
558 |
final TupleType tuplet1 = (TupleType)type1;
|
559 |
final TupleType tuplet2 = (TupleType)type2;
|
560 |
if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size())
|
561 |
return false; |
562 |
final Iterator<Type> innert1 = tuplet1.innerTypes().iterator(); |
563 |
final Iterator<Type> innert2 = tuplet2.innerTypes().iterator(); |
564 |
while (innert1.hasNext())
|
565 |
{ |
566 |
if (!Type.TypeEqual(innert1.next(), innert2.next())) |
567 |
return false; |
568 |
} |
569 |
return true; |
570 |
case OoActionSystemType:
|
571 |
return type1 == type2; // ref equ. // || Covariance((OoActionSystemType)type1, (OoActionSystemType)type2); |
572 |
case OpaqueType:
|
573 |
assert(false); |
574 |
return false; |
575 |
case Null:
|
576 |
case Any:
|
577 |
return true; |
578 |
default:
|
579 |
throw new NotImplementedException(); |
580 |
} |
581 |
} |
582 |
|
583 |
/// <summary>
|
584 |
/// checks if type 2 is a desc. of type 1
|
585 |
/// </summary>
|
586 |
public static boolean Covariance(OoActionSystemType ooActionSystemType, OoActionSystemType ooActionSystemType_2) |
587 |
{ |
588 |
// check if type 2 is a desc. of type 1
|
589 |
while (ooActionSystemType != ooActionSystemType_2 && ooActionSystemType_2.baseType() != null) // ref equ. |
590 |
ooActionSystemType_2 = ooActionSystemType_2.baseType(); |
591 |
|
592 |
return ooActionSystemType == ooActionSystemType_2; // ref equ. |
593 |
} |
594 |
} |