Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / parser / visitors / ooaResolveVisitor.cs @ 3

1
/**
2
  *
3
  *                      OOAS Compiler (Deprecated)
4
  *
5
  * Copyright 2015, Institute for Software Technology, Graz University of
6
  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
7
  * of Technology. All rights reserved.
8
  *
9
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
10
  *
11
  * Please notice that this version of the OOAS compiler is considered de-
12
  * precated. Only the Java version is maintained.
13
  *
14
  * Contributors:
15
  *               Willibald Krenn (TU Graz/AIT)
16
  *               Stefan Tiran (TU Graz/AIT)
17
  */
18

    
19
using System;
20
using System.Collections.Generic;
21
using System.Text;
22

    
23
namespace TUG.Mogentes
24
{
25

    
26
    /// <summary>
27
    /// Requires: ReplaceOpaqueVisitor
28
    /// 
29
    /// After we have an AST without any Opaquetypes, we still need to replace all the
30
    /// UnresolvedIdentifierExpressions. We also need to compute the expression types,
31
    /// which is also necessary to resolve all the identifiers. So, this visitor
32
    /// goes over all expressions and 
33
    ///   - resolves all identifiers
34
    ///   - calculates resulting types (incl. coercion)
35
    /// </summary>
36
    public sealed class OoaResolveExpressionsVisitor : OoaCompleteAstTraversalVisitor
37
    {
38
        // we allow for free variable in expressions. collect them here.
39
        private Stack<SymbolTable> m_freeVariables = new Stack<SymbolTable>();
40
        private Expression m_entryExpression = null;
41

    
42
        // helpers that replace the old expression in the AST by the new one.
43
        private void ReplaceExpression(IAst parent, Expression subElement, Expression newExpression)
44
        {
45
            switch (parent.nodeType)
46
            {
47
                case AstNodeTypeEnum.identifier:
48
                    ReplaceExpressionInIdentifier((Identifier)parent, subElement, newExpression);
49
                    break;
50
                case AstNodeTypeEnum.statement:
51
                    ReplaceExpressionInStatement((Statement)parent, subElement, newExpression);
52
                    break;
53
                default:
54
                    throw new NotImplementedException();
55
            }
56
        }
57
        private void ReplaceExpressionInIdentifier(Identifier identifier, Expression subElement, Expression newExpression)
58
        {
59
            switch (identifier.kind)
60
            {
61
                case IdentifierKind.AttributeIdentifier:
62
                    AttributeIdentifier ident = (AttributeIdentifier)identifier;
63
                    System.Diagnostics.Debug.Assert(ReferenceEquals(ident.initializer, subElement));
64
                    ident.SetInitializer(newExpression);
65
                    break;
66
                case IdentifierKind.Constant:
67
                    ConstantIdentifier aconst = (ConstantIdentifier)identifier;
68
                    System.Diagnostics.Debug.Assert(ReferenceEquals(aconst.Value, subElement));
69
                    aconst.SetValue(newExpression);
70
                    if (newExpression.kind != ExpressionKind.Value)
71
                    {
72
                        Error(aconst.Value, String.Format("{0} not a constant!", aconst.tokenText));
73
                    }
74

    
75
                    break;
76
                default:
77
                    throw new NotImplementedException();
78
            }
79
        }
80
        private void ReplaceExpressionInStatement(Statement statement, Expression subElement, Expression newExpression)
81
        {
82
            switch (statement.kind)
83
            {
84
                case StatementKind.GuardedCommand:
85
                    GuardedCommand gc = (GuardedCommand)statement;
86
                    System.Diagnostics.Debug.Assert(ReferenceEquals(gc.guard, subElement));
87
                    gc.SetGuard(newExpression);
88
                    break;
89
                case StatementKind.SeqBlock:
90
                    SeqBlock sqblock = (SeqBlock)statement;
91
                    System.Diagnostics.Debug.Assert(ReferenceEquals(sqblock.filter, subElement));
92
                    sqblock.SetFilter(null);
93
                    // we convert the filter to a guarded command...
94
                    SeqBlock implseq = new SeqBlock(sqblock.line, sqblock.pos);
95
                    implseq.SetStatements(sqblock.statements);
96
                    GuardedCommand implguard = new GuardedCommand(newExpression, implseq, sqblock.line, sqblock.pos);
97
                    sqblock.SetStatements(new LinkedList<Statement>());
98
                    sqblock.AddStatement(implguard);
99
                    break;
100
                case StatementKind.Assignment:
101
                    Assignment zw = (Assignment)statement;
102
                    bool found = false;
103
                    if (ReferenceEquals(zw.nondetExpression, subElement))
104
                    {
105
                        zw.SetNondetExpression(newExpression);
106
                        found = true;
107
                    }
108
                    else
109
                    {
110
                        LinkedListNode<Expression> anode = zw.places.First;
111
                        while (anode != null)
112
                        {
113
                            if (ReferenceEquals(anode.Value, subElement))
114
                            {
115
                                anode.Value = newExpression;
116
                                found = true;
117
                                break;
118
                            }
119
                            anode = anode.Next;
120
                        }
121

    
122
                        anode = zw.values.First;
123
                        while (anode != null)
124
                        {
125
                            if (ReferenceEquals(anode.Value, subElement))
126
                            {
127
                                anode.Value = newExpression;
128
                                found = true;
129
                                break;
130
                            }
131
                            anode = anode.Next;
132
                        }
133
                    }
134
                    System.Diagnostics.Debug.Assert(found);
135
                    break;
136
                case StatementKind.MethodCall:
137
                    Call call = (Call)statement;
138
                    System.Diagnostics.Debug.Assert(ReferenceEquals(call.callExpression, subElement));
139
                    call.SetCallExpression(newExpression);
140
                    break;
141
                default:
142
                    throw new NotImplementedException();
143
            }
144
        }
145

    
146
        // helper that returns null and adds an error message in the parserstate errorlist.
147
        private Expression Error(Expression expression, string p)
148
        {
149
            ParserError error = new ParserError(m_ParserState.filename,
150
                expression.line, expression.pos, p);
151
            m_ParserState.AddErrorMessage(error);
152
            return null;
153
        }
154
        private Expression Error(int line, int pos, string p)
155
        {
156
            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
157
            m_ParserState.AddErrorMessage(error);
158
            return null;
159
        }
160
        // helper that adds a warning message to the output
161
        private void Warning(Identifier expression, string p)
162
        {
163
            ParserWarning warning = new ParserWarning(m_ParserState.filename,
164
                expression.line, expression.column, p);
165
            m_ParserState.AddWarningMessage(warning);
166
        }
167
        private void Warning(Expression expression, string p)
168
        {
169
            ParserWarning warning = new ParserWarning(m_ParserState.filename,
170
                expression.line, expression.pos, p);
171
            m_ParserState.AddWarningMessage(warning);
172
        }
173
        private void Info(Expression expression, String p)
174
        {
175
            ParserMessage msg = new ParserMessage(m_ParserState.filename,
176
            expression.line, expression.pos, p);
177
            m_ParserState.AddMessage(msg);
178
        }
179

    
180
        private List<TupleConstructor> m_matcherList = new List<TupleConstructor>();
181

    
182
        /// 
183
        ///   Resolve Expressions
184
        /// 
185

    
186
        private Expression ResolveExpression(TernaryOperator expression)
187
        {
188
            if (expression.kind == ExpressionKind.conditional)
189
            {
190

    
191
                Expression left = ResolveExpression(expression.left);
192
                Expression mid = ResolveExpression(expression.mid);
193
                Expression right = ResolveExpression(expression.right);
194

    
195
                if (left == null
196
                    || mid == null
197
                    || right == null)
198
                    return null;
199

    
200
                if (left.type == null ||
201
                    left.type.kind != TypeKind.BoolType)
202
                    return Error(expression, "Conditional: Condition not a bool");
203

    
204
                if (mid.type == null
205
                    || right.type == null)
206
                    return Error(expression, "Conditional: Then or Else branch has void-type");
207

    
208
                UlyssesType acover = UlyssesType.CoverType(mid.type, right.type);
209

    
210
                if (acover == null)
211
                    return Error(expression, String.Format("Conditional: Then and Else branch must be of same type. ({0} <> {1})", mid.type.ToString(), right.type.ToString()));
212

    
213
                if (!UlyssesType.TypeEqual(acover, mid.type))
214
                {
215
                    mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line, mid.pos);
216
                    mid.SetType(acover);
217
                }
218
                if (!UlyssesType.TypeEqual(acover, right.type))
219
                {
220
                    right = new UnaryOperator(ExpressionKind.Cast, right, right.line, right.pos);
221
                    right.SetType(acover);
222
                }
223

    
224

    
225
                expression.SetLeftChild(left);
226
                expression.SetMidChild(mid);
227
                expression.SetRightChild(right);
228
                expression.SetType(mid.type);
229
                return expression;
230
            }
231
            else if (expression.kind == ExpressionKind.foldLR || expression.kind == ExpressionKind.foldRL)
232
            {
233
                CallExpression leftcall =
234
                    expression.left.kind != ExpressionKind.Call ?
235
                    new CallExpression(expression.left, new List<Expression>(), expression.line,
236
                        expression.pos, expression.definingScope)
237
                    : (CallExpression)expression.left;
238

    
239
                leftcall = (CallExpression)ResolveExpression(leftcall, true);
240
                if (leftcall == null)
241
                    return null;
242

    
243
                Expression afun = ResolveExpression(leftcall.child);
244
                leftcall.SetChild(afun);
245
                if (afun == null || afun.type == null || afun.type.kind != TypeKind.FunctionType)
246
                    return Error(expression, "Fold/Map operation needs a method or named action as LHS");
247

    
248
                FunctionType funType = (FunctionType)afun.type;
249
                if (funType.returnType == null && expression.mid != null)
250
                    return Error(expression, "Fold operation needs a method with matching return type");
251
                if (funType.returnType != null && expression.mid == null)
252
                    Warning(expression, "Map operation will discard result of function");
253

    
254
                bool isMap = expression.mid == null;
255
                Expression mid = expression.mid;
256
                if (!isMap)
257
                {
258
                    mid = ResolveExpression(mid);
259
                    if ((funType.parameter.Count - leftcall.arguments.Count) != 2)
260
                        return Error(expression, "Function used in fold operation needs 2 not-instantiated parameters");
261
                }
262
                else if ((funType.parameter.Count - leftcall.arguments.Count) != 1)
263
                    return Error(expression, "Function used in map operation needs one not-instantiated parameter");
264

    
265
                Expression right = ResolveExpression(expression.right);
266
                if (right == null || right.type == null || right.type.kind != TypeKind.ListType)
267
                    return Error(expression, "Fold/Map operation needs list as RHS");
268

    
269
                if (!isMap)
270
                {
271
                    UlyssesType initCover = UlyssesType.CoverType(funType.parameter.Last.Previous.Value, mid.type);
272
                    if (initCover == null)
273
                        return Error(expression, "Next to last parameter does not match initializer type in map operation.");
274
                    if (!UlyssesType.TypeEqual(mid.type, initCover))
275
                        mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line, mid.pos);
276
                    mid.SetType(initCover);
277

    
278

    
279
                    //List<Expression> args = new List<Expression> ();
280
                    leftcall.arguments.Add(new IdentifierExpression(new ParameterIdentifier("_result", initCover, null), 0, 0));
281
                    leftcall.arguments.Add(new IdentifierExpression(new ParameterIdentifier("_elem", funType.parameter.Last.Value, null), 0, 0));
282

    
283
                    //leftcall.SetArguments(args);
284

    
285
                }
286
                // UlyssesType listCover = UlyssesType.CoverType(funType.parameter.Last.Value, ((ListType)right.type).innerType);
287
                // if (listCover == null)
288
                if (!UlyssesType.TypeEqual(funType.parameter.Last.Value, ((ListType)right.type).innerType))
289
                    return Error(expression, "Last paramter does not match inner-type of list in fold/map operation");
290

    
291

    
292
                expression.SetLeftChild(leftcall);
293
                expression.SetMidChild(mid);
294
                expression.SetRightChild(right);
295
                if (!isMap)
296
                    expression.SetType(funType.returnType);
297
                else
298
                    expression.SetType(new NullType());
299
                return expression;
300
            }
301
            else
302
                throw new ArgumentException();
303
        }
