Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / codegen / prolog / OoaPrologExpression.java @ 10

1
/**
2
  *
3
  *                      OOAS Compiler
4
  *
5
  *       Copyright 2015, AIT Austrian Institute of Technology.
6
  * This code is based on the C# Version of the OOAS Compiler, which is
7
  * copyright 2015 by the Institute of Software Technology, Graz University
8
  * of Technology with portions copyright by the AIT Austrian Institute of
9
  * Technology. All rights reserved.
10
  *
11
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
12
  *
13
  * If you modify the file please update the list of contributors below to in-
14
  * clude your name. Please also stick to the coding convention of using TABs
15
  * to do the basic (block-level) indentation and spaces for anything after
16
  * that. (Enable the display of special chars and it should be pretty obvious
17
  * what this means.) Also, remove all trailing whitespace.
18
  *
19
  * Contributors:
20
  *               Willibald Krenn (AIT)
21
  *               Stephan Zimmerer (AIT)
22
  *               Markus Demetz (AIT)
23
  *               Christoph Czurda (AIT)
24
  *
25
  */
26

    
27

    
28
package org.momut.ooas.codegen.prolog;
29

    
30
import java.util.ArrayList;
31

    
32
import org.momut.ooas.ast.expressions.AccessExpression;
33
import org.momut.ooas.ast.expressions.BinaryOperator;
34
import org.momut.ooas.ast.expressions.CallExpression;
35
import org.momut.ooas.ast.expressions.ExistsQuantifier;
36
import org.momut.ooas.ast.expressions.Expression;
37
import org.momut.ooas.ast.expressions.ExpressionKind;
38
import org.momut.ooas.ast.expressions.ForallQuantifier;
39
import org.momut.ooas.ast.expressions.IdentifierExpression;
40
import org.momut.ooas.ast.expressions.ListConstructor;
41
import org.momut.ooas.ast.expressions.MapConstructor;
42
import org.momut.ooas.ast.expressions.ObjectConstructor;
43
import org.momut.ooas.ast.expressions.SetConstructor;
44
import org.momut.ooas.ast.expressions.TernaryOperator;
45
import org.momut.ooas.ast.expressions.TupleConstructor;
46
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
47
import org.momut.ooas.ast.expressions.TypeExpression;
48
import org.momut.ooas.ast.expressions.UnaryOperator;
49
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
50
import org.momut.ooas.ast.expressions.ValueExpression;
51
import org.momut.ooas.ast.identifiers.EnumIdentifier;
52
import org.momut.ooas.ast.identifiers.Identifier;
53
import org.momut.ooas.ast.identifiers.IdentifierKind;
54
import org.momut.ooas.ast.types.EnumType;
55
import org.momut.ooas.ast.types.FunctionType;
56
import org.momut.ooas.ast.types.TypeKind;
57
import org.momut.ooas.ast.types.Type;
58
import org.momut.ooas.ast.types.ValuedEnumType;
59
import org.momut.ooas.codegen.OoasCodeEmitter;
60
import org.momut.ooas.utils.exceptions.ArgumentException;
61
import org.momut.ooas.utils.exceptions.NotImplementedException;
62
import org.momut.ooas.visitors.OoaExpressionVisitor;
63

    
64
public class OoaPrologExpression extends OoaExpressionVisitor
65
{
66
        public static class Factory
67
        {
68
                public final OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, Scratchbook sb)
69
                { return create(idFactory, typeFactory, sb, false); }
70
                public OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, Scratchbook sb, boolean lhs)
71
                { return new OoaPrologExpression(idFactory, typeFactory, sb, this, lhs); }
72
        }
73

    
74
        protected OoasCodeEmitter m_emitter = new OoasCodeEmitter();
75
        protected ArrayList<String> m_tmpVars = new ArrayList<String>();
76
        protected final Scratchbook m_scratchbook;
77
        private boolean m_LhsExpression = false;
78

    
79

    
80
        public ArrayList<String> tmpVariables() { return m_tmpVars; }
81
        public boolean isLhsExpression() { return m_LhsExpression; }
82

    
83
//        private String GetPrologType(UlyssesType aType)
84
//        {
85
//                OoaPrologType pType = createTypeVisitor();
86
//                aType.Accept(pType);
87
//                return pType.toString();
88
//        }
89

    
90
        protected String GetIdentifierString(Identifier anIdentifier)
