Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / visitors / OoaResolveExpressionsVisitor.java @ 12

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.MetaType;
81
import org.momut.ooas.ast.types.NullType;
82
import org.momut.ooas.ast.types.OoActionSystemType;
83
import org.momut.ooas.ast.types.TupleType;
84
import org.momut.ooas.ast.types.TypeKind;
85
import org.momut.ooas.ast.types.Type;
86
import org.momut.ooas.ast.types.ValuedEnumType;
87
import org.momut.ooas.parser.ParserError;
88
import org.momut.ooas.parser.ParserMessage;
89
import org.momut.ooas.parser.ParserState;
90
import org.momut.ooas.parser.ParserWarning;
91
import org.momut.ooas.parser.SymbolTable;
92
import org.momut.ooas.utils.exceptions.ArgumentException;
93
import org.momut.ooas.utils.exceptions.NotImplementedException;
94

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

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

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

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

    
239
        ///
240
        ///   Resolve Expressions
241
        ///
242

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

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

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

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

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

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

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

    
278

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
390
                        expression.SetComprehension(comprehension);
391

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

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

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

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

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

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

    
432
                                tmpitems.add(element);
433
                        }
434

    
435
                        // now we have the resulting type - we still need to insert casts that might be necessary
436
                        for (final Expression item: tmpitems)
437
                        {
438
                                if (!Type.TypeEqual(item.type(), type))
439
                                {
440
                                        // one exception: lists will not be cast. instead we descend into the inner-most lists and statically update their inner types
441
                                        if(item.kind() == ExpressionKind.ListConstr)
442
                                        {
443
                                                item.Accept(new OoaStaticListCastVisitor((ListType) type));
444
                                                item.SetType(type);
445
                                                newitems.add(item);
446
                                        }
447
                                        else
448
                                        {
449
                                                final Expression cast = new UnaryOperator(ExpressionKind.Cast, item, item.line(), item.pos());
450
                                                cast.SetType(type);
451
                                                newitems.add(cast);
452
                                        }
453
                                }
454
                                else
455
                                        newitems.add(item);
456
                        }
457
                }
458

    
459
                expression.SetElements(newitems);
460
                if (comprehension == null)
461
                        restype = new ListType(type, newitems.size(), null);
462
                else
463
                        restype = new ListType(type, -1, null); // we do not know anything about the bound
464

    
465
                expression.SetType(restype);
466
                return expression;
467
        }
468
        private Expression ResolveExpression(SetConstructor expression)
469
        {
470
                Type type = null;
471
                ListType restype = null;
472
                Expression comprehension = null;
473
                if (expression.comprehension() != null)
474
                {
475
                        comprehension = ResolveExpressionNewScope(expression.comprehension());
476

    
477
                        if (comprehension == null)
478
                                return null;
479

    
480
                        if (comprehension.type() == null)
481
                                return Error(expression, "Set comprehension has void expression");
482

    
483
                        if (comprehension.type().kind() != TypeKind.BoolType)
484
                                return Error(expression, "Set comprehension has to be bool-expression");
485

    
486
                        expression.SetComprehension(comprehension);
487

    
488
                        if (expression.items().size() != 1)
489
                                return Error(expression, "Set comprehension expects one initializer expression");
490
                }
491

    
492
                final ArrayList<Expression> newitems = new ArrayList<Expression>();
493
                for (final Expression item: expression.items())
494
                {
495
                        final Expression element = ResolveExpression(item);
496
                        if (element == null)
497
                                return null;
498

    
499
                        if (element.type() == null)
500
                                return Error(expression, "Void expression in set initializer");
501

    
502
                        if (type == null)
503
                                type = element.type();
504
                        type = Type.CoverType(type, element.type());
505
                        if (type == null)
506
                                return Error(expression, "Set initializer needs matching types");
507

    
508
                        newitems.add(element);
509
                }
510
                expression.SetItems(newitems);
511
                restype = new ListType(type, newitems.size(), null);
512

    
513
                expression.SetType(restype);
514
                return expression;
515
        }
516
        private Expression ResolveExpression(MapConstructor expression)
517
        {
518
                Type domain = null;
519
                Type range = null;
520
                final ArrayList<MapConstructor.MapItem> newitems = new ArrayList<MapConstructor.MapItem>();
521

    
522
                for(final MapItem item: expression.items())
523
                {
524
                        final Expression domexpr = ResolveExpression(item.key);
525
                        if (domexpr == null)
526
                                return null;
527

    
528
                        if (domexpr.type() == null)
529
                                return Error(expression, "Domain initializing expression void");
530

    
531
                        if (domain == null)
532
                                domain = domexpr.type();
533

    
534
                        final Expression rangeexpr = ResolveExpression(item.value);
535
                        if (rangeexpr == null)
536
                                return null;
537

    
538
                        if (rangeexpr.type() == null)
539
                                return Error(expression, "Range initializing expression void");
540

    
541
                        if (range == null)
542
                                range = rangeexpr.type();
543

    
544
                        domain = Type.CoverType(domain, domexpr.type());
545
                        range = Type.CoverType(range, rangeexpr.type());
546
                        if (domain == null)
547
                                return Error(expression, "Types of domain expressions do not match");
548

    
549
                        if (range == null)
550
                                return Error(expression, "Types of range expressions do not match");
551

    
552
                        newitems.add(new MapConstructor.MapItem(domexpr, rangeexpr));
553
                }
554

    
555
                expression.SetItems(newitems);
556
                final MapType resulttype = new MapType(domain, range, newitems.size(), null);
557
                expression.SetType(resulttype);
558
                return expression;
559
        }
560
        private Expression ResolveExpression(TupleConstructor expression)
561
        {
562
                final TupleType typeToConstruct = (TupleType)expression.tupleType().type();
563

    
564
                if (expression.values().size() != typeToConstruct.innerTypes().size())
565
                        return Error(expression, String.format("Tuple constructor has wrong arity. (%s <> %s)",
566
                                typeToConstruct.innerTypes().size(), expression.values().size()));
567

    
568
                //TupleType resulttype = new TupleType(null);
569
                final ArrayList<Expression> newvalexprs = new ArrayList<Expression>();
570

    
571
                final Iterator<Type> innerTargetType = typeToConstruct.innerTypes().iterator();
572
                int freeVarCount = 0;
573
                for (final Expression initexpr: expression.values())
574
                {
575
                        final Type innerTargetTypeValue = innerTargetType.next();
576
                        Expression newval = ResolveExpression(initexpr);
577
                        if (newval == null)
578
                                return null;
579
                        if (newval.type() == null)
580
                                return Error(expression, "Element has void type");
581

    
582
                        if (newval.type().kind() == TypeKind.Any)
583
                        {
584
                                // free var - so set type.
585
                                final AnyType freevar = (AnyType)newval.type();
586
                                freevar.VariableIdentifier().SetType(innerTargetTypeValue);
587
                                freevar.VariableIdentifier().SetInitialized(true);
588
                                freeVarCount++;
589
                        }
590
                        else
591
                        {
592
                                final Type acover = Type.CoverType(innerTargetTypeValue, newval.type());
593
                                if (acover == null || !Type.TypeEqualByKind(innerTargetTypeValue, acover))
594
                                        return Error(expression,
595
                                                String.format("Element in tuple constructor has non-matching type (%s <> %s)",
596
                                                                innerTargetTypeValue.toString(), newval.type().toString()));
597

    
598
                                if (!Type.TypeEqual(acover, newval.type()))
599
                                {
600
                                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line(), newval.pos());
601
                                        newval.SetType(acover);
602
                                }
603
                                if (Type.FirstTypeLessRange(innerTargetTypeValue, acover)) {
604
                                        Warning(expression,
605
                                                String.format("Tuple constructor may over/underflow: %s := %s",
606
                                                                innerTargetTypeValue.toString(), acover.toString()));
607
                                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line(), newval.pos());
608
                                        newval.SetType(innerTargetTypeValue);
609
                                }
610
                        }