304
        private Expression ResolveExpression(ForallQuantifier expression)
305
        {
306
            Expression child = ResolveExpression(expression.child);
307
            if (child == null)
308
                return null;
309

    
310
            expression.SetType(new BoolType(null));
311
            expression.SetChild(child);
312
            return expression;
313
        }
314
        private Expression ResolveExpression(ExistsQuantifier expression)
315
        {
316
            Expression child = ResolveExpression(expression.child);
317
            if (child == null)
318
                return null;
319

    
320
            expression.SetType(new BoolType(null));
321
            expression.SetChild(child);
322
            return expression;
323
        }
324
        private Expression ResolveExpression(ListConstructor expression)
325
        {
326
            UlyssesType type = null;
327
            ListType restype = null;
328
            Expression comprehension = null;
329
            if (expression.comprehension != null)
330
            {
331
                comprehension = ResolveExpressionNewScope(expression.comprehension);
332

    
333
                if (comprehension == null)
334
                    return null;
335

    
336
                if (comprehension.type == null)
337
                    return Error(expression, "List comprehension has void expression");
338

    
339
                if (comprehension.type.kind != TypeKind.BoolType)
340
                    return Error(expression, "List comprehension has to be bool-expression");
341

    
342
                expression.SetComprehension(comprehension);
343

    
344
                if (expression.elements.Count != 1)
345
                    return Error(expression, "List comprehension expects one initializer expression");
346
            }
347

    
348
            List<Expression> newitems = new List<Expression>();
349

    
350
            if (expression.elements.Count == 0 || expression.elements[0] == null || (
351
                expression.elements[0].kind == ExpressionKind.Value &&
352
                expression.elements[0] is ValueExpression<object> &&
353
                ((ValueExpression<object>)expression.elements[0]).value == null))
354
            {
355
                // empty list
356
                type = new NullType();
357
            }
358
            else
359
            {
360
                List<Expression> tmpitems = new List<Expression>();
361
                foreach (var item in expression.elements)
362
                {
363
                    Expression element = ResolveExpression(item);
364
                    if (element == null)
365
                        return null;
366
                    if (element.type == null)
367
                        return Error(expression, "Void expression in list initializer");
368

    
369
                    if (element.kind == ExpressionKind.Value &&
370
                        element is ValueExpression<object> &&
371
                        ((ValueExpression<object>)element).value == null)
372
                        return Error(expression, "Not-In-List (nil) values not allowed in a list");
373

    
374
                    // calculate the type we're constructing
375
                    if (type == null)
376
                        type = element.type;
377

    
378
                    type = UlyssesType.CoverType(type, element.type);
379
                    if (type == null)
380
                        return Error(expression, "List constructor needs matching types");
381

    
382
                    tmpitems.Add(element);
383
                }
384

    
385
                // now we have the resulting type - we still need to insert casts that might be necessary
386
                foreach (var item in tmpitems)
387
                {
388
                    if (!UlyssesType.TypeEqual(item.type, type))
389
                    {
390
                        Expression cast = new UnaryOperator(ExpressionKind.Cast, item, item.line, item.pos);
391
                        cast.SetType(type);
392
                        newitems.Add(cast);
393
                    }
394
                    else
395
                        newitems.Add(item);
396
                }
397

    
398
            }
399

    
400
            expression.SetElements(newitems);
401
            if (comprehension == null)
402
                restype = new ListType(type, newitems.Count, null);
403
            else
404
                restype = new ListType(type, -1, null); // we do not know anything about the bound
405

    
406
            expression.SetType(restype);
407
            return expression;
408
        }
409
        private Expression ResolveExpression(SetConstructor expression)
410
        {
411
            UlyssesType type = null;
412
            ListType restype = null;
413
            Expression comprehension = null;
414
            if (expression.comprehension != null)
415
            {
416
                comprehension = ResolveExpressionNewScope(expression.comprehension);
417

    
418
                if (comprehension == null)
419
                    return null;
420

    
421
                if (comprehension.type == null)
422
                    return Error(expression, "Set comprehension has void expression");
423

    
424
                if (comprehension.type.kind != TypeKind.BoolType)
425
                    return Error(expression, "Set comprehension has to be bool-expression");
426

    
427
                expression.SetComprehension(comprehension);
428

    
429
                if (expression.items.Count != 1)
430
                    return Error(expression, "Set comprehension expects one initializer expression");
431
            }
432

    
433
            List<Expression> newitems = new List<Expression>();
434
            foreach (var item in expression.items)
435
            {
436
                Expression element = ResolveExpression(item);
437
                if (element == null)
438
                    return null;
439

    
440
                if (element.type == null)
441
                    return Error(expression, "Void expression in set initializer");
442

    
443
                if (type == null)
444
                    type = element.type;
445
                type = UlyssesType.CoverType(type, element.type);
446
                if (type == null)
447
                    return Error(expression, "Set initializer needs matching types");
448

    
449
                newitems.Add(element);
450
            }
451
            expression.SetItems(newitems);
452
            restype = new ListType(type, newitems.Count, null);
453

    
454
            expression.SetType(restype);
455
            return expression;
456
        }
457
        private Expression ResolveExpression(MapConstructor expression)
458
        {
459
            UlyssesType domain = null;
460
            UlyssesType range = null;
461
            List<MapConstructor.MapItem> newitems = new List<MapConstructor.MapItem>();
462

    
463
            foreach (MapConstructor.MapItem item in expression.items)
464
            {
465
                Expression domexpr = ResolveExpression(item.key);
466
                if (domexpr == null)
467
                    return null;
468

    
469
                if (domexpr.type == null)
470
                    return Error(expression, "Domain initializing expression void");
471

    
472
                if (domain == null)
473
                    domain = domexpr.type;
474

    
475
                Expression rangeexpr = ResolveExpression(item.value);
476
                if (rangeexpr == null)
477
                    return null;
478

    
479
                if (rangeexpr.type == null)
480
                    return Error(expression, "Range initializing expression void");
481

    
482
                if (range == null)
483
                    range = rangeexpr.type;
484

    
485
                domain = UlyssesType.CoverType(domain, domexpr.type);
486
                range = UlyssesType.CoverType(range, rangeexpr.type);
487
                if (domain == null)
488
                    return Error(expression, "Types of domain expressions do not match");
489

    
490
                if (range == null)
491
                    return Error(expression, "Types of range expressions do not match");
492

    
493
                newitems.Add(new MapConstructor.MapItem(domexpr, rangeexpr));
494
            }
495

    
496
            expression.SetItems(newitems);
497
            MapType resulttype = new MapType(domain, range, newitems.Count, null);
498
            expression.SetType(resulttype);
499
            return expression;
500
        }