91
        {
92
                final OoaPrologIdentifier pIdent = createIdentifierVisitor();
93
                anIdentifier.Accept(pIdent);
94
                return pIdent.toString();
95
        }
96

    
97

    
98
        // following call must not happen
99
        @Override
100
        public void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
101
        {
102
                assert(false);
103
        }
104

    
105
        // call of method that returns a value..
106
        @Override
107
        public void visit(CallExpression callExpression)
108
        {
109
                // we handle only function calls within expressions here (must have non-void return!)
110
                final FunctionType funtype = (FunctionType)callExpression.child().type();
111
                if (funtype.returnType() == null)
112
                        throw new ArgumentException("Internal error: Function call in expression with return-type void!");
113

    
114
                String callstatement = "";
115
                final StringBuilder parameter = new StringBuilder();
116

    
117
                final OoaPrologExpression prologexpr = createExpressionVisitor();
118
                callExpression.child().Accept(prologexpr);
119

    
120
                m_emitter.Append(prologexpr.toString());
121
                callstatement = prologexpr.tmpVariables().get(0);
122
                int i = 0;
123
                for (final Expression arg: callExpression.arguments())
124
                {
125
                        if (i != 0)
126
                                parameter.append(", ");
127
                        else
128
                                i++;
129
                        final OoaPrologExpression paramexpr = createExpressionVisitor();
130
                        arg.Accept(paramexpr);
131
                        m_emitter.Append(paramexpr.toString());
132
                        parameter.append(paramexpr.tmpVariables().get(0));
133
                }
134
                if (parameter.length() > 0)
135
                        m_emitter.AppendLine(String.format("%s(%s,%s),", callstatement, parameter, NewTempVariable()));
136
                else
137
                        m_emitter.AppendLine(String.format("%s(%s),", callstatement, NewTempVariable()));
138
        }
139

    
140

    
141
        // we need to map all other things to Prolog constructs
142
        private String OperatorString(Expression expression, Type resultingType)
143
        {
144
                switch (expression.kind())
145
                {
146
                case abs:    // T_ABS:
147
                case card:   // T_CARD:
148
                case dom:    // T_DOM:
149
                case range:  // T_RNG:
150
                case merge:  // T_MERGE:
151
                case elems:  // T_ELEMS:
152
                case head:   // T_HEAD:
153
                case tail:   // T_TAIL:
154
                case conc:   // T_CONC:
155
                case inds:   // T_INDS:
156
                case dinter: // T_DINTER:
157
                case dunion: // T_DUNION:
158
                case domresby:   // T_DOMRESBY:
159
                case domresto:   // T_DOMRESTO:
160
                case rngresby:   // T_RNGRESBY:
161
                case rngresto:   // T_RNGRESTO:
162
                case inter:  // T_INTER:
163
                case union:  // T_UNION:
164
                case diff:   // T_DIFF:
165
                case munion: // T_MUNION:
166
                case seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
167
                case subset:
168
                case elemin:
169
                case notelemin:
170
                case implies:    // T_IMPLIES:
171
                case biimplies:  // T_BIIMPLIES:
172
                case Primed:
173
                case len:    // T_LEN:
174
                        throw new NotImplementedException();
175

    
176
                case div:    // T_DIV:
177
                        return "/";
178
                case idiv:   // T_IDIV:
179
                        return "/";
180
                case mod:    // T_MOD:
181
                        return "mod";
182
                case prod:   // T_PROD:
183
                        return "*";
184
                case sum:    // T_SUM:
185
                        return "+";
186
                case minus:  // T_MINUS:
187
                        return "-";
188
                case less:
189
                        return !isNumericBinary(expression) ? "<" : "#<";
190
                case lessequal:
191
                        return !isNumericBinary(expression) ? "=<" : "#=<";
192
                case greater:
193
                        return !isNumericBinary(expression) ? ">" : "#>";
194
                case greaterequal:
195
                        return !isNumericBinary(expression) ? ">=" : "#>=";
196
                case equal:
197
                        return !isNumericBinary(expression) ? "==" : "#=";
198
                case notequal:
199
                        return !isNumericBinary(expression) ? "\\=" : "#\\=";
200
                case and:    // T_AND:
201
                        throw new NotImplementedException(); // implemented in binaryoperator
202
                case or:     // T_OR:
203
                        throw new NotImplementedException(); // implemented in binaryoperator
204
                case not:
205
                        throw new NotImplementedException(); // implemented in binaryoperator
206

    
207
                case Cast:
208
                        return "";
209

    
210
                default:
211
                        return expression.kind().name(); //Enum.GetName(typeof(ExpressionKind), expression.kind);
212
                }
213
        }
