Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / visitors / OoaResolveExpressionsVisitor.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.visitors;
29

    
30
import java.util.ArrayList;
31
import java.util.Iterator;
32
import java.util.LinkedList;
33
import java.util.Stack;
34

    
35
import org.momut.ooas.ast.AstNodeTypeEnum;
36
import org.momut.ooas.ast.IAst;
37
import org.momut.ooas.ast.expressions.AccessExpression;
38
import org.momut.ooas.ast.expressions.BinaryOperator;
39
import org.momut.ooas.ast.expressions.CallExpression;
40
import org.momut.ooas.ast.expressions.ExistsQuantifier;
41
import org.momut.ooas.ast.expressions.Expression;
42
import org.momut.ooas.ast.expressions.ExpressionKind;
43
import org.momut.ooas.ast.expressions.ForallQuantifier;
44
import org.momut.ooas.ast.expressions.IdentifierExpression;
45
import org.momut.ooas.ast.expressions.LeafExpression;
46
import org.momut.ooas.ast.expressions.ListConstructor;
47
import org.momut.ooas.ast.expressions.MapConstructor;
48
import org.momut.ooas.ast.expressions.SetConstructor;
49
import org.momut.ooas.ast.expressions.TernaryOperator;
50
import org.momut.ooas.ast.expressions.TupleConstructor;
51
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
52
import org.momut.ooas.ast.expressions.TypeExpression;
53
import org.momut.ooas.ast.expressions.UnaryOperator;
54
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
55
import org.momut.ooas.ast.expressions.ValueExpression;
56
import org.momut.ooas.ast.expressions.LeafExpression.LeafTypeEnum;
57
import org.momut.ooas.ast.expressions.MapConstructor.MapItem;
58
import org.momut.ooas.ast.identifiers.AttributeIdentifier;
59
import org.momut.ooas.ast.identifiers.ConstantIdentifier;
60
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier;
61
import org.momut.ooas.ast.identifiers.FunctionIdentifier;
62
import org.momut.ooas.ast.identifiers.Identifier;
63
import org.momut.ooas.ast.identifiers.IdentifierKind;
64
import org.momut.ooas.ast.identifiers.ParameterIdentifier;
65
import org.momut.ooas.ast.identifiers.SelfTypeIdentifier;
66
import org.momut.ooas.ast.statements.Assignment;
67
import org.momut.ooas.ast.statements.Call;
68
import org.momut.ooas.ast.statements.GuardedCommand;
69
import org.momut.ooas.ast.statements.SeqBlock;
70
import org.momut.ooas.ast.statements.Statement;
71
import org.momut.ooas.ast.types.AnyType;
72
import org.momut.ooas.ast.types.BoolType;
73
import org.momut.ooas.ast.types.CharType;
74
import org.momut.ooas.ast.types.EnumType;
75
import org.momut.ooas.ast.types.FloatType;
76
import org.momut.ooas.ast.types.FunctionType;
77
import org.momut.ooas.ast.types.IntType;
78
import org.momut.ooas.ast.types.ListType;
79
import org.momut.ooas.ast.types.MapType;
80
import org.momut.ooas.ast.types.NullType;
81
import org.momut.ooas.ast.types.OoActionSystemType;
82
import org.momut.ooas.ast.types.TupleType;
83
import org.momut.ooas.ast.types.TypeKind;
84
import org.momut.ooas.ast.types.Type;
85
import org.momut.ooas.ast.types.ValuedEnumType;
86
import org.momut.ooas.parser.ParserError;
87
import org.momut.ooas.parser.ParserMessage;
88
import org.momut.ooas.parser.ParserState;
89
import org.momut.ooas.parser.ParserWarning;
90
import org.momut.ooas.parser.SymbolTable;
91
import org.momut.ooas.utils.exceptions.ArgumentException;
92
import org.momut.ooas.utils.exceptions.NotImplementedException;
93

    
94
/// <summary>
95
/// Requires: ReplaceOpaqueVisitor
96
///
97
/// After we have an AST without any Opaquetypes, we still need to replace all the
98
/// UnresolvedIdentifierExpressions. We also need to compute the expression types,
99
/// which is also necessary to resolve all the identifiers. So, this visitor
100
/// goes over all expressions and
101
///   - resolves all identifiers
102
///   - calculates resulting types (incl. coercion)
103
/// </summary>
104
public final class OoaResolveExpressionsVisitor extends OoaCompleteAstTraversalVisitor
105
{
106
        // we allow for free variable in expressions. collect them here.
107
        private final Stack<SymbolTable> m_freeVariables = new Stack<SymbolTable>();
108
        private Expression m_entryExpression = null;
109

    
110
        // helpers that replace the old expression in the AST by the new one.
111
        private void ReplaceExpression(IAst parent, Expression subElement, Expression newExpression)
112
        {
113
                switch (parent.nodeType())
114
                {
115
                        case identifier:
116
                                ReplaceExpressionInIdentifier((Identifier)parent, subElement, newExpression);
117
                                break;
118
                        case statement:
119
                                ReplaceExpressionInStatement((Statement)parent, subElement, newExpression);
120
                                break;
121
                        default:
122
                                throw new NotImplementedException();
123
                }
124
        }
125
        private void ReplaceExpressionInIdentifier(Identifier identifier, Expression subElement, Expression newExpression)
126
        {
127
                switch (identifier.kind())
128
                {
129
                        case AttributeIdentifier:
130
                                final AttributeIdentifier ident = (AttributeIdentifier)identifier;
131
                                assert(ident.initializer() == subElement); // ref equ.
132
                                ident.SetInitializer(newExpression);
133
                                break;
134
                        case Constant:
135
                                final ConstantIdentifier aconst = (ConstantIdentifier)identifier;
136
                                assert(aconst.Value() == subElement); // ref equ
137
                                aconst.SetValue(newExpression);
138
                                if (newExpression.kind() != ExpressionKind.Value)
139
                                        Error(aconst.Value(), String.format("%s not a constant!", aconst.tokenText()));
140
                                break;
141
                        default:
142
                                throw new NotImplementedException();
143
                }
144
        }
145
        private void ReplaceExpressionInStatement(Statement statement, Expression subElement, Expression newExpression)
146
        {
147
                switch (statement.kind())
148
                {
149
                        case GuardedCommand:
150
                                final GuardedCommand gc = (GuardedCommand)statement;
151
                                assert(gc.guard() == subElement); // ref eq
152
                                gc.SetGuard(newExpression);
153
                        break;
154
                        case SeqBlock:
155
                                final SeqBlock sqblock = (SeqBlock)statement;
156
                                assert(sqblock.filter() == subElement); // ref eq
157
                                sqblock.SetFilter(null);
158
                                // we convert the filter to a guarded command...
159
                                final SeqBlock implseq = new SeqBlock(sqblock.line(), sqblock.pos());
160
                                implseq.SetStatements(sqblock.statements());
161
                                final GuardedCommand implguard = new GuardedCommand(newExpression, implseq, sqblock.line(), sqblock.pos());
162
                                sqblock.SetStatements(new LinkedList<Statement>());
163
                                sqblock.AddStatement(implguard);
164
                                break;
165
                        case Assignment:
166
                                final Assignment zw = (Assignment)statement;
167
                                boolean found = false;
168
                                if (zw.nondetExpression() == subElement) // ref eq
169
                                {
170
                                        zw.SetNondetExpression(newExpression);
171
                                        found = true;
172
                                }
173
                                else
174
                                {
175
                                        int cntr = 0;
176
                                        while (cntr < zw.places().size()) {
177
                                                if (zw.places().get(cntr) == subElement) { // ref eq
178
                                                        zw.places().set(cntr, newExpression);
179
                                                        found = true;
180
                                                        break;
181
                                                }
182
                                                cntr ++;
183
                                        }
184
                                        if (!found) {
185
                                                cntr = 0;
186
                                                while (cntr < zw.values().size()) {
187
                                                        if (zw.values().get(cntr) == subElement) { // ref eq.
188
                                                                zw.values().set(cntr, newExpression);
189
                                                                found = true;
190
                                                                break;
191
                                                        }
192
                                                        cntr ++;
193
                                                }
194
                                        }
195
                                }
196
                                assert(found);
197
                                break;
198
                        case MethodCall:
199
                                final Call call = (Call)statement;
200
                                assert(call.callExpression() == subElement); // ref eq.
201
                                call.SetCallExpression(newExpression);
202
                                break;
203
                        default:
204
                                throw new NotImplementedException();
205
                }
206
        }
207

    
208
        // helper that returns null and adds an error message in the parserstate errorlist.
209
        private Expression Error(Expression expression, String p)
210
        {
211
                final ParserError error = new ParserError(m_ParserState.filename,
212
                                expression.line(), expression.pos(), p);
213
                m_ParserState.AddErrorMessage(error);
214
                return null;
215
        }
216
        private void Info(Expression expression, String p)
217
        {
218
                final ParserMessage msg = new ParserMessage(m_ParserState.filename,
219
                                expression.line(), expression.pos(), p);
220
                m_ParserState.AddMessage(msg);
221
        }
222
        // helper that adds a warning message to the output
223
        private void Warning(Identifier expression, String p)
224
        {
225
                final ParserWarning warning = new ParserWarning(m_ParserState.filename,
226
                                expression.line(), expression.column(), p);
227
                m_ParserState.AddWarningMessage(warning);
228
        }
229
        private void Warning(Expression expression, String p)
230
        {
231
                final ParserWarning warning = new ParserWarning(m_ParserState.filename,
232
                                expression.line(), expression.pos(), p);
233
                m_ParserState.AddWarningMessage(warning);
234
        }
235

    
236
        private final ArrayList<TupleConstructor> m_matcherList = new ArrayList<TupleConstructor>();
237

    
238
        ///
239
        ///   Resolve Expressions
240
        ///
241

    
242
        private Expression ResolveExpression(TernaryOperator expression)
243
        {
244
                if (expression.kind() == ExpressionKind.conditional)
245
                {
246
                        final Expression left = ResolveExpression(expression.left());
247
                        Expression mid = ResolveExpression(expression.mid());
248
                        Expression right = ResolveExpression(expression.right());
249

    
250
                        if (left == null || mid == null || right == null)
251
                                return null;
252

    
253
                        if (left.type() == null || left.type().kind() != TypeKind.BoolType)
254
                                return Error(expression, "Conditional: Condition not a bool");
255

    
256
                        if (mid.type() == null || right.type() == null)
257
                                return Error(expression, "Conditional: Then or Else branch has void-type");
258

    
259
                        final Type acover = Type.CoverType(mid.type(), right.type());
260

    
261
                        if (acover == null)
262
                                return Error(expression, String.format(
263
                                        "Conditional: Then and Else branch must be of same type. (%s <> %s)",
264
                                        mid.type().toString(), right.type().toString()));
265

    
266
                        if (!Type.TypeEqual(acover, mid.type()))
267
                        {
268
                                mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line(), mid.pos());
269
                                mid.SetType(acover);
270
                        }
271
                        if (!Type.TypeEqual(acover, right.type()))
272
                        {
273
                                right = new UnaryOperator(ExpressionKind.Cast, right, right.line(), right.pos());
274
                                right.SetType(acover);
275
                        }
276

    
277

    
278
                        expression.SetLeftChild(left);
279
                        expression.SetMidChild(mid);
280
                        expression.SetRightChild(right);
281
                        expression.SetType(mid.type());
282
                        return expression;
283
                }
284
                else if (expression.kind() == ExpressionKind.foldLR || expression.kind() == ExpressionKind.foldRL)
285
                {
286
                        CallExpression leftcall = expression.left().kind() != ExpressionKind.Call
287
                                ? new CallExpression(expression.left(), new ArrayList<Expression>(), expression.line(),
288
                                        expression.pos(), expression.definingScope())
289
                                : (CallExpression)expression.left();
290

    
291
                        leftcall = (CallExpression)ResolveExpression(leftcall, true);
292
                        if (leftcall == null)
293
                                return null;
294

    
295
                        final Expression afun = ResolveExpression(leftcall.child());
296
                        leftcall.SetChild(afun);
297
                        if (afun == null || afun.type() == null || afun.type().kind() != TypeKind.FunctionType)
298
                                return Error(expression, "Fold/Map operation needs a method or named action as LHS");
299

    
300
                        final FunctionType funType = (FunctionType)afun.type();
301
                        if (funType.returnType() == null && expression.mid() != null)
302
                                return Error(expression, "Fold operation needs a method with matching return type");
303
                        if (funType.returnType() != null && expression.mid() == null)
304
                                Warning(expression, "Map operation will discard result of function");
305

    
306
                        final boolean isMap = expression.mid() == null;
307
                        Expression mid = expression.mid();
308
                        if (!isMap)
309
                        {
310
                                mid = ResolveExpression(mid);
311
                                if ((funType.parameter().size() - leftcall.arguments().size()) != 2)
312
                                        return Error(expression, "Function used in fold operation needs 2 not-instantiated parameters");
313
                        } else if ((funType.parameter().size() - leftcall.arguments().size()) != 1)
314
                                return Error(expression, "Function used in map operation needs one not-instantiated parameter");
315

    
316
                        final Expression right = ResolveExpression(expression.right());
317
                        if (right == null || right.type() == null || right.type().kind() != TypeKind.ListType)
318
                                return Error(expression, "Fold/Map operation needs list as RHS");
319

    
320
                        if (!isMap)
321
                        {
322
                                final int nextToLast = funType.parameter().size() - 2;
323
                                final Type initCover = Type.CoverType(funType.parameter().get(nextToLast), mid.type());
324
                                if (initCover == null)
325
                                        return Error(expression, "Next to last parameter does not match initializer type in map operation.");
326
                                if (!Type.TypeEqual(mid.type(), initCover))
327
                                        mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line(), mid.pos());
328
                                mid.SetType(initCover);
329

    
330
                                //List<Expression> args = new List<Expression> ();
331
                                leftcall.arguments().add(new IdentifierExpression(new ParameterIdentifier("_result", initCover, null), 0, 0));
332
                                leftcall.arguments().add(new IdentifierExpression(new ParameterIdentifier("_elem", funType.parameter().peekLast(), null), 0, 0));
333
                                //leftcall.SetArguments(args);
334
                        }
335
                        // UlyssesType listCover = UlyssesType.CoverType(funType.parameter.Last.Value, ((ListType)right.type).innerType);
336
                        // if (listCover == null)
337
                        if (!Type.TypeEqual(funType.parameter().peekLast(), ((ListType)right.type()).innerType()))
338
                                return Error(expression, "Last paramter does not match inner-type of list in fold/map operation");
339

    
340
                        expression.SetLeftChild(leftcall);
341
                        expression.SetMidChild(mid);
342
                        expression.SetRightChild(right);
343
                        if (!isMap)
344
                                expression.SetType(funType.returnType());
345
                        else
346
                                expression.SetType(new NullType());
347
                        return expression;
348
                } else
