Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / codegen / Prolog / ooaPrologExpression.cs

1 3 krennw
/**
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
/*
20
 * Prolog Code Generator
21
 */
22
23
using System;
24
using System.Collections.Generic;
25
using System.Text;
26
using TUG.Mogentes.Codegen;
27
28
29
namespace TUG.Mogentes.Codegen.Prolog
30
{
31
    public class OoaPrologExpression : OoaExpressionVisitor
32
    {
33
        public class Factory
34
        {
35
            public OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory)
36
            { return create(idFactory, typeFactory, false); }
37
            public virtual OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, bool lhs)
38
            { return new OoaPrologExpression(idFactory, typeFactory, this, lhs); }
39
        }
40
41
        protected OoaCodeEmitter m_emitter = new OoaCodeEmitter();
42
        protected List<string> m_tmpVars = new List<string>();
43
        private bool m_LhsExpression = false;
44
45
46
        public List<string> tmpVariables { get { return m_tmpVars; } }
47
        public bool isLhsExpression { get { return m_LhsExpression; } }
48
49
        private string GetPrologType(UlyssesType aType)
50
        {
51
            OoaPrologType pType = createTypeVisitor();
52
            aType.Accept(pType);
53
            return pType.ToString();
54
        }
55
56
        protected string GetIdentifierString(Identifier anIdentifier)
57
        {
58
            OoaPrologIdentifier pIdent = createIdentifierVisitor();
59
            anIdentifier.Accept(pIdent);
60
            return pIdent.ToString();
61
        }
62
63
64
        // following call must not happen
65
        public override void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
66
        {
67
            System.Diagnostics.Debug.Assert(false);
68
        }
69
70
        // call of method that returns a value..
71
        public override void visit(CallExpression callExpression)
72
        {
73
            // we handle only function calls within expressions here (must have non-void return!)
74
            FunctionType funtype = (FunctionType)callExpression.child.type;
75
            if (funtype.returnType == null)
76
                throw new ArgumentException("Internal error: Function call in expression with return-type void!");
77
78
            string callstatement = String.Empty;
79
            StringBuilder parameter = new StringBuilder();
80
81
            OoaPrologExpression prologexpr = createExpressionVisitor();
82
            callExpression.child.Accept(prologexpr);
83
84
            m_emitter.Append(prologexpr.ToString());
85
            callstatement = prologexpr.tmpVariables[0];
86
            int i = 0;
87
            foreach (var arg in callExpression.arguments)
88
            {
89
                if (i != 0)
90
                    parameter.Append(", ");
91
                else
92
                    i++;
93
                OoaPrologExpression paramexpr = createExpressionVisitor();
94
                arg.Accept(paramexpr);
95
                m_emitter.Append(paramexpr.ToString());
96
                parameter.Append(paramexpr.tmpVariables[0]);
97
            }
98
            if (parameter.Length > 0)
99
                m_emitter.AppendLine(String.Format("{0}({1},{2}),", callstatement, parameter, NewTempVariable()));
100
            else
101
                m_emitter.AppendLine(String.Format("{0}({1}),", callstatement, NewTempVariable()));
102
        }
103
104
105
        // we need to map all other things to Prolog constructs
106
        private string OperatorString(Expression expression, UlyssesType resultingType)