214

    
215
        protected boolean isNumericBinary(Expression expression)
216
        {
217
                boolean result = false;
218
                if (expression instanceof BinaryOperator)
219
                {
220
                        result = ((BinaryOperator)expression).left().type().kind() == TypeKind.IntType &&
221
                                        ((BinaryOperator)expression).right().type().kind() == TypeKind.IntType;
222
                }
223
                else if (expression instanceof UnaryOperator)
224
                {
225
                        result = ((UnaryOperator)expression).child().type().kind() == TypeKind.IntType;
226
                }
227
                else throw new NotImplementedException();
228
                return result;
229
        }
230

    
231
        @SuppressWarnings("unchecked")
232
        @Override
233
        public <T> void visit(ValueExpression<T> valueExpression)
234
        {
235
                assert(m_tmpVars.size() == 0);
236
                final String tmpVar = NewTempVariable();
237
                m_emitter.Append(String.format("%s ", tmpVar));
238

    
239

    
240
                if (valueExpression.value() == null)
241
                        m_emitter.Append("= 'null'");
242
                else if (Boolean.class.isAssignableFrom(valueExpression.m_clazz))
243
                        m_emitter.Append(((ValueExpression<Boolean>) valueExpression).value() ? " #= true" : " #= fail");
244
                else if (Character.class.isAssignableFrom(valueExpression.m_clazz))
245
                        m_emitter.Append(String.format("#= '%s'", valueExpression.toString()));
246
                else if (Integer.class.isAssignableFrom(valueExpression.m_clazz))
247
                        m_emitter.Append(String.format("#= %s", valueExpression.toString()));
248
                else
249
                        m_emitter.Append(String.format("= %s", valueExpression.value().toString()));
250

    
251
                m_emitter.AppendLine(",");
252
                assert(m_tmpVars.size() == 1);
253
        }
254

    
255
        @Override
256
        public void visit(IdentifierExpression identifierExpression)
257
        {
258
                if (identifierExpression.identifier().kind() == IdentifierKind.EnumIdentifier)
259
                {
260
                        final EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier();
261
                        final EnumType enumType = (EnumType)enumid.type();
262
                        //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
263
                        if (enumType instanceof ValuedEnumType)
264
                                m_emitter.AppendLine(String.format("%s #= %s,", NewTempVariable(), enumid.Value()));
265
                        else
266
                                m_emitter.AppendLine(String.format("%s #= %s,", NewTempVariable(), enumType.listOfEnumSymbols().indexOf(enumid)));
267
                }
268
                else if (identifierExpression.isSelf())
269
                {
270
                        m_emitter.AppendLine(String.format("%s = %s,", NewTempVariable(), GetIdentifierString(identifierExpression.identifier())));
271
                }
272
                /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
273
                {
274
                        m_emitter.AppendLine(String.format("getVal(%s,%s,_),", GetIdentifierString(identifierExpression.identifier), NewTempVariable(), ));
275
                }*/
276
                else
277
                {
278
                        m_tmpVars.add(GetIdentifierString(identifierExpression.identifier()));
279
                }
280
        }
281

    
282
        @Override
283
        public void visit(TypeExpression typeExpression)
284
        {
285
                if (typeExpression.type().kind() != TypeKind.EnumeratedType)
286
                {
287
                        m_emitter.Append(GetIdentifierString(typeExpression.type().identifier()));
288
                }
289
        }
290

    
291

    
292
        @Override
293
        public void visit(ObjectConstructor objectConstructor)
294
        {
295
                if (objectConstructor.instances().size() > 1)
296
                        throw new NotImplementedException();
297

    
298
                m_emitter.AppendLine(String.format("%s = '%s',", NewTempVariable(), objectConstructor.instances().get(0).Name));
299

    
300
                //m_emitter.Append(String.format("new %s(this)", GetIdentifierString(objectConstructor.type.identifier)));
301
        }
302

    
303
        @Override
304
        public void visit(ListConstructor listConstructor)