501
        private Expression ResolveExpression(TupleConstructor expression)
502
        {
503
            TupleType typeToConstruct = (TupleType)expression.tupleType.type;
504

    
505
            if (expression.values.Count != typeToConstruct.innerTypes.Count)
506
                return Error(expression, String.Format("Tuple constructor has wrong arity. ({0} <> {1})", typeToConstruct.innerTypes.Count, expression.values.Count));
507

    
508
            //TupleType resulttype = new TupleType(null);
509
            List<Expression> newvalexprs = new List<Expression>();
510

    
511
            LinkedListNode<UlyssesType> innerTargetType = typeToConstruct.innerTypes.First;
512
            int freeVarCount = 0;
513
            foreach (var initexpr in expression.values)
514
            {
515
                Expression newval = ResolveExpression(initexpr);
516
                if (newval == null)
517
                    return null;
518
                if (newval.type == null)
519
                    return Error(expression, "Element has void type");
520

    
521
                if (newval.type.kind == TypeKind.Any)
522
                {
523
                    // free var - so set type.
524
                    AnyType freevar = (AnyType)newval.type;
525
                    freevar.VariableIdentifier.SetType(innerTargetType.Value);
526
                    freevar.VariableIdentifier.SetInitialized(true);
527
                    freeVarCount++;
528
                }
529
                else
530
                {
531
                    UlyssesType acover = UlyssesType.CoverType(innerTargetType.Value, newval.type);
532
                    if (acover == null || !UlyssesType.TypeEqualByKind(innerTargetType.Value, acover))
533
                        return Error(expression, String.Format("Element in tuple constructor has non-matching type ({0} <> {1})", innerTargetType.Value.ToString(), newval.type.ToString()));
534

    
535
                    if (!UlyssesType.TypeEqual(acover, newval.type))
536
                    {
537
                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line, newval.pos);
538
                        newval.SetType(acover);
539
                    }
540
                    if (UlyssesType.FirstTypeLessRange(innerTargetType.Value, acover))
541
                        Warning(expression, String.Format("Tuple constructor may over/underflow: {0} := {1}", innerTargetType.Value.ToString(), acover.ToString()));
542
                }
543

    
544

    
545
                newvalexprs.Add(newval);
546
                //resulttype.AddType(newval.type);
547
                innerTargetType = innerTargetType.Next;
548
            }
549

    
550
            if (freeVarCount > 0)
551
            {
552
                if (freeVarCount != expression.values.Count)
553
                    return Error(expression, String.Format("Tuple constructor must have 0 or #elems ({0}) free variables", expression.values.Count));
554
                else
555
                {
556
                    expression.SetIsMatcher(true); // mark this tuple constructor as matcher, since this is the only thing it does..
557
                    m_matcherList.Add(expression); // matcher has to be bound by one equality
558
                }
559
            }
560

    
561
            expression.SetTupleValues(newvalexprs);
562
            //expression.SetType(resulttype);
563
            expression.SetType(typeToConstruct); // the constructor always will create the correct type!
564
            return expression;
565
        }
566

    
567
        private Expression ResolveExpression(QValConstructor expression)
568
        {
569
            Expression basevalue = null;
570
            Expression rangevalue = null;
571

    
572
            basevalue = ResolveExpression(expression.value[0]);
573
            if (basevalue == null || basevalue.kind != ExpressionKind.Access
574
                || basevalue.type == null || basevalue.type.kind != TypeKind.QrType)
575
                return Error(expression, "Landmark expected.");
576
            expression.SetType(basevalue.type);
577
            expression.SetValue(basevalue);
578

    
579
            if (expression.value.Length == 2)
580
            {
581
                rangevalue = ResolveExpression(expression.value[1]);
582
                if (rangevalue == null || rangevalue.kind != ExpressionKind.Access
583
                    || rangevalue.type == null || rangevalue.type.kind != TypeKind.QrType)
584
                    return Error(expression, "Landmark expected.");
585
                if (!UlyssesType.TypeEqual(basevalue.type, rangevalue.type))
586
                    return Error(expression, String.Format("Quantity spaces do not match: {0} <> {1}",
587
                        basevalue.type.ToString(),
588
                        rangevalue.type.ToString()));
589
                expression.AddRange(rangevalue);
590
            }
591
            return expression;
592
        }
593

    
594
        private Expression ResolveExpression(IdentifierExpression expression)
595
        {
596
            // nothing to do here, since we do not have any consts that may be
597
            // folded
598
            if (expression.identifier.kind == IdentifierKind.MethodIdentifier
599
                || expression.identifier.kind == IdentifierKind.NamedActionIdentifier)
600
                m_entryExpression.callTargets.Add((FunctionIdentifier)expression.identifier);
601

    
602
            return expression;
603
        }
604
        private Expression ResolveExpression(UnresolvedIdentifierExpression expression)
605
        {
606
            Identifier anid;
607
            //Identifier self = m_ParserState.Lookup("self");
608

    
609
            if (m_freeVariables.Peek().Defined(expression.tokenText))
610
                anid = m_freeVariables.Peek().Get(expression.tokenText);
611
            else
612
                anid = m_ParserState.Lookup(expression.tokenText, expression.scope);
613

    
614
            if (anid != null)
615
            {
616
                switch (anid.kind)
617
                {
618
                    case IdentifierKind.TypeIdentifier:
619
                        return new TypeExpression(anid.type, expression.line, expression.pos);
620

    
621
                    case IdentifierKind.MethodIdentifier:
622

    
623
                        m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
624
                        SelfTypeIdentifier selfid = (SelfTypeIdentifier)m_ParserState.Lookup("self", expression.scope);
625
                        if ((selfid != null) && ((OoActionSystemType)(selfid).type).symbols.Defined(anid))
626
                        {
627
                            // if it's a self access, add a self identifier (needed by cadp backend, e.g.)
628
                            // self.<method> is handled in a separate method and does not call us here!! (hence this code is working)
629
                            IdentifierExpression aself = new IdentifierExpression(selfid, expression.line, expression.pos);
630
                            aself.setIsSelf(true);
631
                            AccessExpression localaccess = new AccessExpression(aself, new IdentifierExpression(anid, expression.line, expression.pos),
632
                                expression.line, expression.pos);
633
                            ResolveExpression(localaccess);
634
                            return localaccess;
635
                        }
636
                        else
637
                        {
638
                            return new IdentifierExpression(anid, expression.line, expression.pos);
639
                        }
640

    
641
                    case IdentifierKind.NamedActionIdentifier:
642
                        m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
643
                        return new IdentifierExpression(anid, expression.line, expression.pos);
644

    
645
                    case IdentifierKind.Constant:
646
                        if (((ConstantIdentifier)anid).Value != null)
647
                            return ((ConstantIdentifier)anid).Value.Clone();
648
                        else
649
                            return null;
650

    
651
                    default:
652
                        return new IdentifierExpression(anid, expression.line, expression.pos);
653
                }
654
            }
655
            else
656
            {
657
                ExpressionVariableIdentifier freeVar =
658
                    new ExpressionVariableIdentifier(expression.tokenText, expression.line, expression.pos);
659
                freeVar.SetType(new AnyType(freeVar));
660
                m_freeVariables.Peek().AddIdentifier(freeVar);
661

    
662
                // add a warning about free variables - do not change text without changing the text in ooaTypeCheckVisitor..
663
                Warning(freeVar, String.Format("Free variable in expression: '{0}'.", freeVar.tokenText));
664

    
665
                return new IdentifierExpression(freeVar, expression.line, expression.pos);
666
            }
667
        }
668
        private Expression ResolveExpression(TupleMapAccessExpression expression)
669
        {
670
            Expression child = ResolveExpression(expression.child);
671
            if (child == null)
672
                return null;
673

    
674
            Expression arg = ResolveExpression(expression.argument);
675
            if (arg == null)
676
                return null;
677

    
678

    
679
            System.Diagnostics.Debug.Assert(child.type != null);
680

    
681
            if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.TupleType))
682
            {
683
                if ((arg.kind != ExpressionKind.Value)
684
                    || (((LeafExpression)arg).valueType != LeafTypeEnum.integer))
685
                {
686
                    return Error(expression, "Argument to tuple access must be constant integer value!");
687
                }
688
                TupleType aTuple = (TupleType)child.type;
689
                ValueExpression<int> aval = (ValueExpression<int>)arg;
690
                if ((aval.value < 0) || (aval.value >= aTuple.innerTypes.Count))
691
                {
692
                    return Error(expression, "Argument to tuple access has to be in range 0..#elems-1");
693
                }
694
                LinkedListNode<UlyssesType> anode = aTuple.innerTypes.First;
695
                int target = aval.value;
696
                while (target > 0)
697
                {
698
                    target--;
699
                    anode = anode.Next;
700
                }
701
                expression.SetType(anode.Value);
702
            }
