Project

General

Profile

Revision 7

Added by Willibald K. over 8 years ago

changing java, cpp, hpp files to unix line endings

View differences:

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