107
        {
108
            switch (expression.kind)
109
            {
110
                case ExpressionKind.abs:    // T_ABS:
111
                case ExpressionKind.card:   // T_CARD:
112
                case ExpressionKind.dom:    // T_DOM:
113
                case ExpressionKind.range:  // T_RNG:
114
                case ExpressionKind.merge:  // T_MERGE:
115
                case ExpressionKind.elems:  // T_ELEMS:
116
                case ExpressionKind.head:   // T_HEAD:
117
                case ExpressionKind.tail:   // T_TAIL:
118
                case ExpressionKind.conc:   // T_CONC:
119
                case ExpressionKind.inds:   // T_INDS:
120
                case ExpressionKind.dinter: // T_DINTER:
121
                case ExpressionKind.dunion: // T_DUNION:
122
                case ExpressionKind.domresby:   // T_DOMRESBY:
123
                case ExpressionKind.domresto:   // T_DOMRESTO:
124
                case ExpressionKind.rngresby:   // T_RNGRESBY:
125
                case ExpressionKind.rngresto:   // T_RNGRESTO:
126
                case ExpressionKind.inter:  // T_INTER:
127
                case ExpressionKind.union:  // T_UNION:
128
                case ExpressionKind.diff:   // T_DIFF:
129
                case ExpressionKind.munion: // T_MUNION:
130
                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
131
                case ExpressionKind.subset:
132
                case ExpressionKind.elemin:
133
                case ExpressionKind.notelemin:
134
                case ExpressionKind.implies:    // T_IMPLIES:
135
                case ExpressionKind.biimplies:  // T_BIIMPLIES:
136
                case ExpressionKind.Primed:
137
                case ExpressionKind.len:    // T_LEN:
138
                    throw new NotImplementedException();
139
140
                case ExpressionKind.div:    // T_DIV:
141
                    return "/";
142
                case ExpressionKind.idiv:   // T_IDIV:
143
                    return "/";
144
                case ExpressionKind.mod:    // T_MOD:
145
                    return "mod";
146
                case ExpressionKind.prod:   // T_PROD:
147
                    return "*";
148
                case ExpressionKind.sum:    // T_SUM:
149
                    return "+";
150
                case ExpressionKind.minus:  // T_MINUS:
151
                    return "-";
152
                case ExpressionKind.less:
153
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
154
                case ExpressionKind.lessequal:
155
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
156
                case ExpressionKind.greater:
157
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
158
                case ExpressionKind.greaterequal:
159
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
160
                case ExpressionKind.equal:
161
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "==" : "#=";
162
                case ExpressionKind.notequal:
163
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "\\=" : "#\\=";
164
                case ExpressionKind.and:    // T_AND:
165
                    throw new NotImplementedException(); // implemented in binaryoperator
166
                case ExpressionKind.or:     // T_OR:
167
                    throw new NotImplementedException(); // implemented in binaryoperator
168
                case ExpressionKind.not:
169
                    throw new NotImplementedException(); // implemented in binaryoperator
170
171
                case ExpressionKind.Cast:
172
                    return String.Empty;
173
174
                default:
175
                    return Enum.GetName(typeof(ExpressionKind), expression.kind);
176
            }
177
        }
178
179
        protected bool isNumericBinary(Expression expression)
180
        {
181
            bool result = false;
182
            if (expression is BinaryOperator)
183
            {
184
                result = ((BinaryOperator)expression).left.type.kind == TypeKind.IntType &&
185
                    ((BinaryOperator)expression).right.type.kind == TypeKind.IntType;
186
            }
187
            else if (expression is UnaryOperator)
188
            {
189
                result = ((UnaryOperator)expression).child.type.kind == TypeKind.IntType;
190
            }
191
            else throw new NotImplementedException();
192
            return result;
193
        }
194
195
        public override void visit<T>(ValueExpression<T> valueExpression)
196
        {
197
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
198
            string tmpVar = NewTempVariable();
199
            m_emitter.Append(String.Format("{0} ", tmpVar));
200
201
202
            if (valueExpression.value == null)
203
                m_emitter.Append("= 'null'");
204
            else if (valueExpression is ValueExpression<bool>)
205
                m_emitter.Append((valueExpression as ValueExpression<bool>).value ? " #= true" : " #= fail");
206
            else if (valueExpression is ValueExpression<char>)
207
                m_emitter.Append(String.Format("#= '{0}'", valueExpression.ToString()));
208
            else if (valueExpression is ValueExpression<int>)
209
                m_emitter.Append(String.Format("#= {0}", valueExpression.ToString()));
210
            else
211
                m_emitter.Append(String.Format("= {0}", valueExpression.value.ToString()));
212
213
            m_emitter.AppendLine(",");
214
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
215
        }
216
217
        public override void visit(IdentifierExpression identifierExpression)