305
        {
306
                if (listConstructor.hasComprehension())
307
                {
308
                        final OoaPrologExpression compr = createExpressionVisitor();
309
                        listConstructor.comprehension().Accept(compr);
310
                        final OoaPrologExpression elem = createExpressionVisitor();
311
                        listConstructor.elements().get(0).Accept(elem);
312

    
313
                        final StringBuilder enumvars = new StringBuilder();
314
                        int i = 0;
315
                        for (final Identifier v: listConstructor.comprehensionVariables().symbolList())
316
                        {
317
                                final OoaPrologIdentifier ident = createIdentifierVisitor();
318
                                v.Accept(ident);
319

    
320
                                final OoaPrologType identType = createTypeVisitor();
321
                                v.type().Accept(identType);
322

    
323
                                enumvars.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
324
                                i++;
325
                        }
326

    
327
                        m_emitter.AppendLine("% listcomprehension");
328
                        m_emitter.AppendLine(String.format("%s = {%s:[%s]:(%s%s,%s%s)}",
329
                                        NewTempVariable(), elem.tmpVariables().get(0), enumvars.toString(), compr.toString(), compr.tmpVariables().get(0),
330
                                        elem.toString(), "1=1" /*elem.ToString() == String.Empty ? "1=1" : elem.tmpVariables[0]*/));
331
                }
332
                else
333
                {
334
                        m_emitter.AppendLine("% make list");
335
                        m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
336

    
337
                        for (final Expression expr: listConstructor.elements())
338
                        {
339
                                m_emitter.Append(", ");
340

    
341
                                final OoaPrologExpression pVal = createExpressionVisitor();
342
                                expr.Accept(pVal);
343
                                m_emitter.Append(pVal.toString());
344
                                assert(pVal.tmpVariables().size() == 1);
345
                                m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
346
                                m_tmpVars.remove(0);
347
                        }
348
                }
349
                m_emitter.Append(",");
350
                assert(m_tmpVars.size() == 1);
351
        }
352

    
353
        @Override
354
        public void visit(SetConstructor setConstructor)
355
        {
356
                m_emitter.AppendLine("% make set");
357
                // our resulting set.
358
                m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
359

    
360
                for (final Expression expr: setConstructor.items())
361
                {
362
                        m_emitter.Append(", ");
363

    
364
                        final OoaPrologExpression pVal = createExpressionVisitor();
365
                        expr.Accept(pVal);
366
                        m_emitter.Append(pVal.toString());
367
                        assert(pVal.tmpVariables().size() == 1);
368
                        m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
369
                        m_tmpVars.remove(0);
370
                }
371
                m_emitter.Append(",");
372
                assert(m_tmpVars.size() == 1);
373
        }
374

    
375
        @Override
376
        public void visit(MapConstructor mapConstructor)
377
        {
378
                throw new NotImplementedException();
379
        }
380

    
381
        @Override
382
        public void visit(TupleConstructor tupleConstructor)
383
        {
384
                if (tupleConstructor.isMatcher())
385
                {
386
                        // being dealt with in binaryoperator (since we only allow tuple=MyTuple(a,b))
387
                        NewTempVariable();
388
                        return;
389
                }
390
                else
391
                {
392
                        m_emitter.AppendLine("% make tuple");
393
                        m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
394

    
395
                        for (final Expression expr: tupleConstructor.values())
396
                        {
397
                                m_emitter.Append(", ");
398

    
399
                                final OoaPrologExpression pVal = createExpressionVisitor();
400
                                expr.Accept(pVal);
401
                                m_emitter.Append(pVal.toString());
402
                                assert(pVal.tmpVariables().size() == 1);
403
                                m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
404
                                m_tmpVars.remove(0);
405
                        }
406
                        m_emitter.Append(",");
407
                        assert(m_tmpVars.size() == 1);
408
                }
409
        }
410

    
411
        @Override
412
        public void visit(AccessExpression accessExpression)
413
        {
414
                if (accessExpression.left().type().kind() != TypeKind.EnumeratedType &&
415
                    !(accessExpression.right().kind() == ExpressionKind.Identifier &&
416
                    ((IdentifierExpression)accessExpression.right()).identifier().kind() == IdentifierKind.AttributeIdentifier))
417
                {
418
                        assert(m_tmpVars.size() == 0);
419
                        // enums and qr types are directly (statically) converted to nums...
420
                        VisitSub(accessExpression.left(), accessExpression);
421
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
422

    
423
                        VisitSub(accessExpression.right(), accessExpression);
424
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
425

    
426
                        m_tmpVars.add(String.format("%s\\%s", leftresult, rightresult));
427
                }
428
                else
429
                        VisitSub(accessExpression.right(), accessExpression);
430
        }
