Project

General

Profile

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

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.QValConstructor;
44
import org.momut.ooas.ast.expressions.SetConstructor;
45
import org.momut.ooas.ast.expressions.TernaryOperator;
46
import org.momut.ooas.ast.expressions.TupleConstructor;
47
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
48
import org.momut.ooas.ast.expressions.TypeExpression;
49
import org.momut.ooas.ast.expressions.UnaryOperator;
50
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
51
import org.momut.ooas.ast.expressions.ValueExpression;
52
import org.momut.ooas.ast.identifiers.EnumIdentifier;
53
import org.momut.ooas.ast.identifiers.Identifier;
54
import org.momut.ooas.ast.identifiers.IdentifierKind;
55
import org.momut.ooas.ast.identifiers.LandmarkIdentifier;
56
import org.momut.ooas.ast.types.EnumType;
57
import org.momut.ooas.ast.types.FunctionType;
58
import org.momut.ooas.ast.types.TypeKind;
59
import org.momut.ooas.ast.types.UlyssesType;
60
import org.momut.ooas.ast.types.ValuedEnumType;
61
import org.momut.ooas.codegen.OoasCodeEmitter;
62
import org.momut.ooas.utils.exceptions.ArgumentException;
63
import org.momut.ooas.utils.exceptions.NotImplementedException;
64
import org.momut.ooas.visitors.OoaExpressionVisitor;
65

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

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

    
81

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

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

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

    
99

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

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

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

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

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

    
142

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

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

    
209
                case Cast:
210
                        return "";
211

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

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

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

    
241

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

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

    
257
        @Override
258
        public /*override*/ void visit(IdentifierExpression identifierExpression)
259
        {
260
                if (identifierExpression.identifier().kind() == IdentifierKind.LandmarkIdentifier)
261
                {
262
                        final LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier();
263
                        final OoaPrologIdentifier pid = createIdentifierVisitor();
264
                        lmid.Accept(pid);
265
                        //m_emitter.Append(pid.ToString());
266
                        m_tmpVars.add(pid.toString());
267
                        return;
268
                }
269
                else if (identifierExpression.identifier().kind() == IdentifierKind.EnumIdentifier)
270
                {
271
                        final EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier();
272
                        final EnumType enumType = (EnumType)enumid.type();
273
                        //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
274
                        if (enumType instanceof ValuedEnumType)
275
                                m_emitter.AppendLine(String.format("%s #= %s,", NewTempVariable(), enumid.Value()));
276
                        else
277
                                m_emitter.AppendLine(String.format("%s #= %s,", NewTempVariable(), enumType.listOfEnumSymbols().indexOf(enumid)));
278
                }
279
                else if (identifierExpression.isSelf())
280
                {
281
                        m_emitter.AppendLine(String.format("%s = %s,", NewTempVariable(), GetIdentifierString(identifierExpression.identifier())));
282
                }
283
                /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
284
        {
285
            m_emitter.AppendLine(String.format("getVal(%s,%s,_),", GetIdentifierString(identifierExpression.identifier), NewTempVariable(), ));
286
        }*/
287
                else
288
                {
289
                        m_tmpVars.add(GetIdentifierString(identifierExpression.identifier()));
290
                }
291
        }
292

    
293
        @Override
294
        public /*override*/ void visit(TypeExpression typeExpression)
295
        {
296
                if (typeExpression.type().kind() != TypeKind.QrType &&
297
                                typeExpression.type().kind() != TypeKind.EnumeratedType)
298
                {
299
                        m_emitter.Append(GetIdentifierString(typeExpression.type().identifier()));
300
                }
301
        }
302

    
303

    
304
        @Override
305
        public /*override*/ void visit(ObjectConstructor objectConstructor)
306
        {
307
                if (objectConstructor.instances().size() > 1)
308
                        throw new NotImplementedException();
309

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

    
312
                //m_emitter.Append(String.format("new %s(this)", GetIdentifierString(objectConstructor.type.identifier)));
313
        }
314

    
315
        @Override