218
        {
219
            if (identifierExpression.identifier.kind == IdentifierKind.LandmarkIdentifier)
220
            {
221
                LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier;
222
                OoaPrologIdentifier pid = createIdentifierVisitor();
223
                lmid.Accept(pid);
224
                //m_emitter.Append(pid.ToString());
225
                m_tmpVars.Add(pid.ToString());
226
                return;
227
            }
228
            else if (identifierExpression.identifier.kind == IdentifierKind.EnumIdentifier)
229
            {
230
                EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier;
231
                EnumType enumType = (EnumType)enumid.type;
232
                //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
233
                if (enumType is ValuedEnumType)
234
                    m_emitter.AppendLine(String.Format("{0} #= {1},", NewTempVariable(), enumid.Value));
235
                else
236
                    m_emitter.AppendLine(String.Format("{0} #= {1},", NewTempVariable(), enumType.listOfEnumSymbols.IndexOf(enumid).ToString()));
237
            }
238
            else if (identifierExpression.isSelf)
239
            {
240
                m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
241
            }
242
            /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
243
            {
244
                m_emitter.AppendLine(String.Format("getVal({1},{0},_),", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
245
            }*/
246
            else
247
            {
248
                //m_emitter.Append(GetIdentifierString(identifierExpression.identifier));
249
                m_tmpVars.Add(GetIdentifierString(identifierExpression.identifier));
250
            }
251
        }
252
253
        public override void visit(TypeExpression typeExpression)
254
        {
255
            if (typeExpression.type.kind != TypeKind.QrType &&
256
                typeExpression.type.kind != TypeKind.EnumeratedType)
257
            {
258
                //m_emitter.Append(GetIdentifierString(typeExpression.type.identifier));
259
                m_emitter.Append(GetIdentifierString(typeExpression.type.identifier));
260
            }
261
        }
262
263
264
        public override void visit(ObjectConstructor objectConstructor)
265
        {
266
            if (objectConstructor.instances.Count > 1)
267
                throw new NotImplementedException();
268
269
            m_emitter.AppendLine(String.Format("{0} = '{1}',", NewTempVariable(), objectConstructor.instances[0].Name));
270
271
            //m_emitter.Append(String.Format("new {0}(this)", GetIdentifierString(objectConstructor.type.identifier)));
272
        }
273
274
        public override void visit(ListConstructor listConstructor)
275
        {
276
            if (listConstructor.hasComprehension)
277
            {
278
                OoaPrologExpression compr = createExpressionVisitor();
279
                listConstructor.comprehension.Accept(compr);
280
                OoaPrologExpression elem = createExpressionVisitor();
281
                listConstructor.elements[0].Accept(elem);
282
283
                StringBuilder enumvars = new StringBuilder();
284
                int i = 0;
285
                foreach (var v in listConstructor.comprehensionVariables.symbolList)
286
                {
287
                    OoaPrologIdentifier ident = createIdentifierVisitor();
288
                    v.Accept(ident);
289
290
                    OoaPrologType identType = createTypeVisitor();
291
                    v.type.Accept(identType);
292
293
                    enumvars.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
294
                    i++;
295
                }
296
297
                m_emitter.AppendLine("% listcomprehension");
298
                m_emitter.AppendLine(String.Format("{0} = {{{1}:[{2}]:({3}{4},{5}{6})}}",
299
                    NewTempVariable(), elem.tmpVariables[0], enumvars.ToString(), compr.ToString(), compr.tmpVariables[0],
300
                    elem.ToString(), "1=1" /*elem.ToString() == String.Empty ? "1=1" : elem.tmpVariables[0]*/));
301
            }
302
            else
303
            {
304
                m_emitter.AppendLine("% make list");
305
                m_emitter.AppendLine(String.Format("{0} = []", NewTempVariable()));
306
307
                foreach (var expr in listConstructor.elements)
308
                {
309
                    m_emitter.Append(", ");
310
311
                    OoaPrologExpression pVal = createExpressionVisitor();
312
                    expr.Accept(pVal);
313
                    m_emitter.Append(pVal.ToString());
314
                    System.Diagnostics.Debug.Assert(pVal.tmpVariables.Count == 1);
315
                    m_emitter.AppendLine(String.Format("ulyssesListConc({0},[{1}],{2})", m_tmpVars[0], pVal.tmpVariables[0], NewTempVariable()));
316
                    m_tmpVars.RemoveAt(0);
317
                }
318
            }
319
            m_emitter.Append(",");
320
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
321
        }
322
323
        public override void visit(SetConstructor setConstructor)
324
        {
325
            throw new NotImplementedException();
326
        }
327
328
        public override void visit(MapConstructor mapConstructor)
329
        {
330
            throw new NotImplementedException();
331
        }
332
333
        public override void visit(TupleConstructor tupleConstructor)
334
        {
335
            if (tupleConstructor.isMatcher)
336
            {
337
                // being dealt with in binaryoperator (since we only allow tuple=MyTuple(a,b))
338
                NewTempVariable();
339
                return;
340
            }
341
            else
342
            {
343
                m_emitter.AppendLine("% make tuple");
344
                m_emitter.AppendLine(String.Format("{0} = []", NewTempVariable()));
345
346
                foreach (var expr in tupleConstructor.values)
347
                {
348
                    m_emitter.Append(", ");
349
350
                    OoaPrologExpression pVal = createExpressionVisitor();
351
                    expr.Accept(pVal);
352
                    m_emitter.Append(pVal.ToString());
353
                    System.Diagnostics.Debug.Assert(pVal.tmpVariables.Count == 1);
354
                    m_emitter.AppendLine(String.Format("ulyssesListConc({0},[{1}],{2})", m_tmpVars[0], pVal.tmpVariables[0], NewTempVariable()));
355
                    m_tmpVars.RemoveAt(0);
356
                }
357
                m_emitter.Append(",");
358
                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
359
            }
360
        }
361
362
        public override void visit(QValConstructor qValConstructor)
363
        {
364
            OoaPrologIdentifier pident = createIdentifierVisitor();
365
            qValConstructor.type.identifier.Accept(pident);
366
            StringBuilder qVal = new StringBuilder();
367
            if (qValConstructor.value != null || qValConstructor.value.Length != 0)
368
            {
369
                OoaPrologExpression landmark1 = createExpressionVisitor();
370
                qValConstructor.value[0].Accept(landmark1);
371
                qVal.Append(landmark1.ToString());
372
373
                if (qValConstructor.value.Length > 1)
374
                {
375
                    OoaPrologExpression landmark2 = createExpressionVisitor();
376
                    qValConstructor.value[1].Accept(landmark2);
377
                    qVal.Append("..");
378
                    qVal.Append(landmark2.ToString());
379
                }
380
            }
381
            else
382
                qVal.Append("_");
383
384
            string deriv = "_";
385
            switch (qValConstructor.valueDeriv)
386
            {
387
                case QValDeriv.Dec:
388
                    deriv = "dec";
389
                    break;
390
                case QValDeriv.Inc:
391
                    deriv = "inc";
392
                    break;
393
                case QValDeriv.Steady:
394
                    deriv = "std";
395
                    break;
396
397
            }
398
            string tmpVar = NewTempVariable();
399
            m_emitter.AppendLine(String.Format("{3} = ({0}:{1}/{2}),", pident.ToString(), qVal.ToString(), deriv, tmpVar));
400
        }
401
402
        public override void visit(AccessExpression accessExpression)
403
        {
404
            if (accessExpression.left.type.kind != TypeKind.QrType &&
405
                accessExpression.left.type.kind != TypeKind.EnumeratedType &&
406
                !(accessExpression.right.kind == ExpressionKind.Identifier &&
407
                ((IdentifierExpression)accessExpression.right).identifier.kind == IdentifierKind.AttributeIdentifier))
408
            {
409
                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
410
                // enums and qr types are directly (statically) converted to nums...
411
                VisitSub(accessExpression.left, accessExpression);
412
                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
413
414
                VisitSub(accessExpression.right, accessExpression);
415
                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
416
417
                m_tmpVars.Add(String.Format("{0}\\{1}", leftresult, rightresult));
418
            }
419
            else
420
                VisitSub(accessExpression.right, accessExpression);
421
        }
422
423
        public override void visit(BinaryOperator binaryOperator)
424
        {
425
            OoaCodeEmitter origEmitter = m_emitter;
426
427
428
            // eval stack must be empty
429
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
430
            // traverse left
431
            OoaCodeEmitter leftcode = new OoaCodeEmitter();
432
            m_emitter = leftcode;
433
            VisitSub(binaryOperator.left, binaryOperator);
434
            string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
435
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
436
            // traverse right
437
            OoaCodeEmitter rightcode = new OoaCodeEmitter();
438
            m_emitter = rightcode;
439
            VisitSub(binaryOperator.right, binaryOperator);
440
            string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
441
            // eval stack must be empty
442
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
443
444
            m_emitter = origEmitter;
445
446
            // get tmp.var
447
            string tmpVar = NewTempVariable();
448
449
            switch (binaryOperator.kind)
450
            {
451
                case ExpressionKind.elemin:
452
                    m_emitter.Append(leftcode.ToString());
453
                    m_emitter.Append(rightcode.ToString());
454
                    m_emitter.AppendLine(String.Format(" {0} = member({1},{2}),",
455
                        tmpVar, leftresult, rightresult));
456
                    break;
457
                case ExpressionKind.and:    // T_AND:
458
                    m_emitter.Append(leftcode.ToString());
459
                    m_emitter.Append(rightcode.ToString());
460
                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
461
                        tmpVar, leftresult, ",", rightresult));
462
                    break;
463
                case ExpressionKind.or:     // T_OR:
464
                    m_emitter.Append(leftcode.ToString());
465
                    m_emitter.Append(rightcode.ToString());
466
                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
467
                        tmpVar, leftresult, ";", rightresult));