349
                        throw new ArgumentException();
350
        }
351
        private Expression ResolveExpression(ForallQuantifier expression)
352
        {
353
                final Expression child = ResolveExpression(expression.child());
354
                if (child == null)
355
                        return null;
356

    
357
                expression.SetType(new BoolType(null));
358
                expression.SetChild(child);
359
                return expression;
360
        }
361
        private Expression ResolveExpression(ExistsQuantifier expression)
362
        {
363
                final Expression child = ResolveExpression(expression.child());
364
                if (child == null)
365
                        return null;
366

    
367
                expression.SetType(new BoolType(null));
368
                expression.SetChild(child);
369
                return expression;
370
        }
371
        private Expression ResolveExpression(ListConstructor expression)
372
        {
373
                Type type = null;
374
                ListType restype = null;
375
                Expression comprehension = null;
376
                if (expression.comprehension() != null)
377
                {
378
                        comprehension = ResolveExpressionNewScope(expression.comprehension());
379

    
380
                        if (comprehension == null)
381
                                return null;
382

    
383
                        if (comprehension.type() == null)
384
                                return Error(expression, "List comprehension has void expression");
385

    
386
                        if (comprehension.type().kind() != TypeKind.BoolType)
387
                                return Error(expression, "List comprehension has to be bool-expression");
388

    
389
                        expression.SetComprehension(comprehension);
390

    
391
                        if (expression.elements().size() != 1)
392
                                return Error(expression, "List comprehension expects one initializer expression");
393
                }
394

    
395
                final ArrayList<Expression> newitems = new ArrayList<Expression>();
396

    
397
                if (expression.elements().size() == 0 || expression.elements().get(0) == null || (
398
                        expression.elements().get(0).kind() == ExpressionKind.Value &&
399
                        expression.elements().get(0) instanceof ValueExpression<?> &&
400
                        ((ValueExpression<?>)expression.elements().get(0)).value() == null))
401
                {
402
                        // empty list
403
                        type = new NullType();
404
                }
405
                else
406
                {
407
                        final ArrayList<Expression> tmpitems = new ArrayList<Expression>();
408
                        for (final Expression item: expression.elements())
409
                        {
410
                                final Expression element = ResolveExpression(item);
411
                                if (element == null)
412
                                        return null;
413
                                if (element.type() == null)
414
                                        return Error(expression, "Void expression in list initializer");
415

    
416
                                if (element.kind() == ExpressionKind.Value &&
417
                                    element instanceof ValueExpression<?> &&
418
                                    ((ValueExpression<?>)element).value() == null)
419
                                {
420
                                        return Error(expression, "Not-In-List (nil) values not allowed in a list");
421
                                }
422

    
423
                                // calculate the type we're constructing
424
                                if (type == null)
425
                                        type = element.type();
426

    
427
                                type = Type.CoverType(type, element.type());
428
                                if (type == null)
429
                                        return Error(expression, "List constructor needs matching types");
430

    
431
                                tmpitems.add(element);
432
                        }
433

    
434
                        // now we have the resulting type - we still need to insert casts that might be necessary
435
                        for (final Expression item: tmpitems)
436
                        {
437
                                if (!Type.TypeEqual(item.type(), type))
438
                                {
439
                                        final Expression cast = new UnaryOperator(ExpressionKind.Cast, item, item.line(), item.pos());
440
                                        cast.SetType(type);
441
                                        newitems.add(cast);
442
                                }
443
                                else
444
                                        newitems.add(item);
445
                        }
446
                }
447

    
448
                expression.SetElements(newitems);
449
                if (comprehension == null)
450
                        restype = new ListType(type, newitems.size(), null);
451
                else
452
                        restype = new ListType(type, -1, null); // we do not know anything about the bound
453

    
454
                expression.SetType(restype);
455
                return expression;
456
        }
457
        private Expression ResolveExpression(SetConstructor expression)
458
        {
459
                Type type = null;
460
                ListType restype = null;
461
                Expression comprehension = null;
462
                if (expression.comprehension() != null)
463
                {
464
                        comprehension = ResolveExpressionNewScope(expression.comprehension());
465

    
466
                        if (comprehension == null)
467
                                return null;
468

    
469
                        if (comprehension.type() == null)
470
                                return Error(expression, "Set comprehension has void expression");
471

    
472
                        if (comprehension.type().kind() != TypeKind.BoolType)
473
                                return Error(expression, "Set comprehension has to be bool-expression");
474

    
475
                        expression.SetComprehension(comprehension);
476

    
477
                        if (expression.items().size() != 1)
478
                                return Error(expression, "Set comprehension expects one initializer expression");
479
                }
480

    
481
                final ArrayList<Expression> newitems = new ArrayList<Expression>();
482
                for (final Expression item: expression.items())
483
                {
484
                        final Expression element = ResolveExpression(item);
485
                        if (element == null)
486
                                return null;
487

    
488
                        if (element.type() == null)
489
                                return Error(expression, "Void expression in set initializer");
490

    
491
                        if (type == null)
492
                                type = element.type();
493
                        type = Type.CoverType(type, element.type());
494
                        if (type == null)
495
                                return Error(expression, "Set initializer needs matching types");
496

    
497
                        newitems.add(element);
498
                }
499
                expression.SetItems(newitems);
500
                restype = new ListType(type, newitems.size(), null);
501

    
502
                expression.SetType(restype);
503
                return expression;
504
        }