316
        public /*override*/ void visit(ListConstructor listConstructor)
317
        {
318
                if (listConstructor.hasComprehension())
319
                {
320
                        final OoaPrologExpression compr = createExpressionVisitor();
321
                        listConstructor.comprehension().Accept(compr);
322
                        final OoaPrologExpression elem = createExpressionVisitor();
323
                        listConstructor.elements().get(0).Accept(elem);
324

    
325
                        final StringBuilder enumvars = new StringBuilder();
326
                        int i = 0;
327
                        for (final Identifier v: listConstructor.comprehensionVariables().symbolList())
328
                        {
329
                                final OoaPrologIdentifier ident = createIdentifierVisitor();
330
                                v.Accept(ident);
331

    
332
                                final OoaPrologType identType = createTypeVisitor();
333
                                v.type().Accept(identType);
334

    
335
                                enumvars.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
336
                                i++;
337
                        }
338

    
339
                        m_emitter.AppendLine("% listcomprehension");
340
                        m_emitter.AppendLine(String.format("%s = {%s:[%s]:(%s%s,%s%s)}",
341
                                        NewTempVariable(), elem.tmpVariables().get(0), enumvars.toString(), compr.toString(), compr.tmpVariables().get(0),
342
                                        elem.toString(), "1=1" /*elem.ToString() == String.Empty ? "1=1" : elem.tmpVariables[0]*/));
343
                }
344
                else
345
                {
346
                        m_emitter.AppendLine("% make list");
347
                        m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
348

    
349
                        for (final Expression expr: listConstructor.elements())
350
                        {
351
                                m_emitter.Append(", ");
352

    
353
                                final OoaPrologExpression pVal = createExpressionVisitor();
354
                                expr.Accept(pVal);
355
                                m_emitter.Append(pVal.toString());
356
                                assert(pVal.tmpVariables().size() == 1);
357
                                m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
358
                                m_tmpVars.remove(0);
359
                        }
360
                }
361
                m_emitter.Append(",");
362
                assert(m_tmpVars.size() == 1);
363
        }
364

    
365
        @Override
366
        public /*override*/ void visit(SetConstructor setConstructor)
367
        {
368
                m_emitter.AppendLine("% make set");
369
                // our resulting set.
370
                m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
371

    
372
                for (final Expression expr: setConstructor.items())
373
                {
374
                        m_emitter.Append(", ");
375

    
376
                        final OoaPrologExpression pVal = createExpressionVisitor();
377
                        expr.Accept(pVal);
378
                        m_emitter.Append(pVal.toString());
379
                        assert(pVal.tmpVariables().size() == 1);
380
                        m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
381
                        m_tmpVars.remove(0);
382
                }
383
                m_emitter.Append(",");
384
                assert(m_tmpVars.size() == 1);
385
        }
386

    
387
        @Override
388
        public /*override*/ void visit(MapConstructor mapConstructor)
389
        {
390
                throw new NotImplementedException();
391
        }
392

    
393
        @Override
394
        public /*override*/ void visit(TupleConstructor tupleConstructor)
395
        {
396
                if (tupleConstructor.isMatcher())
397
                {
398
                        // being dealt with in binaryoperator (since we only allow tuple=MyTuple(a,b))
399
                        NewTempVariable();
400
                        return;
401
                }
402
                else
403
                {
404
                        m_emitter.AppendLine("% make tuple");
405
                        m_emitter.AppendLine(String.format("%s = []", NewTempVariable()));
406

    
407
                        for (final Expression expr: tupleConstructor.values())
408
                        {
409
                                m_emitter.Append(", ");
410

    
411
                                final OoaPrologExpression pVal = createExpressionVisitor();
412
                                expr.Accept(pVal);
413
                                m_emitter.Append(pVal.toString());
414
                                assert(pVal.tmpVariables().size() == 1);
415
                                m_emitter.AppendLine(String.format("ulyssesListConc(%s,[%s],%s)", m_tmpVars.get(0), pVal.tmpVariables().get(0), NewTempVariable()));
416
                                m_tmpVars.remove(0);
417
                        }
418
                        m_emitter.Append(",");
419
                        assert(m_tmpVars.size() == 1);
420
                }
421
        }