468
                    break;
469
470
                case ExpressionKind.implies:
471
                    m_emitter.Append(leftcode.ToString());
472
                    m_emitter.AppendLine(String.Format(" {0} = ({1} -> ({2}{3}); true), ", // {0} = (({1} -> ({2}{3}); true))
473
                        tmpVar, leftresult, rightcode.ToString(), rightresult));
474
                    break;
475
476
                case ExpressionKind.equal:
477
                    m_emitter.Append(leftcode.ToString());
478
                    m_emitter.Append(rightcode.ToString());
479
                    /*check if we have tupleconstructors as matchers*/
480
                    TupleConstructor matcher = null;
481
                    string aTuple = null;
482
                    if (binaryOperator.left.kind == ExpressionKind.TupleConstr &&
483
                        ((TupleConstructor)binaryOperator.left).isMatcher)
484
                    {
485
                        matcher = (TupleConstructor)binaryOperator.left;
486
                        aTuple = rightresult;
487
                    }
488
                    else if (binaryOperator.right.kind == ExpressionKind.TupleConstr &&
489
                        ((TupleConstructor)binaryOperator.right).isMatcher)
490
                    {
491
                        matcher = (TupleConstructor)binaryOperator.right;
492
                        aTuple = leftresult;
493
                    }
494
495
                    if (matcher == null)