505
        private Expression ResolveExpression(MapConstructor expression)
506
        {
507
                Type domain = null;
508
                Type range = null;
509
                final ArrayList<MapConstructor.MapItem> newitems = new ArrayList<MapConstructor.MapItem>();
510

    
511
                for(final MapItem item: expression.items())
512
                {
513
                        final Expression domexpr = ResolveExpression(item.key);
514
                        if (domexpr == null)
515
                                return null;
516

    
517
                        if (domexpr.type() == null)
518
                                return Error(expression, "Domain initializing expression void");
519

    
520
                        if (domain == null)
521
                                domain = domexpr.type();
522

    
523
                        final Expression rangeexpr = ResolveExpression(item.value);
524
                        if (rangeexpr == null)
525
                                return null;
526

    
527
                        if (rangeexpr.type() == null)
528
                                return Error(expression, "Range initializing expression void");
529

    
530
                        if (range == null)
531
                                range = rangeexpr.type();
532

    
533
                        domain = Type.CoverType(domain, domexpr.type());
534
                        range = Type.CoverType(range, rangeexpr.type());
535
                        if (domain == null)
536
                                return Error(expression, "Types of domain expressions do not match");
537

    
538
                        if (range == null)
539
                                return Error(expression, "Types of range expressions do not match");
540

    
541
                        newitems.add(new MapConstructor.MapItem(domexpr, rangeexpr));
542
                }
543

    
544
                expression.SetItems(newitems);
545
                final MapType resulttype = new MapType(domain, range, newitems.size(), null);
546
                expression.SetType(resulttype);
547
                return expression;
548
        }
549
        private Expression ResolveExpression(TupleConstructor expression)
550
        {
551
                final TupleType typeToConstruct = (TupleType)expression.tupleType().type();
552

    
553
                if (expression.values().size() != typeToConstruct.innerTypes().size())
554
                        return Error(expression, String.format("Tuple constructor has wrong arity. (%s <> %s)",
555
                                typeToConstruct.innerTypes().size(), expression.values().size()));
556

    
557
                //TupleType resulttype = new TupleType(null);
558
                final ArrayList<Expression> newvalexprs = new ArrayList<Expression>();
559

    
560
                final Iterator<Type> innerTargetType = typeToConstruct.innerTypes().iterator();
561
                int freeVarCount = 0;
562
                for (final Expression initexpr: expression.values())
563
                {
564
                        final Type innerTargetTypeValue = innerTargetType.next();
565
                        Expression newval = ResolveExpression(initexpr);
566
                        if (newval == null)
567
                                return null;
568
                        if (newval.type() == null)
569
                                return Error(expression, "Element has void type");
570

    
571
                        if (newval.type().kind() == TypeKind.Any)
572
                        {
573
                                // free var - so set type.
574
                                final AnyType freevar = (AnyType)newval.type();
575
                                freevar.VariableIdentifier().SetType(innerTargetTypeValue);
576
                                freevar.VariableIdentifier().SetInitialized(true);
577
                                freeVarCount++;
578
                        }
579
                        else
580
                        {
581
                                final Type acover = Type.CoverType(innerTargetTypeValue, newval.type());
582
                                if (acover == null || !Type.TypeEqualByKind(innerTargetTypeValue, acover))
583
                                        return Error(expression,
584
                                                String.format("Element in tuple constructor has non-matching type (%s <> %s)",
585
                                                                innerTargetTypeValue.toString(), newval.type().toString()));
586

    
587
                                if (!Type.TypeEqual(acover, newval.type()))
588
                                {
589
                                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line(), newval.pos());
590
                                        newval.SetType(acover);
591
                                }
592
                                if (Type.FirstTypeLessRange(innerTargetTypeValue, acover)) {
593
                                        Warning(expression,
594
                                                String.format("Tuple constructor may over/underflow: %s := %s",
595
                                                                innerTargetTypeValue.toString(), acover.toString()));
596
                                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line(), newval.pos());
597
                                        newval.SetType(innerTargetTypeValue);
598
                                }
599
                        }
600

    
601
                        newvalexprs.add(newval);
602
                        //resulttype.AddType(newval.type);
603
                }
604

    
605
                if (freeVarCount > 0)
606
                {
607
                        if (freeVarCount != expression.values().size())
608
                                return Error(expression, String.format("Tuple constructor must have 0 or #elems (%s) free variables", expression.values().size()));
609
                        else
610
                        {
611
                                expression.SetIsMatcher(true); // mark this tuple constructor as matcher, since this is the only thing it does..
612
                                m_matcherList.add(expression); // matcher has to be bound by one equality
613
                        }
614
                }
615

    
616
                expression.SetTupleValues(newvalexprs);
617
                //expression.SetType(resulttype);
618
                expression.SetType(typeToConstruct); // the constructor always will create the correct type!
619
                return expression;
620
        }
621

    
622
        private Expression ResolveExpression(IdentifierExpression expression)
623
        {
624
                // nothing to do here, since we do not have any consts that may be
625
                // folded
626
                if ((expression.identifier().kind() == IdentifierKind.MethodIdentifier
627
                       || expression.identifier().kind() == IdentifierKind.NamedActionIdentifier)
628
                    && !m_entryExpression.callTargets().contains(expression.identifier()))
629
                {
630
                        m_entryExpression.callTargets().add((FunctionIdentifier)expression.identifier());
631
                }
632

    
633
                return expression;
634
        }
635
        private Expression ResolveExpression(UnresolvedIdentifierExpression expression)
636
        {
637
                Identifier anid;
638
                //Identifier self = m_ParserState.Lookup("self");
639

    
640
                if (m_freeVariables.peek().Defined(expression.tokenText()))
641
                        anid = m_freeVariables.peek().Get(expression.tokenText());
642
                else
643
                        anid = m_ParserState.Lookup(expression.tokenText(), expression.scope());
644

    
645
                if (anid != null)
646
                {
647
                        switch (anid.kind())
648
                        {
649
                        case TypeIdentifier:
650
                                // only return a TypeExpression if this TypeIdentifier didn't come from a "self"
651
                                if (anid instanceof SelfTypeIdentifier) {
652
                                        final IdentifierExpression result = new IdentifierExpression(anid, expression.line(), expression.pos());
653
                                        result.setIsSelf(true);
654
                                        return result;
655
                                } else
656
                                        return new TypeExpression(anid.type(), expression.line(), expression.pos());
657

    
658
                        case MethodIdentifier:
659
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
660
                                final SelfTypeIdentifier selfid = (SelfTypeIdentifier)m_ParserState.Lookup("self", expression.scope());
661
                                if ((selfid != null) && ((OoActionSystemType)(selfid).type()).symbols().Defined(anid))
662
                                {
663
                                        // if it's a self access, add a self identifier (needed by cadp backend, e.g.)
664
                                        // self.<method> is handled in a separate method and does not call us here!! (hence this code is working)
665
                                        final IdentifierExpression aself = new IdentifierExpression(selfid, expression.line(), expression.pos());
666
                                        aself.setIsSelf(true);
667
                                        final AccessExpression localaccess = new AccessExpression(aself, new IdentifierExpression(anid, expression.line(), expression.pos()),
668
                                                        expression.line(), expression.pos());
669
                                        ResolveExpression(localaccess);
670
                                        return localaccess;
671
                                }
672
                                else
673
                                {
674
                                        return new IdentifierExpression(anid, expression.line(), expression.pos());
675
                                }
676

    
677
                        case NamedActionIdentifier:
678
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
679
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
680

    
681
                        case Constant:
682
                                if (((ConstantIdentifier)anid).Value() != null)
683
                                        return ((ConstantIdentifier)anid).Value().Clone();
684
                                else
685
                                        return null;
686

    
687
                        default:
688
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
689
                        }
690
                }
691
                else
692
                {
693
                        final ExpressionVariableIdentifier freeVar =
694
                                        new ExpressionVariableIdentifier(expression.tokenText(), expression.line(), expression.pos());
695
                        freeVar.SetType(new AnyType(freeVar));
696
                        m_freeVariables.peek().AddIdentifier(freeVar);
697

    
698
                        // add a warning about free variables - do not change text without changing the text in ooaTypeCheckVisitor..
699
                        Warning(freeVar, String.format("Free variable in expression: '%s'.", freeVar.tokenText()));
700

    
701
                        return new IdentifierExpression(freeVar, expression.line(), expression.pos());
702
                }
703
        }
704
        private Expression ResolveExpression(TupleMapAccessExpression expression)
705
        {
706
                final Expression child = ResolveExpression(expression.child());
707
                if (child == null)
708
                        return null;
709

    
710
                final Expression arg = ResolveExpression(expression.argument());
711
                if (arg == null)
712
                        return null;
713

    
714

    
715
                assert(child.type() != null);
716

    
717
                if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.TupleType))