703
            else if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.MapType))
704
            {
705
                MapType amap = (MapType)child.type;
706
                expression.SetType(amap.toType);
707
            }
708
            else if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.ListType))
709
            {
710
                // we allow element access of lists via list[i]
711
                ListType alist = (ListType)child.type;
712
                expression.SetType(alist.innerType);
713
            }
714
            else
715
            {
716
                return Error(expression, "Not a list, tuple, or map instance");
717
            }
718
            expression.SetArgument(arg);
719
            expression.SetChild(child);
720
            return expression;
721
        }
722
        private Expression ResolveExpression(CallExpression expression)
723
        {
724
            return ResolveExpression(expression, false);
725
        }
726
        private Expression ResolveExpression(CallExpression expression, bool allowFewerParameters)
727
        {
728
            // calc type of child
729
            Expression child = ResolveExpression(expression.child);
730
            if (child == null)
731
                return null;
732

    
733
            System.Diagnostics.Debug.Assert(child.type != null);
734

    
735
            expression.SetChild(child);
736

    
737
            if (child.type.kind != TypeKind.FunctionType)
738
            {
739
                return Error(expression, "No function to call!");
740
            }
741

    
742

    
743
            FunctionType funtype = (FunctionType)child.type;
744

    
745
            // check whether call of named action is allowed
746
            if (funtype.functionType != FunctionTypeEnum.Method)
747
            {
748
                // see if call is allowed: must not be called from within a named action
749
                IScope callingScope = expression.scope;
750
                while (callingScope != null)
751
                {
752
                    if (callingScope is NamedActionIdentifier || callingScope is MethodIdentifier)
753
                        return Error(expression, "Call of named Action only allowed in do-od block!");
754
                    callingScope = callingScope.GetParentScope();
755
                }
756
            }
757

    
758
            // check arguments
759
            int argsSpec = funtype.parameter.Count;
760
            int argsHave = expression.arguments.Count;
761
            if (argsHave < argsSpec && !allowFewerParameters)
762
            {
763
                return Error(expression, "Too few parameters in function call");
764
            }
765
            if (argsHave > argsSpec)
766
            {
767
                return Error(expression, "Too much parameters in function call");
768
            }
769

    
770
            List<Expression> newargs = new List<Expression>();
771
            LinkedListNode<UlyssesType> demandedArgType = funtype.parameter.First;
772
            foreach (var arg in expression.arguments)
773
            {
774
                Expression newarg = ResolveExpression(arg);
775
                if (newarg == null)
776
                    return null;
777

    
778
                if (newarg.GetUninitializedFreeVariables().Count > 0)
779
                    Error(arg, String.Format("Undefined variable '{0}'", newarg.GetUninitializedFreeVariables()[0].tokenText));
780

    
781
                Expression constantvalue = newarg.kind == ExpressionKind.Value ? newarg : null;
782

    
783
                UlyssesType acover = UlyssesType.CoverType(newarg.type, demandedArgType.Value);
784
                if (acover == null || !UlyssesType.TypeEqualByKind(demandedArgType.Value, acover))
785
                    return Error(arg, String.Format("Argument type does not match; expected: {0} delivered: {1}",
786
                        demandedArgType.Value.ToString(), newarg.type.ToString()));
787

    
788
                newarg = UnaryOperator.TryCoerceUp(newarg, acover);
789

    
790
                if (UlyssesType.FirstTypeLessRange(demandedArgType.Value, acover))
791
                {
792
                    if (constantvalue == null)
793
                    {
794
                        Warning(arg, String.Format("Call parameter may over/underflow: {0} := {1}", demandedArgType.Value.ToString(), acover.ToString()));
795
                        UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, newarg, newarg.line, newarg.pos);
796
                        cast.SetType(demandedArgType.Value);
797
                        newarg = cast;
798
                    }
799
                    else
800
                    {
801
                        Error(arg, String.Format("Call parameter out of range ({0}  := {1})", demandedArgType.Value.ToString(), constantvalue.ToString()));
802
                    }
803
                }
804

    
805
                demandedArgType = demandedArgType.Next;
806
                newargs.Add(newarg);
807
            }
808
            expression.SetArguments(newargs);
809

    
810
            if (funtype.returnType != null)
811
                expression.SetType(funtype.returnType);
812
            return expression;
813
        }
814
        private Expression ResolveExpression(AccessExpression expression)
815
        {
816
            Expression lhs = ResolveExpression(expression.left);
817
            if (lhs == null)
818
                return null;
819
            if (!(expression.right is UnresolvedIdentifierExpression))
820
            {
821
                expression.SetRightChild(ResolveExpression(expression.right));
822
                expression.SetType(expression.right.type);
823
                return expression;
824
            }
825

    
826
            bool selfAccess = (lhs.kind == ExpressionKind.Identifier) && ((IdentifierExpression)lhs).isSelf;
827
            bool staticAccess = lhs.kind == ExpressionKind.Type;
828
            UnresolvedIdentifierExpression access = (UnresolvedIdentifierExpression)expression.right;
829
            // atype could be null...
830
            UlyssesType atype = lhs.type;
831
            if ((lhs.kind == ExpressionKind.Call) && (atype == null))
832
            {
833
                return Error(access, "Can not access return type of void-function");
834
            }
835
            else if (atype == null)
836
            {
837
                return Error(access, "Can not access member of a void type");
838
            }
839

    
840
            // if we did not apply a call expression to a function
841
            if (atype.kind == TypeKind.FunctionType)
842
            {
843
                // we can access the return val...
844
                FunctionType fun = (FunctionType)atype;
845

    
846
                // check arity
847
                if (fun.parameter.Count > 0)
848
                    return Error(access, "Implicit function call not possible: Too few parameters.");
849

    
850
                // check return type
851
                if (fun.returnType == null)
852
                    return Error(access, "Can not access return type of void-function!");
853

    
854
                // call ok
855
                atype = fun.returnType;
856
                // but add callExpression
857
                lhs = new CallExpression(lhs, null, lhs.line, lhs.pos, null); // we do not know the scope
858
                lhs.SetType(atype);
859
            }
860

    
861
            // update left child
862
            expression.SetLeftChild(lhs);
863

    
864

    
865
            switch (atype.kind)
866
            {
867
                case TypeKind.OoActionSystemType:
868
                    Identifier anid = ((OoActionSystemType)atype).ResolveIdentifier(access.tokenText);
869
                    if (anid != null)
870
                    {
871
                        if (anid.kind == IdentifierKind.MethodIdentifier && !m_entryExpression.callTargets.Contains((FunctionIdentifier)anid))
872
                            m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
873

    
874
                        if (staticAccess)
875
                        {
876
                            if ((anid.kind == IdentifierKind.AttributeIdentifier) &&
877
                                (((AttributeIdentifier)anid).isStatic))
878
                            {
879
                                IdentifierExpression newrhs = new IdentifierExpression(anid, access.line, access.pos);
880
                                expression.SetRightChild(newrhs);
881
                            }
882
                            else
883
                                return Error(access, "Can not access non-static member of an action system");
884
                        }
885
                        else
886
                        {
887
                            if (anid.kind != IdentifierKind.MethodIdentifier && !selfAccess)
888
                                return Error(access, "Can only access methods of action system objects");
889
                            else
890
                            {
891
                                IdentifierExpression newrhs = new IdentifierExpression(anid, access.line, access.pos);
892
                                expression.SetRightChild(newrhs);
893
                            }
894
                        }
895
                    }
896
                    else
897
                        return Error(access, String.Format("{0} no member of {1}",
898
                                access.tokenText, ((OoActionSystemType)atype).identifier.tokenText));
899
                    break;
900
                case TypeKind.EnumeratedType:
901
                    EnumType anEnum = (EnumType)atype;
902
                    if (!staticAccess)
903
                    {
904
                        return Error(access, "Enum values can only be accessed statically.");
905
                    }
906
                    if (anEnum.symbolTable.Defined(access.tokenText))
907
                    {
908
                        Identifier enumid = anEnum.symbolTable.Get(access.tokenText);
909
                        IdentifierExpression newrhs = new IdentifierExpression(enumid, access.line, access.pos);
910
                        expression.SetRightChild(newrhs);
911
                    }
912
                    else
913
                        return Error(access, String.Format("{0} not contained in enum {1}",
914
                                access.tokenText, anEnum.identifier.tokenText));
915
                    break;
916
                case TypeKind.QrType:
917
                    QrType aQualitativeType = (QrType)atype;
918
                    if (!staticAccess)
919
                    {
920
                        return Error(access, String.Format("QSpace values can only be accessed statically."));
921
                    }
922
                    if (aQualitativeType.symbolTable.Defined(access.tokenText))
923
                    {
924
                        Identifier landmark = aQualitativeType.symbolTable.Get(access.tokenText);
925
                        IdentifierExpression newrhs = new IdentifierExpression(landmark, access.line, access.pos);
926
                        expression.SetRightChild(newrhs);
927
                    }
928
                    else
929
                        return Error(access, String.Format("{0} not contained in qspace {1}",
930
                                 access.tokenText, aQualitativeType.identifier.tokenText));
931
                    break;
932
                default:
933
                    /*error, we can not access an element with '.' in any other type*/
934
                    return Error(expression, "Expected: System, Enum, Func, or QR type");
935
            }
936

    
937
            expression.SetType(expression.right.type);
938
            return expression;
939
        }