422

    
423
        @Override
424
        public /*override*/ void visit(QValConstructor qValConstructor)
425
        {
426
                final OoaPrologIdentifier pident = createIdentifierVisitor();
427
                qValConstructor.type().identifier().Accept(pident);
428
                final StringBuilder qVal = new StringBuilder();
429
                if (qValConstructor.value() != null || qValConstructor.value().length != 0)
430
                {
431
                        final OoaPrologExpression landmark1 = createExpressionVisitor();
432
                        qValConstructor.value()[0].Accept(landmark1);
433
                        qVal.append(landmark1.toString());
434

    
435
                        if (qValConstructor.value().length > 1)
436
                        {
437
                                final OoaPrologExpression landmark2 = createExpressionVisitor();
438
                                qValConstructor.value()[1].Accept(landmark2);
439
                                qVal.append("..");
440
                                qVal.append(landmark2.toString());
441
                        }
442
                }
443
                else
444
                        qVal.append("_");
445

    
446
                String deriv = "_";
447
                switch (qValConstructor.valueDeriv())
448
                {
449
                case Dec:
450
                        deriv = "dec";
451
                        break;
452
                case Inc:
453
                        deriv = "inc";
454
                        break;
455
                case Steady:
456
                        deriv = "std";
457
                        break;
458
                default:
459
                        throw new NotImplementedException();
460
                }
461
                final String tmpVar = NewTempVariable();
462
                m_emitter.AppendLine(String.format("%s = (%s:%s/%s),", tmpVar, pident.toString(), qVal.toString(), deriv));
463
        }
464

    
465
        @Override
466
        public /*override*/ void visit(AccessExpression accessExpression)
467
        {
468
                if (accessExpression.left().type().kind() != TypeKind.QrType &&
469
                                accessExpression.left().type().kind() != TypeKind.EnumeratedType &&
470
                                !(accessExpression.right().kind() == ExpressionKind.Identifier &&
471
                                ((IdentifierExpression)accessExpression.right()).identifier().kind() == IdentifierKind.AttributeIdentifier))
472
                {
473
                        assert(m_tmpVars.size() == 0);
474
                        // enums and qr types are directly (statically) converted to nums...
475
                        VisitSub(accessExpression.left(), accessExpression);
476
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
477

    
478
                        VisitSub(accessExpression.right(), accessExpression);
479
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
480

    
481
                        m_tmpVars.add(String.format("%s\\%s", leftresult, rightresult));
482
                }
483
                else
484
                        VisitSub(accessExpression.right(), accessExpression);
485
        }
486

    
487
        @Override
488
        public /*override*/ void visit(BinaryOperator binaryOperator)
489
        {
490
                final OoasCodeEmitter origEmitter = m_emitter;
491

    
492

    
493
                // eval stack must be empty
494
                assert(m_tmpVars.size() == 0);
495
                // traverse left
496
                final OoasCodeEmitter leftcode = new OoasCodeEmitter();
497
                m_emitter = leftcode;
498
                VisitSub(binaryOperator.left(), binaryOperator);
499
                final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
500
                assert(m_tmpVars.size() == 0);
501
                // traverse right
502
                final OoasCodeEmitter rightcode = new OoasCodeEmitter();
503
                m_emitter = rightcode;
504
                VisitSub(binaryOperator.right(), binaryOperator);
505
                final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
506
                // eval stack must be empty
507
                assert(m_tmpVars.size() == 0);
508

    
509
                m_emitter = origEmitter;
510

    
511
                // get tmp.var
512
                final String tmpVar = NewTempVariable();
513

    
514
                switch (binaryOperator.kind())
515
                {
516
                case elemin:
517
                        m_emitter.Append(leftcode.toString());
518
                        m_emitter.Append(rightcode.toString());
519
                        m_emitter.AppendLine(String.format(" %s = member(%s,%s),",
520
                                        tmpVar, leftresult, rightresult));
521
                        break;
522
                case and:    // T_AND:
523
                        m_emitter.Append(leftcode.toString());
524
                        m_emitter.Append(rightcode.toString());
525
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
526
                                        tmpVar, leftresult, ",", rightresult));