718
                {
719
                        if ((arg.kind() != ExpressionKind.Value)
720
                            || (((LeafExpression)arg).valueType() != LeafTypeEnum.integer))
721
                        {
722
                                return Error(expression, "Argument to tuple access must be constant integer value!");
723
                        }
724
                        final TupleType aTuple = (TupleType)child.type();
725
                        @SuppressWarnings("unchecked")
726
                        final
727
                        ValueExpression<Integer> aval = (ValueExpression<Integer>)arg;
728
                        if ((aval.value() < 0) || (aval.value() >= aTuple.innerTypes().size()))
729
                        {
730
                                return Error(expression, "Argument to tuple access has to be in range 0..#elems-1");
731
                        }
732
//                        LinkedListNode<UlyssesType> anode = aTuple.innerTypes().First;
733
//                        int target = aval.value();
734
//                        while (target > 0)
735
//                        {
736
//                                target--;
737
//                                anode = anode.Next;
738
//                        }
739
//                        expression.SetType(anode.Value);
740
                        expression.SetType(aTuple.innerTypes().get(aval.value()));
741
                }
742
                else if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.MapType))
743
                {
744
                        final MapType amap = (MapType)child.type();
745
                        expression.SetType(amap.toType());
746
                }
747
                else if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.ListType))
748
                {
749
                        // we allow element access of lists via list[i]
750
                        final ListType alist = (ListType)child.type();
751
                        expression.SetType(alist.innerType());
752
                }
753
                else
754
                {
755
                        return Error(expression, "Not a list, tuple, or map instance");
756
                }
757
                expression.SetArgument(arg);
758
                expression.SetChild(child);
759
                return expression;
760
        }
761
        private Expression ResolveExpression(CallExpression expression)
762
        {
763
                return ResolveExpression(expression, false);
764
        }
765
        private Expression ResolveExpression(CallExpression expression, boolean allowFewerParameters)
766
        {
767
                // calc type of child
768
                final Expression child = ResolveExpression(expression.child());
769
                if (child == null)
770
                        return null;
771

    
772
                assert(child.type() != null);
773

    
774
                expression.SetChild(child);
775

    
776
                if (child.type().kind() != TypeKind.FunctionType)
777
                {
778
                        return Error(expression, "No function to call!");
779
                }
780

    
781

    
782
                final FunctionType funtype = (FunctionType)child.type();
783

    
784
//                // check whether call of named action is allowed
785
//                if (funtype.functionType() != FunctionTypeEnum.Method)
786
//                {
787
//                        // see if call is allowed: must not be called from within a named action
788
//                        IScope callingScope = expression.scope();
789
//                        while (callingScope != null)
790
//                        {
791
//                                if (callingScope instanceof NamedActionIdentifier || callingScope instanceof MethodIdentifier)
792
//                                        return Error(expression, "Call of named Action only allowed in do-od block!");
793
//                                callingScope = callingScope.GetParentScope();
794
//                        }
795
//                }
796

    
797
                // check arguments
798
                final int argsSpec = funtype.parameter().size();
799
                final int argsHave = expression.arguments().size();
800
                if (argsHave < argsSpec && !allowFewerParameters)
801
                {
802
                        return Error(expression, "Too few parameters in function call");
803
                }
804
                if (argsHave > argsSpec)
805
                {
806
                        return Error(expression, "Too much parameters in function call");
807
                }
808

    
809
                final ArrayList<Expression> newargs = new ArrayList<Expression>();
810
                final Iterator<Type> demandedArgType = funtype.parameter().iterator();
811
                for (final Expression arg: expression.arguments())
812
                {
813
                        final Type demandedArgTypeValue = demandedArgType.next();
814
                        Expression newarg = ResolveExpression(arg);
815
                        if (newarg == null)
816
                                return null;
817

    
818
                        if (newarg.GetUninitializedFreeVariables().size() > 0)
819
                                Error(arg, String.format("Undefined variable '%s'",
820
                                        newarg.GetUninitializedFreeVariables().get(0).tokenText()));
821

    
822
                        final Expression constantvalue = newarg.kind() == ExpressionKind.Value ? newarg : null;
823

    
824
                        final Type acover = Type.CoverType(newarg.type(), demandedArgTypeValue);
825
                        if (acover == null || !Type.TypeEqualByKind(demandedArgTypeValue, acover))
826
                                return Error(arg, String.format("Argument type does not match; expected: %s delivered: %s",
827
                                                demandedArgTypeValue.toString(), newarg.type().toString()));
828

    
829
                        newarg = UnaryOperator.TryCoerceUp(newarg, acover);
830

    
831
                        if (Type.FirstTypeLessRange(demandedArgTypeValue, acover))
832
                        {
833
                                if (constantvalue == null)
834
                                {
835
                                        Warning(arg, String.format("Call parameter may over/underflow: %s := %s",
836
                                                        demandedArgTypeValue.toString(), acover.toString()));
837
                                        final UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, newarg, newarg.line(), newarg.pos());
838
                                        cast.SetType(demandedArgTypeValue);
839
                                        newarg = cast;
840
                                }
841
                                else
842
                                {
843
                                        Error(arg, String.format("Call parameter out of range (%s  := %s)",
844
                                                        demandedArgTypeValue.toString(), constantvalue.toString()));
845
                                }
846
                        }
847

    
848
                        newargs.add(newarg);
849
                }
850
                expression.SetArguments(newargs);
851

    
852
                if (funtype.returnType() != null)
853
                        expression.SetType(funtype.returnType());
854
                return expression;
855
        }
856
        private Expression ResolveExpression(AccessExpression expression)
857
        {
858
                Expression lhs = ResolveExpression(expression.left());
859
                if (lhs == null)
860
                        return null;
861
                if (!(expression.right() instanceof UnresolvedIdentifierExpression))
862
                {
863
                        expression.SetRightChild(ResolveExpression(expression.right()));
864
                        expression.SetType(expression.right().type());
865
                        return expression;
866
                }
867

    
868
                final boolean selfAccess = (lhs.kind() == ExpressionKind.Identifier) && ((IdentifierExpression)lhs).isSelf();
869
                final boolean staticAccess = lhs.kind() == ExpressionKind.Type;
870
                final UnresolvedIdentifierExpression access = (UnresolvedIdentifierExpression)expression.right();
871
                // atype could be null...
872
                Type atype = lhs.type();
873
                if ((lhs.kind() == ExpressionKind.Call) && (atype == null))
874
                {
875
                        return Error(access, "Can not access return type of void-function");
876
                }
877
                else if (atype == null)
878
                {
879
                        return Error(access, "Can not access member of a void type");
880
                }
881

    
882
                // if we did not apply a call expression to a function
883
                if (atype.kind() == TypeKind.FunctionType)
884
                {
885
                        // we can access the return val...
886
                        final FunctionType fun = (FunctionType)atype;
887

    
888
                        // check arity
889
                        if (fun.parameter().size() > 0)
890
                                return Error(access, "Implicit function call not possible: Too few parameters.");
891

    
892
                        // check return type
893
                        if (fun.returnType() == null)
894
                                return Error(access, "Can not access return type of void-function!");
895

    
896
                        // call ok
897
                        atype = fun.returnType();
898
                        // but add callExpression
899
                        lhs = new CallExpression(lhs, null, lhs.line(), lhs.pos(), null); // we do not know the scope
900
                        lhs.SetType(atype);
901
                }
902

    
903
                // update left child
904
                expression.SetLeftChild(lhs);
905

    
906

    
907
                switch (atype.kind())
908
                {
909
                case OoActionSystemType:
910
                        final Identifier anid = ((OoActionSystemType)atype).ResolveIdentifier(access.tokenText());
911
                        if (anid != null)
912
                        {
913
                                if (anid.kind() == IdentifierKind.MethodIdentifier && !m_entryExpression.callTargets().contains(anid))
914
                                        m_entryExpression.callTargets().add((FunctionIdentifier)anid);
915

    
916
                                if (staticAccess)
917
                                {
918
                                        if ((anid.kind() == IdentifierKind.AttributeIdentifier) &&
919
                                                        (((AttributeIdentifier)anid).isStatic()))
920
                                        {
921
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
922
                                                expression.SetRightChild(newrhs);
923
                                        }
924
                                        else
925
                                                return Error(access, "Can not access non-static member of an action system");
926
                                }
927
                                else
928
                                {
929
                                        if (anid.kind() != IdentifierKind.MethodIdentifier && !selfAccess)
930
                                                return Error(access, "Can only access methods of action system objects");
931
                                        else
932
                                        {
933
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
934
                                                expression.SetRightChild(newrhs);
935
                                        }
936
                                }
937
                        }
938
                        else
939
                                return Error(access, String.format("%s no member of %s",
940
                                                access.tokenText(), ((OoActionSystemType)atype).identifier().tokenText()));
941
                        break;
942
                case EnumeratedType:
943
                        final EnumType anEnum = (EnumType)atype;
944
                        if (!staticAccess)
945
                        {
946
                                return Error(access, "Enum values can only be accessed statically.");
947
                        }
948
                        if (anEnum.symbolTable().Defined(access.tokenText()))
949
                        {
950
                                final Identifier enumid = anEnum.symbolTable().Get(access.tokenText());
951
                                final IdentifierExpression newrhs = new IdentifierExpression(enumid, access.line(), access.pos());
952
                                expression.SetRightChild(newrhs);
953
                        }
954
                        else
955
                                return Error(access, String.format("%s not contained in enum %s",
956
                                                access.tokenText(), anEnum.identifier().tokenText()));
957
                        break;
958
                default:
959
                        /*error, we can not access an element with '.' in any other type*/
960
                        return Error(expression, "Expected: System, Enum, Func, or QR type");
961
                }
962

    
963
                expression.SetType(expression.right().type());
964
                return expression;
965
        }
966
        private Expression ResolveExpression(UnaryOperator expression)
