Project

General

Profile

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

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 resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
190
                case lessequal:
191
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
192
                case greater:
193
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
194
                case greaterequal:
195
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
196
                case equal:
197
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "==" : "#=";
198
                case notequal:
199
                        return resultingType.kind() == TypeKind.QrType || !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.QrType &&
286
                                typeExpression.type().kind() != TypeKind.EnumeratedType)
287
                {
288
                        m_emitter.Append(GetIdentifierString(typeExpression.type().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.QrType &&
416
                                accessExpression.left().type().kind() != TypeKind.EnumeratedType &&
417
                                !(accessExpression.right().kind() == ExpressionKind.Identifier &&
418
                                ((IdentifierExpression)accessExpression.right()).identifier().kind() == IdentifierKind.AttributeIdentifier))
419
                {
420
                        assert(m_tmpVars.size() == 0);
421
                        // enums and qr types are directly (statically) converted to nums...
422
                        VisitSub(accessExpression.left(), accessExpression);
423
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
424

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

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

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

    
439

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

    
456
                m_emitter = origEmitter;
457

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

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

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

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

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

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

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

    
533

    
534

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

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

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

    
571
                        final String varname = NewTempVariable();
572

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

    
591

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

    
600
                        final String elemVarName = GetIdentifierString(elemId.identifier());
601
                        final String inVarName = GetIdentifierString(currentResultId.identifier());
602

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

    
611
                else
612
                        throw new NotImplementedException();
613
        }
614

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

    
622
                VisitSub(tupleMapAccessExpression.argument(), tupleMapAccessExpression);
623
                final String accessresult = m_tmpVars.get(0); m_tmpVars.remove(0);
624
                assert(m_tmpVars.size() == 0);
625

    
626
                final String tmpresult = NewTempVariable();
627

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

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

    
663

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

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

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

    
673
                                break;
674
                        default:
675
                                throw new NotImplementedException();
676
                        }
677

    
678

    
679
                }
680
        }
681

    
682

    
683
        @Override
684
        public void visit(ForallQuantifier quantifier)
685
        {
686
                final OoaPrologExpression pExpr = createExpressionVisitor();
687
                quantifier.child().Accept(pExpr);
688

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

    
698
                        final OoaPrologType identType = createTypeVisitor();
699
                        v.type().Accept(identType);
700

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

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

    
711

    
712

    
713
        @Override
714
        public void visit(ExistsQuantifier quantifier)
715
        {
716
                final OoaPrologExpression pExpr = createExpressionVisitor();
717
                quantifier.child().Accept(pExpr);
718

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

    
728
                        final OoaPrologType identType = createTypeVisitor();
729
                        v.type().Accept(identType);
730

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

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

    
746
                if (unaryOperator.kind() == ExpressionKind.Cast)
747
                        return;
748

    
749
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
750
                assert(m_tmpVars.size() == 0);
751

    
752
                final String tmpresult = NewTempVariable();
753

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

    
760
                case tail:
761
                        m_emitter.AppendLine(String.format("ulyssesListTail(%s,%s),", childresult, tmpresult));
762
                        break;
763

    
764
                case len:    // T_LEN:
765
                        m_emitter.AppendLine(String.format("ulyssesListLength(%s,%s),", childresult, tmpresult));
766
                        break;
767

    
768
                case not:
769

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

    
778

    
779
                        break;
780

    
781
                case Cast:
782
                        // todo
783
                        break;
784

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

    
798
        @Override
799
        public String toString()
800
        {
801
                return m_emitter.toString();
802
        }
803

    
804
        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory, m_scratchbook); }
805
        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
806
        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory, m_scratchbook); }
807

    
808
        protected final OoaPrologIdentifier.Factory m_idFactory;
809
        protected final OoaPrologType.Factory m_typeFactory;
810
        protected final OoaPrologExpression.Factory m_exprFactory;
811

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

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

    
836

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

    
844
        public int GetUniqueNumber()
845
        {
846
                return m_scratchbook.getNewTmpVarCntrValue();
847
        }
848
}