611

    
612
                        newvalexprs.add(newval);
613
                        //resulttype.AddType(newval.type);
614
                }
615

    
616
                if (freeVarCount > 0)
617
                {
618
                        if (freeVarCount != expression.values().size())
619
                                return Error(expression, String.format("Tuple constructor must have 0 or #elems (%s) free variables", expression.values().size()));
620
                        else
621
                        {
622
                                expression.SetIsMatcher(true); // mark this tuple constructor as matcher, since this is the only thing it does..
623
                                m_matcherList.add(expression); // matcher has to be bound by one equality
624
                        }
625
                }
626

    
627
                expression.SetTupleValues(newvalexprs);
628
                //expression.SetType(resulttype);
629
                expression.SetType(typeToConstruct); // the constructor always will create the correct type!
630
                return expression;
631
        }
632

    
633
        private Expression ResolveExpression(IdentifierExpression expression)
634
        {
635
                // nothing to do here, since we do not have any consts that may be
636
                // folded
637
                if ((expression.identifier().kind() == IdentifierKind.MethodIdentifier
638
                       || expression.identifier().kind() == IdentifierKind.NamedActionIdentifier)
639
                    && !m_entryExpression.callTargets().contains(expression.identifier()))
640
                {
641
                        m_entryExpression.callTargets().add((FunctionIdentifier)expression.identifier());
642
                }
643

    
644
                return expression;
645
        }
646
        private Expression ResolveExpression(UnresolvedIdentifierExpression expression)
647
        {
648
                Identifier anid;
649
                //Identifier self = m_ParserState.Lookup("self");
650

    
651
                if (m_freeVariables.peek().Defined(expression.tokenText()))
652
                        anid = m_freeVariables.peek().Get(expression.tokenText());
653
                else
654
                        anid = m_ParserState.Lookup(expression.tokenText(), expression.scope());
655

    
656
                if (anid != null)
657
                {
658
                        switch (anid.kind())
659
                        {
660
                        case TypeIdentifier:
661
                                // only return a TypeExpression if this TypeIdentifier didn't come from a "self"
662
                                if (anid instanceof SelfTypeIdentifier) {
663
                                        final IdentifierExpression result = new IdentifierExpression(anid, expression.line(), expression.pos());
664
                                        result.setIsSelf(true);
665
                                        return result;
666
                                } else
667
                                        return new TypeExpression(anid.type(), expression.line(), expression.pos());
668

    
669
                        case MethodIdentifier:
670
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
671
                                final SelfTypeIdentifier selfid = (SelfTypeIdentifier)m_ParserState.Lookup("self", expression.scope());
672
                                if ((selfid != null) && ((OoActionSystemType)(selfid).type()).symbols().Defined(anid))
673
                                {
674
                                        // if it's a self access, add a self identifier (needed by cadp backend, e.g.)
675
                                        // self.<method> is handled in a separate method and does not call us here!! (hence this code is working)
676
                                        final IdentifierExpression aself = new IdentifierExpression(selfid, expression.line(), expression.pos());
677
                                        aself.setIsSelf(true);
678
                                        final AccessExpression localaccess = new AccessExpression(aself, new IdentifierExpression(anid, expression.line(), expression.pos()),
679
                                                        expression.line(), expression.pos());
680
                                        ResolveExpression(localaccess);
681
                                        return localaccess;
682
                                }
683
                                else
684
                                {
685
                                        return new IdentifierExpression(anid, expression.line(), expression.pos());
686
                                }
687

    
688
                        case NamedActionIdentifier:
689
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
690
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
691

    
692
                        case Constant:
693
                                if (((ConstantIdentifier)anid).Value() != null)
694
                                        return ((ConstantIdentifier)anid).Value().Clone();
695
                                else
696
                                        return null;
697

    
698
                        default:
699
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
700
                        }
701
                }
702
                else
703
                {
704
                        final ExpressionVariableIdentifier freeVar =
705
                                        new ExpressionVariableIdentifier(expression.tokenText(), expression.line(), expression.pos());
706
                        freeVar.SetType(new AnyType(freeVar));
707
                        m_freeVariables.peek().AddIdentifier(freeVar);
708

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

    
712
                        return new IdentifierExpression(freeVar, expression.line(), expression.pos());
713
                }
714
        }
715
        private Expression ResolveExpression(TupleMapAccessExpression expression)
716
        {
717
                final Expression child = ResolveExpression(expression.child());
718
                if (child == null)
719
                        return null;
720

    
721
                final Expression arg = ResolveExpression(expression.argument());
722
                if (arg == null)
723
                        return null;
724

    
725

    
726
                assert(child.type() != null);
727

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

    
783
                assert(child.type() != null);
784

    
785
                expression.SetChild(child);
786

    
787
                if (child.type().kind() != TypeKind.FunctionType)
788
                {
789
                        return Error(expression, "No function to call!");
790
                }
791

    
792

    
793
                final FunctionType funtype = (FunctionType)child.type();
794

    
795
//                // check whether call of named action is allowed
796
//                if (funtype.functionType() != FunctionTypeEnum.Method)
797
//                {
798
//                        // see if call is allowed: must not be called from within a named action
799
//                        IScope callingScope = expression.scope();
800
//                        while (callingScope != null)
801
//                        {
802
//                                if (callingScope instanceof NamedActionIdentifier || callingScope instanceof MethodIdentifier)
803
//                                        return Error(expression, "Call of named Action only allowed in do-od block!");
804
//                                callingScope = callingScope.GetParentScope();
805
//                        }
806
//                }
807

    
808
                // check arguments
809
                final int argsSpec = funtype.parameter().size();
810
                final int argsHave = expression.arguments().size();
811
                if (argsHave < argsSpec && !allowFewerParameters)
812
                {
813
                        return Error(expression, "Too few parameters in function call");
814
                }
815
                if (argsHave > argsSpec)
816
                {
817
                        return Error(expression, "Too much parameters in function call");
818
                }
819

    
820
                final ArrayList<Expression> newargs = new ArrayList<Expression>();
821
                final Iterator<Type> demandedArgType = funtype.parameter().iterator();
822
                for (final Expression arg: expression.arguments())
823
                {
824
                        final Type demandedArgTypeValue = demandedArgType.next();
825
                        Expression newarg = ResolveExpression(arg);
826
                        if (newarg == null)
827
                                return null;
828

    
829
                        if (newarg.GetUninitializedFreeVariables().size() > 0)
830
                                Error(arg, String.format("Undefined variable '%s'",
831
                                        newarg.GetUninitializedFreeVariables().get(0).tokenText()));
832

    
833
                        final Expression constantvalue = newarg.kind() == ExpressionKind.Value ? newarg : null;
834

    
835
                        final Type acover = Type.CoverType(newarg.type(), demandedArgTypeValue);
836
                        if (acover == null || !Type.TypeEqualByKind(demandedArgTypeValue, acover))
837
                                return Error(arg, String.format("Argument type does not match; expected: %s delivered: %s",
838
                                                demandedArgTypeValue.toString(), newarg.type().toString()));
839

    
840
                        newarg = UnaryOperator.TryCoerceUp(newarg, acover);
841

    
842
                        if (Type.FirstTypeLessRange(demandedArgTypeValue, acover))
843
                        {
844
                                if (constantvalue == null)
845
                                {
846
                                        Warning(arg, String.format("Call parameter may over/underflow: %s := %s",
847
                                                        demandedArgTypeValue.toString(), acover.toString()));
848
                                        final UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, newarg, newarg.line(), newarg.pos());
849
                                        cast.SetType(demandedArgTypeValue);
850
                                        newarg = cast;
851
                                }
852
                                else
853
                                {
854
                                        Error(arg, String.format("Call parameter out of range (%s  := %s)",
855
                                                        demandedArgTypeValue.toString(), constantvalue.toString()));
856
                                }
857
                        }
858

    
859
                        newargs.add(newarg);
860
                }
