Project

General

Profile

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

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.QValConstructor;
49
import org.momut.ooas.ast.expressions.SetConstructor;
50
import org.momut.ooas.ast.expressions.TernaryOperator;
51
import org.momut.ooas.ast.expressions.TupleConstructor;
52
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
53
import org.momut.ooas.ast.expressions.TypeExpression;
54
import org.momut.ooas.ast.expressions.UnaryOperator;
55
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
56
import org.momut.ooas.ast.expressions.ValueExpression;
57
import org.momut.ooas.ast.expressions.LeafExpression.LeafTypeEnum;
58
import org.momut.ooas.ast.expressions.MapConstructor.MapItem;
59
import org.momut.ooas.ast.identifiers.AttributeIdentifier;
60
import org.momut.ooas.ast.identifiers.ConstantIdentifier;
61
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier;
62
import org.momut.ooas.ast.identifiers.FunctionIdentifier;
63
import org.momut.ooas.ast.identifiers.Identifier;
64
import org.momut.ooas.ast.identifiers.IdentifierKind;
65
import org.momut.ooas.ast.identifiers.ParameterIdentifier;
66
import org.momut.ooas.ast.identifiers.SelfTypeIdentifier;
67
import org.momut.ooas.ast.statements.Assignment;
68
import org.momut.ooas.ast.statements.Call;
69
import org.momut.ooas.ast.statements.GuardedCommand;
70
import org.momut.ooas.ast.statements.SeqBlock;
71
import org.momut.ooas.ast.statements.Statement;
72
import org.momut.ooas.ast.types.AnyType;
73
import org.momut.ooas.ast.types.BoolType;
74
import org.momut.ooas.ast.types.CharType;
75
import org.momut.ooas.ast.types.EnumType;
76
import org.momut.ooas.ast.types.FloatType;
77
import org.momut.ooas.ast.types.FunctionType;
78
import org.momut.ooas.ast.types.IntType;
79
import org.momut.ooas.ast.types.ListType;
80
import org.momut.ooas.ast.types.MapType;
81
import org.momut.ooas.ast.types.NullType;
82
import org.momut.ooas.ast.types.OoActionSystemType;
83
import org.momut.ooas.ast.types.QrType;
84
import org.momut.ooas.ast.types.TupleType;
85
import org.momut.ooas.ast.types.TypeKind;
86
import org.momut.ooas.ast.types.UlyssesType;
87
import org.momut.ooas.ast.types.ValuedEnumType;
88
import org.momut.ooas.parser.ParserError;
89
import org.momut.ooas.parser.ParserMessage;
90
import org.momut.ooas.parser.ParserState;
91
import org.momut.ooas.parser.ParserWarning;
92
import org.momut.ooas.parser.SymbolTable;
93
import org.momut.ooas.utils.exceptions.ArgumentException;
94
import org.momut.ooas.utils.exceptions.NotImplementedException;
95

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

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

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

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

    
240
        ///
241
        ///   Resolve Expressions
242
        ///
243

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

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

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

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

    
261
                        final UlyssesType acover = UlyssesType.CoverType(mid.type(), right.type());
262

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

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

    
279

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
391
                        expression.SetComprehension(comprehension);
392

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

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

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

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

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

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

    
433
                                tmpitems.add(element);
434
                        }
435

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

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

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

    
468
                        if (comprehension == null)
469
                                return null;
470

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

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

    
477
                        expression.SetComprehension(comprehension);
478

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

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

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

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

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

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

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

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

    
522
                        if (domain == null)
523
                                domain = domexpr.type();
524

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

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

    
532
                        if (range == null)
533
                                range = rangeexpr.type();
534

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

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

    
543
                        newitems.add(new MapConstructor.MapItem(domexpr, rangeexpr));
544
                }
545

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

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

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

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

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

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

    
603
                        newvalexprs.add(newval);
604
                        //resulttype.AddType(newval.type);
605
                }
606

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

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

    
624
        private Expression ResolveExpression(QValConstructor expression)
625
        {
626
                Expression basevalue = null;
627
                Expression rangevalue = null;
628

    
629
                basevalue = ResolveExpression(expression.value()[0]);
630
                if (basevalue == null || basevalue.kind() != ExpressionKind.Access
631
                    || basevalue.type() == null || basevalue.type().kind() != TypeKind.QrType)
632
                        return Error(expression, "Landmark expected.");
633
                expression.SetType(basevalue.type());
634
                expression.SetValue(basevalue);
635

    
636
                if (expression.value().length == 2)
637
                {
638
                        rangevalue = ResolveExpression(expression.value()[1]);
639
                        if (rangevalue == null || rangevalue.kind() != ExpressionKind.Access
640
                            || rangevalue.type() == null || rangevalue.type().kind() != TypeKind.QrType)
641
                                return Error(expression, "Landmark expected.");
642
                        if (!UlyssesType.TypeEqual(basevalue.type(), rangevalue.type()))
643
                                return Error(expression, String.format("Quantity spaces do not match: %s <> %s",
644
                                                basevalue.type().toString(),
645
                                                rangevalue.type().toString()));
646
                        expression.AddRange(rangevalue);
647
                }
648
                return expression;
649
        }
650

    
651
        private Expression ResolveExpression(IdentifierExpression expression)
652
        {
653
                // nothing to do here, since we do not have any consts that may be
654
                // folded
655
                if ((expression.identifier().kind() == IdentifierKind.MethodIdentifier
656
                       || expression.identifier().kind() == IdentifierKind.NamedActionIdentifier)
657
                    && !m_entryExpression.callTargets().contains(expression.identifier()))
658
                {
659
                        m_entryExpression.callTargets().add((FunctionIdentifier)expression.identifier());
660
                }
661

    
662
                return expression;
663
        }
664
        private Expression ResolveExpression(UnresolvedIdentifierExpression expression)