431

    
432
        @Override
433
        public void visit(BinaryOperator binaryOperator)
434
        {
435
                final OoasCodeEmitter origEmitter = m_emitter;
436

    
437

    
438
                // eval stack must be empty
439
                assert(m_tmpVars.size() == 0);
440
                // traverse left
441
                final OoasCodeEmitter leftcode = new OoasCodeEmitter();
442
                m_emitter = leftcode;
443
                VisitSub(binaryOperator.left(), binaryOperator);
444
                final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
445
                assert(m_tmpVars.size() == 0);
446
                // traverse right
447
                final OoasCodeEmitter rightcode = new OoasCodeEmitter();
448
                m_emitter = rightcode;
449
                VisitSub(binaryOperator.right(), binaryOperator);
450
                final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
451
                // eval stack must be empty
452
                assert(m_tmpVars.size() == 0);
453

    
454
                m_emitter = origEmitter;
455

    
456
                // get tmp.var
457
                final String tmpVar = NewTempVariable();
458

    
459
                switch (binaryOperator.kind())
460
                {
461
                case elemin:
462
                        m_emitter.Append(leftcode.toString());
463
                        m_emitter.Append(rightcode.toString());
464
                        m_emitter.AppendLine(String.format(" %s = member(%s,%s),",
465
                                        tmpVar, leftresult, rightresult));
466
                        break;
467
                case and:    // T_AND:
468
                        m_emitter.Append(leftcode.toString());
469
                        m_emitter.Append(rightcode.toString());
470
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
471
                                        tmpVar, leftresult, ",", rightresult));
472
                        break;
473
                case or:     // T_OR:
474
                        m_emitter.Append(leftcode.toString());
475
                        m_emitter.Append(rightcode.toString());
476
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
477
                                        tmpVar, leftresult, ";", rightresult));
478
                        break;
479

    
480
                case implies:
481
                        m_emitter.Append(leftcode.toString());
482
                        m_emitter.AppendLine(String.format(" %s = (%s -> (%s%s); true), ", // {0} = (({1} -> ({2}{3}); true))
483
                                        tmpVar, leftresult, rightcode.toString(), rightresult));
484
                        break;
485

    
486
                case equal:
487
                        m_emitter.Append(leftcode.toString());
488
                        m_emitter.Append(rightcode.toString());
489
                        /*check if we have tupleconstructors as matchers*/
490
                        TupleConstructor matcher = null;
491
                        String aTuple = null;
492
                        if (binaryOperator.left().kind() == ExpressionKind.TupleConstr &&
493
                                        ((TupleConstructor)binaryOperator.left()).isMatcher())
494
                        {
495
                                matcher = (TupleConstructor)binaryOperator.left();
496
                                aTuple = rightresult;
497
                        }
498
                        else if (binaryOperator.right().kind() == ExpressionKind.TupleConstr &&
499
                                        ((TupleConstructor)binaryOperator.right()).isMatcher())
500
                        {
501
                                matcher = (TupleConstructor)binaryOperator.right();
502
                                aTuple = leftresult;
503
                        }
504

    
505
                        if (matcher == null)
506
                                m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
507
                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
508
                        else
509
                        {
510
                                m_emitter.Append(String.format("%s = unify(%s = [", tmpVar, aTuple));
511
                                int cntr = 0;
512
                                for(final Expression x: matcher.values())
513
                                {
514
                                        if (cntr != 0)
515
                                                m_emitter.Append(", ");
516
                                        else
517
                                                cntr++;
518

    
519
                                        if (x.kind() != ExpressionKind.Identifier)
520
                                                throw new ArgumentException();
521

    
522
                                        final IdentifierExpression ident = (IdentifierExpression)x;
523
                                        final OoaPrologIdentifier avisitor = createIdentifierVisitor();
524
                                        ident.Accept(avisitor);
525
                                        m_emitter.Append(avisitor.toString());
526
                                }
527
                                m_emitter.AppendLine("]),");
528
                        }
529
                        break;
530

    
531

    
532

    
533
                case conc:
534
                        m_emitter.Append(leftcode.toString());
535
                        m_emitter.Append(rightcode.toString());