861
                expression.SetArguments(newargs);
862

    
863
                if (funtype.returnType() != null)
864
                        expression.SetType(funtype.returnType());
865
                return expression;
866
        }
867
        private Expression ResolveExpression(AccessExpression expression)
868
        {
869
                Expression lhs = ResolveExpression(expression.left());
870
                if (lhs == null)
871
                        return null;
872
                if (!(expression.right() instanceof UnresolvedIdentifierExpression))
873
                {
874
                        expression.SetRightChild(ResolveExpression(expression.right()));
875
                        expression.SetType(expression.right().type());
876
                        return expression;
877
                }
878

    
879
                final boolean selfAccess = (lhs.kind() == ExpressionKind.Identifier) && ((IdentifierExpression)lhs).isSelf();
880
                final boolean staticAccess = lhs.kind() == ExpressionKind.Type;
881
                final UnresolvedIdentifierExpression access = (UnresolvedIdentifierExpression)expression.right();
882
                // atype could be null...
883
                Type atype = lhs.type();
884
                if ((lhs.kind() == ExpressionKind.Call) && (atype == null))
885
                {
886
                        return Error(access, "Can not access return type of void-function");
887
                }
888
                else if (atype == null)
889
                {
890
                        return Error(access, "Can not access member of a void type");
891
                }
892

    
893
                // if we did not apply a call expression to a function
894
                if (atype.kind() == TypeKind.FunctionType)
895
                {
896
                        // we can access the return val...
897
                        final FunctionType fun = (FunctionType)atype;
898

    
899
                        // check arity
900
                        if (fun.parameter().size() > 0)
901
                                return Error(access, "Implicit function call not possible: Too few parameters.");
902

    
903
                        // check return type
904
                        if (fun.returnType() == null)
905
                                return Error(access, "Can not access return type of void-function!");
906

    
907
                        // call ok
908
                        atype = fun.returnType();
909
                        // but add callExpression
910
                        lhs = new CallExpression(lhs, null, lhs.line(), lhs.pos(), null); // we do not know the scope
911
                        lhs.SetType(atype);
912
                }
913

    
914
                // update left child
915
                expression.SetLeftChild(lhs);
916

    
917

    
918
                if (staticAccess) {
919
                        if (atype.kind() != TypeKind.MetaType)
920
                                return Error(access, "Expected meta type.");
921
                        atype = ((MetaType)atype).Type();
922
                }
923

    
924

    
925
                switch (atype.kind())
926
                {
927
                case OoActionSystemType:
928
                        final Identifier anid = ((OoActionSystemType)atype).ResolveIdentifier(access.tokenText());
929
                        if (anid != null)
930
                        {
931
                                if (anid.kind() == IdentifierKind.MethodIdentifier && !m_entryExpression.callTargets().contains(anid))
932
                                        m_entryExpression.callTargets().add((FunctionIdentifier)anid);
933

    
934
                                if (staticAccess)
935
                                {
936
                                        if ((anid.kind() == IdentifierKind.AttributeIdentifier) &&
937
                                                        (((AttributeIdentifier)anid).isStatic()))
938
                                        {
939
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
940
                                                expression.SetRightChild(newrhs);
941
                                        }
942
                                        else
943
                                                return Error(access, "Can not access non-static member of an action system");
944
                                }
945
                                else
946
                                {
947
                                        if (anid.kind() != IdentifierKind.MethodIdentifier && !selfAccess)
948
                                                return Error(access, "Can only access methods of action system objects");
949
                                        else
950
                                        {
951
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
952
                                                expression.SetRightChild(newrhs);
953
                                        }
954
                                }
955
                        }
956
                        else
957
                                return Error(access, String.format("%s no member of %s",
958
                                                access.tokenText(), ((OoActionSystemType)atype).identifier().tokenText()));
959
                        break;
960
                case EnumeratedType:
961
                        final EnumType anEnum = (EnumType)atype;
962
                        if (!staticAccess)
963
                        {
964
                                return Error(access, "Enum values can only be accessed statically.");
965
                        }
966
                        if (anEnum.symbolTable().Defined(access.tokenText()))
967
                        {
968
                                final Identifier enumid = anEnum.symbolTable().Get(access.tokenText());
969
                                final IdentifierExpression newrhs = new IdentifierExpression(enumid, access.line(), access.pos());
970
                                expression.SetRightChild(newrhs);
971
                        }
972
                        else
973
                                return Error(access, String.format("%s not contained in enum %s",
974
                                                access.tokenText(), anEnum.identifier().tokenText()));
975
                        break;
976
                default:
977
                        /*error, we can not access an element with '.' in any other type*/
978
                        return Error(expression, "Expected: System, Enum, or Function");
979
                }
980

    
981
                expression.SetType(expression.right().type());
982
                return expression;
983
        }
984
        private Expression ResolveExpression(UnaryOperator expression)