496
                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
497
                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
498
                    else
499
                    {
500
                        m_emitter.Append(String.Format("{0} = unify({1} = [", tmpVar, aTuple));
501
                        int cntr = 0;
502
                        foreach (var x in matcher.values)
503
                        {
504
                            if (cntr != 0)
505
                                m_emitter.Append(", ");
506
                            else
507
                                cntr++;
508
509
                            if (x.kind != ExpressionKind.Identifier)
510
                                throw new ArgumentException();
511
512
                            IdentifierExpression ident = (IdentifierExpression)x;
513
                            OoaPrologIdentifier avisitor = createIdentifierVisitor();
514
                            ident.Accept(avisitor);
515
                            m_emitter.Append(avisitor.ToString());
516
                        }
517
                        m_emitter.AppendLine("]),");
518
                    }
519
                    break;
520
521
522
523
                case ExpressionKind.conc:
524
                    m_emitter.Append(leftcode.ToString());
525
                    m_emitter.Append(rightcode.ToString());
526
                    m_emitter.AppendLine(String.Format("ulyssesListConc({1},{2},{0}),", tmpVar, leftresult, rightresult));
527
                    break;
528
529
                default:
530
                    m_emitter.Append(leftcode.ToString());
531
                    m_emitter.Append(rightcode.ToString());