527
                        break;
528
                case or:     // T_OR:
529
                        m_emitter.Append(leftcode.toString());
530
                        m_emitter.Append(rightcode.toString());
531
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
532
                                        tmpVar, leftresult, ";", rightresult));
533
                        break;
534

    
535
                case implies:
536
                        m_emitter.Append(leftcode.toString());
537
                        m_emitter.AppendLine(String.format(" %s = (%s -> (%s%s); true), ", // {0} = (({1} -> ({2}{3}); true))
538
                                        tmpVar, leftresult, rightcode.toString(), rightresult));
539
                        break;
540

    
541
                case equal:
542
                        m_emitter.Append(leftcode.toString());
543
                        m_emitter.Append(rightcode.toString());
544
                        /*check if we have tupleconstructors as matchers*/
545
                        TupleConstructor matcher = null;
546
                        String aTuple = null;
547
                        if (binaryOperator.left().kind() == ExpressionKind.TupleConstr &&
548
                                        ((TupleConstructor)binaryOperator.left()).isMatcher())
549
                        {
550
                                matcher = (TupleConstructor)binaryOperator.left();
551
                                aTuple = rightresult;
552
                        }
553
                        else if (binaryOperator.right().kind() == ExpressionKind.TupleConstr &&
554
                                        ((TupleConstructor)binaryOperator.right()).isMatcher())
555
                        {
556
                                matcher = (TupleConstructor)binaryOperator.right();
557
                                aTuple = leftresult;
558
                        }
559

    
560
                        if (matcher == null)
561
                                m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
562
                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
563
                        else
564
                        {
565
                                m_emitter.Append(String.format("%s = unify(%s = [", tmpVar, aTuple));
566
                                int cntr = 0;
567
                                for(final Expression x: matcher.values())
568
                                {
569
                                        if (cntr != 0)
570
                                                m_emitter.Append(", ");
571
                                        else
572
                                                cntr++;
573

    
574
                                        if (x.kind() != ExpressionKind.Identifier)
575
                                                throw new ArgumentException();
576

    
577
                                        final IdentifierExpression ident = (IdentifierExpression)x;
578
                                        final OoaPrologIdentifier avisitor = createIdentifierVisitor();
579
                                        ident.Accept(avisitor);
580
                                        m_emitter.Append(avisitor.toString());
581
                                }
582
                                m_emitter.AppendLine("]),");
583
                        }
584
                        break;
585

    
586

    
587

    
588
                case conc:
589
                        m_emitter.Append(leftcode.toString());
590
                        m_emitter.Append(rightcode.toString());
591
                        m_emitter.AppendLine(String.format("ulyssesListConc(%s,%s,%s),", leftresult, rightresult, tmpVar));
592
                        break;
593

    
594
                default:
595
                        m_emitter.Append(leftcode.toString());
596
                        m_emitter.Append(rightcode.toString());
597
                        if (binaryOperator.left().type().kind() == TypeKind.QrType)
598
                                m_emitter.Append("qEval");
599
                        //m_emitter.Append("(");
600
                        if (binaryOperator.type().kind() == TypeKind.IntType)
601
                                m_emitter.AppendLine(String.format(" %s #= (%s %s %s), ",
602
                                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
603
                        else
604
                                m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
605
                                                tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left().type()), rightresult));
606
                        //m_emitter.Append(")");
607
                        break;
608
                }
609
                assert(m_tmpVars.size() == 1);
610
        }
611

    
612
        @Override
613
        public /*override*/ void visit(TernaryOperator ternaryOperator)