940
        private Expression ResolveExpression(UnaryOperator expression)
941
        {
942
            Expression child = ResolveExpression(expression.child);
943
            // if there was some error, then exit
944
            if (child == null)
945
                return null;
946

    
947
            if (child.type == null)
948
                return Error(expression, "Can not apply unary operator to void-expression");
949

    
950

    
951
            switch (expression.kind)
952
            {
953
                case ExpressionKind.Primed:
954
                    expression.SetType(child.type);
955
                    break;
956

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

    
1092
            expression.SetChild(child);
1093
            return expression;
1094
        }
1095
        private Expression ResolveExpression(BinaryOperator expression)
1096
        {
1097
            Expression lhs = ResolveExpression(expression.left);
1098
            Expression rhs = ResolveExpression(expression.right);
1099

    
1100

    
1101
            // if there was some error, then exit
1102
            if ((lhs == null) || (rhs == null))
1103
                return null;
1104

    
1105
            UlyssesType lt = lhs.type;
1106
            UlyssesType rt = rhs.type;
1107

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

    
1111

    
1112
            switch (expression.kind)
1113
            {
1114
                /*map operators*/
1115
                case ExpressionKind.domresby:   // list of A * map A to B -> map A to B
1116
                case ExpressionKind.domresto:   // list of A * map A to B -> map A to B
1117
                    if (lt.kind != TypeKind.ListType)
1118
                        return Error(expression, "Domain restriction operator expects list on LHS");
1119
                    if (rt.kind != TypeKind.MapType)
1120
                        return Error(expression, "Domain restriction operator expects map on RHS");
1121
                    ListType domlist = (ListType)lt;
1122
                    MapType domMap = (MapType)rt;
1123
                    if (!UlyssesType.TypeEqual(domlist.innerType, domMap.fromType))
1124
                        return Error(expression, "Inner type of list and domain-type of map do not match");
1125
                    // since this is a restriction, maxnumofelems is ok
1126
                    expression.SetType(domMap);
1127
                    break;
1128
                case ExpressionKind.rngresby:   // map A to B * list of B -> map A to B
1129
                case ExpressionKind.rngresto:   // map A to B * list of B -> map A to B
1130
                    if (lt.kind != TypeKind.MapType)
1131
                        return Error(expression, "Range restriction operator expects map on LHS");
1132
                    if (rt.kind != TypeKind.ListType)
1133
                        return Error(expression, "Rangle restriction operator expects list on RHS");
1134
                    ListType rangelist = (ListType)rt;
1135
                    domMap = (MapType)lt;
1136
                    if (!UlyssesType.TypeEqual(rangelist.innerType, domMap.fromType))
1137
                        return Error(expression, "Inner type of list and rangle-type of map do not match");
1138
                    // since this is a restriction, maxnumofelems is ok
1139
                    expression.SetType(domMap);
1140
                    break;
1141
                case ExpressionKind.munion:     // map A to B * map A to B -> map A to B
1142
                    if (lt.kind != TypeKind.MapType ||
1143
                        rt.kind != TypeKind.MapType)
1144
                        return Error(expression, "Map union expects maps on LHS and RHS");
1145
                    domMap = (MapType)lt;
1146
                    MapType rngMap = (MapType)rt;
1147
                    if (!UlyssesType.TypeEqual(domMap.fromType, rngMap.fromType) ||
1148
                        !UlyssesType.TypeEqual(domMap.toType, rngMap.toType))
1149
                        return Error(expression, "Domain and Range types of maps must be equal");
1150
                    // union may change maximum number of elements..
1151
                    MapType resMap = new MapType(domMap.fromType, domMap.toType,
1152
                        domMap.maxNumberOfElements + rngMap.maxNumberOfElements, null);
1153
                    expression.SetType(resMap);
1154
                    break;
1155
                /*set/list binary*/
1156
                case ExpressionKind.conc:       // list of A * list of A -> list of A
1157
                    if (lt.kind != TypeKind.ListType ||
1158
                        rt.kind != TypeKind.ListType)
1159
                        return Error(expression, "List concatenation expects two lists.");
1160
                    ListType la = (ListType)lt;
1161
                    ListType lb = (ListType)rt;
1162

    
1163
                    if (lb.innerType.kind == TypeKind.Null || lb.maxNumberOfElements == 0)
1164
                        return lhs;
1165
                    if (la.innerType.kind == TypeKind.Null || la.maxNumberOfElements == 0)
1166
                        return rhs;
1167
                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
1168
                        return Error(expression, String.Format("Set/List concatenation expects two lists of same type. ({0} <> {1})", la.ToString(), lb.ToString()));
1169
                    ListType resultList = new ListType(la.innerType,
1170
                        la.maxNumberOfElements + lb.maxNumberOfElements, null);
1171
                    expression.SetType(resultList);
1172
                    break;
1173
                case ExpressionKind.diff:       // list of A * list of A -> list of A (does not respect dupes)
1174
                    if (lt.kind != TypeKind.ListType ||
1175
                        rt.kind != TypeKind.ListType)
1176
                        return Error(expression, "Set difference expects two lists.");
1177
                    la = (ListType)lt;
1178
                    lb = (ListType)rt;
1179
                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
1180
                        return Error(expression, "Set difference expects two lists of same type.");
1181
                    expression.SetType(la);
1182
                    break;
1183
                case ExpressionKind.inter:      // list of A * list of A -> list of A (does not respect dupes)
1184
                    if (lt.kind != TypeKind.ListType ||
1185
                        rt.kind != TypeKind.ListType)
1186
                        return Error(expression, "Set intersection expects two lists.");
1187
                    la = (ListType)lt;
1188
                    lb = (ListType)rt;
1189
                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
1190
                        return Error(expression, "Set intersection expects two lists of same type.");
1191
                    expression.SetType(la.maxNumberOfElements > lb.maxNumberOfElements ? la : lb);
1192
                    break;
1193
                case ExpressionKind.elemin:     // A * list of A -> bool
1194
                case ExpressionKind.notelemin:  // A * list of A -> bool
1195
                    if (rt.kind != TypeKind.ListType)
1196
                        return Error(expression, "Element (not) in operator expects list-type as RHS.");
1197
                    lb = (ListType)rt;
1198
                    if (!UlyssesType.TypeEqual(lt, lb.innerType))
1199
                        return Error(expression, "List and element must be of same type.");
1200
                    expression.SetType(new BoolType(null));
1201
                    break;
1202
                case ExpressionKind.subset:     // list of A * list of A -> bool (does not respect dupes)
1203
                    if (lt.kind != TypeKind.ListType ||
1204
                        rt.kind != TypeKind.ListType)
1205
                        return Error(expression, "Subset operation expects two lists.");
1206
                    la = (ListType)lt;
1207
                    lb = (ListType)rt;
1208
                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
1209
                        return Error(expression, "Subset operation expects two lists of same type.");
1210
                    expression.SetType(new BoolType(null));
1211
                    break;
1212
                case ExpressionKind.union:      // list of A * list of A -> list of A (does not respect dupes)
1213
                    if (lt.kind != TypeKind.ListType ||
1214
                        rt.kind != TypeKind.ListType)
1215
                        return Error(expression, "Set union expects two lists.");
1216
                    la = (ListType)lt;
1217
                    lb = (ListType)rt;
1218

    
1219
                    if (la.innerType.kind == TypeKind.Null || la.maxNumberOfElements == 0)
1220
                        return rhs;
1221
                    if (lb.innerType.kind == TypeKind.Null || lb.maxNumberOfElements == 0)
1222
                        return lhs;
1223

    
1224
                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
1225
                        return Error(expression, "Set union expects two lists of same type.");
1226
                    resultList = new ListType(la.innerType,
1227
                        la.maxNumberOfElements + lb.maxNumberOfElements, null);
1228
                    expression.SetType(resultList);
1229
                    break;
1230

    
1231
                /*numeric binary*/
1232
                case ExpressionKind.pow:
1233
                    if (!lt.IsNumeric() ||
1234
                        !rt.IsNumeric())
1235
                        return Error(expression, "Operator expects LHS and RHS to be numeric");
1236
                    if (lt.kind == TypeKind.IntType
1237
                        && rt.kind == TypeKind.IntType)
1238
                        expression.SetType(lt);
1239
                    else
1240
                        if (lt.kind == TypeKind.FloatType)
1241
                            expression.SetType(lt);
1242
                        else
1243
                        {
1244
                            IntType anint = (IntType)lt;
1245
                            expression.SetType(new FloatType(anint.rangeLow, anint.rangeHigh,
1246
                                FloatType.defaultPrecision, null));
1247
                        }
1248
                    break;
1249

    
1250
                case ExpressionKind.idiv:
1251
                case ExpressionKind.mod:
1252
                    if (rt.kind != TypeKind.IntType ||
1253
                        lt.kind != TypeKind.IntType)
1254
                        return Error(expression, "Operator expects LHS and RHS to be integer");
1255
                    expression.SetType(Expression.ArithmeticCover(lt, rt, expression.kind));
1256
                    break;
1257
                case ExpressionKind.div:
1258
                    if (!rt.IsNumeric() || !lt.IsNumeric())
1259
                        return Error(expression, "Operator expects LHS and RHS to be numeric");
1260
                    if (lhs.type is ValuedEnumType)
1261
                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
1262
                    if (rhs.type is ValuedEnumType)
1263
                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
1264
                    UlyssesType cover = Expression.ArithmeticCover(lt, rt, expression.kind);
1265
                    expression.SetType(cover);
1266
                    break;
1267
                case ExpressionKind.minus:
1268
                    if (!rt.IsNumeric() || !lt.IsNumeric())
1269
                        return Error(expression, "Operator expects LHS and RHS to be numeric");
1270
                    if (lhs.type is ValuedEnumType)
1271
                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
1272
                    if (rhs.type is ValuedEnumType)
1273
                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
1274
                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
1275
                    expression.SetType(cover);
1276
                    break;
1277
                case ExpressionKind.prod:
1278
                    if (!rt.IsNumeric() || !lt.IsNumeric())
1279
                        return Error(expression, "Operator expects LHS and RHS to be numeric");
1280
                    if (lhs.type is ValuedEnumType)
1281
                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
1282
                    if (rhs.type is ValuedEnumType)
1283
                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
1284
                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
1285
                    expression.SetType(cover);
1286
                    break;
1287
                case ExpressionKind.sum:
1288
                    if (!rt.IsNumeric() || !lt.IsNumeric())
1289
                        return Error(expression, "Operator expects LHS and RHS to be numeric");
1290
                    if (lhs.type is ValuedEnumType)
1291
                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
1292
                    if (rhs.type is ValuedEnumType)
1293
                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
1294
                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
1295
                    expression.SetType(cover);
1296
                    break;
1297
                case ExpressionKind.greater:
1298
                case ExpressionKind.greaterequal:
1299
                case ExpressionKind.less:
1300
                case ExpressionKind.lessequal:
1301
                    if (!((rt.IsNumeric() && lt.IsNumeric()) || (rt.IsQualitative() && lt.IsQualitative())))
1302
                        return Error(expression, "Operator expects LHS and RHS to be numeric or qualitative");
1303
                    cover = UlyssesType.CoverType(lt, rt);
1304
                    if (cover != null)
1305
                    {
1306
                        lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1307
                        rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1308
                        expression.SetType(new BoolType(null));
1309
                    }
1310
                    else
1311
                        return Error(expression, String.Format("Operator expects LHS and RHS to be of same type ({0} <> {1})", lhs.type.ToString(), rhs.type.ToString()));
1312
                    break;
1313
                /*bool binary*/
1314
                case ExpressionKind.and:
1315
                    if (rt.kind != TypeKind.BoolType ||
1316
                        lt.kind != TypeKind.BoolType)
1317
                        return Error(expression, "Operator expects LHS and RHS of bool.");
1318

    
1319
                    expression.SetType(rt);
1320
                    // little bit of optimization..
1321
                    if (rhs.kind == ExpressionKind.Value
1322
                        && ((ValueExpression<bool>)rhs).value == false)
1323
                        return rhs;
1324
                    else if (lhs.kind == ExpressionKind.Value
1325
                        && ((ValueExpression<bool>)lhs).value == false)
1326
                        return lhs;
1327

    
1328
                    // if both are true, then this will be taken care of in constant folding.
1329
                    break;
1330
                case ExpressionKind.biimplies:
1331
                    if (rt.kind != TypeKind.BoolType ||
1332
                        lt.kind != TypeKind.BoolType)
1333
                        return Error(expression, "Operator expects LHS and RHS of bool.");
1334
                    expression.SetType(rt);
1335
                    break;
1336
                case ExpressionKind.implies:
1337
                    if (rt.kind != TypeKind.BoolType ||
1338
                        lt.kind != TypeKind.BoolType)
1339
                        return Error(expression, "Operator expects LHS and RHS of bool.");
1340
                    expression.SetType(rt);
1341

    
1342
                    // ex falso...
1343
                    if (lhs.kind == ExpressionKind.Value
1344
                        && ((ValueExpression<bool>)lhs).value == false)
1345
                    {
1346
                        Expression shortcut = new ValueExpression<bool>(true, expression.line, expression.pos);
1347
                        shortcut.SetType(lt);
1348
                        return shortcut;
1349
                    }
1350

    
1351
                    break;
1352
                case ExpressionKind.or:
1353
                    if (rt.kind != TypeKind.BoolType ||
1354
                        lt.kind != TypeKind.BoolType)
1355
                        return Error(expression, "Operator expects LHS and RHS of bool.");
1356
                    expression.SetType(rt);
1357

    
1358
                    if (rhs.kind == ExpressionKind.Value
1359
                        && ((ValueExpression<bool>)rhs).value == true)
1360
                        return rhs;
1361
                    else if (lhs.kind == ExpressionKind.Value
1362
                        && ((ValueExpression<bool>)lhs).value == true)
1363
                        return lhs;
1364
                    break;
1365
                /*other binary*/
1366
                case ExpressionKind.equal:
1367
                case ExpressionKind.notequal:
1368
                    cover = UlyssesType.CoverType(lt, rt);
1369
                    if (cover != null)
1370
                    {
1371
                        /* see whether we have a tuple-matcher on one side.. */
1372
                        if (expression.kind == ExpressionKind.equal)
1373
                        {
1374
                            if (lhs.kind == ExpressionKind.TupleConstr &&
1375
                                ((TupleConstructor)lhs).isMatcher)
1376
                            {
1377
                                if (rhs.kind == ExpressionKind.TupleConstr &&
1378
                                    ((TupleConstructor)rhs).isMatcher)
1379
                                    return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1380
                                m_matcherList.Remove((TupleConstructor)lhs);
1381
                            }
1382
                            else if (rhs.kind == ExpressionKind.TupleConstr &&
1383
                                    ((TupleConstructor)rhs).isMatcher)
1384
                            {
1385
                                if (lhs.kind == ExpressionKind.TupleConstr &&
1386
                                    ((TupleConstructor)lhs).isMatcher)
1387
                                    return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
1388
                                m_matcherList.Remove((TupleConstructor)rhs);
1389
                            }
1390
                        }
1391

    
1392
                        lhs = UnaryOperator.TryCoerceUp(lhs, cover);
1393
                        rhs = UnaryOperator.TryCoerceUp(rhs, cover);
1394
                        expression.SetType(new BoolType(null));
1395
                    }
1396
                    else
1397
                        return Error(expression, String.Format("Operator expects LHS and RHS to be of same type ({0} <> {1})", lhs.type.ToString(), rhs.type.ToString()));
1398
                    break;
1399
                case ExpressionKind.seqmod_mapoverride:
1400
                    if (rt.kind != TypeKind.MapType)
1401
                        return Error(expression, "Map expected as RHS on sequence modification or map override.");
1402
                    // list of A * map int to A -> list of A or
1403
                    if (lt.kind == TypeKind.ListType)
1404
                    {
1405
                        // we're in sequence modification.
1406
                        domlist = (ListType)lt;
1407
                        rngMap = (MapType)rt;
1408
                        if (rngMap.fromType.kind != TypeKind.IntType)
1409
                            return Error(expression, "Domain of map has to be integer");
1410
                        if (!UlyssesType.TypeEqual(domlist.innerType, rngMap.toType))
1411
                            return Error(expression, "Type of list expected to match range of map");
1412
                        // since we only replace elements in the list (by matching ones from the map),
1413
                        // we're save to return the original list..
1414
                        expression.SetType(lt);
1415
                    }
1416
                    // map A to B * map A to B -> map A to B
1417
                    else if (lt.kind == TypeKind.MapType)
1418
                    {
1419
                        domMap = (MapType)lt;
1420
                        rngMap = (MapType)rt;
1421
                        if (!UlyssesType.TypeEqual(domMap.fromType, rngMap.fromType) ||
1422
                             !UlyssesType.TypeEqual(domMap.toType, rngMap.toType))
1423
                            return Error(expression, "Maps need same domain and range types");
1424
                        // since we override entries in the first map:
1425
                        expression.SetType(domMap);
1426
                    }
1427
                    else
1428
                        return Error(expression, "Sequence Modification or Map override expects list or map as LHS");
1429
                    break;
1430
                default:
1431
                    throw new NotImplementedException();
1432
            }
1433

    
1434
            // set subtrees.
1435
            expression.SetLeftChild(lhs);
1436
            expression.SetRightChild(rhs);
1437

    
1438
            // we only allow:  a = MyTuple(c,d) style matchers
1439
            if (m_matcherList.Count > 0)
1440
            {
1441
                m_matcherList.Clear();
1442
                return Error(expression, "Free variables in tuple constructor only allowed in expressions of the form 'atuple = ATupleConstructor(free1,free2...)'");
1443
            }
1444

    
1445
            // try simple constant folding
1446
            return ApplyConstantFolding(expression);
1447
        }
1448

    
1449

    
1450
        /// 
1451
        ///  We're also doing a bit of constant folding here.
1452
        /// 
1453

    
1454
        private Expression ApplyConstantFolding(UnaryOperator expression)
1455
        {
1456
            Expression child = expression.child;
1457
            if (child.type.IsNumeric() && expression.kind == ExpressionKind.Cast)
1458
            {
1459
                switch (expression.type.kind)
1460
                {
1461
                    case TypeKind.FloatType:
1462
                        if (child.type.kind == TypeKind.IntType && child.kind == ExpressionKind.Value)
1463
                        {
1464
                            Expression result = new ValueExpression<double>(((ValueExpression<int>)child).value, child.line, child.pos);
1465
                            result.SetType(expression.type);
1466
                            return result;
1467
                        }
1468
                        break;
1469
                }
1470
            }
1471
            return expression;
1472
        }
1473

    
1474
        private Expression ApplyConstantFolding(BinaryOperator expression)
1475
        {
1476
            Expression lhs = expression.left;
1477
            Expression rhs = expression.right;
1478

    
1479
            if (lhs.kind == ExpressionKind.Cast)
1480
            {
1481
                lhs = ApplyConstantFolding((UnaryOperator)lhs);
1482
                expression.SetLeftChild(lhs);
1483
            }
1484
            if (rhs.kind == ExpressionKind.Cast)
1485
            {
1486
                rhs = ApplyConstantFolding((UnaryOperator)rhs);
1487
                expression.SetRightChild(rhs);
1488
            }
1489

    
1490

    
1491
            if (lhs.kind == ExpressionKind.Value && rhs.kind == ExpressionKind.Value)
1492
                if (expression.type.kind == TypeKind.FloatType)
1493
                {
1494
                    double fval1 = ((ValueExpression<double>)lhs).value;
1495
                    double fval2 = ((ValueExpression<double>)rhs).value;
1496
                    double result = 0;
1497
                    switch (expression.kind)
1498
                    {
1499

    
1500
                        case ExpressionKind.sum:
1501
                            result = fval1 + fval2;
1502
                            break;
1503
                        case ExpressionKind.minus:
1504
                            result = fval1 - fval2;
1505
                            break;
1506
                        case ExpressionKind.prod:
1507
                            result = fval1 * fval2;
1508
                            break;
1509
                        case ExpressionKind.div:
1510
                            if (fval2 == 0)
1511
                                return Error(expression, "Division not defined");
1512
                            result = fval1 / fval2;
1513
                            break;
1514
                        default:
1515
                            // bail out, if we can not handle it
1516
                            return expression;
1517
                    }
1518
                    if (result < ((FloatType)expression.type).low
1519
                        || result > ((FloatType)expression.type).high)
1520
                        return Error(expression, "Internal Error: value after constant folding not in float-range!");
1521

    
1522
                    ValueExpression<double> resexp = new ValueExpression<double>(result, expression.line, expression.pos);
1523
                    resexp.SetType(expression.type);
1524
                    return resexp;
1525
                }
1526
                else if (expression.type.kind == TypeKind.IntType)
1527
                {
1528
                    int val1 = ((ValueExpression<int>)lhs).value;
1529
                    int val2 = ((ValueExpression<int>)rhs).value;
1530
                    int result = 0;
1531
                    switch (expression.kind)
1532
                    {
1533
                        case ExpressionKind.sum:
1534
                            result = val1 + val2;
1535
                            break;
1536
                        case ExpressionKind.minus:
1537
                            result = val1 - val2;
1538
                            break;
1539
                        case ExpressionKind.prod:
1540
                            result = val1 * val2;
1541
                            break;
1542
                        case ExpressionKind.idiv:
1543
                            if (val2 == 0)
1544
                                return Error(expression, "Division not defined.");
1545
                            result = val1 / val2;
1546
                            break;
1547
                        case ExpressionKind.mod:
1548
                            result = val1 % val2;
1549
                            break;
1550
                        default:
1551
                            // bail out, if we can not handle it
1552
                            return expression;
1553
                    }
1554

    
1555
                    if (result < ((IntType)expression.type).rangeLow
1556
                        || result > ((IntType)expression.type).rangeHigh)
1557
                        return Error(expression, "Internal Error: value after constant folding not in int-range!");
1558

    
1559
                    ValueExpression<int> intres = new ValueExpression<int>(result, expression.line, expression.pos);
1560
                    intres.SetType(expression.type);
1561
                    return intres;
1562
                }
1563
                else if (expression.type.kind == TypeKind.BoolType)
1564
                {
1565
                    bool result = false;
1566
                    switch (expression.kind)
1567
                    {
1568
                        case ExpressionKind.greater:
1569
                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
1570
                            switch (lhs.type.kind)
1571
                            {
1572
                                case TypeKind.IntType:
1573
                                    result = ((ValueExpression<int>)lhs).value >
1574
                                                ((ValueExpression<int>)rhs).value;
1575
                                    break;
1576
                                case TypeKind.FloatType:
1577
                                    result = ((ValueExpression<double>)lhs).value >
1578
                                                ((ValueExpression<double>)rhs).value;
1579
                                    break;
1580
                                default:
1581
                                    return expression;
1582
                            }
1583
                            break;
1584
                        case ExpressionKind.greaterequal:
1585
                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
1586
                            switch (lhs.type.kind)
1587
                            {
1588
                                case TypeKind.IntType:
1589
                                    result = ((ValueExpression<int>)lhs).value >=
1590
                                                ((ValueExpression<int>)rhs).value;
1591
                                    break;
1592
                                case TypeKind.FloatType:
1593
                                    result = ((ValueExpression<double>)lhs).value >=
1594
                                                ((ValueExpression<double>)rhs).value;
1595
                                    break;
1596
                                default:
1597
                                    return expression;
1598
                            }
1599
                            break;
1600
                        case ExpressionKind.less:
1601
                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
1602
                            switch (lhs.type.kind)
1603
                            {
1604
                                case TypeKind.IntType:
1605
                                    result = ((ValueExpression<int>)lhs).value <
1606
                                                ((ValueExpression<int>)rhs).value;
1607
                                    break;
1608
                                case TypeKind.FloatType:
1609
                                    result = ((ValueExpression<double>)lhs).value <
1610
                                                ((ValueExpression<double>)rhs).value;
1611
                                    break;
1612
                                default:
1613
                                    return expression;
1614
                            }
1615
                            break;
1616
                        case ExpressionKind.lessequal:
1617
                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
1618
                            switch (lhs.type.kind)
1619
                            {
1620
                                case TypeKind.IntType:
1621
                                    result = ((ValueExpression<int>)lhs).value <=
1622
                                                ((ValueExpression<int>)rhs).value;
1623
                                    break;
1624
                                case TypeKind.FloatType:
1625
                                    result = ((ValueExpression<double>)lhs).value <=
1626
                                                ((ValueExpression<double>)rhs).value;
1627
                                    break;
1628
                                default:
1629
                                    return expression;
1630
                            }
1631
                            break;
1632
                        case ExpressionKind.and:
1633
                            result = ((ValueExpression<bool>)lhs).value && ((ValueExpression<bool>)rhs).value;
1634
                            break;
1635
                        case ExpressionKind.equal:
1636
                            // we have to be careful here, since equal takes all sorts of types..
1637
                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
1638
                            switch (lhs.type.kind)
1639
                            {
1640
                                case TypeKind.BoolType:
1641
                                    result = ((ValueExpression<bool>)lhs).value ==
1642
                                        ((ValueExpression<bool>)rhs).value;
1643
                                    break;
1644
                                case TypeKind.IntType:
1645
                                    result = ((ValueExpression<int>)lhs).value ==
1646
                                        ((ValueExpression<int>)rhs).value;
1647
                                    break;
1648
                                case TypeKind.FloatType:
1649
                                    result = ((ValueExpression<double>)lhs).value ==
1650
                                        ((ValueExpression<double>)rhs).value;
1651
                                    break;
1652
                                default:
1653
                                    return expression;
1654
                            }
1655
                            break;
1656
                        case ExpressionKind.biimplies:
1657
                            result = ((ValueExpression<bool>)lhs).value == ((ValueExpression<bool>)rhs).value;
1658
                            break;
1659
                        case ExpressionKind.implies:
1660
                            result = !((ValueExpression<bool>)lhs).value || ((ValueExpression<bool>)rhs).value;
1661
                            break;
1662
                        case ExpressionKind.or:
1663
                            result = ((ValueExpression<bool>)lhs).value || ((ValueExpression<bool>)rhs).value;
1664
                            break;
1665
                        default:
1666
                            return expression;
1667
                    }
1668
                    ValueExpression<bool> boolres = new ValueExpression<bool>(result, expression.line, expression.pos);
1669
                    boolres.SetType(expression.type);
1670
                    return boolres;
1671
                }
1672

    
1673
            return expression;
1674
        }
1675

    
1676

    
1677
        /// 
1678
        ///  "jump table" (could by avoided by 'dynamic' type as found in c#4)
1679
        /// 
1680

    
1681
        private Expression ResolveExpression(Expression expression)
1682
        {
1683
            if (expression == null) return null;
1684

    
1685
            Expression result = expression;
1686

    
1687
            switch (expression.kind)
1688
            {
1689
                case ExpressionKind.Value:
1690
                    LeafExpression aValue = (LeafExpression)expression;
1691
                    switch (aValue.valueType)
1692
                    {
1693
                        case LeafTypeEnum.boolean:
1694
                            expression.SetType(new BoolType(null));
1695
                            break;
1696
                        case LeafTypeEnum.chr:
1697
                            expression.SetType(new CharType(null));// IntType(0, 255, null));
1698
                            break;
1699
                        case LeafTypeEnum.complex:
1700
                        case LeafTypeEnum.identifier:
1701
                            System.Diagnostics.Debug.Assert(false);
1702
                            break;
1703
                        case LeafTypeEnum.integer:
1704
                            int val = ((ValueExpression<int>)expression).value;
1705
                            expression.SetType(new IntType(val, val, null));
1706
                            break;
1707
                        case LeafTypeEnum.qval:
1708
                            throw new NotImplementedException();
1709
                        case LeafTypeEnum.real:
1710
                            double fval = ((ValueExpression<double>)expression).value;
1711
                            expression.SetType(new FloatType(fval, fval, fval, null));
1712
                            break;
1713
                        case LeafTypeEnum.reference:
1714
                            object aref = ((ValueExpression<object>)expression).value;
1715
                            if (aref == null)
1716
                                expression.SetType(new NullType());
1717
                            else
1718
                            {
1719
                                System.Diagnostics.Debug.Assert(false);
1720
                                return null;
1721
                            }
1722
                            break;
1723
                        case LeafTypeEnum.unset:
1724
                            throw new NotImplementedException();
1725
                    }
1726
                    result = expression;
1727
                    break;
1728

    
1729
                /* ternary operators */
1730
                case ExpressionKind.conditional:
1731
                case ExpressionKind.foldLR:
1732
                case ExpressionKind.foldRL:
1733
                    result = ResolveExpression((TernaryOperator)expression);
1734
                    break;
1735

    
1736
                /* forall */
1737
                case ExpressionKind.forall:
1738
                    result = ResolveExpression((ForallQuantifier)expression);
1739
                    break;
1740

    
1741
                /* exists */
1742
                case ExpressionKind.exists:
1743
                    result = ResolveExpression((ExistsQuantifier)expression);
1744
                    break;
1745

    
1746
                /* constructors */
1747
                case ExpressionKind.ListConstr:
1748
                    result = ResolveExpression((ListConstructor)expression);
1749
                    break;
1750
                case ExpressionKind.SetConstr:
1751
                    result = ResolveExpression((SetConstructor)expression);
1752
                    break;
1753
                case ExpressionKind.MapConstr:
1754
                    result = ResolveExpression((MapConstructor)expression);
1755
                    break;
1756
                case ExpressionKind.TupleConstr:
1757
                    result = ResolveExpression((TupleConstructor)expression);
1758
                    break;
1759
                case ExpressionKind.ObjectConstr:
1760
                    result = expression;
1761
                    break;
1762
                case ExpressionKind.QValConstr:
1763
                    result = ResolveExpression((QValConstructor)expression);
1764
                    break;
1765

    
1766
                /* identifiers */
1767
                case ExpressionKind.Identifier:
1768
                    result = ResolveExpression((IdentifierExpression)expression);
1769
                    break;
1770
                case ExpressionKind.UnresolvedIdentifier:
1771
                    result = ResolveExpression((UnresolvedIdentifierExpression)expression);
1772
                    break;
1773

    
1774
                /* evaluate */
1775
                case ExpressionKind.TupleMapAccess:
1776
                    result = ResolveExpression((TupleMapAccessExpression)expression);
1777
                    break;
1778
                case ExpressionKind.Call:
1779
                    result = ResolveExpression((CallExpression)expression);
1780
                    break;
1781

    
1782
                /* access some element within a class.. */
1783
                case ExpressionKind.Access:
1784
                    result = ResolveExpression((AccessExpression)expression);
1785
                    break;
1786

    
1787

    
1788
                case ExpressionKind.Cast:
1789
                    UnaryOperator cast = (UnaryOperator)expression;
1790

    
1791
                    /*prevent casts of complex datatypes, e.g. lists etc..*/
1792
                    if (cast.type.kind != TypeKind.OoActionSystemType)
1793
                        return Error(cast, String.Format("Cast operator needs class type as argument"));
1794

    
1795
                    cast.SetChild(ResolveExpression(cast.child));
1796
                    UlyssesType acover = UlyssesType.CoverType(cast.type, cast.child.type);
1797
                    bool upcast = UlyssesType.TypeEqual(acover, cast.type);           // the cast is safe; Mostly used in list constructors..
1798
                    bool downcast = UlyssesType.TypeEqual(acover, cast.child.type); // downcast, unsafe.
1799
                    if (downcast)
1800
                        Info(cast, String.Format("Potentially unsafe downcast: {0} as {1} (cover: {2})",
1801
                            cast.child.type.ToString(), cast.type.ToString(), acover.ToString()));
1802
                    if (acover == null || !(upcast || downcast))
1803
                    if (acover == null || !UlyssesType.TypeEqual(acover, cast.type))
1804
                        return Error(cast, String.Format("Invalid cast: {0} as {1} (cover: {2})", cast.child.type.ToString(), cast.type.ToString(), acover != null ? acover.ToString() : "<none>"));
1805
                    result = cast;
1806
                    break;
1807

    
1808
                /* general unary operators */
1809
                case ExpressionKind.Primed:
1810
                case ExpressionKind.unminus:
1811
                case ExpressionKind.unplus:
1812
                case ExpressionKind.not:
1813
                case ExpressionKind.abs:
1814
                case ExpressionKind.dom:
1815
                case ExpressionKind.range:
1816
                case ExpressionKind.merge:
1817
                case ExpressionKind.card:
1818
                case ExpressionKind.dconc:
1819
                case ExpressionKind.dinter:
1820
                case ExpressionKind.dunion:
1821
                case ExpressionKind.elems:
1822
                case ExpressionKind.head:
1823
                case ExpressionKind.inds:
1824
                case ExpressionKind.len:
1825
                case ExpressionKind.tail:
1826
                    result = ResolveExpression((UnaryOperator)expression);
1827
                    break;
1828

    
1829
                /* general binary operators */
1830
                case ExpressionKind.domresby:
1831
                case ExpressionKind.domresto:
1832
                case ExpressionKind.rngresby:
1833
                case ExpressionKind.rngresto:
1834
                case ExpressionKind.munion:
1835
                case ExpressionKind.conc:
1836
                case ExpressionKind.diff:
1837
                case ExpressionKind.inter:
1838
                case ExpressionKind.elemin:
1839
                case ExpressionKind.notelemin:
1840
                case ExpressionKind.subset:
1841
                case ExpressionKind.union:
1842
                case ExpressionKind.div:
1843
                case ExpressionKind.greater:
1844
                case ExpressionKind.greaterequal:
1845
                case ExpressionKind.idiv:
1846
                case ExpressionKind.less:
1847
                case ExpressionKind.lessequal:
1848
                case ExpressionKind.minus:
1849
                case ExpressionKind.mod:
1850
                case ExpressionKind.pow:
1851
                case ExpressionKind.prod:
1852
                case ExpressionKind.sum:
1853
                case ExpressionKind.and:
1854
                case ExpressionKind.biimplies:
1855
                case ExpressionKind.implies:
1856
                case ExpressionKind.or:
1857
                case ExpressionKind.equal:
1858
                case ExpressionKind.notequal:
1859
                case ExpressionKind.seqmod_mapoverride:
1860
                    result = ResolveExpression((BinaryOperator)expression);
1861
                    break;
1862
                default:
1863
                    throw new NotImplementedException();
1864
            }
1865

    
1866
            return result;
1867
        }
1868

    
1869

    
1870
        public Expression ResolveExpressionNewScope(Expression toResolve)
1871
        {
1872
            Expression result = null;
1873

    
1874
            m_freeVariables.Push(new SymbolTable());
1875
            try
1876
            {
1877
                result = ResolveExpression(toResolve);
1878
            }
1879
            finally
1880
            {
1881
                if (result != null)
1882
                    result.SetFreeVariables(m_freeVariables.Pop());
1883
            }
1884
            return result;
1885
        }
1886

    
1887

    
1888
        /// 
1889
        ///  called for every element in the ast        
1890
        /// 
1891

    
1892
        protected override void VisitAstElement(IAst subElement, IAst parent)
1893
        {
1894
            if (subElement.nodeType == AstNodeTypeEnum.expression)
1895
            {
1896
                // calculate a new (resolved) expression
1897
                m_freeVariables.Push(new SymbolTable());
1898
                // save toplevel -- used to keep track of method calls.
1899
                m_entryExpression = (Expression)subElement;
1900

    
1901
                Expression newExpression = ResolveExpression(m_entryExpression);
1902
                // replace the expression in the parent
1903
                if (newExpression != null)
1904
                {
1905
                    newExpression.SetFreeVariables(m_freeVariables.Pop());
1906
                    ReplaceExpression(parent, (Expression)subElement, newExpression);
1907
                }
1908

    
1909
            }
1910
            else
1911
                subElement.Accept(this); // saves us the call to base.VisitAstElement
1912
        }
1913

    
1914

    
1915
        /// 
1916
        ///  PUBLIC METHODS
1917
        /// 
1918

    
1919
        public OoaResolveExpressionsVisitor(ParserState aState)
1920
            : base(aState)
1921
        {
1922
            if (aState == null)
1923
                throw new ArgumentException();
1924
        }
1925
    }
1926

    
1927
}