532
                    if (binaryOperator.left.type.kind == TypeKind.QrType)
533
                        m_emitter.Append("qEval");
534
                    //m_emitter.Append("(");
535
                    if (binaryOperator.type.kind == TypeKind.IntType)
536
                        m_emitter.AppendLine(String.Format(" {0} #= ({1} {2} {3}), ",
537
                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
538
                    else
539
                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
540
                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
541
                    //m_emitter.Append(")");
542
                    break;
543
            }
544
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
545
        }
546
547
        public override void visit(TernaryOperator ternaryOperator)
548
        {
549
            if (ternaryOperator.kind == ExpressionKind.conditional)
550
            {
551
                VisitSub(ternaryOperator.left, ternaryOperator);
552
                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
553
                VisitSub(ternaryOperator.mid, ternaryOperator);
554
                string midresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
555
                VisitSub(ternaryOperator.right, ternaryOperator);
556
                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
557
558
                string varname = NewTempVariable();
559
560
                // (cond, expr #= var; #\ (cond), expr #= var)
561
                m_emitter.Append("((");
562
                m_emitter.Append(leftresult);
563
                m_emitter.Append(", unify(");
564
                m_emitter.Append(midresult);
565
                m_emitter.Append(String.Format(" = {0}) );( call(\\+({1})), unify(", varname, leftresult));
566
                m_emitter.Append(rightresult);
567
                m_emitter.Append(String.Format(" = {0}) )),", varname));
568
            }
569
            else if (ternaryOperator.kind == ExpressionKind.foldRL)
570
                throw new NotImplementedException();
571
            else if (ternaryOperator.kind == ExpressionKind.foldLR)
572
            {
573
                VisitSub(ternaryOperator.mid, ternaryOperator);
574
                string midresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
575
                VisitSub(ternaryOperator.right, ternaryOperator);
576
                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
577
578
579
                int uniqueNumer = GetUniqueNumber();
580
                m_emitter.Append(String.Format("fun_fold({0},{1},(_Elem_{2}, _In_{2}, Out_{2},(", midresult,
581
                    rightresult, uniqueNumer));
582
583
584
                // hack the current element and current result values to match the declaration above (change from __result, __elem)
585
                CallExpression leftcall = (CallExpression)ternaryOperator.left;
586
                IdentifierExpression elemId = (IdentifierExpression)leftcall.arguments[leftcall.arguments.Count - 1];
587
                elemId.identifier.SetTokenText(String.Format("Elem_{0}", uniqueNumer));
588
                IdentifierExpression currentResultId = (IdentifierExpression)leftcall.arguments[leftcall.arguments.Count - 2];
589
                currentResultId.identifier.SetTokenText(String.Format("In_{0}", uniqueNumer));
590
591
                VisitSub(leftcall, ternaryOperator);
592
                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
593
                string tmpresult = NewTempVariable();
594
                m_emitter.Append(String.Format(" Out_{1} = {2})),{0}),", tmpresult, uniqueNumer, leftresult));
595
            }
596
597
598
599
            else
600
                throw new NotImplementedException();
601
        }
602
603
        public override void visit(TupleMapAccessExpression tupleMapAccessExpression)