536
                        m_emitter.AppendLine(String.format("ulyssesListConc(%s,%s,%s),", leftresult, rightresult, tmpVar));
537
                        break;
538

    
539
                default:
540
                        m_emitter.Append(leftcode.toString());
541
                        m_emitter.Append(rightcode.toString());
542
                        //m_emitter.Append("(");
543
                        if (binaryOperator.type().kind() == TypeKind.IntType)
544
                                m_emitter.AppendLine(String.format(" %s #= (%s %s %s), ",
545
                                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
546
                        else
547
                                m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
548
                                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
549
                        //m_emitter.Append(")");
550
                        break;
551
                }
552
                assert(m_tmpVars.size() == 1);
553
        }
554

    
555
        @Override
556
        public void visit(TernaryOperator ternaryOperator)
557
        {
558
                if (ternaryOperator.kind() == ExpressionKind.conditional)
559
                {
560
                        VisitSub(ternaryOperator.left(), ternaryOperator);
561
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
562
                        VisitSub(ternaryOperator.mid(), ternaryOperator);
563
                        final String midresult = m_tmpVars.get(0); m_tmpVars.remove(0);
564
                        VisitSub(ternaryOperator.right(), ternaryOperator);
565
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
566

    
567
                        final String varname = NewTempVariable();
568

    
569
                        // (cond, expr #= var; #\ (cond), expr #= var)
570
                        m_emitter.Append("((");
571
                        m_emitter.Append(leftresult);
572
                        m_emitter.Append(", unify(");
573
                        m_emitter.Append(midresult);
574
                        m_emitter.Append(String.format(" = %s) );( call(\\+(%s)), unify(", varname, leftresult));
575
                        m_emitter.Append(rightresult);
576
                        m_emitter.Append(String.format(" = %s) )),", varname));
577
                }
578
                else if (ternaryOperator.kind() == ExpressionKind.foldRL)
579
                        throw new NotImplementedException();
580
                else if (ternaryOperator.kind() == ExpressionKind.foldLR)
581
                {
582
                        VisitSub(ternaryOperator.mid(), ternaryOperator);
583
                        final String midresult = m_tmpVars.get(0); m_tmpVars.remove(0);
584
                        VisitSub(ternaryOperator.right(), ternaryOperator);
585
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
586

    
587

    
588
                        // make vars unique
589
                        final int uniqueNumer = GetUniqueNumber();
590
                        final CallExpression leftcall = (CallExpression)ternaryOperator.left();
591
                        final IdentifierExpression elemId = (IdentifierExpression)leftcall.arguments().get(leftcall.arguments().size() - 1);
592
                        elemId.identifier().SetTokenText(String.format("Elem_%s", uniqueNumer));
593
                        final IdentifierExpression currentResultId = (IdentifierExpression)leftcall.arguments().get(leftcall.arguments().size() - 2);
594
                        currentResultId.identifier().SetTokenText(String.format("In_%s", uniqueNumer));
595

    
596
                        final String elemVarName = GetIdentifierString(elemId.identifier());
597
                        final String inVarName = GetIdentifierString(currentResultId.identifier());
598

    
599
                        m_emitter.Append(String.format("fun_fold(%s,%s,(%s, %s, Out_%s,(",
600
                                        midresult, rightresult, elemVarName, inVarName, uniqueNumer));
601
                        VisitSub(leftcall, ternaryOperator);
602
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
603
                        final String tmpresult = NewTempVariable();
604
                        m_emitter.Append(String.format(" Out_%s = %s)),%s),", uniqueNumer, leftresult, tmpresult));
605
                }
606

    
607
                else
608
                        throw new NotImplementedException();
609
        }
610

    
611
        @Override
612
        public void visit(TupleMapAccessExpression tupleMapAccessExpression)