614
        {
615
                if (ternaryOperator.kind() == ExpressionKind.conditional)
616
                {
617
                        VisitSub(ternaryOperator.left(), ternaryOperator);
618
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
619
                        VisitSub(ternaryOperator.mid(), ternaryOperator);
620
                        final String midresult = m_tmpVars.get(0); m_tmpVars.remove(0);
621
                        VisitSub(ternaryOperator.right(), ternaryOperator);
622
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
623

    
624
                        final String varname = NewTempVariable();
625

    
626
                        // (cond, expr #= var; #\ (cond), expr #= var)
627
                        m_emitter.Append("((");
628
                        m_emitter.Append(leftresult);
629
                        m_emitter.Append(", unify(");
630
                        m_emitter.Append(midresult);
631
                        m_emitter.Append(String.format(" = %s) );( call(\\+(%s)), unify(", varname, leftresult));
632
                        m_emitter.Append(rightresult);
633
                        m_emitter.Append(String.format(" = %s) )),", varname));
634
                }
635
                else if (ternaryOperator.kind() == ExpressionKind.foldRL)
636
                        throw new NotImplementedException();
637
                else if (ternaryOperator.kind() == ExpressionKind.foldLR)
638
                {
639
                        VisitSub(ternaryOperator.mid(), ternaryOperator);
640
                        final String midresult = m_tmpVars.get(0); m_tmpVars.remove(0);
641
                        VisitSub(ternaryOperator.right(), ternaryOperator);
642
                        final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
643

    
644

    
645
                        // make vars unique
646
                        final int uniqueNumer = GetUniqueNumber();
647
                        final CallExpression leftcall = (CallExpression)ternaryOperator.left();
648
                        final IdentifierExpression elemId = (IdentifierExpression)leftcall.arguments().get(leftcall.arguments().size() - 1);
649
                        elemId.identifier().SetTokenText(String.format("Elem_%s", uniqueNumer));
650
                        final IdentifierExpression currentResultId = (IdentifierExpression)leftcall.arguments().get(leftcall.arguments().size() - 2);
651
                        currentResultId.identifier().SetTokenText(String.format("In_%s", uniqueNumer));
652

    
653
                        final String elemVarName = GetIdentifierString(elemId.identifier());
654
                        final String inVarName = GetIdentifierString(currentResultId.identifier());
655

    
656
                        m_emitter.Append(String.format("fun_fold(%s,%s,(%s, %s, Out_%s,(",
657
                                        midresult, rightresult, elemVarName, inVarName, uniqueNumer));
658
                        VisitSub(leftcall, ternaryOperator);
659
                        final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
660
                        final String tmpresult = NewTempVariable();
661
                        m_emitter.Append(String.format(" Out_%s = %s)),%s),", uniqueNumer, leftresult, tmpresult));
662
                }
663

    
664
                else
665
                        throw new NotImplementedException();
666
        }
667

    
668
        @Override
669
        public /*override*/ void visit(TupleMapAccessExpression tupleMapAccessExpression)
