Project

General

Profile

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

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

    
27

    
28
package org.momut.ooas.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.MetaType;
57
import org.momut.ooas.ast.types.TypeKind;
58
import org.momut.ooas.ast.types.Type;
59
import org.momut.ooas.ast.types.ValuedEnumType;
60
import org.momut.ooas.codegen.OoasCodeEmitter;
61
import org.momut.ooas.utils.exceptions.ArgumentException;
62
import org.momut.ooas.utils.exceptions.NotImplementedException;
63
import org.momut.ooas.visitors.OoaExpressionVisitor;
64

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

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

    
80

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

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

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

    
98

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

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

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

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

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

    
141

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

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

    
208
                case Cast:
209
                        return "";
210

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

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

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

    
240

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

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

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

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

    
292

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
438

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

    
455
                m_emitter = origEmitter;
456

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

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

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

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

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

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

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

    
532

    
533

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

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

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

    
568
                        final String varname = NewTempVariable();
569

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

    
588

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

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

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

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

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

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

    
623
                final String tmpresult = NewTempVariable();
624

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

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

    
660

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

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

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

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

    
675

    
676
                }
677
        }
678

    
679

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

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

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

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

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

    
708

    
709

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

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

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

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

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

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

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

    
749
                final String tmpresult = NewTempVariable();
750

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

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

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

    
765
                case not:
766

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

    
775

    
776
                        break;
777

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

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

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

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

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

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

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

    
833

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

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