613
        {
614
                assert(m_tmpVars.size() == 0);
615
                VisitSub(tupleMapAccessExpression.child(), tupleMapAccessExpression);
616
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
617

    
618
                VisitSub(tupleMapAccessExpression.argument(), tupleMapAccessExpression);
619
                final String accessresult = m_tmpVars.get(0); m_tmpVars.remove(0);
620
                assert(m_tmpVars.size() == 0);
621

    
622
                final String tmpresult = NewTempVariable();
623

    
624
                if (!m_LhsExpression)
625
                {
626
                        switch (tupleMapAccessExpression.child().type().kind())
627
                        {
628
                        case TupleType:
629
                                m_emitter.AppendLine(String.format("ulyssesTupleAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
630
                                break;
631
                        case MapType:
632
                                m_emitter.AppendLine(String.format("ulyssesMapAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
633
                                break;
634
                        case ListType:
635
                                m_emitter.AppendLine(String.format("ulyssesListAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
636
                                break;
637
                        default:
638
                                throw new NotImplementedException();
639
                        }
640
                        assert(m_tmpVars.size() == 1);
641
                }
642
                else
643
                {
644
                        /*>>>>> See comment in ooaTypeCheckVisitor on method CheckPlace! <<<<<<<<<*/
645
                        switch (tupleMapAccessExpression.child().type().kind())
646
                        {
647
                        case ListType:
648
                                boolean isAttribute;
649
                                isAttribute = tupleMapAccessExpression.child().kind() == ExpressionKind.Identifier &&
650
                                                ((IdentifierExpression)tupleMapAccessExpression.child()).identifier().kind() == IdentifierKind.AttributeIdentifier;
651

    
652
                                isAttribute = isAttribute || tupleMapAccessExpression.child().kind() == ExpressionKind.Access
653
                                                && ((AccessExpression)tupleMapAccessExpression.child()).left().kind() == ExpressionKind.Identifier
654
                                                && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child()).left()).isSelf()
655
                                                && ((AccessExpression)tupleMapAccessExpression.child()).right().kind() == ExpressionKind.Identifier
656
                                                && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child()).right()).identifier().kind()
657
                                                == IdentifierKind.AttributeIdentifier;
658

    
659

    
660
                                final String newlist = String.format("RESVAR_%s", m_scratchbook.getNewTmpVarCntrValue());
661

    
662
                                m_emitter.AppendLine(String.format("ulyssesListWrite(%s,%s,%s,%s),", childresult, accessresult, tmpresult, newlist));
663

    
664
                                if (isAttribute)
665
                                { m_emitter.AppendLine(String.format("%s := %s,", childresult, newlist)); }
666
                                else
667
                                { throw new NotImplementedException(); }
668

    
669
                                break;
670
                        default:
671
                                throw new NotImplementedException();
672
                        }
673

    
674

    
675
                }
676
        }
677

    
678

    
679
        @Override
680
        public void visit(ForallQuantifier quantifier)
681
        {
682
                final OoaPrologExpression pExpr = createExpressionVisitor();
683
                quantifier.child().Accept(pExpr);
684

    
685
                // TEMPXY = forall(enumerate1([var:type,...]),pred(var..))
686
                final StringBuilder Generator = new StringBuilder();
687
                final StringBuilder nullGuard = new StringBuilder();
688
                int i = 0;
689
                for (final Identifier v: quantifier.symbols().symbolList())
690
                {
691
                        final OoaPrologIdentifier ident = createIdentifierVisitor();
692
                        v.Accept(ident);
693

    
694
                        final OoaPrologType identType = createTypeVisitor();
695
                        v.type().Accept(identType);
696

    
697
                        Generator.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
698
                        if (v.type().kind() == TypeKind.OoActionSystemType)
699
                                nullGuard.append(String.format("(%s == null) ; ", ident.toString()));
700
                        i++;
701
                }
702

    
703
                m_emitter.AppendLine(String.format("%s = forall([%s], (%s(%s%s))),",
704
                                NewTempVariable(), Generator.toString(), nullGuard.toString(), pExpr.toString(), pExpr.tmpVariables().get(0)));
705
        }
706

    
707

    
708

    
709
        @Override
710
        public void visit(ExistsQuantifier quantifier)
711
        {
712
                final OoaPrologExpression pExpr = createExpressionVisitor();
713
                quantifier.child().Accept(pExpr);
714

    
715
                // TEMPXY = exists(enumerate1([var:type,...]),pred(var..))
716
                final StringBuilder Generator = new StringBuilder();
717
                final StringBuilder nullGuard = new StringBuilder();
718
                int i = 0;
719
                for (final Identifier v: quantifier.symbols().symbolList())
720
                {
721
                        final OoaPrologIdentifier ident = createIdentifierVisitor();
722
                        v.Accept(ident);
723

    
724
                        final OoaPrologType identType = createTypeVisitor();
725
                        v.type().Accept(identType);
726

    
727
                        Generator.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
728
                        if (v.type().kind() == TypeKind.OoActionSystemType)
729
                                nullGuard.append(String.format("(%s \\= null), ", ident.toString()));
730
                        i++;
731
                }
732

    
733
                m_emitter.AppendLine(String.format("%s = exists([%s], (%s(%s%s))),",
734
                                NewTempVariable(), Generator.toString(), nullGuard.toString(), pExpr.toString(), pExpr.tmpVariables().get(0)));
735
        }
736
        @Override
737
        public void visit(UnaryOperator unaryOperator)
738
        {
739
                assert(m_tmpVars.size() == 0);
740
                VisitSub(unaryOperator.child(), unaryOperator);
741

    
742
                if (unaryOperator.kind() == ExpressionKind.Cast)
743
                        return;
744

    
745
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
746
                assert(m_tmpVars.size() == 0);
747

    
748
                final String tmpresult = NewTempVariable();
749

    
750
                switch (unaryOperator.kind())
751
                {
752
                case head:
753
                        m_emitter.AppendLine(String.format("ulyssesListHead(%s,%s),", childresult, tmpresult));
754
                        break;
755

    
756
                case tail:
757
                        m_emitter.AppendLine(String.format("ulyssesListTail(%s,%s),", childresult, tmpresult));
758
                        break;
759

    
760
                case len:    // T_LEN:
761
                        m_emitter.AppendLine(String.format("ulyssesListLength(%s,%s),", childresult, tmpresult));
762
                        break;
763

    
764
                case not:
765

    
766
                        if (unaryOperator.type().kind() == TypeKind.IntType)
767
                                m_emitter.Append(String.format(" %s #= call(\\+", tmpresult));
768
                        else
769
                                m_emitter.Append(String.format(" %s = call(\\+", tmpresult));
770
                        m_emitter.Append("(");
771
                        m_emitter.Append(childresult);
772
                        m_emitter.AppendLine(")),");
773

    
774

    
775
                        break;
776

    
777
                case Cast:
778
                        // todo
779
                        break;
780

    
781
                default:
782
                        if (unaryOperator.type().kind() == TypeKind.IntType)
783
                                m_emitter.Append(String.format(" %s #= (%s", tmpresult, OperatorString(unaryOperator, unaryOperator.child().type())));
784
                        else
785
                                m_emitter.Append(String.format(" %s = (%s", tmpresult, OperatorString(unaryOperator, unaryOperator.child().type())));
786
                        m_emitter.Append("(");
787
                        m_emitter.Append(childresult);
788
                        m_emitter.AppendLine(")),");
789
                        break;
790
                }
791
                assert(m_tmpVars.size() == 1);
792
        }
793

    
794
        @Override
795
        public String toString()
796
        {
797
                return m_emitter.toString();
798
        }
799

    
800
        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory, m_scratchbook); }