665
        {
666
                Identifier anid;
667
                //Identifier self = m_ParserState.Lookup("self");
668

    
669
                if (m_freeVariables.peek().Defined(expression.tokenText()))
670
                        anid = m_freeVariables.peek().Get(expression.tokenText());
671
                else
672
                        anid = m_ParserState.Lookup(expression.tokenText(), expression.scope());
673

    
674
                if (anid != null)
675
                {
676
                        switch (anid.kind())
677
                        {
678
                        case TypeIdentifier:
679
                                // only return a TypeExpression if this TypeIdentifier didn't come from a "self"
680
                                if (anid instanceof SelfTypeIdentifier) {
681
                                        final IdentifierExpression result = new IdentifierExpression(anid, expression.line(), expression.pos());
682
                                        result.setIsSelf(true);
683
                                        return result;
684
                                } else
685
                                        return new TypeExpression(anid.type(), expression.line(), expression.pos());
686

    
687
                        case MethodIdentifier:
688
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
689
                                final SelfTypeIdentifier selfid = (SelfTypeIdentifier)m_ParserState.Lookup("self", expression.scope());
690
                                if ((selfid != null) && ((OoActionSystemType)(selfid).type()).symbols().Defined(anid))
691
                                {
692
                                        // if it's a self access, add a self identifier (needed by cadp backend, e.g.)
693
                                        // self.<method> is handled in a separate method and does not call us here!! (hence this code is working)
694
                                        final IdentifierExpression aself = new IdentifierExpression(selfid, expression.line(), expression.pos());
695
                                        aself.setIsSelf(true);
696
                                        final AccessExpression localaccess = new AccessExpression(aself, new IdentifierExpression(anid, expression.line(), expression.pos()),
697
                                                        expression.line(), expression.pos());
698
                                        ResolveExpression(localaccess);
699
                                        return localaccess;
700
                                }
701
                                else
702
                                {
703
                                        return new IdentifierExpression(anid, expression.line(), expression.pos());
704
                                }
705

    
706
                        case NamedActionIdentifier:
707
                                m_entryExpression.callTargets().add((FunctionIdentifier)anid);
708
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
709

    
710
                        case Constant:
711
                                if (((ConstantIdentifier)anid).Value() != null)
712
                                        return ((ConstantIdentifier)anid).Value().Clone();
713
                                else
714
                                        return null;
715

    
716
                        default:
717
                                return new IdentifierExpression(anid, expression.line(), expression.pos());
718
                        }
719
                }
720
                else
721
                {
722
                        final ExpressionVariableIdentifier freeVar =
723
                                        new ExpressionVariableIdentifier(expression.tokenText(), expression.line(), expression.pos());
724
                        freeVar.SetType(new AnyType(freeVar));
725
                        m_freeVariables.peek().AddIdentifier(freeVar);
726

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

    
730
                        return new IdentifierExpression(freeVar, expression.line(), expression.pos());
731
                }
732
        }
733
        private Expression ResolveExpression(TupleMapAccessExpression expression)
734
        {
735
                final Expression child = ResolveExpression(expression.child());
736
                if (child == null)
737
                        return null;
738

    
739
                final Expression arg = ResolveExpression(expression.argument());
740
                if (arg == null)
741
                        return null;
742

    
743

    
744
                assert(child.type() != null);
745

    
746
                if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.TupleType))
747
                {
748
                        if ((arg.kind() != ExpressionKind.Value)
749
                            || (((LeafExpression)arg).valueType() != LeafTypeEnum.integer))
750
                        {
751
                                return Error(expression, "Argument to tuple access must be constant integer value!");
752
                        }
753
                        final TupleType aTuple = (TupleType)child.type();
754
                        @SuppressWarnings("unchecked")
755
                        final
756
                        ValueExpression<Integer> aval = (ValueExpression<Integer>)arg;
757
                        if ((aval.value() < 0) || (aval.value() >= aTuple.innerTypes().size()))
758
                        {
759
                                return Error(expression, "Argument to tuple access has to be in range 0..#elems-1");
760
                        }
761
//                        LinkedListNode<UlyssesType> anode = aTuple.innerTypes().First;
762
//                        int target = aval.value();
763
//                        while (target > 0)
764
//                        {
765
//                                target--;
766
//                                anode = anode.Next;
767
//                        }
768
//                        expression.SetType(anode.Value);
769
                        expression.SetType(aTuple.innerTypes().get(aval.value()));
770
                }
771
                else if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.MapType))
772
                {
773
                        final MapType amap = (MapType)child.type();
774
                        expression.SetType(amap.toType());
775
                }
776
                else if ((child.kind() != ExpressionKind.Type) && (child.type().kind() == TypeKind.ListType))
777
                {
778
                        // we allow element access of lists via list[i]
779
                        final ListType alist = (ListType)child.type();
780
                        expression.SetType(alist.innerType());
781
                }
782
                else
783
                {
784
                        return Error(expression, "Not a list, tuple, or map instance");
785
                }
786
                expression.SetArgument(arg);
787
                expression.SetChild(child);
788
                return expression;
789
        }
790
        private Expression ResolveExpression(CallExpression expression)
791
        {
792
                return ResolveExpression(expression, false);
793
        }
794
        private Expression ResolveExpression(CallExpression expression, boolean allowFewerParameters)
795
        {
796
                // calc type of child
797
                final Expression child = ResolveExpression(expression.child());
798
                if (child == null)
799
                        return null;
800

    
801
                assert(child.type() != null);
802

    
803
                expression.SetChild(child);
804

    
805
                if (child.type().kind() != TypeKind.FunctionType)
806
                {
807
                        return Error(expression, "No function to call!");
808
                }
809

    
810

    
811
                final FunctionType funtype = (FunctionType)child.type();
812

    
813
//                // check whether call of named action is allowed
814
//                if (funtype.functionType() != FunctionTypeEnum.Method)
815
//                {
816
//                        // see if call is allowed: must not be called from within a named action
817
//                        IScope callingScope = expression.scope();
818
//                        while (callingScope != null)
819
//                        {
820
//                                if (callingScope instanceof NamedActionIdentifier || callingScope instanceof MethodIdentifier)
821
//                                        return Error(expression, "Call of named Action only allowed in do-od block!");
822
//                                callingScope = callingScope.GetParentScope();
823
//                        }
824
//                }
825

    
826
                // check arguments
827
                final int argsSpec = funtype.parameter().size();
828
                final int argsHave = expression.arguments().size();
829
                if (argsHave < argsSpec && !allowFewerParameters)
830
                {
831
                        return Error(expression, "Too few parameters in function call");
832
                }
833
                if (argsHave > argsSpec)
834
                {
835
                        return Error(expression, "Too much parameters in function call");
836
                }
837

    
838
                final ArrayList<Expression> newargs = new ArrayList<Expression>();
839
                final Iterator<UlyssesType> demandedArgType = funtype.parameter().iterator();
840
                for (final Expression arg: expression.arguments())
841
                {
842
                        final UlyssesType demandedArgTypeValue = demandedArgType.next();
843
                        Expression newarg = ResolveExpression(arg);
844
                        if (newarg == null)
845
                                return null;
846

    
847
                        if (newarg.GetUninitializedFreeVariables().size() > 0)
848
                                Error(arg, String.format("Undefined variable '%s'",
849
                                        newarg.GetUninitializedFreeVariables().get(0).tokenText()));
850

    
851
                        final Expression constantvalue = newarg.kind() == ExpressionKind.Value ? newarg : null;
852

    
853
                        final UlyssesType acover = UlyssesType.CoverType(newarg.type(), demandedArgTypeValue);
854
                        if (acover == null || !UlyssesType.TypeEqualByKind(demandedArgTypeValue, acover))
855
                                return Error(arg, String.format("Argument type does not match; expected: %s delivered: %s",
856
                                                demandedArgTypeValue.toString(), newarg.type().toString()));
857

    
858
                        newarg = UnaryOperator.TryCoerceUp(newarg, acover);
859

    
860
                        if (UlyssesType.FirstTypeLessRange(demandedArgTypeValue, acover))
861
                        {
862
                                if (constantvalue == null)
863
                                {
864
                                        Warning(arg, String.format("Call parameter may over/underflow: %s := %s",
865
                                                        demandedArgTypeValue.toString(), acover.toString()));
866
                                        final UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, newarg, newarg.line(), newarg.pos());
867
                                        cast.SetType(demandedArgTypeValue);
868
                                        newarg = cast;
869
                                }
870
                                else
871
                                {
872
                                        Error(arg, String.format("Call parameter out of range (%s  := %s)",
873
                                                        demandedArgTypeValue.toString(), constantvalue.toString()));
874
                                }
875
                        }
876

    
877
                        newargs.add(newarg);
878
                }