604
        {
605
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
606
            VisitSub(tupleMapAccessExpression.child, tupleMapAccessExpression);
607
            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
608
609
            VisitSub(tupleMapAccessExpression.argument, tupleMapAccessExpression);
610
            string accessresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
611
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
612
613
            string tmpresult = NewTempVariable();
614
615
            if (!m_LhsExpression)
616
            {
617
                switch (tupleMapAccessExpression.child.type.kind)
618
                {
619
                    case TypeKind.TupleType:
620
                        m_emitter.AppendLine(String.Format("ulyssesTupleAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
621
                        break;
622
                    case TypeKind.MapType:
623
                        m_emitter.AppendLine(String.Format("ulyssesMapAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
624
                        break;
625
                    case TypeKind.ListType:
626
                        m_emitter.AppendLine(String.Format("ulyssesListAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
627
                        break;
628
                    default:
629
                        throw new NotImplementedException();
630
                }
631
                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
632
            }
633
            else
634
            {
635
                /*>>>>> See comment in ooaTypeCheckVisitor on method CheckPlace! <<<<<<<<<*/
636
                switch (tupleMapAccessExpression.child.type.kind)
637
                {
638
                    case TypeKind.ListType:
639
                        bool isAttribute;
640
                        isAttribute = tupleMapAccessExpression.child.kind == ExpressionKind.Identifier &&
641
                            ((IdentifierExpression)tupleMapAccessExpression.child).identifier.kind == IdentifierKind.AttributeIdentifier;
642
643
                        isAttribute = isAttribute || tupleMapAccessExpression.child.kind == ExpressionKind.Access
644
                            && ((AccessExpression)tupleMapAccessExpression.child).left.kind == ExpressionKind.Identifier
645
                            && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child).left).isSelf
646
                            && ((AccessExpression)tupleMapAccessExpression.child).right.kind == ExpressionKind.Identifier
647
                            && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child).right).identifier.kind
648
                                == IdentifierKind.AttributeIdentifier;
649
650
651
                        tmpVarCntr++;
652
                        string newlist = String.Format("RESVAR_{0}", tmpVarCntr);
653
654
                        m_emitter.AppendLine(String.Format("ulyssesListWrite({0},{1},{2},{3}),", childresult, accessresult, tmpresult, newlist));
655
656
                        if (isAttribute)
657
                        { m_emitter.AppendLine(String.Format("{0} := {1},", childresult, newlist)); }
658
                        else
659
                        { throw new NotImplementedException(); }
660
661
                        break;
662
                    default:
663
                        throw new NotImplementedException();
664
                }
665
666
667
            }
668
        }
669
670
671
        public override void visit(ForallQuantifier quantifier)
672
        {
673
            OoaPrologExpression pExpr = createExpressionVisitor();
674
            quantifier.child.Accept(pExpr);
675
676
            // TEMPXY = forall(enumerate1([var:type,...]),pred(var..))
677
            StringBuilder Generator = new StringBuilder();
678
            int i = 0;
679
            foreach (var v in quantifier.symbols.symbolList)
680
            {
681
                OoaPrologIdentifier ident = createIdentifierVisitor();
682
                v.Accept(ident);
683
684
                OoaPrologType identType = createTypeVisitor();
685
                v.type.Accept(identType);
686
687
                Generator.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
688
                i++;
689
            }
690
691
            m_emitter.AppendLine(String.Format("{0} = forall([{1}],({2}{3})),",
692
            NewTempVariable(), Generator.ToString(), pExpr.ToString(), pExpr.tmpVariables[0]));
693
        }
694
695
696
697
        public override void visit(ExistsQuantifier quantifier)
698
        {
699
            OoaPrologExpression pExpr = createExpressionVisitor();
700
            quantifier.child.Accept(pExpr);
701
702
            // TEMPXY = exists(enumerate1([var:type,...]),pred(var..))
703
            StringBuilder Generator = new StringBuilder();
704
            int i = 0;
705
            foreach (var v in quantifier.symbols.symbolList)
706
            {
707
                OoaPrologIdentifier ident = createIdentifierVisitor();
708
                v.Accept(ident);
709
710
                OoaPrologType identType = createTypeVisitor();
711
                v.type.Accept(identType);
712
713
                Generator.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
714
                i++;
715
            }
716
717
            m_emitter.AppendLine(String.Format("{0} = exists([{1}],({2}{3})),",
718
            NewTempVariable(), Generator.ToString(), pExpr.ToString(), pExpr.tmpVariables[0]));
719
        }
720
        public override void visit(UnaryOperator unaryOperator)
721
        {
722
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
723
            VisitSub(unaryOperator.child, unaryOperator);
724
725
            if (unaryOperator.kind == ExpressionKind.Cast)
726
                return;
727
728
            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
729
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
730
731
            string tmpresult = NewTempVariable();
732
733
            switch (unaryOperator.kind)
734
            {
735
                case ExpressionKind.head:
736
                    m_emitter.AppendLine(String.Format("ulyssesListHead({1},{0}),", tmpresult, childresult));
737
                    break;
738
739
                case ExpressionKind.tail:
740
                    m_emitter.AppendLine(String.Format("ulyssesListTail({1},{0}),", tmpresult, childresult));
741
                    break;
742
743
                case ExpressionKind.len:    // T_LEN:
744
                    m_emitter.AppendLine(String.Format("ulyssesListLength({1},{0}),", tmpresult, childresult));
745
                    break;
746
747
                case ExpressionKind.not:
748
749
                    if (unaryOperator.type.kind == TypeKind.IntType)
750
                        m_emitter.Append(String.Format(" {0} #= call(\\+", tmpresult));
751
                    else
752
                        m_emitter.Append(String.Format(" {0} = call(\\+", tmpresult));
753
                    m_emitter.Append("(");
754
                    m_emitter.Append(childresult);
755
                    m_emitter.AppendLine(")),");
756
757
758
                    break;
759
760
                case ExpressionKind.Cast:
761
                    // todo
762
                    break;
763
764
                default:
765
                    if (unaryOperator.type.kind == TypeKind.IntType)
766
                        m_emitter.Append(String.Format(" {0} #= ({1}", tmpresult, OperatorString(unaryOperator, unaryOperator.child.type)));
767
                    else
768
                        m_emitter.Append(String.Format(" {0} = ({1}", tmpresult, OperatorString(unaryOperator, unaryOperator.child.type)));
769
                    m_emitter.Append("(");
770
                    m_emitter.Append(childresult);
771
                    m_emitter.AppendLine(")),");
772
                    break;
773
            }
774
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
775
        }
776
777
        public override string ToString()
778
        {
779
            return m_emitter.ToString();
780
        }
781
782
        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory); }