967
        {
968
                final Expression child = ResolveExpression(expression.child());
969
                // if there was some error, then exit
970
                if (child == null)
971
                        return null;
972

    
973
                if (child.type() == null)
974
                        return Error(expression, "Can not apply unary operator to void-expression");
975

    
976

    
977
                switch (expression.kind())
978
                {
979
                case Primed:
980
                        expression.SetType(child.type());
981
                        break;
982

    
983
                        /*map unary*/
984
                case dom:           // map A to B -> list of A
985
                        if (child.type().kind() != TypeKind.MapType)
986
                                return Error(expression, "Domain operator only applicable to map types.");
987
                        MapType amap = (MapType)child.type();
988
                        ListType list = new ListType(amap.fromType(), amap.maxNumberOfElements(), null);
989
                        expression.SetType(list);
990
                        break;
991
                case range:         // map A to B -> list of B
992
                        if (child.type().kind() != TypeKind.MapType)
993
                                return Error(expression, "Range operator only applicable to map types.");
994
                        amap = (MapType)child.type();
995
                        list = new ListType(amap.toType(), amap.maxNumberOfElements(), null);
996
                        expression.SetType(list);
997
                        break;
998
                case merge:         // list of map A to B -> map A to B
999
                        if ((child.type().kind() == TypeKind.ListType) &&
1000
                                        (((ListType)child.type()).innerType().kind() == TypeKind.MapType))
1001
                        {
1002
                                expression.SetType(((ListType)child.type()).innerType());
1003
                                break;
1004
                        }
1005
                        else
1006
                                return Error(expression, "Merge operator only applicable to a list of maps");
1007
                        /*set/list unary*/
1008
                case card:       // list of A -> int (does not respect dupes, i.e. dupes do not count)
1009
                        if (child.type().kind() != TypeKind.ListType)
1010
                                return Error(expression, "Cardinality operator only applicable to list types.");
1011
                        expression.SetType(new IntType(0, ((ListType)child.type()).maxNumberOfElements(), null));
1012
                        break;
1013
                case dconc:      // list of list of A -> list of A
1014
                        if ((child.type().kind() == TypeKind.ListType)
1015
                                        && (((ListType)child.type()).innerType().kind() == TypeKind.ListType))
1016
                        {
1017
                                list = (ListType)child.type();
1018
                                final ListType innerlist = (ListType)list.innerType();
1019
                                final int maxnumber = innerlist.maxNumberOfElements() * list.maxNumberOfElements();
1020
                                expression.SetType(new ListType(innerlist.innerType(), maxnumber, null));
1021
                                break;
1022
                        }
1023
                        else
1024
                                return Error(expression, "Distributed Concatenation operator only applicable to list of lists");
1025
                case dinter:     // list of list of A -> list of A (intersection, does not respect dupes)
1026
                        if ((child.type().kind() == TypeKind.ListType)
1027
                                        && (((ListType)child.type()).innerType().kind() == TypeKind.ListType))
1028
                        {
1029
                                list = (ListType)child.type();
1030
                                final ListType innerlist = (ListType)list.innerType();
1031
                                final int maxnumber = innerlist.maxNumberOfElements();
1032
                                expression.SetType(new ListType(innerlist.innerType(), maxnumber, null));
1033
                                break;
1034
                        }
1035
                        else
1036
                                return Error(expression, "Distributed Intersection operator only applicable to list of lists");
1037
                case dunion:     // list of list of A -> list of A (union, does not respect dupes)
1038
                        if ((child.type().kind() == TypeKind.ListType)
1039
                                        && (((ListType)child.type()).innerType().kind() == TypeKind.ListType))
1040
                        {
1041
                                list = (ListType)child.type();
1042
                                final ListType innerlist = (ListType)list.innerType();
1043
                                // better upper limit?!
1044
                                                final int maxnumber = innerlist.maxNumberOfElements() * list.maxNumberOfElements();
1045
                                                expression.SetType(new ListType(innerlist.innerType(), maxnumber, null));
1046
                                                break;
1047
                        }
1048
                        else
1049
                                return Error(expression, "Distributed Union operator only applicable to list of lists");
1050
                case elems:      // list of A -> list of A (does not respect dupes)
1051
                        if (child.type().kind() != TypeKind.ListType)
1052
                                return Error(expression, "Element operator only applicable to list");
1053
                        expression.SetType(child.type());
1054
                        break;
1055
                case head:       // list of A -> A
1056
                        if (child.type().kind() != TypeKind.ListType)
1057
                                return Error(expression, "Head operator only applicable to list");
1058
                        expression.SetType(((ListType)child.type()).innerType());
1059
                        break;
1060
                case inds:       // list of A -> list of int
1061
                        if (child.type().kind() != TypeKind.ListType)
1062
                                return Error(expression, "Indices operator only applicable to list");
1063
                        list = (ListType)child.type();
1064
                        final IntType inner = new IntType(0, list.maxNumberOfElements(), null);
1065
                        expression.SetType(new ListType(inner, list.maxNumberOfElements(), null));
1066
                        break;
1067
                case len:        // list of A -> int (dupes count)
1068
                        if (child.type().kind() != TypeKind.ListType)
1069
                                return Error(expression, "Length operator only applicable to list");
1070
                        list = (ListType)child.type();
1071
                        expression.SetType(new IntType(0, list.maxNumberOfElements(), null));
1072
                        break;
1073
                case tail:       // list of A -> list of A
1074
                        if (child.type().kind() != TypeKind.ListType)
1075
                                return Error(expression, "Tail operator only applicable to list");
1076
                        list = (ListType)child.type();
1077
                        if (list.maxNumberOfElements() == 0)
1078
                                return Error(expression, "Tail operator only applicable to list of length > 0");
1079
                        final int newmaxelems = list.maxNumberOfElements() - 1;
1080
                        if (newmaxelems == 0)
1081
                                Warning(expression, "Tail operator returns empty list.");
1082
                        // set the return type null when list is empty?
1083
                        expression.SetType(new ListType(list.innerType(), newmaxelems, null));
1084
                        break;
1085
                        /*unary numberic*/
1086
                case unminus:
1087
                        if (!child.type().IsNumeric())
1088
                                return Error(expression, "Unary minus only applicable to numeric types");
1089
                        expression.SetType(Expression.ArithmeticCover(child.type(), null, expression.kind()));
1090
                        break;
1091
                case unplus:
1092
                        if (!child.type().IsNumeric())
1093
                                return Error(expression, "Unary plus only applicable to numeric types");
1094
                        expression.SetType(child.type());
1095
                        break;
1096
                case abs:
1097
                        if (!child.type().IsNumeric())
1098
                                return Error(expression, "Abs only applicable to numeric types");
1099
                        expression.SetType(child.type());
1100
                        break;
1101
                case not:
1102
                        if (/*!IsNumeric(child.type) && */
1103
                                        (child.type().kind() != TypeKind.BoolType))
1104
                                return Error(expression, "Not only applicable to bool types");
1105
                        expression.SetType(child.type());
1106
                        break;
1107
                        /*unary quantors*/
1108
                case forall:
1109
                        expression.SetType(new BoolType(null));
1110
                        break;
1111
                case exists:
1112
                        expression.SetType(new BoolType(null));
1113
                        break;
1114
                default:
1115
                        throw new NotImplementedException();
1116
                }
1117

    
1118
                expression.SetChild(child);
1119
                return expression;
1120
        }
1121
        @SuppressWarnings("unchecked")
1122
        private Expression ResolveExpression(BinaryOperator expression)