879
                expression.SetArguments(newargs);
880

    
881
                if (funtype.returnType() != null)
882
                        expression.SetType(funtype.returnType());
883
                return expression;
884
        }
885
        private Expression ResolveExpression(AccessExpression expression)
886
        {
887
                Expression lhs = ResolveExpression(expression.left());
888
                if (lhs == null)
889
                        return null;
890
                if (!(expression.right() instanceof UnresolvedIdentifierExpression))
891
                {
892
                        expression.SetRightChild(ResolveExpression(expression.right()));
893
                        expression.SetType(expression.right().type());
894
                        return expression;
895
                }
896

    
897
                final boolean selfAccess = (lhs.kind() == ExpressionKind.Identifier) && ((IdentifierExpression)lhs).isSelf();
898
                final boolean staticAccess = lhs.kind() == ExpressionKind.Type;
899
                final UnresolvedIdentifierExpression access = (UnresolvedIdentifierExpression)expression.right();
900
                // atype could be null...
901
                UlyssesType atype = lhs.type();
902
                if ((lhs.kind() == ExpressionKind.Call) && (atype == null))
903
                {
904
                        return Error(access, "Can not access return type of void-function");
905
                }
906
                else if (atype == null)
907
                {
908
                        return Error(access, "Can not access member of a void type");
909
                }
910

    
911
                // if we did not apply a call expression to a function
912
                if (atype.kind() == TypeKind.FunctionType)
913
                {
914
                        // we can access the return val...
915
                        final FunctionType fun = (FunctionType)atype;
916

    
917
                        // check arity
918
                        if (fun.parameter().size() > 0)
919
                                return Error(access, "Implicit function call not possible: Too few parameters.");
920

    
921
                        // check return type
922
                        if (fun.returnType() == null)
923
                                return Error(access, "Can not access return type of void-function!");
924

    
925
                        // call ok
926
                        atype = fun.returnType();
927
                        // but add callExpression
928
                        lhs = new CallExpression(lhs, null, lhs.line(), lhs.pos(), null); // we do not know the scope
929
                        lhs.SetType(atype);
930
                }
931

    
932
                // update left child
933
                expression.SetLeftChild(lhs);
934

    
935

    
936
                switch (atype.kind())
937
                {
938
                case OoActionSystemType:
939
                        final Identifier anid = ((OoActionSystemType)atype).ResolveIdentifier(access.tokenText());
940
                        if (anid != null)
941
                        {
942
                                if (anid.kind() == IdentifierKind.MethodIdentifier && !m_entryExpression.callTargets().contains(anid))
943
                                        m_entryExpression.callTargets().add((FunctionIdentifier)anid);
944

    
945
                                if (staticAccess)
946
                                {
947
                                        if ((anid.kind() == IdentifierKind.AttributeIdentifier) &&
948
                                                        (((AttributeIdentifier)anid).isStatic()))
949
                                        {
950
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
951
                                                expression.SetRightChild(newrhs);
952
                                        }
953
                                        else
954
                                                return Error(access, "Can not access non-static member of an action system");
955
                                }
956
                                else
957
                                {
958
                                        if (anid.kind() != IdentifierKind.MethodIdentifier && !selfAccess)
959
                                                return Error(access, "Can only access methods of action system objects");
960
                                        else
961
                                        {
962
                                                final IdentifierExpression newrhs = new IdentifierExpression(anid, access.line(), access.pos());
963
                                                expression.SetRightChild(newrhs);
964
                                        }
965
                                }
966
                        }
967
                        else
968
                                return Error(access, String.format("%s no member of %s",
969
                                                access.tokenText(), ((OoActionSystemType)atype).identifier().tokenText()));
970
                        break;
971
                case EnumeratedType:
972
                        final EnumType anEnum = (EnumType)atype;
973
                        if (!staticAccess)
974
                        {
975
                                return Error(access, "Enum values can only be accessed statically.");
976
                        }
977
                        if (anEnum.symbolTable().Defined(access.tokenText()))
978
                        {
979
                                final Identifier enumid = anEnum.symbolTable().Get(access.tokenText());
980
                                final IdentifierExpression newrhs = new IdentifierExpression(enumid, access.line(), access.pos());
981
                                expression.SetRightChild(newrhs);
982
                        }
983
                        else
984
                                return Error(access, String.format("%s not contained in enum %s",
985
                                                access.tokenText(), anEnum.identifier().tokenText()));
986
                        break;
987
                case QrType:
988
                        final QrType aQualitativeType = (QrType)atype;
989
                        if (!staticAccess)
990
                        {
991
                                return Error(access, "QSpace values can only be accessed statically.");
992
                        }
993
                        if (aQualitativeType.symbolTable().Defined(access.tokenText()))
994
                        {
995
                                final Identifier landmark = aQualitativeType.symbolTable().Get(access.tokenText());
996
                                final IdentifierExpression newrhs = new IdentifierExpression(landmark, access.line(), access.pos());
997
                                expression.SetRightChild(newrhs);
998
                        }
999
                        else
1000
                                return Error(access, String.format("%s not contained in qspace %s",
1001
                                                access.tokenText(), aQualitativeType.identifier().tokenText()));
1002
                        break;
1003
                default:
1004
                        /*error, we can not access an element with '.' in any other type*/
1005
                        return Error(expression, "Expected: System, Enum, Func, or QR type");
1006
                }
1007

    
1008
                expression.SetType(expression.right().type());
1009
                return expression;
1010
        }
1011
        private Expression ResolveExpression(UnaryOperator expression)