783
        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
784
        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory); }
785
786
        protected readonly OoaPrologIdentifier.Factory m_idFactory;
787
        protected readonly OoaPrologType.Factory m_typeFactory;
788
        protected readonly OoaPrologExpression.Factory m_exprFactory;
789
790
        protected OoaPrologExpression(
791
            OoaPrologIdentifier.Factory idFactory,
792
            OoaPrologType.Factory typeFactory,
793
            OoaPrologExpression.Factory expressionFactory)
794
            : this(idFactory, typeFactory, expressionFactory, false)
795
        {
796
        }
797
798
        protected OoaPrologExpression(
799
            OoaPrologIdentifier.Factory idFactory,
800
            OoaPrologType.Factory typeFactory,
801
            OoaPrologExpression.Factory expressionFactory,
802
            bool isLHS)
803
            : base()
804
        {
805
            m_LhsExpression = isLHS;
806
            m_idFactory = idFactory;
807
            m_typeFactory = typeFactory;
808
            m_exprFactory = expressionFactory;
809
        }
810
811
812
        static int tmpVarCntr = 0;
813
        public string NewTempVariable()
814
        {
815
            tmpVarCntr++;
816
            string result = String.Format("TMPVAR_{0}", tmpVarCntr);
817
            m_tmpVars.Add(result);
818
            return result;
819
        }
820
821
        public int GetUniqueNumber()
822
        {
823
            tmpVarCntr++;
824
            return tmpVarCntr;
825
        }
826
827
    }
828
}