1123
        {
1124
                Expression lhs = ResolveExpression(expression.left());
1125
                Expression rhs = ResolveExpression(expression.right());
1126

    
1127

    
1128
                // if there was some error, then exit
1129
                if ((lhs == null) || (rhs == null))
1130
                        return null;
1131

    
1132
                final Type lt = lhs.type();
1133
                final Type rt = rhs.type();
1134

    
1135
                if ((lt == null) || (rt == null))
1136
                        return Error(expression, "Binary operator not applicable to void-type subexpression.");
1137

    
1138

    
1139
                switch (expression.kind())
1140
                {
1141
                /*map operators*/
1142
                case domresby:   // list of A * map A to B -> map A to B
1143
                case domresto:   // list of A * map A to B -> map A to B
1144
                        if (lt.kind() != TypeKind.ListType)
1145
                                return Error(expression, "Domain restriction operator expects list on LHS");
1146
                        if (rt.kind() != TypeKind.MapType)
1147
                                return Error(expression, "Domain restriction operator expects map on RHS");
1148
                        ListType domlist = (ListType)lt;
1149
                        MapType domMap = (MapType)rt;
1150
                        if (!Type.TypeEqual(domlist.innerType(), domMap.fromType()))
1151
                                return Error(expression, "Inner type of list and domain-type of map do not match");
1152
                        // since this is a restriction, maxnumofelems is ok
1153
                        expression.SetType(domMap);
1154
                        break;
1155
                case rngresby:   // map A to B * list of B -> map A to B
1156
                case rngresto:   // map A to B * list of B -> map A to B
1157
                        if (lt.kind() != TypeKind.MapType)
1158
                                return Error(expression, "Range restriction operator expects map on LHS");
1159
                        if (rt.kind() != TypeKind.ListType)
1160
                                return Error(expression, "Rangle restriction operator expects list on RHS");
1161
                        final ListType rangelist = (ListType)rt;
1162
                        domMap = (MapType)lt;
1163
                        if (!Type.TypeEqual(rangelist.innerType(), domMap.fromType()))
1164
                                return Error(expression, "Inner type of list and rangle-type of map do not match");
1165
                        // since this is a restriction, maxnumofelems is ok
1166
                        expression.SetType(domMap);
1167
                        break;
1168
                case munion:     // map A to B * map A to B -> map A to B
1169
                        if (lt.kind() != TypeKind.MapType ||
1170
                        rt.kind() != TypeKind.MapType)
1171
                                return Error(expression, "Map union expects maps on LHS and RHS");
1172
                        domMap = (MapType)lt;
1173
                        MapType rngMap = (MapType)rt;
1174
                        if (!Type.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1175
                                        !Type.TypeEqual(domMap.toType(), rngMap.toType()))
1176
                                return Error(expression, "Domain and Range types of maps must be equal");
1177
                        // union may change maximum number of elements..
1178
                        final MapType resMap = new MapType(domMap.fromType(), domMap.toType(),
1179
                                        domMap.maxNumberOfElements() + rngMap.maxNumberOfElements(), null);
1180
                        expression.SetType(resMap);
1181
                        break;
1182
                        /*set/list binary*/
1183
                case conc:       // list of A * list of A -> list of A
1184
                        if (lt.kind() != TypeKind.ListType ||
1185
                        rt.kind() != TypeKind.ListType)
1186
                                return Error(expression, "List concatenation expects two lists.");
1187
                        ListType la = (ListType)lt;
1188
                        ListType lb = (ListType)rt;
1189

    
1190
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1191
                                return lhs;
1192
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1193
                                return rhs;
1194
                        if (!Type.TypeEqual(la.innerType(), lb.innerType()))
1195
                                return Error(expression, String.format("Set/List concatenation expects two lists of same type. (%s <> %s)", la.toString(), lb.toString()));
1196
                        ListType resultList = new ListType(la.innerType(),
1197
                                        la.maxNumberOfElements() + lb.maxNumberOfElements(), null);
1198
                        expression.SetType(resultList);
1199
                        break;
1200
                case diff:       // list of A * list of A -> list of A (does not respect dupes)
1201
                        if (lt.kind() != TypeKind.ListType ||
1202
                        rt.kind() != TypeKind.ListType)
1203
                                return Error(expression, "Set difference expects two lists.");
1204
                        la = (ListType)lt;
1205
                        lb = (ListType)rt;
1206
                        if (!Type.TypeEqual(la.innerType(), lb.innerType()))
1207
                                return Error(expression, "Set difference expects two lists of same type.");
1208
                        expression.SetType(la);
1209
                        break;
1210
                case inter:      // list of A * list of A -> list of A (does not respect dupes)
1211
                        if (lt.kind() != TypeKind.ListType ||
1212
                        rt.kind() != TypeKind.ListType)
1213
                                return Error(expression, "Set intersection expects two lists.");
1214
                        la = (ListType)lt;
1215
                        lb = (ListType)rt;
1216
                        if (!Type.TypeEqual(la.innerType(), lb.innerType()))
1217
                                return Error(expression, "Set intersection expects two lists of same type.");
1218
                        expression.SetType(la.maxNumberOfElements() > lb.maxNumberOfElements() ? la : lb);
1219
                        break;
1220
                case elemin:     // A * list of A -> bool
1221
                case notelemin:  // A * list of A -> bool
1222
                        if (rt.kind() != TypeKind.ListType)
1223
                                return Error(expression, "Element (not) in operator expects list-type as RHS.");
1224
                        lb = (ListType)rt;
1225
                        if (lhs.kind() == ExpressionKind.Value)
1226
                                lhs = UnaryOperator.TryCoerceUp(lhs, lb.innerType());
1227
                        final Type leftType = lhs.type();
1228
                        if (!Type.TypeEqual(leftType, lb.innerType()))
1229
                                return Error(expression, String.format("List and element must be of same type: %s in %s",
1230
                                                lt == null ? "<null>" : lt.toString(), lb ==null || lb.innerType() == null ? "<null>" : lb.innerType().toString()));
1231
                        expression.SetType(new BoolType(null));
1232
                        break;
1233
                case subset:     // list of A * list of A -> bool (does not respect dupes)
1234
                        if (lt.kind() != TypeKind.ListType ||
1235
                        rt.kind() != TypeKind.ListType)
1236
                                return Error(expression, "Subset operation expects two lists.");
1237
                        la = (ListType)lt;
1238
                        lb = (ListType)rt;
1239
                        if (!Type.TypeEqual(la.innerType(), lb.innerType()))
1240
                                return Error(expression, "Subset operation expects two lists of same type.");
1241
                        expression.SetType(new BoolType(null));
1242
                        break;
1243
                case union:      // list of A * list of A -> list of A (does not respect dupes)
1244
                        if (lt.kind() != TypeKind.ListType ||
1245
                        rt.kind() != TypeKind.ListType)
1246
                                return Error(expression, "Set union expects two lists.");
1247
                        la = (ListType)lt;
1248
                        lb = (ListType)rt;
1249

    
1250
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1251
                                return rhs;
1252
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1253
                                return lhs;
1254

    
1255
                        if (!Type.TypeEqual(la.innerType(), lb.innerType()))
1256
                                return Error(expression, "Set union expects two lists of same type.");
1257
                        resultList = new ListType(la.innerType(),
1258
                                        la.maxNumberOfElements() + lb.maxNumberOfElements(), null);
1259
                        expression.SetType(resultList);
1260
                        break;
1261

    
1262
                        /*numeric binary*/
1263
                case pow:
1264
                        if (!lt.IsNumeric() || !rt.IsNumeric())
1265
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1266
                        if (lt.kind() == TypeKind.IntType && rt.kind() == TypeKind.IntType)
1267
                                expression.SetType(lt);
1268
                        else
1269
                                if (lt.kind() == TypeKind.FloatType)
1270
                                        expression.SetType(lt);
1271
                                else
1272
                                {
1273
                                        final IntType anint = (IntType)lt;
1274
                                        expression.SetType(new FloatType(anint.rangeLow(), anint.rangeHigh(),
1275
                                                        FloatType.defaultPrecision(), null));
1276
                                }
1277
                        break;
1278

    
1279
                case idiv:
1280
                case mod:
1281
                        if (rt.kind() != TypeKind.IntType || lt.kind() != TypeKind.IntType)
1282
                                return Error(expression, "Operator expects LHS and RHS to be integer");
1283
                        expression.SetType(Expression.ArithmeticCover(lt, rt, expression.kind()));
1284
                        break;
1285
                case div:
1286
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1287
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1288
                        if (lhs.type() instanceof ValuedEnumType)
1289
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1290
                        if (rhs.type() instanceof ValuedEnumType)
1291
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1292
                        Type cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1293
                        expression.SetType(cover);
1294
                        break;
1295
                case minus:
1296
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1297
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1298
                        if (lhs.type() instanceof ValuedEnumType)
1299
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1300
                        if (rhs.type() instanceof ValuedEnumType)
1301
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1302
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1303
                        expression.SetType(cover);
1304
                        break;
1305
                case prod:
1306
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1307
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1308
                        if (lhs.type() instanceof ValuedEnumType)
1309
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1310
                        if (rhs.type() instanceof ValuedEnumType)
1311
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1312
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1313
                        expression.SetType(cover);
1314
                        break;
1315
                case sum:
1316
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1317
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1318
                        if (lhs.type() instanceof ValuedEnumType)
1319
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1320
                        if (rhs.type() instanceof ValuedEnumType)
1321
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1322
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1323
                        expression.SetType(cover);
1324
                        break;
1325
                case greater:
1326
                case greaterequal:
1327
                case less:
1328
                case lessequal:
1329
                        if (!((rt.IsNumeric() && lt.IsNumeric()) ))
1330
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1331
                        cover = Type.CoverType(lt, rt);
1332
                        if (cover != null)
1333
                        {
1334
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1335
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1336
                                expression.SetType(new BoolType(null));
1337
                        }
1338
                        else
1339
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1340
                        break;
1341
                        /*bool binary*/
1342
                case and:
1343
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1344
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1345

    
1346
                        expression.SetType(rt);
1347
                        // little bit of optimization..
1348
                        if (rhs.kind() == ExpressionKind.Value
1349
                                        && ((ValueExpression<Boolean>)rhs).value() == false)
1350
                                return rhs;
1351
                        else if (lhs.kind() == ExpressionKind.Value
1352
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1353
                                return lhs;
1354

    
1355
                        // if both are true, then this will be taken care of in constant folding.
1356
                        break;
1357
                case biimplies:
1358
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1359
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1360
                        expression.SetType(rt);
1361
                        break;
1362
                case implies:
1363
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1364
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1365
                        expression.SetType(rt);
1366

    
1367
                        // ex falso...
1368
                        if (lhs.kind() == ExpressionKind.Value
1369
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1370
                        {
1371
                                final Expression shortcut = new ValueExpression<Boolean>(true, expression.line(), expression.pos(), Boolean.class);
1372
                                shortcut.SetType(lt);
1373
                                return shortcut;
1374
                        }
1375

    
1376
                        break;
1377
                case or:
1378
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1379
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1380
                        expression.SetType(rt);
1381

    
1382
                        if (rhs.kind() == ExpressionKind.Value
1383
                                        && ((ValueExpression<Boolean>)rhs).value() == true)
1384
                                return rhs;
1385
                        else if (lhs.kind() == ExpressionKind.Value
1386
                                        && ((ValueExpression<Boolean>)lhs).value() == true)
1387
                                return lhs;
1388
                        break;
1389
                        /*other binary*/
1390
                case equal:
1391
                case notequal:
1392
                        cover = Type.CoverType(lt, rt);
1393
                        if (cover != null)
1394
                        {
1395
                                /* see whether we have a tuple-matcher on one side.. */
1396
                                if (expression.kind() == ExpressionKind.equal)
1397
                                {
1398
                                        if (lhs.kind() == ExpressionKind.TupleConstr &&
1399
                                                        ((TupleConstructor)lhs).isMatcher())
1400
                                        {
1401
                                                if (rhs.kind() == ExpressionKind.TupleConstr &&
1402
                                                                ((TupleConstructor)rhs).isMatcher())
1403
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1404
                                                m_matcherList.remove(lhs);
1405
                                        }
1406
                                        else if (rhs.kind() == ExpressionKind.TupleConstr &&
1407
                                                        ((TupleConstructor)rhs).isMatcher())
1408
                                        {
1409
                                                if (lhs.kind() == ExpressionKind.TupleConstr &&
1410
                                                                ((TupleConstructor)lhs).isMatcher())
1411
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1412
                                                m_matcherList.remove(rhs);
1413
                                        }
1414
                                }
1415

    
1416
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1417
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1418
                                expression.SetType(new BoolType(null));
1419
                        }
1420
                        else
1421
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1422
                        break;
1423
                case seqmod_mapoverride:
1424
                        if (rt.kind() != TypeKind.MapType)
1425
                                return Error(expression, "Map expected as RHS on sequence modification or map override.");
1426
                        // list of A * map int to A -> list of A or
1427
                        if (lt.kind() == TypeKind.ListType)
1428
                        {
1429
                                // we're in sequence modification.
1430
                                domlist = (ListType)lt;
1431
                                rngMap = (MapType)rt;
1432
                                if (rngMap.fromType().kind() != TypeKind.IntType)
1433
                                        return Error(expression, "Domain of map has to be integer");
1434
                                if (!Type.TypeEqual(domlist.innerType(), rngMap.toType()))
1435
                                        return Error(expression, "Type of list expected to match range of map");
1436
                                // since we only replace elements in the list (by matching ones from the map),
1437
                                // we're save to return the original list..
1438
                                expression.SetType(lt);
1439
                        }
1440
                        // map A to B * map A to B -> map A to B
1441
                        else if (lt.kind() == TypeKind.MapType)
1442
                        {
1443
                                domMap = (MapType)lt;
1444
                                rngMap = (MapType)rt;
1445
                                if (!Type.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1446
                                                !Type.TypeEqual(domMap.toType(), rngMap.toType()))
1447
                                        return Error(expression, "Maps need same domain and range types");
1448
                                // since we override entries in the first map:
1449
                                expression.SetType(domMap);
1450
                        }
1451
                        else
1452
                                return Error(expression, "Sequence Modification or Map override expects list or map as LHS");
1453
                        break;
1454
                default:
1455
                        throw new NotImplementedException();
1456
                }
1457

    
1458
                // set subtrees.
1459
                expression.SetLeftChild(lhs);
1460
                expression.SetRightChild(rhs);
1461

    
1462
                // we only allow:  a = MyTuple(c,d) style matchers
1463
                if (m_matcherList.size() > 0)
1464
                {
1465
                        m_matcherList.clear();
1466
                        return Error(expression, "Free variables in tuple constructor only allowed in expressions of the form 'atuple = ATupleConstructor(free1,free2...)'");
1467
                }
1468

    
1469
                // try simple constant folding
1470
                return ApplyConstantFolding(expression);
1471
        }
1472

    
1473

    
1474
        ///
1475
        ///  We're also doing a bit of constant folding here.
1476
        ///
1477

    
1478
        @SuppressWarnings("unchecked")
1479
        private Expression ApplyConstantFolding(UnaryOperator expression)
1480
        {
1481
                final Expression child = expression.child();
1482
                if (child.type().IsNumeric() && expression.kind() == ExpressionKind.Cast)
1483
                {
1484
                        switch (expression.type().kind())
1485
                        {
1486
                        case FloatType:
1487
                                if (child.type().kind() == TypeKind.IntType && child.kind() == ExpressionKind.Value)
1488
                                {
1489
                                        final Expression result = new ValueExpression<Double>((double)((ValueExpression<Integer>)child).value(), child.line(), child.pos(), Double.class);
1490
                                        result.SetType(expression.type());
1491
                                        return result;
1492
                                }
1493
                                break;
1494
                        default:
1495
                                break;
1496
                        }
1497
                }
1498
                return expression;
1499
        }
1500

    
1501
        @SuppressWarnings("unchecked")
1502
        private Expression ApplyConstantFolding(BinaryOperator expression)
1503
        {
1504
                Expression lhs = expression.left();
1505
                Expression rhs = expression.right();
1506

    
1507
                if (lhs.kind() == ExpressionKind.Cast)
1508
                {
1509
                        lhs = ApplyConstantFolding((UnaryOperator)lhs);
1510
                        expression.SetLeftChild(lhs);
1511
                }
1512
                if (rhs.kind() == ExpressionKind.Cast)
1513
                {
1514
                        rhs = ApplyConstantFolding((UnaryOperator)rhs);
1515
                        expression.SetRightChild(rhs);
1516
                }
1517

    
1518

    
1519
                if (lhs.kind() == ExpressionKind.Value && rhs.kind() == ExpressionKind.Value)
1520
                        if (expression.type().kind() == TypeKind.FloatType)
1521
                        {
1522
                                final double fval1 = ((ValueExpression<Double>)lhs).value();
1523
                                final double fval2 = ((ValueExpression<Double>)rhs).value();
1524
                                double result = 0;
1525
                                switch (expression.kind())
1526
                                {
1527

    
1528
                                case sum:
1529
                                        result = fval1 + fval2;
1530
                                        break;
1531
                                case minus:
1532
                                        result = fval1 - fval2;
1533
                                        break;
1534
                                case prod:
1535
                                        result = fval1 * fval2;
1536
                                        break;
1537
                                case div:
1538
                                        if (fval2 == 0)
1539
                                                return Error(expression, "Division not defined");
1540
                                        result = fval1 / fval2;
1541
                                        break;
1542
                                default:
1543
                                        // bail out, if we can not handle it
1544
                                        return expression;
1545
                                }
1546
                                if (result < ((FloatType)expression.type()).low()
1547
                                                || result > ((FloatType)expression.type()).high())
1548
                                        return Error(expression, "Internal Error: value after constant folding not in float-range!");
1549

    
1550
                                final ValueExpression<Double> resexp = new ValueExpression<Double>(result, expression.line(), expression.pos(), Double.class);
1551
                                resexp.SetType(expression.type());
1552
                                return resexp;
1553
                        }
1554
                        else if (expression.type().kind() == TypeKind.IntType)
1555
                        {
1556
                                final int val1 = ((ValueExpression<Integer>)lhs).value();
1557
                                final int val2 = ((ValueExpression<Integer>)rhs).value();
1558
                                int result = 0;
1559
                                switch (expression.kind())
1560
                                {
1561
                                case sum:
1562
                                        result = val1 + val2;
1563
                                        break;
1564
                                case minus:
1565
                                        result = val1 - val2;
1566
                                        break;
1567
                                case prod:
1568
                                        result = val1 * val2;
1569
                                        break;
1570
                                case idiv:
1571
                                        if (val2 == 0)
1572
                                                return Error(expression, "Division not defined.");
1573
                                        result = val1 / val2;
1574
                                        break;
1575
                                case mod:
1576
                                        result = val1 % val2;
1577
                                        break;
1578
                                default:
1579
                                        // bail out, if we can not handle it
1580
                                        return expression;
1581
                                }
1582

    
1583
                                if (result < ((IntType)expression.type()).rangeLow()
1584
                                                || result > ((IntType)expression.type()).rangeHigh())
1585
                                        return Error(expression, "Internal Error: value after constant folding not in int-range!");
1586

    
1587
                                final ValueExpression<Integer> intres = new ValueExpression<Integer>(result, expression.line(), expression.pos(), Integer.class);
1588
                                intres.SetType(expression.type());
1589
                                return intres;
1590
                        }
1591
                        else if (expression.type().kind() == TypeKind.BoolType)
1592
                        {
1593
                                boolean result = false;
1594
                                switch (expression.kind())
1595
                                {
1596
                                case greater:
1597
                                        assert(lhs.type().kind() == rhs.type().kind());
1598
                                        switch (lhs.type().kind())
1599
                                        {
1600
                                        case IntType:
1601
                                                result = ((ValueExpression<Integer>)lhs).value() >
1602
                                                        ((ValueExpression<Integer>)rhs).value();
1603
                                                break;
1604
                                        case FloatType:
1605
                                                result = ((ValueExpression<Double>)lhs).value() >
1606
                                                        ((ValueExpression<Double>)rhs).value();
1607
                                                break;
1608
                                        default:
1609
                                                return expression;
1610
                                        }
1611
                                        break;
1612
                                case greaterequal:
1613
                                        assert(lhs.type().kind() == rhs.type().kind());
1614
                                        switch (lhs.type().kind())
1615
                                        {
1616
                                        case IntType:
1617
                                                result = ((ValueExpression<Integer>)lhs).value() >=
1618
                                                        ((ValueExpression<Integer>)rhs).value();
1619
                                                break;
1620
                                        case FloatType:
1621
                                                result = ((ValueExpression<Double>)lhs).value() >=
1622
                                                        ((ValueExpression<Double>)rhs).value();
1623
                                                break;
1624
                                        default:
1625
                                                return expression;
1626
                                        }
1627
                                        break;
1628
                                case less:
1629
                                        assert(lhs.type().kind() == rhs.type().kind());
1630
                                        switch (lhs.type().kind())
1631
                                        {
1632
                                        case IntType:
1633
                                                result = ((ValueExpression<Integer>)lhs).value() <
1634
                                                        ((ValueExpression<Integer>)rhs).value();
1635
                                                break;
1636
                                        case FloatType:
1637
                                                result = ((ValueExpression<Double>)lhs).value() <
1638
                                                        ((ValueExpression<Double>)rhs).value();
1639
                                                break;
1640
                                        default:
1641
                                                return expression;
1642
                                        }
1643
                                        break;
1644
                                case lessequal:
1645
                                        assert(lhs.type().kind() == rhs.type().kind());
1646
                                        switch (lhs.type().kind())
1647
                                        {
1648
                                        case IntType:
1649
                                                result = ((ValueExpression<Integer>)lhs).value() <=
1650
                                                        ((ValueExpression<Integer>)rhs).value();
1651
                                                break;
1652
                                        case FloatType:
1653
                                                result = ((ValueExpression<Double>)lhs).value() <=
1654
                                                        ((ValueExpression<Double>)rhs).value();
1655
                                                break;
1656
                                        default:
1657
                                                return expression;
1658
                                        }
1659
                                        break;
1660
                                case and:
1661
                                        result = ((ValueExpression<Boolean>)lhs).value() && ((ValueExpression<Boolean>)rhs).value();
1662
                                        break;
1663
                                case equal:
1664
                                        // we have to be careful here, since equal takes all sorts of types..
1665
                                        assert(lhs.type().kind() == rhs.type().kind());
1666
                                        switch (lhs.type().kind())
1667
                                        {
1668
                                        case BoolType:
1669
                                                result = ((ValueExpression<Boolean>)lhs).value() ==
1670
                                                        ((ValueExpression<Boolean>)rhs).value();
1671
                                                break;
1672
                                        case IntType:
1673
                                                result = ((ValueExpression<Integer>)lhs).value() ==
1674
                                                        ((ValueExpression<Integer>)rhs).value();
1675
                                                break;
1676
                                        case FloatType:
1677
                                                result = ((ValueExpression<Double>)lhs).value() ==
1678
                                                        ((ValueExpression<Double>)rhs).value();
1679
                                                break;
1680
                                        default:
1681
                                                return expression;
1682
                                        }
1683
                                        break;
1684
                                case biimplies:
1685
                                        result = ((ValueExpression<Boolean>)lhs).value() == ((ValueExpression<Boolean>)rhs).value();
1686
                                        break;
1687
                                case implies:
1688
                                        result = !((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1689
                                        break;
1690
                                case or:
1691
                                        result = ((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1692
                                        break;
1693
                                default:
1694
                                        return expression;
1695
                                }
1696
                                final ValueExpression<Boolean> boolres = new ValueExpression<Boolean>(result, expression.line(), expression.pos(), Boolean.class);
1697
                                boolres.SetType(expression.type());
1698
                                return boolres;
1699
                        }
1700

    
1701
                return expression;
1702
        }
1703

    
1704

    
1705
        ///
1706
        ///  "jump table" (could by avoided by 'dynamic' type as found in c#4)
1707
        ///
1708

    
1709
        @SuppressWarnings("unchecked")
1710
        private Expression ResolveExpression(Expression expression)
1711
        {
1712
                if (expression == null) return null;
1713

    
1714
                Expression result = expression;
1715

    
1716
                switch (expression.kind())
1717
                {
1718
                case Value:
1719
                        final LeafExpression aValue = (LeafExpression)expression;
1720
                        switch (aValue.valueType())
1721
                        {
1722
                        case bool:
1723
                                expression.SetType(new BoolType(null));
1724
                                break;
1725
                        case chr:
1726
                                expression.SetType(new CharType(null));// IntType(0, 255, null));
1727
                                break;
1728
                        case complex:
1729
                        case identifier:
1730
                                assert(false);
1731
                                break;
1732
                        case integer:
1733
                                final int val = ((ValueExpression<Integer>)expression).value();
1734
                                expression.SetType(new IntType(val, val, null));
1735
                                break;
1736
                        case qval:
1737
                                throw new NotImplementedException();
1738
                        case real:
1739
                                final double fval = ((ValueExpression<Double>)expression).value();
1740
                                expression.SetType(new FloatType(fval, fval, fval, null));
1741
                                break;
1742
                        case reference:
1743
                                final Object aref = ((ValueExpression<?>)expression).value();
1744
                                if (aref == null)
1745
                                        expression.SetType(new NullType());
1746
                                else
1747
                                {
1748
                                        assert(false);
1749
                                        return null;
1750
                                }
1751
                                break;
1752
                        case unset:
1753
                                throw new NotImplementedException();
1754
                        default:
1755
                                break;
1756
                        }
1757
                        result = expression;
1758
                        break;
1759

    
1760
                        /* ternary operators */
1761
                case conditional:
1762
                case foldLR:
1763
                case foldRL:
1764
                        result = ResolveExpression((TernaryOperator)expression);
1765
                        break;
1766

    
1767
                        /* forall */
1768
                case forall:
1769
                        result = ResolveExpression((ForallQuantifier)expression);
1770
                        break;
1771

    
1772
                        /* exists */
1773
                case exists:
1774
                        result = ResolveExpression((ExistsQuantifier)expression);
1775
                        break;
1776

    
1777
                        /* constructors */
1778
                case ListConstr:
1779
                        result = ResolveExpression((ListConstructor)expression);
1780
                        break;
1781
                case SetConstr:
1782
                        result = ResolveExpression((SetConstructor)expression);
1783
                        break;
1784
                case MapConstr:
1785
                        result = ResolveExpression((MapConstructor)expression);
1786
                        break;
1787
                case TupleConstr:
1788
                        result = ResolveExpression((TupleConstructor)expression);
1789
                        break;
1790
                case ObjectConstr:
1791
                        result = expression;
1792
                        break;
1793

    
1794
                        /* identifiers */
1795
                case Identifier:
1796
                        result = ResolveExpression((IdentifierExpression)expression);
1797
                        break;
1798
                case UnresolvedIdentifier:
1799
                        result = ResolveExpression((UnresolvedIdentifierExpression)expression);
1800
                        break;
1801

    
1802
                        /* evaluate */
1803
                case TupleMapAccess:
1804
                        result = ResolveExpression((TupleMapAccessExpression)expression);
1805
                        break;
1806
                case Call:
1807
                        result = ResolveExpression((CallExpression)expression);
1808
                        break;
1809

    
1810
                        /* access some element within a class.. */
1811
                case Access:
1812
                        result = ResolveExpression((AccessExpression)expression);
1813
                        break;
1814

    
1815

    
1816
                case Cast:
1817
                        final UnaryOperator cast = (UnaryOperator)expression;
1818

    
1819
                        /*prevent casts of complex datatypes, e.g. lists etc..*/
1820
                        if (cast.type().kind() != TypeKind.OoActionSystemType)
1821
                                return Error(cast, String.format("Cast operator needs class type as argument. (Expected: OoActionSystemType, Found: %s)", cast.type().kind().name()));
1822

    
1823
                        cast.SetChild(ResolveExpression(cast.child()));
1824
                        final Type acover = Type.CoverType(cast.type(), cast.child().type());
1825
                        final boolean upcast = Type.TypeEqual(acover, cast.type());           // the cast is safe; Mostly used in list constructors..
1826
                        final boolean downcast = Type.TypeEqual(acover, cast.child().type()); // downcast, unsafe.
1827
                        if (downcast)
1828
                                Info(cast, String.format("Potentially unsafe downcast: %s as %s (cover: %s)",
1829
                                        cast.child().type().toString(), cast.type().toString(), acover.toString()));
1830
                        if (acover == null || !(upcast || downcast))
1831
                                return Error(cast, String.format("Invalid cast: %s as %s (cover: %s)",
1832
                                        cast.child().type().toString(), cast.type().toString(), acover != null ? acover.toString() : "<none>"));
1833

    
1834
                        result = cast;
1835
                        break;
1836

    
1837
                        /* general unary operators */
1838
                case Primed:
1839
                case unminus:
1840
                case unplus:
1841
                case not:
1842
                case abs:
1843
                case dom:
1844
                case range:
1845
                case merge:
1846
                case card:
1847
                case dconc:
1848
                case dinter:
1849
                case dunion:
1850
                case elems:
1851
                case head:
1852
                case inds:
1853
                case len:
1854
                case tail:
1855
                        result = ResolveExpression((UnaryOperator)expression);
1856
                        break;
1857

    
1858
                        /* general binary operators */
1859
                case domresby:
1860
                case domresto:
1861
                case rngresby:
1862
                case rngresto:
1863
                case munion:
1864
                case conc:
1865
                case diff:
1866
                case inter:
1867
                case elemin:
1868
                case notelemin:
1869
                case subset:
1870
                case union:
1871
                case div:
1872
                case greater:
1873
                case greaterequal:
1874
                case idiv:
1875
                case less:
1876
                case lessequal:
1877
                case minus:
1878
                case mod:
1879
                case pow:
1880
                case prod:
1881
                case sum:
1882
                case and:
1883
                case biimplies:
1884
                case implies:
1885
                case or:
1886
                case equal:
1887
                case notequal:
1888
                case seqmod_mapoverride:
1889
                        result = ResolveExpression((BinaryOperator)expression);
1890
                        break;
1891
                default:
1892
                        throw new NotImplementedException();
1893
                }
1894

    
1895
                return result;
1896
        }
1897

    
1898

    
1899
        public Expression ResolveExpressionNewScope(Expression toResolve)
1900
        {
1901
                Expression result = null;
1902

    
1903
                m_freeVariables.push(new SymbolTable());
1904
                try
1905
                {
1906
                        result = ResolveExpression(toResolve);
1907
                }
1908
                finally
1909
                {
1910
                        if (result != null)
1911
                                result.SetFreeVariables(m_freeVariables.pop());
1912
                }
1913
                return result;
1914
        }
1915

    
1916

    
1917
        ///
1918
        ///  called for every element in the ast
1919
        ///
1920

    
1921
        @Override
1922
        protected void VisitAstElement(IAst subElement, IAst parent)
1923
        {
1924
                if (subElement.nodeType() == AstNodeTypeEnum.expression)
1925
                {
1926
                        // calculate a new (resolved) expression
1927
                        m_freeVariables.push(new SymbolTable());
1928
                        // save toplevel -- used to keep track of method calls.
1929
                        m_entryExpression = (Expression)subElement;
1930

    
1931
                        final Expression newExpression = ResolveExpression(m_entryExpression);
1932
                        // replace the expression in the parent
1933
                        if (newExpression != null)
1934
                        {
1935
                                newExpression.SetFreeVariables(m_freeVariables.pop());
1936
                                ReplaceExpression(parent, (Expression)subElement, newExpression);
1937
                        }
1938

    
1939
                }
1940
                else
1941
                        subElement.Accept(this); // saves us the call to base.VisitAstElement
1942
        }
1943

    
1944

    
1945
        ///
1946
        ///  PUBLIC METHODS
1947
        ///
1948

    
1949
        public OoaResolveExpressionsVisitor(ParserState aState)
1950
        {
1951
                super (aState);
1952
                if (aState == null)
1953
                        throw new ArgumentException();
1954
        }
1955
}