1012
        {
1013
                final Expression child = ResolveExpression(expression.child());
1014
                // if there was some error, then exit
1015
                if (child == null)
1016
                        return null;
1017

    
1018
                if (child.type() == null)
1019
                        return Error(expression, "Can not apply unary operator to void-expression");
1020

    
1021

    
1022
                switch (expression.kind())
1023
                {
1024
                case Primed:
1025
                        expression.SetType(child.type());
1026
                        break;
1027

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

    
1163
                expression.SetChild(child);
1164
                return expression;
1165
        }
1166
        @SuppressWarnings("unchecked")
1167
        private Expression ResolveExpression(BinaryOperator expression)
1168
        {
1169
                Expression lhs = ResolveExpression(expression.left());
1170
                Expression rhs = ResolveExpression(expression.right());
1171

    
1172

    
1173
                // if there was some error, then exit
1174
                if ((lhs == null) || (rhs == null))
1175
                        return null;
1176

    
1177
                final UlyssesType lt = lhs.type();
1178
                final UlyssesType rt = rhs.type();
1179

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

    
1183

    
1184
                switch (expression.kind())
1185
                {
1186
                /*map operators*/
1187
                case domresby:   // list of A * map A to B -> map A to B
1188
                case domresto:   // list of A * map A to B -> map A to B
1189
                        if (lt.kind() != TypeKind.ListType)
1190
                                return Error(expression, "Domain restriction operator expects list on LHS");
1191
                        if (rt.kind() != TypeKind.MapType)
1192
                                return Error(expression, "Domain restriction operator expects map on RHS");
1193
                        ListType domlist = (ListType)lt;
1194
                        MapType domMap = (MapType)rt;
1195
                        if (!UlyssesType.TypeEqual(domlist.innerType(), domMap.fromType()))
1196
                                return Error(expression, "Inner type of list and domain-type of map do not match");
1197
                        // since this is a restriction, maxnumofelems is ok
1198
                        expression.SetType(domMap);
1199
                        break;
1200
                case rngresby:   // map A to B * list of B -> map A to B
1201
                case rngresto:   // map A to B * list of B -> map A to B
1202
                        if (lt.kind() != TypeKind.MapType)
1203
                                return Error(expression, "Range restriction operator expects map on LHS");
1204
                        if (rt.kind() != TypeKind.ListType)
1205
                                return Error(expression, "Rangle restriction operator expects list on RHS");
1206
                        final ListType rangelist = (ListType)rt;
1207
                        domMap = (MapType)lt;
1208
                        if (!UlyssesType.TypeEqual(rangelist.innerType(), domMap.fromType()))
1209
                                return Error(expression, "Inner type of list and rangle-type of map do not match");
1210
                        // since this is a restriction, maxnumofelems is ok
1211
                        expression.SetType(domMap);
1212
                        break;
1213
                case munion:     // map A to B * map A to B -> map A to B
1214
                        if (lt.kind() != TypeKind.MapType ||
1215
                        rt.kind() != TypeKind.MapType)
1216
                                return Error(expression, "Map union expects maps on LHS and RHS");
1217
                        domMap = (MapType)lt;
1218
                        MapType rngMap = (MapType)rt;
1219
                        if (!UlyssesType.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1220
                                        !UlyssesType.TypeEqual(domMap.toType(), rngMap.toType()))
1221
                                return Error(expression, "Domain and Range types of maps must be equal");
1222
                        // union may change maximum number of elements..
1223
                        final MapType resMap = new MapType(domMap.fromType(), domMap.toType(),
1224
                                        domMap.maxNumberOfElements() + rngMap.maxNumberOfElements(), null);
1225
                        expression.SetType(resMap);
1226
                        break;
1227
                        /*set/list binary*/
1228
                case conc:       // list of A * list of A -> list of A
1229
                        if (lt.kind() != TypeKind.ListType ||
1230
                        rt.kind() != TypeKind.ListType)
1231
                                return Error(expression, "List concatenation expects two lists.");
1232
                        ListType la = (ListType)lt;
1233
                        ListType lb = (ListType)rt;
1234

    
1235
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1236
                                return lhs;
1237
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1238
                                return rhs;
1239
                        if (!UlyssesType.TypeEqual(la.innerType(), lb.innerType()))
1240
                                return Error(expression, String.format("Set/List concatenation expects two lists of same type. (%s <> %s)", la.toString(), lb.toString()));
1241
                        ListType resultList = new ListType(la.innerType(),
1242
                                        la.maxNumberOfElements() + lb.maxNumberOfElements(), null);
1243
                        expression.SetType(resultList);
1244
                        break;
1245
                case diff:       // list of A * list of A -> list of A (does not respect dupes)
1246
                        if (lt.kind() != TypeKind.ListType ||
1247
                        rt.kind() != TypeKind.ListType)
1248
                                return Error(expression, "Set difference expects two lists.");
1249
                        la = (ListType)lt;
1250
                        lb = (ListType)rt;
1251
                        if (!UlyssesType.TypeEqual(la.innerType(), lb.innerType()))
1252
                                return Error(expression, "Set difference expects two lists of same type.");
1253
                        expression.SetType(la);
1254
                        break;
1255
                case inter:      // list of A * list of A -> list of A (does not respect dupes)
1256
                        if (lt.kind() != TypeKind.ListType ||
1257
                        rt.kind() != TypeKind.ListType)
1258
                                return Error(expression, "Set intersection expects two lists.");
1259
                        la = (ListType)lt;
1260
                        lb = (ListType)rt;
1261
                        if (!UlyssesType.TypeEqual(la.innerType(), lb.innerType()))
1262
                                return Error(expression, "Set intersection expects two lists of same type.");
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 UlyssesType leftType = lhs.type();
1273
                        if (!UlyssesType.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 ||
1280
                        rt.kind() != TypeKind.ListType)
1281
                                return Error(expression, "Subset operation expects two lists.");
1282
                        la = (ListType)lt;
1283
                        lb = (ListType)rt;
1284
                        if (!UlyssesType.TypeEqual(la.innerType(), lb.innerType()))
1285
                                return Error(expression, "Subset operation expects two lists of same type.");
1286
                        expression.SetType(new BoolType(null));
1287
                        break;
1288
                case union:      // list of A * list of A -> list of A (does not respect dupes)
1289
                        if (lt.kind() != TypeKind.ListType ||
1290
                        rt.kind() != TypeKind.ListType)
1291
                                return Error(expression, "Set union expects two lists.");
1292
                        la = (ListType)lt;
1293
                        lb = (ListType)rt;
1294

    
1295
                        if (la.innerType().kind() == TypeKind.Null || la.maxNumberOfElements() == 0)
1296
                                return rhs;
1297
                        if (lb.innerType().kind() == TypeKind.Null || lb.maxNumberOfElements() == 0)
1298
                                return lhs;
1299

    
1300
                        if (!UlyssesType.TypeEqual(la.innerType(), lb.innerType()))
1301
                                return Error(expression, "Set union expects two lists of same type.");
1302
                        resultList = new ListType(la.innerType(),
1303
                                        la.maxNumberOfElements() + lb.maxNumberOfElements(), null);
1304
                        expression.SetType(resultList);
1305
                        break;
1306

    
1307
                        /*numeric binary*/
1308
                case pow:
1309
                        if (!lt.IsNumeric() || !rt.IsNumeric())
1310
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1311
                        if (lt.kind() == TypeKind.IntType && rt.kind() == TypeKind.IntType)
1312
                                expression.SetType(lt);
1313
                        else
1314
                                if (lt.kind() == TypeKind.FloatType)
1315
                                        expression.SetType(lt);
1316
                                else
1317
                                {
1318
                                        final IntType anint = (IntType)lt;
1319
                                        expression.SetType(new FloatType(anint.rangeLow(), anint.rangeHigh(),
1320
                                                        FloatType.defaultPrecision(), null));
1321
                                }
1322
                        break;
1323

    
1324
                case idiv:
1325
                case mod:
1326
                        if (rt.kind() != TypeKind.IntType || lt.kind() != TypeKind.IntType)
1327
                                return Error(expression, "Operator expects LHS and RHS to be integer");
1328
                        expression.SetType(Expression.ArithmeticCover(lt, rt, expression.kind()));
1329
                        break;
1330
                case div:
1331
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1332
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1333
                        if (lhs.type() instanceof ValuedEnumType)
1334
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1335
                        if (rhs.type() instanceof ValuedEnumType)
1336
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1337
                        UlyssesType cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1338
                        expression.SetType(cover);
1339
                        break;
1340
                case minus:
1341
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1342
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1343
                        if (lhs.type() instanceof ValuedEnumType)
1344
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1345
                        if (rhs.type() instanceof ValuedEnumType)
1346
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1347
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1348
                        expression.SetType(cover);
1349
                        break;
1350
                case prod:
1351
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1352
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1353
                        if (lhs.type() instanceof ValuedEnumType)
1354
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1355
                        if (rhs.type() instanceof ValuedEnumType)
1356
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1357
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1358
                        expression.SetType(cover);
1359
                        break;
1360
                case sum:
1361
                        if (!rt.IsNumeric() || !lt.IsNumeric())
1362
                                return Error(expression, "Operator expects LHS and RHS to be numeric");
1363
                        if (lhs.type() instanceof ValuedEnumType)
1364
                                lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type()).getIntType());
1365
                        if (rhs.type() instanceof ValuedEnumType)
1366
                                rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type()).getIntType());