985
        {
986
                final Expression child = ResolveExpression(expression.child());
987
                // if there was some error, then exit
988
                if (child == null)
989
                        return null;
990

    
991
                if (child.type() == null)
992
                        return Error(expression, "Can not apply unary operator to void-expression");
993

    
994

    
995
                switch (expression.kind())
996
                {
997
                case Primed:
998
                        expression.SetType(child.type());
999
                        break;
1000

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

    
1136
                expression.SetChild(child);
1137
                return expression;
1138
        }
1139
        @SuppressWarnings("unchecked")
1140
        private Expression ResolveExpression(BinaryOperator expression)
1141
        {
1142
                Expression lhs = ResolveExpression(expression.left());
1143
                Expression rhs = ResolveExpression(expression.right());
1144

    
1145

    
1146
                // if there was some error, then exit
1147
                if ((lhs == null) || (rhs == null))
1148
                        return null;
1149

    
1150
                final Type lt = lhs.type();
1151
                final Type rt = rhs.type();
1152

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

    
1156

    
1157
                switch (expression.kind())
1158
                {
1159
                /*map operators*/
1160
                case domresby:   // list of A * map A to B -> map A to B
1161
                case domresto:   // list of A * map A to B -> map A to B
1162
                        if (lt.kind() != TypeKind.ListType)
1163
                                return Error(expression, "Domain restriction operator expects list on LHS");
1164
                        if (rt.kind() != TypeKind.MapType)
1165
                                return Error(expression, "Domain restriction operator expects map on RHS");
1166
                        ListType domlist = (ListType)lt;
1167
                        MapType domMap = (MapType)rt;
1168
                        if (!Type.TypeEqual(domlist.innerType(), domMap.fromType()))
1169
                                return Error(expression, "Inner type of list and domain-type of map do not match");
1170
                        // since this is a restriction, maxnumofelems is ok
1171
                        expression.SetType(domMap);
1172
                        break;
1173
                case rngresby:   // map A to B * list of B -> map A to B
1174
                case rngresto:   // map A to B * list of B -> map A to B
1175
                        if (lt.kind() != TypeKind.MapType)
1176
                                return Error(expression, "Range restriction operator expects map on LHS");
1177
                        if (rt.kind() != TypeKind.ListType)
1178
                                return Error(expression, "Range restriction operator expects list on RHS");
1179
                        final ListType rangelist = (ListType)rt;
1180
                        domMap = (MapType)lt;
1181
                        if (!Type.TypeEqual(rangelist.innerType(), domMap.fromType()))
1182
                                return Error(expression, "Inner type of list and rangle-type of map do not match");
1183
                        // since this is a restriction, maxnumofelems is ok
1184
                        expression.SetType(domMap);
1185
                        break;
1186
                case munion:     // map A to B * map A to B -> map A to B
1187
                        if (lt.kind() != TypeKind.MapType ||
1188
                        rt.kind() != TypeKind.MapType)
1189
                                return Error(expression, "Map union expects maps on LHS and RHS");
1190
                        domMap = (MapType)lt;
1191
                        MapType rngMap = (MapType)rt;
1192
                        if (!Type.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1193
                                        !Type.TypeEqual(domMap.toType(), rngMap.toType()))
1194
                                return Error(expression, "Domain and Range types of maps must be equal");
1195
                        // union may change maximum number of elements..
1196
                        final MapType resMap = new MapType(domMap.fromType(), domMap.toType(),
1197
                                        domMap.maxNumberOfElements() + rngMap.maxNumberOfElements(), null);
1198
                        expression.SetType(resMap);
1199
                        break;
1200
                        /*set/list binary*/
1201
                case conc:       // list of A * list of A -> list of A
1202
                        if (lt.kind() != TypeKind.ListType ||
1203
                        rt.kind() != TypeKind.ListType)
1204
                                return Error(expression, "List concatenation expects two lists.");
1205
                        ListType la = (ListType)lt;
1206
                        ListType lb = (ListType)rt;
1207

    
1208
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1209
                                return lhs;
1210
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1211
                                return rhs;
1212

    
1213
                        if (!Type.TypeEqual(la.innerType(), lb.innerType())) {
1214
                                final ListType coverType = (ListType) Type.CoverType(la, lb);
1215
                                if(coverType == null)
1216
                                        return Error(expression, String.format("Set/List concatenation expects two lists of same type. (%s <> %s)", la.toString(), lb.toString())); // FIXME adjust error message
1217

    
1218
                                if(!Type.TypeEqual(la, coverType))
1219
                                        lhs.Accept(new OoaStaticListCastVisitor(coverType));
1220
                                if(!Type.TypeEqual(lb, coverType))
1221
                                        rhs.Accept(new OoaStaticListCastVisitor(coverType));
1222

    
1223
                                expression.SetType(new ListType(coverType.innerType(), la.maxNumberOfElements() + lb.maxNumberOfElements(), null));
1224
                        } else
1225
                                expression.SetType(new ListType(la.innerType(), la.maxNumberOfElements() + lb.maxNumberOfElements(), null));
1226

    
1227
                        break;
1228
                case diff:       // list of A * list of A -> list of A (does not respect dupes)
1229
                        if (lt.kind() != TypeKind.ListType || rt.kind() != TypeKind.ListType)
1230
                                return Error(expression, "Set difference expects two lists.");
1231
                        la = (ListType)lt;
1232
                        lb = (ListType)rt;
1233
                        if (!Type.TypeEqual(la.innerType(), lb.innerType())) {
1234
                                final ListType coverType = (ListType) Type.CoverType(la, lb);
1235
                                if(coverType == null)
1236
                                        return Error(expression, "Set difference expects two lists of same type."); // FIXME adjust error message
1237

    
1238
                                if(!Type.TypeEqual(la, coverType))
1239
                                        lhs.Accept(new OoaStaticListCastVisitor(coverType));
1240
                                if(!Type.TypeEqual(lb, coverType))
1241
                                        rhs.Accept(new OoaStaticListCastVisitor(coverType));
1242

    
1243
                                expression.SetType(coverType);
1244
                        } else
1245
                                expression.SetType(la);
1246
                        break;
1247
                case inter:      // list of A * list of A -> list of A (does not respect dupes)
1248
                        if (lt.kind() != TypeKind.ListType ||
1249
                        rt.kind() != TypeKind.ListType)
1250
                                return Error(expression, "Set intersection expects two lists.");
1251
                        la = (ListType)lt;
1252
                        lb = (ListType)rt;
1253
                        if (!Type.TypeEqual(la.innerType(), lb.innerType())) {
1254
                                final ListType coverType = (ListType) Type.CoverType(la, lb);
1255
                                if(coverType == null)
1256
                                        return Error(expression, "Set intersection expects two lists of same type.");
1257
                                if(!Type.TypeEqual(la, coverType))
1258
                                        lhs.Accept(new OoaStaticListCastVisitor(coverType));
1259
                                if(!Type.TypeEqual(lb, coverType))
1260
                                        rhs.Accept(new OoaStaticListCastVisitor(coverType));
1261
                                expression.SetType(coverType);
1262
                        } else
1263
                                expression.SetType(la.maxNumberOfElements() > lb.maxNumberOfElements() ? la : lb);
1264
                        break;
1265
                case elemin:     // A * list of A -> bool
1266
                case notelemin:  // A * list of A -> bool
1267
                        if (rt.kind() != TypeKind.ListType)
1268
                                return Error(expression, "Element (not) in operator expects list-type as RHS.");
1269
                        lb = (ListType)rt;
1270
                        if (lhs.kind() == ExpressionKind.Value)
1271
                                lhs = UnaryOperator.TryCoerceUp(lhs, lb.innerType());
1272
                        final Type leftType = lhs.type();
1273
                        if (!Type.TypeEqual(leftType, lb.innerType()))
1274
                                return Error(expression, String.format("List and element must be of same type: %s in %s",
1275
                                                lt == null ? "<null>" : lt.toString(), lb ==null || lb.innerType() == null ? "<null>" : lb.innerType().toString()));
1276
                        expression.SetType(new BoolType(null));
1277
                        break;
1278
                case subset:     // list of A * list of A -> bool (does not respect dupes)
1279
                        if (lt.kind() != TypeKind.ListType || rt.kind() != TypeKind.ListType)
1280
                                return Error(expression, "Subset operation expects two lists.");
1281
                        la = (ListType)lt;
1282
                        lb = (ListType)rt;
1283
                        if (!Type.TypeEqual(la.innerType(), lb.innerType())) {
1284
                                final ListType coverType = (ListType) Type.CoverType(la, lb);
1285
                                if(coverType == null)
1286
                                        return Error(expression, "Subset operation expects two lists of same type.");
1287

    
1288
                                if(!Type.TypeEqual(la, coverType))
1289
                                        lhs.Accept(new OoaStaticListCastVisitor(coverType));
1290
                                if(!Type.TypeEqual(lb, coverType))
1291
                                        rhs.Accept(new OoaStaticListCastVisitor(coverType));
1292
                        }
1293
                        expression.SetType(new BoolType(null));
1294
                        break;
1295
                case union:      // list of A * list of A -> list of A (does not respect dupes)
1296
                        if (lt.kind() != TypeKind.ListType ||
1297
                        rt.kind() != TypeKind.ListType)
1298
                                return Error(expression, "Set union expects two lists.");
1299
                        la = (ListType)lt;
1300
                        lb = (ListType)rt;
1301

    
1302
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1303
                                return rhs;
1304
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1305
                                return lhs;
1306

    
1307
                        if (!Type.TypeEqual(la.innerType(), lb.innerType())) {
1308
                                final ListType coverType = (ListType) Type.CoverType(la, lb);
1309
                                if(coverType == null)
1310
                                        return Error(expression, "Set union expects two lists of same type.");
1311
                                if(!Type.TypeEqual(la, coverType))
1312
                                        lhs.Accept(new OoaStaticListCastVisitor(coverType));
1313
                                if(!Type.TypeEqual(lb, coverType))
1314
                                        rhs.Accept(new OoaStaticListCastVisitor(coverType));
1315

    
1316
                                expression.SetType(new ListType(coverType.innerType(), la.maxNumberOfElements() + lb.maxNumberOfElements(), null));
1317
                        } else
1318
                                expression.SetType(new ListType(la.innerType(), la.maxNumberOfElements() + lb.maxNumberOfElements(), null));
1319
                        break;
1320

    
1321
                        /*numeric binary*/
1322
                case pow:
1323
                        if (!lt.IsNumeric() || !rt.IsNumeric())
1324
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1325
                        if (lt.kind() == TypeKind.IntType && rt.kind() == TypeKind.IntType)
1326
                                expression.SetType(lt);
1327
                        else
1328
                                if (lt.kind() == TypeKind.FloatType)
1329
                                        expression.SetType(lt);
1330
                                else
1331
                                {
1332
                                        final IntType anint = (IntType)lt;
1333
                                        expression.SetType(new FloatType(anint.rangeLow(), anint.rangeHigh(),
1334
                                                        FloatType.defaultPrecision(), null));
1335
                                }
1336
                        break;
1337

    
1338
                case idiv:
1339
                case mod:
1340
                        if (rt.kind() != TypeKind.IntType || lt.kind() != TypeKind.IntType)
1341
                                return Error(expression, "Operator expects LHS and RHS to be integer");
1342
                        expression.SetType(Expression.ArithmeticCover(lt, rt, expression.kind()));
1343
                        break;
1344
                case div:
1345
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1346
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1347
                        if (lhs.type() instanceof ValuedEnumType)
1348
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1349
                        if (rhs.type() instanceof ValuedEnumType)
1350
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1351
                        Type cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1352
                        expression.SetType(cover);
1353
                        break;
1354
                case minus:
1355
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1356
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1357
                        if (lhs.type() instanceof ValuedEnumType)
1358
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1359
                        if (rhs.type() instanceof ValuedEnumType)
1360
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1361
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1362
                        expression.SetType(cover);
1363
                        break;
1364
                case prod:
1365
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1366
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1367
                        if (lhs.type() instanceof ValuedEnumType)
1368
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1369
                        if (rhs.type() instanceof ValuedEnumType)
1370
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1371
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1372
                        expression.SetType(cover);
1373
                        break;
1374
                case sum:
1375
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1376
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1377
                        if (lhs.type() instanceof ValuedEnumType)
1378
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1379
                        if (rhs.type() instanceof ValuedEnumType)
1380
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1381
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1382
                        expression.SetType(cover);
1383
                        break;
1384
                case greater:
1385
                case greaterequal:
1386
                case less:
1387
                case lessequal:
1388
                        if (!((rt.IsNumeric() && lt.IsNumeric()) ))
1389
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1390
                        cover = Type.CoverType(lt, rt);
1391
                        if (cover != null)
1392
                        {
1393
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1394
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1395
                                expression.SetType(new BoolType(null));
1396
                        }
1397
                        else
1398
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1399
                        break;
1400
                        /*bool binary*/
1401
                case and:
1402
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1403
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1404

    
1405
                        expression.SetType(rt);
1406
                        // little bit of optimization..
1407
                        if (rhs.kind() == ExpressionKind.Value
1408
                                        && ((ValueExpression<Boolean>)rhs).value() == false)
1409
                                return rhs;
1410
                        else if (lhs.kind() == ExpressionKind.Value
1411
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1412
                                return lhs;
1413

    
1414
                        // if both are true, then this will be taken care of in constant folding.
1415
                        break;
1416
                case biimplies:
1417
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1418
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1419
                        expression.SetType(rt);
1420
                        break;
1421
                case implies:
1422
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1423
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1424
                        expression.SetType(rt);
1425

    
1426
                        // ex falso...
1427
                        if (lhs.kind() == ExpressionKind.Value
1428
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1429
                        {
1430
                                final Expression shortcut = new ValueExpression<Boolean>(true, expression.line(), expression.pos(), Boolean.class);
1431
                                shortcut.SetType(lt);
1432
                                return shortcut;
1433
                        }
1434

    
1435
                        break;
1436
                case or:
1437
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1438
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1439
                        expression.SetType(rt);
1440

    
1441
                        if (rhs.kind() == ExpressionKind.Value
1442
                                        && ((ValueExpression<Boolean>)rhs).value() == true)
1443
                                return rhs;
1444
                        else if (lhs.kind() == ExpressionKind.Value
1445
                                        && ((ValueExpression<Boolean>)lhs).value() == true)
1446
                                return lhs;
1447
                        break;
1448
                        /*other binary*/
1449
                case equal:
1450
                case notequal:
1451
                        cover = Type.CoverType(lt, rt);
1452
                        if (cover != null)
1453
                        {
1454
                                /* see whether we have a tuple-matcher on one side.. */
1455
                                if (expression.kind() == ExpressionKind.equal)
1456
                                {
1457
                                        if (lhs.kind() == ExpressionKind.TupleConstr &&
1458
                                                        ((TupleConstructor)lhs).isMatcher())
1459
                                        {
1460
                                                if (rhs.kind() == ExpressionKind.TupleConstr &&
1461
                                                                ((TupleConstructor)rhs).isMatcher())
1462
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1463
                                                m_matcherList.remove(lhs);
1464
                                        }
1465
                                        else if (rhs.kind() == ExpressionKind.TupleConstr &&
1466
                                                        ((TupleConstructor)rhs).isMatcher())
1467
                                        {
1468
                                                if (lhs.kind() == ExpressionKind.TupleConstr &&
1469
                                                                ((TupleConstructor)lhs).isMatcher())
1470
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1471
                                                m_matcherList.remove(rhs);
1472
                                        }
1473

    
1474
                                        /* This adds support for "equality-style assignments" in expressions. Not yet supported by the backend though :(
1475
                                        if (lhs.type().kind() == TypeKind.Any || rhs.type().kind() == TypeKind.Any)
1476
                                        {
1477
                                                if (lhs.type().kind() == TypeKind.Any && rhs.type().kind() == TypeKind.Any)
1478
                                                        return Error(expression, "Free variables on both sides of equality sign.");
1479
                                                // free var - so set type and mark initialized
1480
                                                final AnyType freevar =  lhs.type().kind() == TypeKind.Any ? (AnyType)lhs.type() : (AnyType)rhs.type();
1481
                                                freevar.VariableIdentifier().SetType(cover);
1482
                                                freevar.VariableIdentifier().SetInitialized(true);
1483
                                                lhs.SetType(cover);
1484
                                        }
1485
                                        */
1486
                                }
1487

    
1488
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1489
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1490
                                expression.SetType(new BoolType(null));
1491
                        }
1492
                        else
1493
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1494
                        break;
1495
                case seqmod_mapoverride:
1496
                        if (rt.kind() != TypeKind.MapType)
1497
                                return Error(expression, "Map expected as RHS on sequence modification or map override.");
1498
                        // list of A * map int to A -> list of A or
1499
                        if (lt.kind() == TypeKind.ListType)
1500
                        {
1501
                                // we're in sequence modification.
1502
                                domlist = (ListType)lt;
1503
                                rngMap = (MapType)rt;
1504
                                if (rngMap.fromType().kind() != TypeKind.IntType)
1505
                                        return Error(expression, "Domain of map has to be integer");
1506
                                if (!Type.TypeEqual(domlist.innerType(), rngMap.toType()))
1507
                                        return Error(expression, "Type of list expected to match range of map");
1508
                                // since we only replace elements in the list (by matching ones from the map),
1509
                                // we're save to return the original list..
1510
                                expression.SetType(lt);
1511
                        }
1512
                        // map A to B * map A to B -> map A to B
1513
                        else if (lt.kind() == TypeKind.MapType)
1514
                        {
1515
                                domMap = (MapType)lt;
1516
                                rngMap = (MapType)rt;
1517
                                if (!Type.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1518
                                                !Type.TypeEqual(domMap.toType(), rngMap.toType()))
1519
                                        return Error(expression, "Maps need same domain and range types");
1520
                                // since we override entries in the first map:
1521
                                expression.SetType(domMap);
1522
                        }
1523
                        else
1524
                                return Error(expression, "Sequence Modification or Map override expects list or map as LHS");
1525
                        break;
1526
                default:
1527
                        throw new NotImplementedException();
1528
                }
1529

    
1530
                // set subtrees.
1531
                expression.SetLeftChild(lhs);
1532
                expression.SetRightChild(rhs);
1533

    
1534
                // we only allow:  a = MyTuple(c,d) style matchers
1535
                if (m_matcherList.size() > 0)
1536
                {
1537
                        m_matcherList.clear();
1538
                        return Error(expression, "Free variables in tuple constructor only allowed in expressions of the form 'atuple = ATupleConstructor(free1,free2...)'");
1539
                }
1540

    
1541
                // try simple constant folding
1542
                return ApplyConstantFolding(expression);
1543
        }
1544

    
1545

    
1546
        ///
1547
        ///  We're also doing a bit of constant folding here.
1548
        ///
1549

    
1550
        @SuppressWarnings("unchecked")
1551
        private Expression ApplyConstantFolding(UnaryOperator expression)
1552
        {
1553
                final Expression child = expression.child();
1554
                if (child.type().IsNumeric() && expression.kind() == ExpressionKind.Cast)
1555
                {
1556
                        switch (expression.type().kind())
1557
                        {
1558
                        case FloatType:
1559
                                if (child.type().kind() == TypeKind.IntType && child.kind() == ExpressionKind.Value)
1560
                                {
1561
                                        final Expression result = new ValueExpression<Double>((double)((ValueExpression<Integer>)child).value(), child.line(), child.pos(), Double.class);
1562
                                        result.SetType(expression.type());
1563
                                        return result;
1564
                                }
1565
                                break;
1566
                        default:
1567
                                break;
1568
                        }
1569
                }
1570
                return expression;
1571
        }
1572

    
1573
        @SuppressWarnings("unchecked")
1574
        private Expression ApplyConstantFolding(BinaryOperator expression)
1575
        {
1576
                Expression lhs = expression.left();
1577
                Expression rhs = expression.right();
1578

    
1579
                if (lhs.kind() == ExpressionKind.Cast)
1580
                {
1581
                        lhs = ApplyConstantFolding((UnaryOperator)lhs);
1582
                        expression.SetLeftChild(lhs);
1583
                }
1584
                if (rhs.kind() == ExpressionKind.Cast)
1585
                {
1586
                        rhs = ApplyConstantFolding((UnaryOperator)rhs);
1587
                        expression.SetRightChild(rhs);
1588
                }
1589

    
1590

    
1591
                if (lhs.kind() == ExpressionKind.Value && rhs.kind() == ExpressionKind.Value)
1592
                        if (expression.type().kind() == TypeKind.FloatType)
1593
                        {
1594
                                final double fval1 = ((ValueExpression<Double>)lhs).value();
1595
                                final double fval2 = ((ValueExpression<Double>)rhs).value();
1596
                                double result = 0;
1597
                                switch (expression.kind())
1598
                                {
1599

    
1600
                                case sum:
1601
                                        result = fval1 + fval2;
1602
                                        break;
1603
                                case minus:
1604
                                        result = fval1 - fval2;
1605
                                        break;
1606
                                case prod:
1607
                                        result = fval1 * fval2;
1608
                                        break;
1609
                                case div:
1610
                                        if (fval2 == 0)
1611
                                                return Error(expression, "Division not defined");
1612
                                        result = fval1 / fval2;
1613
                                        break;
1614
                                default:
1615
                                        // bail out, if we can not handle it
1616
                                        return expression;
1617
                                }
1618
                                if (result < ((FloatType)expression.type()).low()
1619
                                                || result > ((FloatType)expression.type()).high())
1620
                                        return Error(expression, "Internal Error: value after constant folding not in float-range!");
1621

    
1622
                                final ValueExpression<Double> resexp = new ValueExpression<Double>(result, expression.line(), expression.pos(), Double.class);
1623
                                resexp.SetType(expression.type());
1624
                                return resexp;
1625
                        }
1626
                        else if (expression.type().kind() == TypeKind.IntType)
1627
                        {
1628
                                final int val1 = ((ValueExpression<Integer>)lhs).value();
1629
                                final int val2 = ((ValueExpression<Integer>)rhs).value();
1630
                                int result = 0;
1631
                                switch (expression.kind())
1632
                                {
1633
                                case sum:
1634
                                        result = val1 + val2;
1635
                                        break;
1636
                                case minus:
1637
                                        result = val1 - val2;
1638
                                        break;
1639
                                case prod:
1640
                                        result = val1 * val2;
1641
                                        break;
1642
                                case idiv:
1643
                                        if (val2 == 0)
1644
                                                return Error(expression, "Division not defined.");
1645
                                        result = val1 / val2;
1646
                                        break;
1647
                                case mod:
1648
                                        result = val1 % val2;
1649
                                        break;
1650
                                default:
1651
                                        // bail out, if we can not handle it
1652
                                        return expression;
1653
                                }
1654

    
1655
                                if (result < ((IntType)expression.type()).rangeLow()
1656
                                                || result > ((IntType)expression.type()).rangeHigh())
1657
                                        return Error(expression, "Internal Error: value after constant folding not in int-range!");
1658

    
1659
                                final ValueExpression<Integer> intres = new ValueExpression<Integer>(result, expression.line(), expression.pos(), Integer.class);
1660
                                intres.SetType(expression.type());
1661
                                return intres;
1662
                        }
1663
                        else if (expression.type().kind() == TypeKind.BoolType)
1664
                        {
1665
                                boolean result = false;
1666
                                switch (expression.kind())
1667
                                {
1668
                                case greater:
1669
                                        assert(lhs.type().kind() == rhs.type().kind());
1670
                                        switch (lhs.type().kind())
1671
                                        {
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 greaterequal:
1685
                                        assert(lhs.type().kind() == rhs.type().kind());
1686
                                        switch (lhs.type().kind())
1687
                                        {
1688
                                        case IntType:
1689
                                                result = ((ValueExpression<Integer>)lhs).value() >=
1690
                                                        ((ValueExpression<Integer>)rhs).value();
1691
                                                break;
1692
                                        case FloatType:
1693
                                                result = ((ValueExpression<Double>)lhs).value() >=
1694
                                                        ((ValueExpression<Double>)rhs).value();
1695
                                                break;
1696
                                        default:
1697
                                                return expression;
1698
                                        }
1699
                                        break;
1700
                                case less:
1701
                                        assert(lhs.type().kind() == rhs.type().kind());
1702
                                        switch (lhs.type().kind())
1703
                                        {
1704
                                        case IntType:
1705
                                                result = ((ValueExpression<Integer>)lhs).value() <
1706
                                                        ((ValueExpression<Integer>)rhs).value();
1707
                                                break;
1708
                                        case FloatType:
1709
                                                result = ((ValueExpression<Double>)lhs).value() <
1710
                                                        ((ValueExpression<Double>)rhs).value();
1711
                                                break;
1712
                                        default:
1713
                                                return expression;
1714
                                        }
1715
                                        break;
1716
                                case lessequal:
1717
                                        assert(lhs.type().kind() == rhs.type().kind());
1718
                                        switch (lhs.type().kind())
1719
                                        {
1720
                                        case IntType:
1721
                                                result = ((ValueExpression<Integer>)lhs).value() <=
1722
                                                        ((ValueExpression<Integer>)rhs).value();
1723
                                                break;
1724
                                        case FloatType:
1725
                                                result = ((ValueExpression<Double>)lhs).value() <=
1726
                                                        ((ValueExpression<Double>)rhs).value();
1727
                                                break;
1728
                                        default:
1729
                                                return expression;
1730
                                        }
1731
                                        break;
1732
                                case and:
1733
                                        result = ((ValueExpression<Boolean>)lhs).value() && ((ValueExpression<Boolean>)rhs).value();
1734
                                        break;
1735
                                case equal:
1736
                                        // we have to be careful here, since equal takes all sorts of types..
1737
                                        assert(lhs.type().kind() == rhs.type().kind());
1738
                                        switch (lhs.type().kind())
1739
                                        {
1740
                                        case BoolType:
1741
                                                result = ((ValueExpression<Boolean>)lhs).value() ==
1742
                                                        ((ValueExpression<Boolean>)rhs).value();
1743
                                                break;
1744
                                        case IntType:
1745
                                                result = ((ValueExpression<Integer>)lhs).value() ==
1746
                                                        ((ValueExpression<Integer>)rhs).value();
1747
                                                break;
1748
                                        case FloatType:
1749
                                                result = ((ValueExpression<Double>)lhs).value() ==
1750
                                                        ((ValueExpression<Double>)rhs).value();
1751
                                                break;
1752
                                        default:
1753
                                                return expression;
1754
                                        }
1755
                                        break;
1756
                                case biimplies:
1757
                                        result = ((ValueExpression<Boolean>)lhs).value() == ((ValueExpression<Boolean>)rhs).value();
1758
                                        break;
1759
                                case implies:
1760
                                        result = !((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1761
                                        break;
1762
                                case or:
1763
                                        result = ((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1764
                                        break;
1765
                                default:
1766
                                        return expression;
1767
                                }
1768
                                final ValueExpression<Boolean> boolres = new ValueExpression<Boolean>(result, expression.line(), expression.pos(), Boolean.class);
1769
                                boolres.SetType(expression.type());
1770
                                return boolres;
1771
                        }
1772

    
1773
                return expression;
1774
        }
1775

    
1776

    
1777
        ///
1778
        ///  "jump table" (could by avoided by 'dynamic' type as found in c#4)
1779
        ///
1780

    
1781
        @SuppressWarnings("unchecked")
1782
        private Expression ResolveExpression(Expression expression)
1783
        {
1784
                if (expression == null) return null;
1785

    
1786
                Expression result = expression;
1787

    
1788
                switch (expression.kind())
1789
                {
1790
                case Value:
1791
                        final LeafExpression aValue = (LeafExpression)expression;
1792
                        switch (aValue.valueType())
1793
                        {
1794
                        case bool:
1795
                                expression.SetType(new BoolType(null));
1796
                                break;
1797
                        case chr:
1798
                                expression.SetType(new CharType(null));// IntType(0, 255, null));
1799
                                break;
1800
                        case complex:
1801
                        case identifier:
1802
                                assert(false);
1803
                                break;
1804
                        case integer:
1805
                                final int val = ((ValueExpression<Integer>)expression).value();
1806
                                expression.SetType(new IntType(val, val, null));
1807
                                break;
1808
                        case qval:
1809
                                throw new NotImplementedException();
1810
                        case real:
1811
                                final double fval = ((ValueExpression<Double>)expression).value();
1812
                                expression.SetType(new FloatType(fval, fval, fval, null));
1813
                                break;
1814
                        case reference:
1815
                                final Object aref = ((ValueExpression<?>)expression).value();
1816
                                if (aref == null)
1817
                                        expression.SetType(new NullType());
1818
                                else
1819
                                {
1820
                                        assert(false);
1821
                                        return null;
1822
                                }
1823
                                break;
1824
                        case unset:
1825
                                throw new NotImplementedException();
1826
                        default:
1827
                                break;
1828
                        }
1829
                        result = expression;
1830
                        break;
1831

    
1832
                        /* ternary operators */
1833
                case conditional:
1834
                case foldLR:
1835
                case foldRL:
1836
                        result = ResolveExpression((TernaryOperator)expression);
1837
                        break;
1838

    
1839
                        /* forall */
1840
                case forall:
1841
                        result = ResolveExpression((ForallQuantifier)expression);
1842
                        break;
1843

    
1844
                        /* exists */
1845
                case exists:
1846
                        result = ResolveExpression((ExistsQuantifier)expression);
1847
                        break;
1848

    
1849
                        /* constructors */
1850
                case ListConstr:
1851
                        result = ResolveExpression((ListConstructor)expression);
1852
                        break;
1853
                case SetConstr:
1854
                        result = ResolveExpression((SetConstructor)expression);
1855
                        break;
1856
                case MapConstr:
1857
                        result = ResolveExpression((MapConstructor)expression);
1858
                        break;
1859
                case TupleConstr:
1860
                        result = ResolveExpression((TupleConstructor)expression);
1861
                        break;
1862
                case ObjectConstr:
1863
                        result = expression;
1864
                        break;
1865

    
1866
                        /* identifiers */
1867
                case Identifier:
1868
                        result = ResolveExpression((IdentifierExpression)expression);
1869
                        break;
1870
                case UnresolvedIdentifier:
1871
                        result = ResolveExpression((UnresolvedIdentifierExpression)expression);
1872
                        break;
1873

    
1874
                        /* evaluate */
1875
                case TupleMapAccess:
1876
                        result = ResolveExpression((TupleMapAccessExpression)expression);
1877
                        break;
1878
                case Call:
1879
                        result = ResolveExpression((CallExpression)expression);
1880
                        break;
1881

    
1882
                        /* access some element within a class.. */
1883
                case Access:
1884
                        result = ResolveExpression((AccessExpression)expression);
1885
                        break;
1886

    
1887

    
1888
                case Cast:
1889
                        final UnaryOperator cast = (UnaryOperator)expression;
1890

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

    
1895
                        cast.SetChild(ResolveExpression(cast.child()));
1896
                        final Type acover = Type.CoverType(cast.type(), cast.child().type());
1897
                        final boolean upcast = Type.TypeEqual(acover, cast.type());           // the cast is safe; Mostly used in list constructors..
1898
                        final boolean downcast = Type.TypeEqual(acover, cast.child().type()); // downcast, unsafe.
1899
                        if (downcast)
1900
                                Info(cast, String.format("Potentially unsafe downcast: %s as %s (cover: %s)",
1901
                                        cast.child().type().toString(), cast.type().toString(), acover.toString()));
1902
                        if (acover == null || !(upcast || downcast))
1903
                                return Error(cast, String.format("Invalid cast: %s as %s (cover: %s)",
1904
                                        cast.child().type().toString(), cast.type().toString(), acover != null ? acover.toString() : "<none>"));
1905

    
1906
                        result = cast;
1907
                        break;
1908

    
1909
                        /* general unary operators */
1910
                case Primed:
1911
                case unminus:
1912
                case unplus:
1913
                case not:
1914
                case abs:
1915
                case dom:
1916
                case range:
1917
                case merge:
1918
                case card:
1919
                case dconc:
1920
                case dinter:
1921
                case dunion:
1922
                case elems:
1923
                case head:
1924
                case inds:
1925
                case len:
1926
                case tail:
1927
                        result = ResolveExpression((UnaryOperator)expression);
1928
                        break;
1929

    
1930
                        /* general binary operators */
1931
                case domresby:
1932
                case domresto:
1933
                case rngresby:
1934
                case rngresto:
1935
                case munion:
1936
                case conc:
1937
                case diff:
1938
                case inter:
1939
                case elemin:
1940
                case notelemin:
1941
                case subset:
1942
                case union:
1943
                case div:
1944
                case greater:
1945
                case greaterequal:
1946
                case idiv:
1947
                case less:
1948
                case lessequal:
1949
                case minus:
1950
                case mod:
1951
                case pow:
1952
                case prod:
1953
                case sum:
1954
                case and:
1955
                case biimplies:
1956
                case implies:
1957
                case or:
1958
                case equal:
1959
                case notequal:
1960
                case seqmod_mapoverride:
1961
                        result = ResolveExpression((BinaryOperator)expression);
1962
                        break;
1963
                default:
1964
                        throw new NotImplementedException();
1965
                }
1966

    
1967
                return result;
1968
        }
1969

    
1970

    
1971
        public Expression ResolveExpressionNewScope(Expression toResolve)
1972
        {
1973
                Expression result = null;
1974

    
1975
                m_freeVariables.push(new SymbolTable());
1976
                try
1977
                {
1978
                        result = ResolveExpression(toResolve);
1979
                }
1980
                finally
1981
                {
1982
                        if (result != null)
1983
                                result.SetFreeVariables(m_freeVariables.pop());
1984
                }
1985
                return result;
1986
        }
1987

    
1988

    
1989
        ///
1990
        ///  called for every element in the ast
1991
        ///
1992

    
1993
        @Override
1994
        protected void VisitAstElement(IAst subElement, IAst parent)
1995
        {
1996
                if (subElement.nodeType() == AstNodeTypeEnum.expression)
1997
                {
1998
                        // calculate a new (resolved) expression
1999
                        m_freeVariables.push(new SymbolTable());
2000
                        // save toplevel -- used to keep track of method calls.
2001
                        m_entryExpression = (Expression)subElement;
2002

    
2003
                        final Expression newExpression = ResolveExpression(m_entryExpression);
2004
                        // replace the expression in the parent
2005
                        if (newExpression != null)
2006
                        {
2007
                                newExpression.SetFreeVariables(m_freeVariables.pop());
2008
                                ReplaceExpression(parent, (Expression)subElement, newExpression);
2009
                        }
2010

    
2011
                }
2012
                else
2013
                        subElement.Accept(this); // saves us the call to base.VisitAstElement
2014
        }
2015

    
2016

    
2017
        ///
2018
        ///  PUBLIC METHODS
2019
        ///
2020

    
2021
        public OoaResolveExpressionsVisitor(ParserState aState)
2022
        {
2023
                super (aState);
2024
                if (aState == null)
2025
                        throw new ArgumentException();
2026
        }
2027
}