670
        {
671
                assert(m_tmpVars.size() == 0);
672
                VisitSub(tupleMapAccessExpression.child(), tupleMapAccessExpression);
673
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
674

    
675
                VisitSub(tupleMapAccessExpression.argument(), tupleMapAccessExpression);
676
                final String accessresult = m_tmpVars.get(0); m_tmpVars.remove(0);
677
                assert(m_tmpVars.size() == 0);
678

    
679
                final String tmpresult = NewTempVariable();
680

    
681
                if (!m_LhsExpression)
682
                {
683
                        switch (tupleMapAccessExpression.child().type().kind())
684
                        {
685
                        case TupleType:
686
                                m_emitter.AppendLine(String.format("ulyssesTupleAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
687
                                break;
688
                        case MapType:
689
                                m_emitter.AppendLine(String.format("ulyssesMapAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
690
                                break;
691
                        case ListType:
692
                                m_emitter.AppendLine(String.format("ulyssesListAccess(%s,%s,%s),", childresult, accessresult, tmpresult));
693
                                break;
694
                        default:
695
                                throw new NotImplementedException();
696
                        }
697
                        assert(m_tmpVars.size() == 1);
698
                }
699
                else
700
                {
701
                        /*>>>>> See comment in ooaTypeCheckVisitor on method CheckPlace! <<<<<<<<<*/
702
                        switch (tupleMapAccessExpression.child().type().kind())
703
                        {
704
                        case ListType:
705
                                boolean isAttribute;
706
                                isAttribute = tupleMapAccessExpression.child().kind() == ExpressionKind.Identifier &&
707
                                                ((IdentifierExpression)tupleMapAccessExpression.child()).identifier().kind() == IdentifierKind.AttributeIdentifier;
708

    
709
                                isAttribute = isAttribute || tupleMapAccessExpression.child().kind() == ExpressionKind.Access
710
                                                && ((AccessExpression)tupleMapAccessExpression.child()).left().kind() == ExpressionKind.Identifier
711
                                                && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child()).left()).isSelf()
712
                                                && ((AccessExpression)tupleMapAccessExpression.child()).right().kind() == ExpressionKind.Identifier
713
                                                && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child()).right()).identifier().kind()
714
                                                == IdentifierKind.AttributeIdentifier;
715

    
716

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

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

    
721
                                if (isAttribute)
722
                                { m_emitter.AppendLine(String.format("%s := %s,", childresult, newlist)); }
723
                                else
724
                                { throw new NotImplementedException(); }
725

    
726
                                break;
727
                        default:
728
                                throw new NotImplementedException();
729
                        }
730

    
731

    
732
                }
733
        }
734

    
735

    
736
        @Override
737
        public /*override*/ void visit(ForallQuantifier quantifier)
738
        {
739
                final OoaPrologExpression pExpr = createExpressionVisitor();
740
                quantifier.child().Accept(pExpr);
741

    
742
                // TEMPXY = forall(enumerate1([var:type,...]),pred(var..))
743
                final StringBuilder Generator = new StringBuilder();
744
                final StringBuilder nullGuard = new StringBuilder();
745
                int i = 0;
746
                for (final Identifier v: quantifier.symbols().symbolList())
747
                {
748
                        final OoaPrologIdentifier ident = createIdentifierVisitor();
749
                        v.Accept(ident);
750

    
751
                        final OoaPrologType identType = createTypeVisitor();
752
                        v.type().Accept(identType);
753

    
754
                        Generator.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
755
                        if (v.type().kind() == TypeKind.OoActionSystemType)
756
                                nullGuard.append(String.format("(%s == null) ; ", ident.toString()));
757
                        i++;
758
                }
759

    
760
                m_emitter.AppendLine(String.format("%s = forall([%s], (%s(%s%s))),",
761
                                NewTempVariable(), Generator.toString(), nullGuard.toString(), pExpr.toString(), pExpr.tmpVariables().get(0)));
762
        }
763

    
764

    
765

    
766
        @Override
767
        public /*override*/ void visit(ExistsQuantifier quantifier)
768
        {
769
                final OoaPrologExpression pExpr = createExpressionVisitor();
770
                quantifier.child().Accept(pExpr);
771

    
772
                // TEMPXY = exists(enumerate1([var:type,...]),pred(var..))
773
                final StringBuilder Generator = new StringBuilder();
774
                final StringBuilder nullGuard = new StringBuilder();
775
                int i = 0;
776
                for (final Identifier v: quantifier.symbols().symbolList())
777
                {
778
                        final OoaPrologIdentifier ident = createIdentifierVisitor();
779
                        v.Accept(ident);
780

    
781
                        final OoaPrologType identType = createTypeVisitor();
782
                        v.type().Accept(identType);
783

    
784
                        Generator.append(String.format("%s %s: %s", i == 0 ? "" : ",", ident.toString(), identType.toString()));
785
                        if (v.type().kind() == TypeKind.OoActionSystemType)
786
                                nullGuard.append(String.format("(%s \\= null), ", ident.toString()));
787
                        i++;
788
                }
789

    
790
                m_emitter.AppendLine(String.format("%s = exists([%s], (%s(%s%s))),",
791
                                NewTempVariable(), Generator.toString(), nullGuard.toString(), pExpr.toString(), pExpr.tmpVariables().get(0)));
792
        }