1367
                        cover = Expression.ArithmeticCover(lt, rt, expression.kind());
1368
                        expression.SetType(cover);
1369
                        break;
1370
                case greater:
1371
                case greaterequal:
1372
                case less:
1373
                case lessequal:
1374
                        if (!((rt.IsNumeric() && lt.IsNumeric()) || (rt.IsQualitative() && lt.IsQualitative())))
1375
                                return Error(expression, "Operator expects LHS and RHS to be numeric or qualitative");
1376
                        cover = UlyssesType.CoverType(lt, rt);
1377
                        if (cover != null)
1378
                        {
1379
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1380
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1381
                                expression.SetType(new BoolType(null));
1382
                        }
1383
                        else
1384
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1385
                        break;
1386
                        /*bool binary*/
1387
                case and:
1388
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1389
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1390

    
1391
                        expression.SetType(rt);
1392
                        // little bit of optimization..
1393
                        if (rhs.kind() == ExpressionKind.Value
1394
                                        && ((ValueExpression<Boolean>)rhs).value() == false)
1395
                                return rhs;
1396
                        else if (lhs.kind() == ExpressionKind.Value
1397
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1398
                                return lhs;
1399

    
1400
                        // if both are true, then this will be taken care of in constant folding.
1401
                        break;
1402
                case biimplies:
1403
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1404
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1405
                        expression.SetType(rt);
1406
                        break;
1407
                case implies:
1408
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1409
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1410
                        expression.SetType(rt);
1411

    
1412
                        // ex falso...
1413
                        if (lhs.kind() == ExpressionKind.Value
1414
                                        && ((ValueExpression<Boolean>)lhs).value() == false)
1415
                        {
1416
                                final Expression shortcut = new ValueExpression<Boolean>(true, expression.line(), expression.pos(), Boolean.class);
1417
                                shortcut.SetType(lt);
1418
                                return shortcut;
1419
                        }
1420

    
1421
                        break;
1422
                case or:
1423
                        if (rt.kind() != TypeKind.BoolType || lt.kind() != TypeKind.BoolType)
1424
                                return Error(expression, "Operator expects LHS and RHS of bool.");
1425
                        expression.SetType(rt);
1426

    
1427
                        if (rhs.kind() == ExpressionKind.Value
1428
                                        && ((ValueExpression<Boolean>)rhs).value() == true)
1429
                                return rhs;
1430
                        else if (lhs.kind() == ExpressionKind.Value
1431
                                        && ((ValueExpression<Boolean>)lhs).value() == true)
1432
                                return lhs;
1433
                        break;
1434
                        /*other binary*/
1435
                case equal:
1436
                case notequal:
1437
                        cover = UlyssesType.CoverType(lt, rt);
1438
                        if (cover != null)
1439
                        {
1440
                                /* see whether we have a tuple-matcher on one side.. */
1441
                                if (expression.kind() == ExpressionKind.equal)
1442
                                {
1443
                                        if (lhs.kind() == ExpressionKind.TupleConstr &&
1444
                                                        ((TupleConstructor)lhs).isMatcher())
1445
                                        {
1446
                                                if (rhs.kind() == ExpressionKind.TupleConstr &&
1447
                                                                ((TupleConstructor)rhs).isMatcher())
1448
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1449
                                                m_matcherList.remove(lhs);
1450
                                        }
1451
                                        else if (rhs.kind() == ExpressionKind.TupleConstr &&
1452
                                                        ((TupleConstructor)rhs).isMatcher())
1453
                                        {
1454
                                                if (lhs.kind() == ExpressionKind.TupleConstr &&
1455
                                                                ((TupleConstructor)lhs).isMatcher())
1456
                                                        return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1457
                                                m_matcherList.remove(rhs);
1458
                                        }
1459
                                }
1460

    
1461
                                lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1462
                                rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1463
                                expression.SetType(new BoolType(null));
1464
                        }
1465
                        else
1466
                                return Error(expression, String.format("Operator expects LHS and RHS to be of same type (%s <> %s)", lhs.type().toString(), rhs.type().toString()));
1467
                        break;
1468
                case seqmod_mapoverride:
1469
                        if (rt.kind() != TypeKind.MapType)
1470
                                return Error(expression, "Map expected as RHS on sequence modification or map override.");
1471
                        // list of A * map int to A -> list of A or
1472
                        if (lt.kind() == TypeKind.ListType)
1473
                        {
1474
                                // we're in sequence modification.
1475
                                domlist = (ListType)lt;
1476
                                rngMap = (MapType)rt;
1477
                                if (rngMap.fromType().kind() != TypeKind.IntType)
1478
                                        return Error(expression, "Domain of map has to be integer");
1479
                                if (!UlyssesType.TypeEqual(domlist.innerType(), rngMap.toType()))
1480
                                        return Error(expression, "Type of list expected to match range of map");
1481
                                // since we only replace elements in the list (by matching ones from the map),
1482
                                // we're save to return the original list..
1483
                                expression.SetType(lt);
1484
                        }
1485
                        // map A to B * map A to B -> map A to B
1486
                        else if (lt.kind() == TypeKind.MapType)
1487
                        {
1488
                                domMap = (MapType)lt;
1489
                                rngMap = (MapType)rt;
1490
                                if (!UlyssesType.TypeEqual(domMap.fromType(), rngMap.fromType()) ||
1491
                                                !UlyssesType.TypeEqual(domMap.toType(), rngMap.toType()))
1492
                                        return Error(expression, "Maps need same domain and range types");
1493
                                // since we override entries in the first map:
1494
                                expression.SetType(domMap);
1495
                        }
1496
                        else
1497
                                return Error(expression, "Sequence Modification or Map override expects list or map as LHS");
1498
                        break;
1499
                default:
1500
                        throw new NotImplementedException();
1501
                }