801
        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
802
        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory, m_scratchbook); }
803

    
804
        protected final OoaPrologIdentifier.Factory m_idFactory;
805
        protected final OoaPrologType.Factory m_typeFactory;
806
        protected final OoaPrologExpression.Factory m_exprFactory;
807

    
808
        protected OoaPrologExpression(
809
                        OoaPrologIdentifier.Factory idFactory,
810
                        OoaPrologType.Factory typeFactory,
811
                        Scratchbook scratchbook,
812
                        OoaPrologExpression.Factory expressionFactory)
813
        {
814
                this(idFactory, typeFactory, scratchbook, expressionFactory, false);
815
        }
816

    
817
        protected OoaPrologExpression(
818
                        OoaPrologIdentifier.Factory idFactory,
819
                        OoaPrologType.Factory typeFactory,
820
                        Scratchbook scratchbook,
821
                        OoaPrologExpression.Factory expressionFactory,
822
                        boolean isLHS)
823
        {
824
                super();
825
                m_LhsExpression = isLHS;
826
                m_idFactory = idFactory;
827
                m_typeFactory = typeFactory;
828
                m_exprFactory = expressionFactory;
829
                m_scratchbook = scratchbook;
830
        }
831

    
832

    
833
        public String NewTempVariable()
834
        {
835
                final String result = String.format("TMPVAR_%s", m_scratchbook.getNewTmpVarCntrValue());
836
                m_tmpVars.add(result);
837
                return result;
838
        }
839

    
840
        public int GetUniqueNumber()
841
        {
842
                return m_scratchbook.getNewTmpVarCntrValue();
843
        }
844
}