793
        @Override
794
        public /*override*/ void visit(UnaryOperator unaryOperator)
795
        {
796
                assert(m_tmpVars.size() == 0);
797
                VisitSub(unaryOperator.child(), unaryOperator);
798

    
799
                if (unaryOperator.kind() == ExpressionKind.Cast)
800
                        return;
801

    
802
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
803
                assert(m_tmpVars.size() == 0);
804

    
805
                final String tmpresult = NewTempVariable();
806

    
807
                switch (unaryOperator.kind())
808
                {
809
                case head:
810
                        m_emitter.AppendLine(String.format("ulyssesListHead(%s,%s),", childresult, tmpresult));
811
                        break;
812

    
813
                case tail:
814
                        m_emitter.AppendLine(String.format("ulyssesListTail(%s,%s),", childresult, tmpresult));
815
                        break;
816

    
817
                case len:    // T_LEN:
818
                        m_emitter.AppendLine(String.format("ulyssesListLength(%s,%s),", childresult, tmpresult));
819
                        break;
820

    
821
                case not:
822

    
823
                        if (unaryOperator.type().kind() == TypeKind.IntType)
824
                                m_emitter.Append(String.format(" %s #= call(\\+", tmpresult));
825
                        else
826
                                m_emitter.Append(String.format(" %s = call(\\+", tmpresult));
827
                        m_emitter.Append("(");
828
                        m_emitter.Append(childresult);
829
                        m_emitter.AppendLine(")),");
830

    
831

    
832
                        break;
833

    
834
                case Cast:
835
                        // todo
836
                        break;
837

    
838
                default:
839
                        if (unaryOperator.type().kind() == TypeKind.IntType)
840
                                m_emitter.Append(String.format(" %s #= (%s", tmpresult, OperatorString(unaryOperator, unaryOperator.child().type())));
841
                        else
842
                                m_emitter.Append(String.format(" %s = (%s", tmpresult, OperatorString(unaryOperator, unaryOperator.child().type())));
843
                        m_emitter.Append("(");
844
                        m_emitter.Append(childresult);
845
                        m_emitter.AppendLine(")),");
846
                        break;
847
                }
848
                assert(m_tmpVars.size() == 1);
849
        }
850

    
851
        @Override
852
        public /*override*/ String toString()
853
        {
854
                return m_emitter.toString();
855
        }
856

    
857
        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory, m_scratchbook); }
858
        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
859
        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory, m_scratchbook); }
860

    
861
        protected final OoaPrologIdentifier.Factory m_idFactory;
862
        protected final OoaPrologType.Factory m_typeFactory;
863
        protected final OoaPrologExpression.Factory m_exprFactory;
864

    
865
        protected OoaPrologExpression(
866
                        OoaPrologIdentifier.Factory idFactory,
867
                        OoaPrologType.Factory typeFactory,
868
                        Scratchbook scratchbook,
869
                        OoaPrologExpression.Factory expressionFactory)
870
        {
871
                this(idFactory, typeFactory, scratchbook, expressionFactory, false);
872
        }
873

    
874
        protected OoaPrologExpression(
875
                        OoaPrologIdentifier.Factory idFactory,
876
                        OoaPrologType.Factory typeFactory,
877
                        Scratchbook scratchbook,
878
                        OoaPrologExpression.Factory expressionFactory,
879
                        boolean isLHS)
880
        {
881
                super();
882
                m_LhsExpression = isLHS;
883
                m_idFactory = idFactory;
884
                m_typeFactory = typeFactory;
885
                m_exprFactory = expressionFactory;
886
                m_scratchbook = scratchbook;
887
        }
888

    
889

    
890
        public String NewTempVariable()
891
        {
892
                final String result = String.format("TMPVAR_%s", m_scratchbook.getNewTmpVarCntrValue());
893
                m_tmpVars.add(result);
894
                return result;
895
        }
896

    
897
        public int GetUniqueNumber()
898
        {
899
                return m_scratchbook.getNewTmpVarCntrValue();
900
        }
901
}