1502

    
1503
                // set subtrees.
1504
                expression.SetLeftChild(lhs);
1505
                expression.SetRightChild(rhs);
1506

    
1507
                // we only allow:  a = MyTuple(c,d) style matchers
1508
                if (m_matcherList.size() > 0)
1509
                {
1510
                        m_matcherList.clear();
1511
                        return Error(expression, "Free variables in tuple constructor only allowed in expressions of the form 'atuple = ATupleConstructor(free1,free2...)'");
1512
                }
1513

    
1514
                // try simple constant folding
1515
                return ApplyConstantFolding(expression);
1516
        }
1517

    
1518

    
1519
        ///
1520
        ///  We're also doing a bit of constant folding here.
1521
        ///
1522

    
1523
        @SuppressWarnings("unchecked")
1524
        private Expression ApplyConstantFolding(UnaryOperator expression)
1525
        {
1526
                final Expression child = expression.child();
1527
                if (child.type().IsNumeric() && expression.kind() == ExpressionKind.Cast)
1528
                {
1529
                        switch (expression.type().kind())
1530
                        {
1531
                        case FloatType:
1532
                                if (child.type().kind() == TypeKind.IntType && child.kind() == ExpressionKind.Value)
1533
                                {
1534
                                        final Expression result = new ValueExpression<Double>((double)((ValueExpression<Integer>)child).value(), child.line(), child.pos(), Double.class);
1535
                                        result.SetType(expression.type());
1536
                                        return result;
1537
                                }
1538
                                break;
1539
                        default:
1540
                                break;
1541
                        }
1542
                }
1543
                return expression;
1544
        }
1545

    
1546
        @SuppressWarnings("unchecked")
1547
        private Expression ApplyConstantFolding(BinaryOperator expression)
1548
        {
1549
                Expression lhs = expression.left();
1550
                Expression rhs = expression.right();
1551

    
1552
                if (lhs.kind() == ExpressionKind.Cast)
1553
                {
1554
                        lhs = ApplyConstantFolding((UnaryOperator)lhs);
1555
                        expression.SetLeftChild(lhs);
1556
                }
1557
                if (rhs.kind() == ExpressionKind.Cast)
1558
                {
1559
                        rhs = ApplyConstantFolding((UnaryOperator)rhs);
1560
                        expression.SetRightChild(rhs);
1561
                }
1562

    
1563

    
1564
                if (lhs.kind() == ExpressionKind.Value && rhs.kind() == ExpressionKind.Value)
1565
                        if (expression.type().kind() == TypeKind.FloatType)
1566
                        {
1567
                                final double fval1 = ((ValueExpression<Double>)lhs).value();
1568
                                final double fval2 = ((ValueExpression<Double>)rhs).value();
1569
                                double result = 0;
1570
                                switch (expression.kind())
1571
                                {
1572

    
1573
                                case sum:
1574
                                        result = fval1 + fval2;
1575
                                        break;
1576
                                case minus:
1577
                                        result = fval1 - fval2;
1578
                                        break;
1579
                                case prod:
1580
                                        result = fval1 * fval2;
1581
                                        break;
1582
                                case div:
1583
                                        if (fval2 == 0)
1584
                                                return Error(expression, "Division not defined");
1585
                                        result = fval1 / fval2;
1586
                                        break;
1587
                                default:
1588
                                        // bail out, if we can not handle it
1589
                                        return expression;
1590
                                }
1591
                                if (result < ((FloatType)expression.type()).low()
1592
                                                || result > ((FloatType)expression.type()).high())
1593
                                        return Error(expression, "Internal Error: value after constant folding not in float-range!");
1594

    
1595
                                final ValueExpression<Double> resexp = new ValueExpression<Double>(result, expression.line(), expression.pos(), Double.class);
1596
                                resexp.SetType(expression.type());
1597
                                return resexp;
1598
                        }
1599
                        else if (expression.type().kind() == TypeKind.IntType)
1600
                        {
1601
                                final int val1 = ((ValueExpression<Integer>)lhs).value();
1602
                                final int val2 = ((ValueExpression<Integer>)rhs).value();
1603
                                int result = 0;
1604
                                switch (expression.kind())
1605
                                {
1606
                                case sum:
1607
                                        result = val1 + val2;
1608
                                        break;
1609
                                case minus:
1610
                                        result = val1 - val2;
1611
                                        break;
1612
                                case prod:
1613
                                        result = val1 * val2;
1614
                                        break;
1615
                                case idiv:
1616
                                        if (val2 == 0)
1617
                                                return Error(expression, "Division not defined.");
1618
                                        result = val1 / val2;
1619
                                        break;
1620
                                case mod:
1621
                                        result = val1 % val2;
1622
                                        break;
1623
                                default:
1624
                                        // bail out, if we can not handle it
1625
                                        return expression;
1626
                                }
1627

    
1628
                                if (result < ((IntType)expression.type()).rangeLow()
1629
                                                || result > ((IntType)expression.type()).rangeHigh())
1630
                                        return Error(expression, "Internal Error: value after constant folding not in int-range!");
1631

    
1632
                                final ValueExpression<Integer> intres = new ValueExpression<Integer>(result, expression.line(), expression.pos(), Integer.class);
1633
                                intres.SetType(expression.type());
1634
                                return intres;
1635
                        }
1636
                        else if (expression.type().kind() == TypeKind.BoolType)
1637
                        {
1638
                                boolean result = false;
1639
                                switch (expression.kind())
1640
                                {
1641
                                case greater:
1642
                                        assert(lhs.type().kind() == rhs.type().kind());
1643
                                        switch (lhs.type().kind())
1644
                                        {
1645
                                        case IntType:
1646
                                                result = ((ValueExpression<Integer>)lhs).value() >
1647
                                                        ((ValueExpression<Integer>)rhs).value();
1648
                                                break;
1649
                                        case FloatType:
1650
                                                result = ((ValueExpression<Double>)lhs).value() >
1651
                                                        ((ValueExpression<Double>)rhs).value();
1652
                                                break;
1653
                                        default:
1654
                                                return expression;
1655
                                        }
1656
                                        break;
1657
                                case greaterequal:
1658
                                        assert(lhs.type().kind() == rhs.type().kind());
1659
                                        switch (lhs.type().kind())
1660
                                        {
1661
                                        case IntType:
1662
                                                result = ((ValueExpression<Integer>)lhs).value() >=
1663
                                                        ((ValueExpression<Integer>)rhs).value();
1664
                                                break;
1665
                                        case FloatType:
1666
                                                result = ((ValueExpression<Double>)lhs).value() >=
1667
                                                        ((ValueExpression<Double>)rhs).value();
1668
                                                break;
1669
                                        default:
1670
                                                return expression;
1671
                                        }
1672
                                        break;
1673
                                case less:
1674
                                        assert(lhs.type().kind() == rhs.type().kind());
1675
                                        switch (lhs.type().kind())
1676
                                        {
1677
                                        case IntType:
1678
                                                result = ((ValueExpression<Integer>)lhs).value() <
1679
                                                        ((ValueExpression<Integer>)rhs).value();
1680
                                                break;
1681
                                        case FloatType:
1682
                                                result = ((ValueExpression<Double>)lhs).value() <
1683
                                                        ((ValueExpression<Double>)rhs).value();
1684
                                                break;
1685
                                        default:
1686
                                                return expression;
1687
                                        }
1688
                                        break;
1689
                                case lessequal:
1690
                                        assert(lhs.type().kind() == rhs.type().kind());
1691
                                        switch (lhs.type().kind())
1692
                                        {
1693
                                        case IntType:
1694
                                                result = ((ValueExpression<Integer>)lhs).value() <=
1695
                                                        ((ValueExpression<Integer>)rhs).value();
1696
                                                break;
1697
                                        case FloatType:
1698
                                                result = ((ValueExpression<Double>)lhs).value() <=
1699
                                                        ((ValueExpression<Double>)rhs).value();
1700
                                                break;
1701
                                        default:
1702
                                                return expression;
1703
                                        }
1704
                                        break;
1705
                                case and:
1706
                                        result = ((ValueExpression<Boolean>)lhs).value() && ((ValueExpression<Boolean>)rhs).value();
1707
                                        break;
1708
                                case equal:
1709
                                        // we have to be careful here, since equal takes all sorts of types..
1710
                                        assert(lhs.type().kind() == rhs.type().kind());
1711
                                        switch (lhs.type().kind())
1712
                                        {
1713
                                        case BoolType:
1714
                                                result = ((ValueExpression<Boolean>)lhs).value() ==
1715
                                                        ((ValueExpression<Boolean>)rhs).value();
1716
                                                break;
1717
                                        case IntType:
1718
                                                result = ((ValueExpression<Integer>)lhs).value() ==
1719
                                                        ((ValueExpression<Integer>)rhs).value();
1720
                                                break;
1721
                                        case FloatType:
1722
                                                result = ((ValueExpression<Double>)lhs).value() ==
1723
                                                        ((ValueExpression<Double>)rhs).value();
1724
                                                break;
1725
                                        default:
1726
                                                return expression;
1727
                                        }
1728
                                        break;
1729
                                case biimplies:
1730
                                        result = ((ValueExpression<Boolean>)lhs).value() == ((ValueExpression<Boolean>)rhs).value();
1731
                                        break;
1732
                                case implies:
1733
                                        result = !((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1734
                                        break;
1735
                                case or:
1736
                                        result = ((ValueExpression<Boolean>)lhs).value() || ((ValueExpression<Boolean>)rhs).value();
1737
                                        break;
1738
                                default:
1739
                                        return expression;
1740
                                }
1741
                                final ValueExpression<Boolean> boolres = new ValueExpression<Boolean>(result, expression.line(), expression.pos(), Boolean.class);
1742
                                boolres.SetType(expression.type());
1743
                                return boolres;
1744
                        }
1745

    
1746
                return expression;
1747
        }
1748

    
1749

    
1750
        ///
1751
        ///  "jump table" (could by avoided by 'dynamic' type as found in c#4)
1752
        ///
1753

    
1754
        @SuppressWarnings("unchecked")
1755
        private Expression ResolveExpression(Expression expression)
1756
        {
1757
                if (expression == null) return null;
1758

    
1759
                Expression result = expression;
1760

    
1761
                switch (expression.kind())
1762
                {
1763
                case Value:
1764
                        final LeafExpression aValue = (LeafExpression)expression;
1765
                        switch (aValue.valueType())
1766
                        {
1767
                        case bool:
1768
                                expression.SetType(new BoolType(null));
1769
                                break;
1770
                        case chr:
1771
                                expression.SetType(new CharType(null));// IntType(0, 255, null));
1772
                                break;
1773
                        case complex:
1774
                        case identifier:
1775
                                assert(false);
1776
                                break;
1777
                        case integer:
1778
                                final int val = ((ValueExpression<Integer>)expression).value();
1779
                                expression.SetType(new IntType(val, val, null));
1780
                                break;
1781
                        case qval:
1782
                                throw new NotImplementedException();
1783
                        case real:
1784
                                final double fval = ((ValueExpression<Double>)expression).value();
1785
                                expression.SetType(new FloatType(fval, fval, fval, null));
1786
                                break;
1787
                        case reference:
1788
                                final Object aref = ((ValueExpression<?>)expression).value();
1789
                                if (aref == null)
1790
                                        expression.SetType(new NullType());
1791
                                else
1792
                                {
1793
                                        assert(false);
1794
                                        return null;
1795
                                }
1796
                                break;
1797
                        case unset:
1798
                                throw new NotImplementedException();
1799
                        default:
1800
                                break;
1801
                        }
1802
                        result = expression;
1803
                        break;
1804

    
1805
                        /* ternary operators */
1806
                case conditional:
1807
                case foldLR:
1808
                case foldRL:
1809
                        result = ResolveExpression((TernaryOperator)expression);
1810
                        break;
1811

    
1812
                        /* forall */
1813
                case forall:
1814
                        result = ResolveExpression((ForallQuantifier)expression);
1815
                        break;
1816

    
1817
                        /* exists */
1818
                case exists:
1819
                        result = ResolveExpression((ExistsQuantifier)expression);
1820
                        break;
1821

    
1822
                        /* constructors */
1823
                case ListConstr:
1824
                        result = ResolveExpression((ListConstructor)expression);
1825
                        break;
1826
                case SetConstr:
1827
                        result = ResolveExpression((SetConstructor)expression);
1828
                        break;
1829
                case MapConstr:
1830
                        result = ResolveExpression((MapConstructor)expression);
1831
                        break;
1832
                case TupleConstr:
1833
                        result = ResolveExpression((TupleConstructor)expression);
1834
                        break;
1835
                case ObjectConstr:
1836
                        result = expression;
1837
                        break;
1838
                case QValConstr:
1839
                        result = ResolveExpression((QValConstructor)expression);
1840
                        break;
1841

    
1842
                        /* identifiers */
1843
                case Identifier:
1844
                        result = ResolveExpression((IdentifierExpression)expression);
1845
                        break;
1846
                case UnresolvedIdentifier:
1847
                        result = ResolveExpression((UnresolvedIdentifierExpression)expression);
1848
                        break;
1849

    
1850
                        /* evaluate */
1851
                case TupleMapAccess:
1852
                        result = ResolveExpression((TupleMapAccessExpression)expression);
1853
                        break;
1854
                case Call:
1855
                        result = ResolveExpression((CallExpression)expression);
1856
                        break;
1857

    
1858
                        /* access some element within a class.. */
1859
                case Access:
1860
                        result = ResolveExpression((AccessExpression)expression);
1861
                        break;
1862

    
1863

    
1864
                case Cast:
1865
                        final UnaryOperator cast = (UnaryOperator)expression;
1866

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

    
1871
                        cast.SetChild(ResolveExpression(cast.child()));
1872
                        final UlyssesType acover = UlyssesType.CoverType(cast.type(), cast.child().type());
1873
                        final boolean upcast = UlyssesType.TypeEqual(acover, cast.type());           // the cast is safe; Mostly used in list constructors..
1874
                        final boolean downcast = UlyssesType.TypeEqual(acover, cast.child().type()); // downcast, unsafe.
1875
                        if (downcast)
1876
                                Info(cast, String.format("Potentially unsafe downcast: %s as %s (cover: %s)",
1877
                                        cast.child().type().toString(), cast.type().toString(), acover.toString()));
1878
                        if (acover == null || !(upcast || downcast))
1879
                                return Error(cast, String.format("Invalid cast: %s as %s (cover: %s)",
1880
                                        cast.child().type().toString(), cast.type().toString(), acover != null ? acover.toString() : "<none>"));
1881

    
1882
                        result = cast;
1883
                        break;
1884

    
1885
                        /* general unary operators */
1886
                case Primed:
1887
                case unminus:
1888
                case unplus:
1889
                case not:
1890
                case abs:
1891
                case dom:
1892
                case range:
1893
                case merge:
1894
                case card:
1895
                case dconc:
1896
                case dinter:
1897
                case dunion:
1898
                case elems:
1899
                case head:
1900
                case inds:
1901
                case len:
1902
                case tail:
1903
                        result = ResolveExpression((UnaryOperator)expression);
1904
                        break;
1905

    
1906
                        /* general binary operators */
1907
                case domresby:
1908
                case domresto:
1909
                case rngresby:
1910
                case rngresto:
1911
                case munion:
1912
                case conc:
1913
                case diff:
1914
                case inter:
1915
                case elemin:
1916
                case notelemin:
1917
                case subset:
1918
                case union:
1919
                case div:
1920
                case greater:
1921
                case greaterequal:
1922
                case idiv:
1923
                case less:
1924
                case lessequal:
1925
                case minus:
1926
                case mod:
1927
                case pow:
1928
                case prod:
1929
                case sum:
1930
                case and:
1931
                case biimplies:
1932
                case implies:
1933
                case or:
1934
                case equal:
1935
                case notequal:
1936
                case seqmod_mapoverride:
1937
                        result = ResolveExpression((BinaryOperator)expression);
1938
                        break;
1939
                default:
1940
                        throw new NotImplementedException();
1941
                }
1942

    
1943
                return result;
1944
        }
1945

    
1946

    
1947
        public Expression ResolveExpressionNewScope(Expression toResolve)
1948
        {
1949
                Expression result = null;
1950

    
1951
                m_freeVariables.push(new SymbolTable());
1952
                try
1953
                {
1954
                        result = ResolveExpression(toResolve);
1955
                }
1956
                finally
1957
                {
1958
                        if (result != null)
1959
                                result.SetFreeVariables(m_freeVariables.pop());
1960
                }
1961
                return result;
1962
        }
1963

    
1964

    
1965
        ///
1966
        ///  called for every element in the ast
1967
        ///
1968

    
1969
        @Override
1970
        protected void VisitAstElement(IAst subElement, IAst parent)
1971
        {
1972
                if (subElement.nodeType() == AstNodeTypeEnum.expression)
1973
                {
1974
                        // calculate a new (resolved) expression
1975
                        m_freeVariables.push(new SymbolTable());
1976
                        // save toplevel -- used to keep track of method calls.
1977
                        m_entryExpression = (Expression)subElement;
1978

    
1979
                        final Expression newExpression = ResolveExpression(m_entryExpression);
1980
                        // replace the expression in the parent
1981
                        if (newExpression != null)
1982
                        {
1983
                                newExpression.SetFreeVariables(m_freeVariables.pop());
1984
                                ReplaceExpression(parent, (Expression)subElement, newExpression);
1985
                        }
1986

    
1987
                }
1988
                else
1989
                        subElement.Accept(this); // saves us the call to base.VisitAstElement
1990
        }
1991

    
1992

    
1993
        ///
1994
        ///  PUBLIC METHODS
1995
        ///
1996

    
1997
        public OoaResolveExpressionsVisitor(ParserState aState)
1998
        {
1999
                super (aState);
2000
                if (aState == null)
2001
                        throw new ArgumentException();
2002
        }
2003
}