Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / codegen / cadp / CadpExpression.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.cadp;
29

    
30
import java.util.ArrayList;
31
import java.util.HashSet;
32
import java.util.Iterator;
33
import java.util.List;
34

    
35
import org.momut.ooas.ast.expressions.AccessExpression;
36
import org.momut.ooas.ast.expressions.BinaryOperator;
37
import org.momut.ooas.ast.expressions.CallExpression;
38
import org.momut.ooas.ast.expressions.ExistsQuantifier;
39
import org.momut.ooas.ast.expressions.Expression;
40
import org.momut.ooas.ast.expressions.ExpressionKind;
41
import org.momut.ooas.ast.expressions.ForallQuantifier;
42
import org.momut.ooas.ast.expressions.IdentifierExpression;
43
import org.momut.ooas.ast.expressions.ListConstructor;
44
import org.momut.ooas.ast.expressions.MapConstructor;
45
import org.momut.ooas.ast.expressions.ObjectConstructor;
46
import org.momut.ooas.ast.expressions.SetConstructor;
47
import org.momut.ooas.ast.expressions.TernaryOperator;
48
import org.momut.ooas.ast.expressions.TupleConstructor;
49
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
50
import org.momut.ooas.ast.expressions.TypeExpression;
51
import org.momut.ooas.ast.expressions.UnaryOperator;
52
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
53
import org.momut.ooas.ast.expressions.ValueExpression;
54
import org.momut.ooas.ast.expressions.LeafExpression.LeafTypeEnum;
55
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier;
56
import org.momut.ooas.ast.identifiers.FunctionIdentifier;
57
import org.momut.ooas.ast.identifiers.Identifier;
58
import org.momut.ooas.ast.identifiers.IdentifierKind;
59
import org.momut.ooas.ast.types.FunctionType;
60
import org.momut.ooas.ast.types.ListType;
61
import org.momut.ooas.ast.types.MapType;
62
import org.momut.ooas.ast.types.OoActionSystemInstance;
63
import org.momut.ooas.ast.types.OoActionSystemType;
64
import org.momut.ooas.ast.types.TupleType;
65
import org.momut.ooas.ast.types.TypeKind;
66
import org.momut.ooas.ast.types.Type;
67
import org.momut.ooas.codegen.OoasCodeEmitter;
68
import org.momut.ooas.parser.SymbolTable;
69
import org.momut.ooas.visitors.OoaExpressionVisitor;
70

    
71
/// <summary>
72
/// Knows how to construct a C-CADP expression from an AST-expression
73
/// (only basic arithmetical operations supported)
74
/// </summary>
75
public final class CadpExpression extends OoaExpressionVisitor
76
{
77
        private OoasCodeEmitter m_emitter = new OoasCodeEmitter();
78
        private final CadpActionInfo m_procInfo;
79
        private final ArrayList<Identifier> m_usedIdentifier = new ArrayList<Identifier>();
80
        private static OoasCodeEmitter m_helperCode = new OoasCodeEmitter();
81
        private static OoasCodeEmitter m_resetCode = new OoasCodeEmitter();
82

    
83
        public static HashSet<String> emittedOperations = new HashSet<String>();
84
        public List<Identifier> usedIdentifiers() { return m_usedIdentifier; }
85

    
86
        private String OperatorString(Expression expression)
87
        {
88
                switch (expression.kind())
89
                {
90
                case abs:    // T_ABS:
91
                case card:   // T_CARD:
92
                case dom:    // T_DOM:
93
                case range:  // T_RNG:
94
                case merge:  // T_MERGE:
95
                case elems:  // T_ELEMS:
96
                case inds:   // T_INDS:
97
                case dinter: // T_DINTER:
98
                case dunion: // T_DUNION:
99
                case domresby:   // T_DOMRESBY:
100
                case domresto:   // T_DOMRESTO:
101
                case rngresby:   // T_RNGRESBY:
102
                case rngresto:   // T_RNGRESTO:
103
                case inter:  // T_INTER:
104
                case union:  // T_UNION:
105
                case munion: // T_MUNION:
106
                case seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
107
                case subset:
108
                case biimplies:  // T_BIIMPLIES:
109
                case Primed:
110
                        throw new UnsupportedOperationException();
111

    
112
                case notelemin:
113
                case elemin:
114
                case implies:    // T_IMPLIES:
115
                case conc:   // T_CONC:
116
                case head:   // T_HEAD:
117
                case tail:   // T_TAIL:
118
                case len:    // T_LEN:
119
                        throw new IllegalArgumentException(); // handled directly in binary operator! (T_CONC instanceof still todo, however)
120

    
121

    
122
                case div:    // T_DIV:
123
                        return "/";
124
                case idiv:   // T_IDIV:
125
                        return "/";
126
                case mod:    // T_MOD:
127
                        return "%";
128
                case prod:   // T_PROD:
129
                        return "*";
130
                case sum:    // T_SUM:
131
                        return "+";
132
                case minus:  // T_MINUS:
133
                        return "-";
134
                case less:
135
                        return "<";
136
                case lessequal:
137
                        return "<=";
138
                case greater:
139
                        return ">";
140
                case greaterequal:
141
                        return ">=";
142
                case equal:
143
                        return "==";
144
                case notequal:
145
                        return "!=";
146
                case and:    // T_AND:
147
                        return "&&";
148
                case or:     // T_OR:
149
                        return "||";
150
                case not:
151
                        return "!";
152

    
153
                case Cast:
154
                        throw new IllegalArgumentException(); // handled elsewhere
155
                        /*if (expression.type != null)
156
                    return "("+expression.type().ToString()+")";
157
                else
158
                    return "(??Cast??)";*/
159

    
160
                default:
161
                        return expression.kind().toString();
162
                }
163
        }
164
        @Override
165
        public <T>void visit(ValueExpression<T> valueExpression)
166
        {
167
                if (valueExpression.value() == null)
168
                {
169
                        m_emitter.Append("NULL");
170
                }
171
                else if (valueExpression.valueType() == LeafTypeEnum.bool)
172
                {
173
                        // bad hack..
174
                        final boolean aboolval = (Boolean)valueExpression.value();
175
                        m_emitter.AppendLine(aboolval ? "1" : "0");
176
                }
177
                else if (valueExpression.valueType() == LeafTypeEnum.chr)
178
                        m_emitter.Append(String.format("'%1$s'", valueExpression.toString()));
179
                else
180
                        m_emitter.Append(valueExpression.value().toString());
181
        }
182
        @Override
183
        public  void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
184
        {
185
                throw new IllegalArgumentException();
186
        }
187

    
188
        @Override
189
        public  void visit(IdentifierExpression identifierExpression)
190
        {
191
                final CadpIdentifier idvis = new CadpIdentifier(m_procInfo.stateVariableString);
192
                identifierExpression.Accept(idvis);
193
                m_emitter.Append(idvis.toString());
194

    
195
                if (identifierExpression.identifier().kind() == IdentifierKind.ExpressionVariableIdentifier)
196
                {
197
                        // we need to define the variable
198
                        // declare free variables
199
                        final ExpressionVariableIdentifier id = (ExpressionVariableIdentifier)identifierExpression.identifier();
200
                        if (!emittedVariabes.contains(id))
201
                        {
202
                                emittedVariabes.add(id);
203
                                final CadpType atype = new CadpType();
204
                                id.type().Accept(atype);
205
                                varDecl.Append(String.format("%1$s %2$s; ", atype.ToString(), idvis.toString()));
206
                        }
207
                }
208
                // we memorize all identifiers
209
                if (!m_usedIdentifier.contains(identifierExpression.identifier()))
210
                        m_usedIdentifier.add(identifierExpression.identifier());
211
        }
212

    
213
        @Override
214
        public  void visit(TypeExpression typeExpression)
215
        {
216
                m_emitter.Append(typeExpression.type().identifier().tokenText());
217
        }
218

    
219
        @Override
220
        public  void visit(ListConstructor listConstructor)
221
        {
222
                final ListType aListType = (ListType)listConstructor.type();
223
                if (!listConstructor.hasComprehension())
224
                {
225
                        CadpType.EmitType(aListType);
226

    
227
                        m_emitter.Append(String.format("%1$s%2$s(%3$s", CadpType.constructorString, CadpIdentifier.GetIdentifierString(aListType.identifier()), listConstructor.elements().size()));
228
                        int i;
229
                        for (i = 0; i < aListType.maxNumberOfElements(); i++)
230
                        {
231
                                m_emitter.Append(", ");
232
                                if (i < listConstructor.elements().size())
233
                                        listConstructor.elements().get(i).Accept(this);
234
                                else
235
                                        m_emitter.Append(String.format("%1$s%2$s(%3$s%2$s())", CadpType.enumString, CadpIdentifier.GetIdentifierString(aListType.innerType().identifier()), CadpType.lowString));
236
                        }
237
                        m_emitter.Append(")");
238
                }
239
                else
240
                {
241
                        final CadpExpression compExpr = new CadpExpression(new CadpActionInfo(null, -1, 0, m_procInfo.toDoListString, m_procInfo.doneListString, "aState"), emittedVariabes);
242
                        if (listConstructor.comprehension() != null)
243
                                listConstructor.comprehension().Accept(compExpr);
244
                        else
245
                                new ValueExpression<Integer>(1, 0, 0, Integer.class).Accept(compExpr);
246

    
247
                        final CadpExpression listElementExpr = new CadpExpression(m_procInfo, emittedVariabes);
248
                        listConstructor.elements().get(0).Accept(listElementExpr);
249

    
250
                        // get a list of imported variabes
251
                        compExpr.usedIdentifiers().addAll(listElementExpr.usedIdentifiers());
252
                        final List<Identifier> importVars = getListOfAccessedIdentifiers(compExpr, listConstructor.comprehensionVariables());
253

    
254

    
255
                        // Idea: reduce importVars by compExpr.VariableDeclarations
256
                        // importVars.RemoveAll( (x) => if (x in compExpr.Vara... ) return true);
257

    
258
                        // BEGIN FIXXME
259
                        final List<Identifier> varsToRemove = new ArrayList<Identifier>();
260

    
261
                        for (final Identifier id : importVars)
262
                        {
263
                                final CadpType atype = new CadpType();
264
                                id.type().Accept(atype);
265
                                final String typeAndName = (String.format("%1$s %2$s; ", atype.ToString(), id.tokenText()));
266

    
267
                                if (compExpr.VariableDeclarations().contains(typeAndName))
268
                                        varsToRemove.add(id);
269
                        }
270
                        int tmpcntr = importVars.size() -1;
271
                        for (tmpcntr = importVars.size() -1; tmpcntr>=0; tmpcntr--)
272
                                if (varsToRemove.contains(importVars.get(tmpcntr)))
273
                                        importVars.remove(tmpcntr);
274
                        // END FIXXME
275

    
276
                        final String functionName = String.format("create_dyn_list_%1$s", OoaCADPVisitor.getUIntHashCode(listConstructor));
277
                        m_emitter.Append(functionName);
278
                        m_emitter.Append(String.format("( %1$s", this.m_procInfo.stateVariableString));
279
                        for (final Identifier x : importVars)
280
                        {
281
                                m_emitter.Append(",");
282
                                m_emitter.Append(String.format("%1$s", CadpIdentifier.GetIdentifierString(x)));
283
                        }
284
                        m_emitter.Append(")");
285

    
286
                        // emit helper
287
                        final ListType listType = (ListType)listConstructor.type();
288
                        CadpType.EmitType(listType.innerType());
289
                        final OoasCodeEmitter helper = new OoasCodeEmitter();
290
                        final String listtypename = String.format("struct_list_%1$s", CadpType.DumpType(listType.innerType()).replaceAll(" ", "_"));
291

    
292

    
293
                        final StringBuilder typedefbuilder = new StringBuilder();
294
                        typedefbuilder.append("#ifdef WINDOWSPACK" + System.lineSeparator());
295
                        typedefbuilder.append("#pragma pack(1)" + System.lineSeparator());
296
                        typedefbuilder.append("#endif" + System.lineSeparator());
297
                        typedefbuilder.append(String.format("struct %2$s { struct %2$s *next; %1$s element;} UNIXPACK;", CadpType.DumpType(listType.innerType()), listtypename));
298
                        typedefbuilder.append(System.lineSeparator());
299
                        final String listStruct = typedefbuilder.toString();
300
                        CadpType.AddTypeDefinition(listStruct);
301

    
302
                        helper.AppendLine(String.format("struct %1$s* %2$s(CAESAR_TYPE_STATE aState", listtypename, functionName));
303
                        for (final Identifier x : importVars)
304
                        {
305
                                helper.Append(", ");
306
                                helper.Append(String.format("%1$s %2$s", CadpType.DumpType(x.type()), CadpIdentifier.GetIdentifierString(x)));
307
                        }
308
                        helper.AppendLine("){");
309

    
310
                        helper.AppendLine(String.format("struct %1$s* result = NULL;", listtypename));
311
                        helper.AppendLine(String.format("struct %1$s* __currhead = NULL;", listtypename));
312
                        helper.AppendLine(compExpr.VariableDeclarations());
313

    
314
                        int loops = 0;
315
                        for (final Identifier enumvar : listConstructor.comprehensionVariables().symbolList())
316
                        {
317
                                helper.AppendLine(String.format("long long iterator_%1$s;", CadpIdentifier.GetIdentifierString(enumvar)));
318
                                helper.AppendLine(String.format("for (iterator_%1$s = %2$s; iterator_%1$s <= %3$s; iterator_%1$s++) {",
319
                                                CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetMinVal(enumvar.type()), CadpType.GetMaxVal(enumvar.type())));
320

    
321
                                if (compExpr.VariableDeclarations().contains(String.format(" %1$s;", CadpIdentifier.GetIdentifierString(enumvar))))
322
                                        helper.AppendLine(String.format("/*%1$s*/ %2$s = %3$s(iterator_%2$s);",
323
                                                        CadpType.DumpType(enumvar.type()), CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetEnumVal(enumvar.type())));
324
                                else
325
                                        helper.AppendLine(String.format("%1$s %2$s = %3$s(iterator_%2$s);",
326
                                                        CadpType.DumpType(enumvar.type()), CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetEnumVal(enumvar.type())));
327
                                loops++;
328
                        }
329

    
330
                        helper.AppendLine(String.format("%1$s __newElem;", CadpType.DumpType(listType.innerType())));
331

    
332

    
333
                        helper.AppendLine(String.format("if ((%1$s) && (CALC_INVALID == 0)) { __newElem = %2$s; ", compExpr.toString(), listElementExpr.toString()));
334

    
335
                        helper.AppendLine(String.format("struct %1$s* __listelem =  (struct %1$s*) malloc(sizeof(struct %1$s));", listtypename));
336
                        helper.AppendLine(String.format("if (__listelem == NULL) { fprintf(stderr,\"malloc failure\"); exit(1);}"));
337
                        helper.AppendLine(String.format("memset((char*)__listelem,0,sizeof(struct %1$s));", listtypename));
338

    
339
                        helper.AppendLine(String.format(String.format("memcpy(&(__listelem->element),&__newElem, sizeof(%1$s));", CadpType.DumpType(listType.innerType()))));
340
                        helper.AppendLine(String.format("if (result == NULL) result = __listelem; else __currhead->next = __listelem; __currhead = __listelem;"));
341

    
342
                        helper.AppendLine("} /*if*/");
343
                        helper.AppendLine("if (CALC_INVALID == 1) CALC_INVALID = 0;");
344
                        while (loops > 0)
345
                        {
346
                                helper.AppendLine("}");
347
                                loops--;
348
                        }
349
                        helper.AppendLine("return result; }");
350

    
351
                        m_helperCode.Append(helper.toString());
352
                }
353
        }
354

    
355
        @Override
356
        public  void visit(SetConstructor setConstructor)
357
        {
358
                final ListType aSetType = (ListType)setConstructor.type();
359
                m_emitter.Append(String.format(" /*set constr*/ %1$s%2$s(", CadpType.constructorString, CadpIdentifier.GetIdentifierString(aSetType.identifier())));
360
                m_emitter.Append(setConstructor.items().size());
361
                for (final Expression x : setConstructor.items())
362
                {
363
                        m_emitter.Append(", ");
364
                        x.Accept(this);
365
                }
366
                m_emitter.Append(")");
367
        }
368

    
369
        @Override
370
        public  void visit(MapConstructor mapConstructor)
371
        {
372
                throw new UnsupportedOperationException();
373
        }
374

    
375
        @Override
376
        public  void visit(TupleConstructor tupleConstructor)
377
        {
378
                final TupleType aTupleType = (TupleType)tupleConstructor.type();
379

    
380
                if (tupleConstructor.isMatcher())
381
                {
382
                        // being dealt with in binaryoperator (since we only allow tuple=MyTuple(a,b))
383
                        throw new IllegalArgumentException();
384
                }
385
                else
386
                {
387
                        m_emitter.Append(String.format("%1$s%2$s(", CadpType.constructorString, CadpIdentifier.GetIdentifierString(aTupleType.identifier())));
388
                        int i = 0;
389
                        for (final Expression x : tupleConstructor.values())
390
                        {
391
                                if (i != 0)
392
                                        m_emitter.Append(", ");
393
                                else
394
                                        i++;
395
                                x.Accept(this);
396
                        }
397
                        m_emitter.Append(")");
398
                }
399
        }
400

    
401
        @Override
402
        public void visit(ObjectConstructor objectConstructor)
403
        {
404
                final OoActionSystemInstance instance = objectConstructor.GetNextInstance();
405
                CadpType.EmitType(instance.Type);
406
                if (objectConstructor.instances().size() == 1)
407
                {
408
                        m_emitter.Append(String.format("%1$s", instance.Name));
409
                }
410
                else
411
                {
412
                        final String helpername = String.format("obj_constr_%1$s", OoaCADPVisitor.getUIntHashCode(objectConstructor));
413
                        m_emitter.Append(String.format("%1$s()", helpername));
414

    
415
                        // emit helper
416

    
417
                        final OoasCodeEmitter helper = new OoasCodeEmitter();
418
                        helper.AppendLine(String.format("int %1$s_counter = 0;", helpername));
419
                        m_resetCode.AppendLine(String.format("%1$s_counter = 0;", helpername));
420
                        helper.AppendLine(String.format("%1$s %2$s(){", CadpType.DumpType(objectConstructor.type()), helpername));
421
                        int i = 0;
422
                        for (final OoActionSystemInstance x : objectConstructor.instances())
423
                        {
424
                                CadpType.EmitType(x.Type);
425
                                helper.AppendLine(String.format("if (%1$s_counter == %2$s) {%1$s_counter++; return %3$s;}",
426
                                                helpername, i, x.Name));
427
                                i++;
428
                        }
429
                        helper.AppendLine(String.format("fprintf(stderr,\"constructor called too often: %1$s\"); exit(1);", helpername));
430
                        helper.Append("}");
431
                        m_helperCode.AppendLine(helper.toString());
432
                }
433
        }
434

    
435

    
436
        @Override
437
        public  void visit(AccessExpression accessExpression)
438
        {
439
                // if this instanceof some "<enumType>.<enumValue>" access, then just print the numeric value of <enumValue>
440
                if (accessExpression.left().kind() == ExpressionKind.Type &&
441
                    ((TypeExpression)accessExpression.left()).type().kind() == TypeKind.EnumeratedType )
442
                {
443
                        accessExpression.right().Accept(this);
444
                        return;
445
                }
446

    
447
                // we normally skip the self, except for the case of method
448
                // accesses (where we need to go over the jumptable
449
                if (accessExpression.left().kind() == ExpressionKind.Identifier &&
450
                                ((IdentifierExpression)accessExpression.left()).isSelf())
451
                {
452
                        if (accessExpression.right().kind() != ExpressionKind.Identifier ||
453
                                        ((IdentifierExpression)accessExpression.right()).identifier().kind() != IdentifierKind.MethodIdentifier)
454
                        {
455
                                accessExpression.right().Accept(this);
456
                                return;
457
                        }
458
                }
459

    
460
                accessExpression.left().Accept(this);
461
                m_emitter.Append(".");
462
                // in oder to save memory, we do method access via a jump table
463
                if (((IdentifierExpression)accessExpression.right()).identifier().kind() == IdentifierKind.MethodIdentifier ||
464
                                ((IdentifierExpression)accessExpression.right()).identifier().kind() == IdentifierKind.NamedActionIdentifier)
465
                        m_emitter.Append("methods->");
466
                accessExpression.right().Accept(this);
467
        }
468

    
469

    
470
        OoasCodeEmitter varDecl = new OoasCodeEmitter();
471
        HashSet<Identifier> emittedVariabes = new HashSet<Identifier>();
472

    
473
        public void addEmittedVariables(HashSet<Identifier> elementsToAdd)
474
        {
475
                emittedVariabes.addAll(elementsToAdd);
476
        }
477

    
478
        private void EmitMatcher(TupleConstructor tupleConstructor, Expression expression)
479
        {
480
                final OoasCodeEmitter tmp = m_emitter;
481
                // get the expression
482
                m_emitter = new OoasCodeEmitter();
483
                expression.Accept(this);
484
                final OoasCodeEmitter expr = m_emitter;
485
                m_emitter = tmp;
486

    
487
                // treat cases of MyTuple(a,b..) = <expr>
488
                final Iterator<Type> elem = ((TupleType)tupleConstructor.type()).innerTypes().iterator();
489
                int i = 0;
490
                m_emitter.Append("(");
491
                while (elem.hasNext())
492
                {
493
                        final Expression var = tupleConstructor.values().get(i);
494

    
495
                        if (i != 0)
496
                                m_emitter.Append(" , ");
497

    
498
                        var.Accept(this);
499
                        m_emitter.Append(String.format(" = (%1$s).elem_%2$s ", expr.toString(), i));
500

    
501
                        i++;
502
                }
503
                m_emitter.Append(", 1==1)");
504
        }
505

    
506
        private void EmitDefaultBinaryOperator(BinaryOperator binaryOperator)
507
        {
508
                m_emitter.Append("(");
509
                VisitSub(binaryOperator.left(), binaryOperator);
510
                m_emitter.Append(") ");
511
                m_emitter.Append(OperatorString(binaryOperator));
512
                m_emitter.Append(" (");
513
                VisitSub(binaryOperator.right(), binaryOperator);
514
                m_emitter.Append(")");
515
        }
516

    
517
        @Override
518
        public  void visit(BinaryOperator binaryOperator)
519
        {
520
                switch (binaryOperator.kind())
521
                {
522
                case equal:
523
                        /*check if we have tupleconstructors as matchers*/
524
                        if (binaryOperator.left().kind() == ExpressionKind.TupleConstr &&
525
                        ((TupleConstructor)binaryOperator.left()).isMatcher())
526
                        {
527
                                EmitMatcher((TupleConstructor)binaryOperator.left(), binaryOperator.right());
528
                        }
529
                        else if (binaryOperator.right().kind() == ExpressionKind.TupleConstr &&
530
                                        ((TupleConstructor)binaryOperator.right()).isMatcher())
531
                        {
532
                                EmitMatcher((TupleConstructor)binaryOperator.right(), binaryOperator.left());
533
                        }/* check whether we must use memcmp */
534
                        else if (!CadpType.IsNumeric(binaryOperator.left().type()))
535
                        {
536
                                m_emitter.Append("0 == ");
537
                                EmitComplexEqual(binaryOperator);
538
                        }
539
                        else
540
                                EmitDefaultBinaryOperator(binaryOperator);
541
                        break;
542
                case notequal:
543
                        if (!CadpType.IsNumeric(binaryOperator.left().type()))
544
                        {
545
                                m_emitter.Append("0 != ");
546
                                EmitComplexEqual(binaryOperator);
547
                        }
548
                        else
549
                                EmitDefaultBinaryOperator(binaryOperator);
550
                        break;
551
                case conc:
552
                        final String conc = EmitConcOperation(binaryOperator);
553
                        m_emitter.Append(String.format("%1$s(", conc));
554
                        VisitSub(binaryOperator.left(), binaryOperator);
555
                        m_emitter.Append(",");
556
                        VisitSub(binaryOperator.right(), binaryOperator);
557
                        m_emitter.Append(")");
558
                        break;
559
                case implies:
560
                        m_emitter.Append("!(");
561
                        VisitSub(binaryOperator.left(), binaryOperator);
562
                        m_emitter.Append(") || (");
563
                        VisitSub(binaryOperator.right(), binaryOperator);
564
                        m_emitter.Append(")");
565
                        break;
566
                case elemin:
567
                        EmitInOperator(binaryOperator);
568
                        break;
569
                case notelemin:
570
                        EmitNotInOperator(binaryOperator);
571
                        break;
572
                case diff:   // T_DIFF:
573
                        final String diff = EmitSetDifference(binaryOperator);
574
                        m_emitter.Append(String.format("%1$s(", diff));
575
                        VisitSub(binaryOperator.left(), binaryOperator);
576
                        m_emitter.Append(",");
577
                        VisitSub(binaryOperator.right(), binaryOperator);
578
                        m_emitter.Append(")");
579
                        break;
580
                default:
581
                        EmitDefaultBinaryOperator(binaryOperator);
582
                        break;
583
                }
584
        }
585

    
586
        private String EmitSetDifference(BinaryOperator binaryOperator)
587
        {
588
                final String childBTypeName = CadpIdentifier.GetIdentifierString(binaryOperator.right().type().identifier());
589
                final String childATypeName = CadpIdentifier.GetIdentifierString(binaryOperator.left().type().identifier());
590
                final String result = String.format("op_listdiff_%1$s_%2$s", childATypeName, childBTypeName);
591
                if (emittedOperations.contains(result))
592
                        return result;
593

    
594
                CadpType.EmitType(binaryOperator.type());
595
                final ListType alist = (ListType)binaryOperator.type();
596
                final Type innerType = alist.innerType();
597
                final String resultTypeName = CadpIdentifier.GetIdentifierString(binaryOperator.type().identifier());
598

    
599
                m_helperCode.AppendLine(String.format("%4$s %3$s(%1$s listA, %2$s listB){", childATypeName, childBTypeName, result, resultTypeName));
600
                m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
601
                m_helperCode.AppendLine(String.format("int len = 0; int i; int j;"));
602

    
603
                m_helperCode.AppendLine(String.format("for (i = 0; i < listA.length; i++) {"));
604
                m_helperCode.AppendLine(String.format("for (j = 0; j < listB.length; j++) {"));
605
                m_helperCode.AppendLine(String.format("if (memcmp(&listA.elements[i],&listB.elements[j],sizeof(%1$s))==0)", CadpType.DumpType(innerType)));
606
                m_helperCode.AppendLine("goto NotCopy;");
607
                m_helperCode.AppendLine("}");
608
                m_helperCode.AppendLine(String.format("memcpy(&result.elements[len],&listA.elements[i],sizeof(%1$s));", CadpType.DumpType(innerType)));
609
                m_helperCode.AppendLine("len++;");
610
                m_helperCode.AppendLine("NotCopy:");
611
                m_helperCode.AppendLine("len = len;");
612
                m_helperCode.AppendLine("}");
613
                m_helperCode.AppendLine("result.length = len;");
614

    
615
                // in case our resulttype was set wider..
616
                m_helperCode.AppendLine(String.format("int counter;"));
617
                m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= result.length; counter--) {", ((ListType)binaryOperator.type()).maxNumberOfElements() - 1));
618
                m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
619
                                CadpType.enumString, CadpIdentifier.GetIdentifierString(alist.innerType().identifier()), CadpType.lowString));
620

    
621
                m_helperCode.AppendLine("return result; }");
622

    
623
                emittedOperations.add(result);
624
                return result;
625
        }
626

    
627
        private void EmitInOperator(BinaryOperator binop)
628
        {
629
                m_emitter.Append(String.format("0 != setin_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
630
                VisitSub(binop.left(), binop);
631
                m_emitter.Append(",");
632
                VisitSub(binop.right(), binop);
633
                m_emitter.Append(")");
634

    
635
                CadpType.EmitType(binop.left().type());
636
                CadpType.EmitType(binop.right().type());
637
                final OoasCodeEmitter helper = new OoasCodeEmitter();
638
                helper.Append(String.format("int setin_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
639
                helper.AppendLine(String.format("%1$s arg1, %2$s arg2){", CadpType.DumpType(binop.left().type()), CadpType.DumpType(binop.right().type())));
640
                helper.AppendLine("int __counter;");
641
                helper.AppendLine(String.format("for (__counter = 0; __counter < arg2.length; __counter++)"/*, CadpType.GetMaxVal(binop.right().type)*/));
642
                helper.AppendLine(String.format("if (memcmp(&arg1,&(arg2.elements[__counter]),sizeof(%1$s))==0) return 1;", CadpType.DumpType(binop.left().type())));
643
                helper.AppendLine("return 0;}");
644
                m_helperCode.Append(helper.toString());
645
        }
646

    
647

    
648
        private void EmitNotInOperator(BinaryOperator binop)
649
        {
650
                m_emitter.Append(String.format("0 == setin_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
651
                VisitSub(binop.left(), binop);
652
                m_emitter.Append(",");
653
                VisitSub(binop.right(), binop);
654
                m_emitter.Append(")");
655

    
656
                CadpType.EmitType(binop.left().type());
657
                CadpType.EmitType(binop.right().type());
658
                final OoasCodeEmitter helper = new OoasCodeEmitter();
659
                helper.Append(String.format("int setin_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
660
                helper.AppendLine(String.format("%1$s arg1, %2$s arg2){", CadpType.DumpType(binop.left().type()), CadpType.DumpType(binop.right().type())));
661
                helper.AppendLine("int __counter;");
662
                helper.AppendLine(String.format("for (__counter = 0; __counter < arg2.length; __counter++)"/*, CadpType.GetMaxVal(binop.right().type)*/));
663
                helper.AppendLine(String.format("if (memcmp(&arg1,&(arg2.elements[__counter]),sizeof(%1$s))==0) return 1;", CadpType.DumpType(binop.left().type())));
664
                helper.AppendLine("return 0;}");
665
                m_helperCode.Append(helper.toString());
666
        }
667

    
668

    
669

    
670
        private void EmitComplexEqual(BinaryOperator binop)
671
        {
672
                m_emitter.Append(String.format("complex_equal_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
673
                VisitSub(binop.left(), binop);
674
                m_emitter.Append(",");
675
                VisitSub(binop.right(), binop);
676
                m_emitter.Append(")");
677

    
678
                CadpType.EmitType(binop.left().type());
679
                CadpType.EmitType(binop.right().type());
680
                final OoasCodeEmitter helper = new OoasCodeEmitter();
681
                helper.Append(String.format("int complex_equal_%1$s(", OoaCADPVisitor.getUIntHashCode(binop)));
682
                helper.AppendLine(String.format("%1$s arg1, %2$s arg2){", CadpType.DumpType(binop.left().type()), CadpType.DumpType(binop.right().type())));
683
                helper.AppendLine(String.format("return memcmp(&arg1, &arg2, sizeof(%1$s));}", CadpIdentifier.GetIdentifierString(binop.left().type().identifier())));
684
                m_helperCode.Append(helper.toString());
685
        }
686

    
687
        private String EmitConcOperation(BinaryOperator binaryOperator)
688
        {
689
                final String childBTypeName = CadpIdentifier.GetIdentifierString(binaryOperator.right().type().identifier());
690
                final String childATypeName = CadpIdentifier.GetIdentifierString(binaryOperator.left().type().identifier());
691
                final String result = String.format("op_conc_%1$s_%2$s", childATypeName, childBTypeName);
692
                if (emittedOperations.contains(result))
693
                        return result;
694

    
695
                CadpType.EmitType(binaryOperator.type());
696
                final ListType alist = (ListType)binaryOperator.type();
697
                final Type innerType = alist.innerType();
698
                final String resultTypeName = CadpIdentifier.GetIdentifierString(binaryOperator.type().identifier());
699

    
700
                m_helperCode.AppendLine(String.format("%4$s %3$s(%1$s listA, %2$s listB){", childATypeName, childBTypeName, result, resultTypeName));
701
                m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
702
                m_helperCode.AppendLine(String.format("result.length = listA.length + listB.length;"));
703

    
704
                m_helperCode.AppendLine(String.format("if (result.length > %1$s) { printf(\"Concatenation result too long! %2$s\\n\"); abort();}", alist.maxNumberOfElements(), result));
705
                m_helperCode.AppendLine(String.format("memcpy(&result.elements[0],&listA.elements[0],listA.length * sizeof(%1$s));", CadpType.DumpType(innerType)));
706
                m_helperCode.AppendLine(String.format("memcpy(&result.elements[listA.length],&listB.elements[0],listB.length * sizeof(%1$s));", CadpType.DumpType(innerType)));
707
                m_helperCode.AppendLine(String.format("int counter;"));
708
                m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= (listA.length + listB.length); counter--) {", alist.maxNumberOfElements() - 1));
709
                m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
710
                                CadpType.enumString, CadpIdentifier.GetIdentifierString(alist.innerType().identifier()), CadpType.lowString));
711
                m_helperCode.AppendLine("return result; }");
712

    
713
                emittedOperations.add(result);
714
                return result;
715
        }
716

    
717
        @Override
718
        public  void visit(TernaryOperator ternaryOperator)
719
        {
720
                if (ternaryOperator.kind() == ExpressionKind.conditional)
721
                {
722
                        m_emitter.Append("(");
723
                        VisitSub(ternaryOperator.left(), ternaryOperator);
724
                        m_emitter.Append(" ? ");
725

    
726
                        VisitSub(ternaryOperator.mid(), ternaryOperator);
727
                        m_emitter.Append(" : ");
728

    
729
                        VisitSub(ternaryOperator.right(), ternaryOperator);
730
                        m_emitter.Append(")");
731
                }
732
                else if (ternaryOperator.kind() == ExpressionKind.foldLR ||
733
                                ternaryOperator.kind() == ExpressionKind.foldRL)
734
                {
735
                        final CallExpression leftcall = (CallExpression)ternaryOperator.left();
736
                        final Expression initializer = ternaryOperator.mid();
737
                        final Expression listgetter = ternaryOperator.right();
738

    
739
                        m_emitter.Append(String.format("fold_%1$s(%2$s", OoaCADPVisitor.getUIntHashCode(ternaryOperator), m_procInfo.stateVariableString));
740

    
741

    
742
                        final CadpExpression cadpexpr = new CadpExpression(m_procInfo, emittedVariabes);
743
                        leftcall.child().Accept(cadpexpr);
744
                        final List<String> paramtypes = new ArrayList<String>();
745
                        final List<String> parameters = new ArrayList<String>();
746
                        for (int i = 0; i < leftcall.arguments().size() - 2; i++)
747
                        {
748
                                final Expression arg = leftcall.arguments().get(i);
749
                                final CadpExpression paramexpr = new CadpExpression(m_procInfo, emittedVariabes);
750
                                arg.Accept(paramexpr);
751
                                m_emitter.Append(",");
752
                                m_emitter.Append(paramexpr.toString());
753
                        }
754

    
755
                        final FunctionType fun = (FunctionType)leftcall.child().type();
756
                        final FunctionIdentifier funid = (FunctionIdentifier) fun.identifier();
757
                        final Iterator<Type> node = fun.parameter().iterator();
758
                        for (int i = 0; i < fun.parameter().size() - 2; i++)
759
                        {
760
                                final Type nodeValue = node.next();
761
                                paramtypes.add(CadpType.DumpType(nodeValue));
762
                                final CadpIdentifier paramid = new CadpIdentifier(m_procInfo.stateVariableString);
763
                                funid.parameter().get(i).Accept(paramid);
764
                                parameters.add(paramid.toString());
765
                        }
766

    
767
                        m_emitter.Append(")");
768

    
769

    
770
                        CadpType.EmitType(initializer.type());
771
                        CadpType.EmitType(listgetter.type());
772
                        final ListType thelist = (ListType)listgetter.type();
773
                        CadpType.EmitType(thelist.innerType());
774
                        final OoasCodeEmitter helper = new OoasCodeEmitter();
775
                        helper.Append(String.format("%2$s fold_%1$s(CAESAR_TYPE_STATE oldState", OoaCADPVisitor.getUIntHashCode(ternaryOperator), CadpType.DumpType(leftcall.type())));
776
                        if (paramtypes.size() > 0)
777
                        {
778
                                for (int i = 0; i < paramtypes.size(); i++)
779
                                {
780
                                        helper.Append(",");
781
                                        helper.Append(paramtypes.get(i));
782
                                        helper.Append(" ");
783
                                        helper.Append(parameters.get(i));
784
                                }
785
                        }
786
                        helper.AppendLine("){");
787

    
788
                        helper.AppendLine(String.format("int __iterator;"));
789
                        helper.AppendLine(String.format("%1$s param__result;", CadpType.DumpType(leftcall.type())));
790
                        helper.AppendLine(String.format("%1$s __thelist;", CadpType.DumpType(listgetter.type())));
791
                        helper.AppendLine(String.format("%1$s param__elem;", CadpType.DumpType(thelist.innerType())));
792

    
793
                        final CadpActionInfo actionInfo = new CadpActionInfo(m_procInfo.action, -1, 0, m_procInfo.toDoListString, m_procInfo.doneListString, "oldState");
794

    
795
                        final CadpExpression initvizcode = new CadpExpression(actionInfo, emittedVariabes);
796
                        initializer.Accept(initvizcode);
797
                        helper.AppendLine(initvizcode.VariableDeclarations());
798
                        helper.AppendLine(String.format("param__result = %1$s;", initvizcode.toString()));
799

    
800
                        final CadpExpression listgettercode = new CadpExpression(actionInfo, emittedVariabes);
801
                        listgetter.Accept(listgettercode);
802
                        helper.AppendLine(listgettercode.VariableDeclarations());
803
                        helper.AppendLine(String.format("__thelist = %1$s;", listgettercode.toString()));
804

    
805
                        final CadpExpression filtercall = new CadpExpression(actionInfo, emittedVariabes);
806
                        leftcall.Accept(filtercall);
807
                        helper.AppendLine(filtercall.VariableDeclarations());
808

    
809
                        if (ternaryOperator.kind() == ExpressionKind.foldLR)
810
                                helper.AppendLine(String.format("for (__iterator = 0; __iterator < __thelist.length; __iterator++) {"));
811
                        else
812
                                helper.AppendLine(String.format("for (__iterator = __thelist.length - 1; __iterator >= 0; __iterator--) {"));
813

    
814
                        helper.AppendLine(String.format("param__elem = __thelist.elements[__iterator];"));
815
                        helper.AppendLine(String.format("param__result = %1$s;", filtercall.toString()));
816

    
817

    
818
                        helper.AppendLine("}");
819
                        helper.AppendLine("return param__result;}");
820
                        m_helperCode.Append(helper.toString());
821
                }
822
                else
823
                        throw new UnsupportedOperationException();
824
        }
825

    
826
        @Override
827
        public  void visit(TupleMapAccessExpression tupleMapAccessExpression)
828
        {
829
                VisitSub(tupleMapAccessExpression.child(), tupleMapAccessExpression);
830
                if (tupleMapAccessExpression.child().type().kind() == TypeKind.TupleType)
831
                {
832
                        // the access value needs to be a constant integer
833
                        @SuppressWarnings("unchecked")
834
                        final ValueExpression<Integer> accessValue = (ValueExpression<Integer>)tupleMapAccessExpression.argument();
835
                        m_emitter.Append(String.format(".elem_%1$s", accessValue.value()));
836
                }
837
                else if (tupleMapAccessExpression.child().type().kind() == TypeKind.ListType)
838
                {
839
                        m_emitter.Append(".elements[");
840
                        VisitSub(tupleMapAccessExpression.argument(), tupleMapAccessExpression);
841
                        m_emitter.Append("]");
842
                }
843
                else
844
                        throw new UnsupportedOperationException();
845
        }
846
        @Override
847
        public  void visit(CallExpression callExpression)
848
        {
849
                /* this only supports calls to functions that return ONE value (deterministically) and do not change the state
850
                 * in a non-deterministic way
851
                 * ATTENTION: call-statements are treated in cadpstatement. this code only deals with calls within expressions!!
852
                 */
853

    
854
                final FunctionType funtype = (FunctionType)callExpression.child().type();
855
                if (funtype.returnType() == null)
856
                        throw new IllegalArgumentException("Internal error: Function call in expression with return-type void!");
857

    
858
                /* create temp variable for result */
859
                final String tmpresult = String.format("detcallresult_%1$s", OoaCADPVisitor.getUIntHashCode(callExpression));
860
                final String tmpaftercallstates = String.format("callresult_%1$s", OoaCADPVisitor.getUIntHashCode(callExpression));
861

    
862
                varDecl.AppendLine(String.format("%1$s %2$s;", CadpType.DumpType(funtype.returnType()), tmpresult));
863
                varDecl.AppendLine(String.format("struct STATE_LIST * %1$s;", tmpaftercallstates));
864
                /* create call */
865
                final CadpExpression cadpexpr = new CadpExpression(m_procInfo, emittedVariabes);
866
                callExpression.child().Accept(cadpexpr);
867
                final String callstatement = cadpexpr.toString();
868
                varDecl.Append(cadpexpr.VariableDeclarations());
869
                m_usedIdentifier.addAll(cadpexpr.usedIdentifiers());
870
                final StringBuilder parameter = new StringBuilder(m_procInfo.stateVariableString);
871
                for (final Expression arg : callExpression.arguments())
872
                {
873
                        parameter.append(", ");
874
                        final CadpExpression paramexpr = new CadpExpression(m_procInfo, emittedVariabes);
875
                        arg.Accept(paramexpr);
876
                        parameter.append(paramexpr.toString());
877
                }
878
                parameter.append(String.format(", &(%1$s)", tmpresult));
879

    
880
                m_emitter.Append("(");
881
                m_emitter.Append(String.format("%3$s = %1$s(%2$s)", callstatement, parameter, tmpaftercallstates));
882
                m_emitter.Append(",");
883
                m_emitter.Append(String.format(" CALC_INVALID = %1$s == NULL ? (fprintf(stderr,\"call to %2$s returns NULL!\\n\"), 1) : (%1$s->next == NULL ? CALC_INVALID : (fprintf(stderr,\"call to %2$s non-deterministic!\\n\"), 1))", tmpaftercallstates, callstatement.replaceAll("\"", "'")));
884
                if (!funtype.isPureFunction())
885
                {
886
                        m_emitter.Append(",");
887
                        m_emitter.Append(String.format(" elem = %1$s == NULL ? elem : (list_insert_list(%2$s, %1$s),%1$s)", tmpaftercallstates, m_procInfo.doneListString));
888
                }
889
                m_emitter.Append(",");
890
                m_emitter.Append(String.format("%1$s", tmpresult));
891
                m_emitter.Append(")");
892
        }
893

    
894

    
895
        private interface IFilter<T> {
896
                boolean apply (T input); // poor man's anonymous function
897
        }
898

    
899
        private static <T> void removeAll(List<T> list, IFilter<T> filter) {
900
                int max;
901
                for (max = list.size() - 1; max >= 0; max --) {
902
                        if (filter.apply(list.get(max)))
903
                                list.remove(max);
904
                }
905
        }
906

    
907
        private List<Identifier> getListOfAccessedIdentifiers(CadpExpression child, final SymbolTable currentScopeSymbols)
908
        {
909
                final List<Identifier> importVars = new ArrayList<Identifier>(child.usedIdentifiers());
910
                if (currentScopeSymbols != null)
911
                        removeAll(importVars, new IFilter<Identifier>(){
912
                                @Override
913
                                public boolean apply(Identifier input) {
914
                                        return currentScopeSymbols.symbolList().contains(input);
915
                                }});
916

    
917
                removeAll(importVars, new IFilter<Identifier>(){
918
                        @Override
919
                        public boolean apply(Identifier input) {
920
                                return input.kind() == IdentifierKind.AttributeIdentifier || // we pass the complete state..
921
                                       input.kind() == IdentifierKind.EnumIdentifier ||      // constant
922
                                       input.kind() == IdentifierKind.MethodIdentifier ||
923
                                       input.kind() == IdentifierKind.NamedActionIdentifier;
924
                        }
925
                });
926
                return importVars;
927
        }
928

    
929

    
930
        @Override
931
        public  void visit(ForallQuantifier quantifier)
932
        {
933
                final CadpActionInfo info = new CadpActionInfo(null, -1, -1, m_procInfo.toDoListString, m_procInfo.doneListString, "oldstate");
934
                final CadpExpression compExpr = new CadpExpression(info, emittedVariabes);
935
                quantifier.child().Accept(compExpr);
936

    
937
                // get a list of imported variabes
938
                final List<Identifier> importVars = getListOfAccessedIdentifiers(compExpr, quantifier.symbols());
939

    
940
                final String functionName = String.format("forall_%1$s", OoaCADPVisitor.getUIntHashCode(quantifier));
941
                m_emitter.Append(String.format("1 == %1$s", functionName));
942
                m_emitter.Append(String.format("( %1$s", this.m_procInfo.stateVariableString));
943
                for (final Identifier x : importVars)
944
                {
945
                        m_emitter.Append(",");
946
                        m_emitter.Append(String.format("%1$s", CadpIdentifier.GetIdentifierString(x)));
947
                }
948
                m_emitter.Append(")");
949

    
950
                // emit helper
951
                final OoasCodeEmitter helper = new OoasCodeEmitter();
952
                helper.AppendLine(String.format("int %1$s(CAESAR_TYPE_STATE %2$s", functionName, "oldstate"));
953
                for (final Identifier x : importVars)
954
                {
955
                        helper.Append(", ");
956
                        helper.Append(String.format("%1$s %2$s", CadpType.DumpType(x.type()), CadpIdentifier.GetIdentifierString(x)));
957
                }
958
                helper.AppendLine("){");
959

    
960
                helper.AppendLine(compExpr.VariableDeclarations());
961

    
962
                int loops = 0;
963
                for (final Identifier enumvar : quantifier.symbols().symbolList())
964
                {
965
                        CadpType.EmitType(enumvar.type());
966
                        helper.AppendLine(String.format("long long iterator_%1$s;", CadpIdentifier.GetIdentifierString(enumvar)));
967
                        helper.AppendLine(String.format("for (iterator_%1$s = %2$s; iterator_%1$s <= %3$s; iterator_%1$s++) {",
968
                                        CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetMinVal(enumvar.type()), CadpType.GetMaxVal(enumvar.type())));
969
                        helper.AppendLine(String.format("/*%1$s*/ %2$s = %3$s(iterator_%2$s);",
970
                                        CadpType.DumpType(enumvar.type()), CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetEnumVal(enumvar.type())));
971
                        if (enumvar.type().kind() == TypeKind.OoActionSystemType)
972
                        {
973
                                // treat nulls - ignore them
974
                                helper.AppendLine(String.format("if (memcmp(&%1$s, &%2$s, sizeof(%3$s)) == 0) continue;",
975
                                                CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetNullConstant((OoActionSystemType)enumvar.type()), CadpType.DumpType(enumvar.type())));
976
                        }
977
                        loops++;
978
                }
979

    
980
                helper.AppendLine(String.format("if (!("));
981
                helper.AppendLine(compExpr.toString());
982
                helper.AppendLine(String.format(") ) return 0;"));
983

    
984

    
985
                while (loops > 0)
986
                {
987
                        helper.AppendLine("}");
988
                        loops--;
989
                }
990
                helper.AppendLine("return 1; }");
991

    
992
                m_helperCode.Append(helper.toString());
993
        }
994

    
995
        @Override
996
        public  void visit(ExistsQuantifier quantifier)
997
        {
998
                final CadpActionInfo info = new CadpActionInfo(null, -1, -1, m_procInfo.toDoListString, m_procInfo.doneListString, "oldstate");
999
                final CadpExpression compExpr = new CadpExpression(info, emittedVariabes);
1000
                quantifier.child().Accept(compExpr);
1001

    
1002
                // get a list of imported variabes
1003
                final List<Identifier> importVars = getListOfAccessedIdentifiers(compExpr, quantifier.symbols());
1004

    
1005
                final String functionName = String.format("exists_%1$s",  OoaCADPVisitor.getUIntHashCode(quantifier));
1006
                m_emitter.Append(String.format("1 == %1$s", functionName));
1007
                m_emitter.Append(String.format("( %1$s", this.m_procInfo.stateVariableString));
1008
                for (final Identifier x : importVars)
1009
                {
1010
                        m_emitter.Append(",");
1011
                        m_emitter.Append(String.format("%1$s", CadpIdentifier.GetIdentifierString(x)));
1012
                }
1013
                m_emitter.Append(")");
1014

    
1015
                // emit helper
1016
                final OoasCodeEmitter helper = new OoasCodeEmitter();
1017
                helper.Append(String.format("int %1$s(CAESAR_TYPE_STATE %2$s", functionName, "oldstate"));
1018
                for (final Identifier x : importVars)
1019
                {
1020
                        helper.Append(", ");
1021
                        helper.Append(String.format("%1$s %2$s", CadpType.DumpType(x.type()), CadpIdentifier.GetIdentifierString(x)));
1022
                }
1023
                helper.AppendLine("){");
1024

    
1025
                helper.AppendLine(compExpr.VariableDeclarations());
1026

    
1027
                int loops = 0;
1028
                for (final Identifier enumvar : quantifier.symbols().symbolList())
1029
                {
1030
                        CadpType.EmitType(enumvar.type());
1031
                        helper.AppendLine(String.format("long long iterator_%1$s;", CadpIdentifier.GetIdentifierString(enumvar)));
1032
                        helper.AppendLine(String.format("for (iterator_%1$s = %2$s; iterator_%1$s <= %3$s; iterator_%1$s++) {",
1033
                                        CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetMinVal(enumvar.type()), CadpType.GetMaxVal(enumvar.type())));
1034
                        helper.AppendLine(String.format("/*%1$s*/ %2$s = %3$s(iterator_%2$s);",
1035
                                        CadpType.DumpType(enumvar.type()), CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetEnumVal(enumvar.type())));
1036
                        if (enumvar.type().kind() == TypeKind.OoActionSystemType)
1037
                        {
1038
                                // treat nulls - ignore them
1039
                                helper.AppendLine(String.format("if (memcmp(&%1$s, &%2$s, sizeof(%3$s)) == 0) continue;",
1040
                                                CadpIdentifier.GetIdentifierString(enumvar), CadpType.GetNullConstant((OoActionSystemType)enumvar.type()), CadpType.DumpType(enumvar.type())));
1041
                        }
1042
                        loops++;
1043
                }
1044

    
1045
                helper.AppendLine(String.format("if (("));
1046
                helper.AppendLine(compExpr.toString());
1047
                helper.AppendLine(String.format(") ) return 1;"));
1048

    
1049

    
1050
                while (loops > 0)
1051
                {
1052
                        helper.AppendLine("}");
1053
                        loops--;
1054
                }
1055
                helper.AppendLine("return 0; }");
1056

    
1057
                m_helperCode.Append(helper.toString());
1058
        }
1059

    
1060
        private static final class RefBool {
1061
                boolean value = false;
1062
        }
1063

    
1064
        @Override
1065
        public  void visit(UnaryOperator unaryOperator)
1066
        {
1067
                switch (unaryOperator.kind())
1068
                {
1069
                case tail:
1070
                        final String tail = EmitTailOperation(unaryOperator);
1071
                        m_emitter.Append(String.format("%1$s(", tail));
1072
                        VisitSub(unaryOperator.child(), unaryOperator);
1073
                        m_emitter.Append(")");
1074
                        break;
1075
                case head:
1076
                        m_emitter.Append("(");
1077
                        VisitSub(unaryOperator.child(), unaryOperator);
1078
                        m_emitter.Append(String.format(").elements[0]"));
1079
                        break;
1080
                case len:
1081
                        m_emitter.Append("(");
1082
                        VisitSub(unaryOperator.child(), unaryOperator);
1083
                        m_emitter.Append(String.format(").length"));
1084
                        break;
1085
                case Cast:
1086
                        m_emitter.Append("/*cast*/");
1087
                        final RefBool doSub = new RefBool();
1088
                        final String cast = EmitCastOperation(unaryOperator, /*out*/ doSub);
1089
                        if (doSub.value)
1090
                        {
1091
                                m_emitter.Append(String.format("(%1$s(", cast));
1092
                                VisitSub(unaryOperator.child(), unaryOperator);
1093
                                m_emitter.Append("))");
1094
                        }
1095
                        break;
1096
                default:
1097
                        m_emitter.Append(" ");
1098
                        m_emitter.Append(OperatorString(unaryOperator));
1099
                        m_emitter.Append("(");
1100
                        VisitSub(unaryOperator.child(), unaryOperator);
1101
                        m_emitter.Append(")");
1102
                        break;
1103
                }
1104
        }
1105

    
1106
        /* The cast support in this target instanceof limited: We can not cast differently sized types!
1107
         * Hence list and map lengths must be equal.
1108
         * */
1109
        private boolean CADPCastEquivalent(Type type1, Type type2)
1110
        {
1111
                if ((type1 == null) || (type2 == null))
1112
                        return false;
1113

    
1114
                final TypeKind tk1 = type1.kind();
1115
                final TypeKind tk2 = type2.kind();
1116

    
1117
                // if of different kind, then return false..
1118
                if (tk1 != tk2)
1119
                        return false;
1120

    
1121
                // if same kind, make a rigorous check
1122
                switch (tk1)
1123
                {
1124
                case IntType:
1125
                        return true; // we don't care about the range, since all ints are 32bit wide, which is the max that can be defined in OOAS
1126
                case BoolType:
1127
                        return true;
1128
                case FloatType:
1129
                        throw new UnsupportedOperationException(); // float type instanceof not used. other than that, we could return true
1130
                case EnumeratedType:
1131
                        return type1 == type2; // reference equals!
1132
                case ListType:
1133
                        final ListType listt1 = (ListType)type1;
1134
                        final ListType listt2 = (ListType)type2;
1135
                        return CADPCastEquivalent(listt1.innerType(), listt2.innerType()) &&
1136
                                        listt1.maxNumberOfElements() == listt2.maxNumberOfElements();
1137
                case MapType:
1138
                        final MapType mapt1 = (MapType)type1;
1139
                        final MapType mapt2 = (MapType)type2;
1140
                        return CADPCastEquivalent(mapt1.fromType(), mapt2.fromType()) &&
1141
                                        CADPCastEquivalent(mapt1.toType(), mapt2.toType()) &&
1142
                                        mapt1.maxNumberOfElements() == mapt2.maxNumberOfElements();
1143
                case TupleType:
1144
                        final TupleType tuplet1 = (TupleType)type1;
1145
                        final TupleType tuplet2 = (TupleType)type2;
1146
                        if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size())
1147
                                return false;
1148
                        final Iterator<Type> innert1 = tuplet1.innerTypes().iterator();
1149
                        final Iterator<Type> innert2 = tuplet2.innerTypes().iterator();
1150
                        while (innert1.hasNext())
1151
                        {
1152
                                final Type innert1Value = innert1.next();
1153
                                final Type innert2Value = innert2.next();
1154

    
1155
                                if (!CADPCastEquivalent(innert1Value, innert2Value))
1156
                                        return false;
1157
                        }
1158
                        return true;
1159
                case OoActionSystemType:
1160
                        return type1 == type2 /*ref. eq.*/ ||
1161
                                        Type.Covariance((OoActionSystemType)type2, (OoActionSystemType)type1);
1162
                case OpaqueType:
1163
                        throw new IllegalArgumentException();
1164
                case Null:
1165
                case Any:
1166
                        return true;
1167
                default:
1168
                        throw new UnsupportedOperationException();
1169
                }
1170
        }
1171

    
1172

    
1173
        private String EmitCastOperation(UnaryOperator unaryOperator, /*out*/ RefBool doSub)
1174
        {
1175
                doSub.value = true;
1176
                if (unaryOperator.child().kind() == ExpressionKind.ListConstr &&
1177
                                ((ListConstructor)unaryOperator.child()).hasComprehension())
1178
                {
1179
                        // we get a malloced list an have to cut it down
1180
                        final String childTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.child().type().identifier());
1181
                        final String resultTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier());
1182
                        final String result = String.format("op_cast_malloc_%1$s_%2$s", childTypeName, resultTypeName);
1183

    
1184
                        if (emittedOperations.contains(result))
1185
                                return result;
1186

    
1187
                        // emit target type
1188
                        CadpType.EmitType(unaryOperator.type());
1189

    
1190
                        switch (unaryOperator.type().kind())
1191
                        {
1192
                        case ListType:
1193
                                final ListType toType = (ListType)unaryOperator.type();
1194
                                final ListType fromType = (ListType)unaryOperator.child().type();
1195
                                final String listStruct = String.format("struct struct_list_%1$s", CadpType.DumpType(fromType.innerType()).replaceAll(" ", "_"));
1196

    
1197
                                if (!(fromType.innerType().kind() == TypeKind.Null || CADPCastEquivalent(fromType.innerType(), toType.innerType())))
1198
                                        throw new UnsupportedOperationException(String.format("CADP Target does not support this type of cast: '%1$s' to '%2$s'", fromType.innerType().toString(), toType.innerType().toString()));
1199
                                m_helperCode.AppendLine(String.format("%3$s %2$s(%1$s *toCast){", listStruct, result, resultTypeName));
1200
                                m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
1201
                                m_helperCode.AppendLine(String.format("%1$s *tmp = toCast;", listStruct));
1202
                                m_helperCode.AppendLine(String.format("int len = 0;"));
1203
                                m_helperCode.AppendLine(String.format("result.length = 0;"));
1204

    
1205
                                m_helperCode.AppendLine("while (toCast != NULL)");
1206
                                m_helperCode.AppendLine("{");
1207
                                m_helperCode.AppendLine(String.format("    if (len < %1$s)", toType.maxNumberOfElements()));
1208
                                m_helperCode.AppendLine("    {");
1209
                                m_helperCode.AppendLine(String.format("memcpy(&result.elements[len],&(toCast->element),sizeof(%1$s));", CadpType.DumpType(toType.innerType())));
1210
                                m_helperCode.AppendLine(String.format("result.length = len+1;"));
1211
                                m_helperCode.AppendLine("    }");
1212
                                m_helperCode.AppendLine("    else ");
1213
                                m_helperCode.AppendLine("        CALC_INVALID = 1;");
1214
                                m_helperCode.AppendLine("    len++;");
1215
                                m_helperCode.AppendLine("    tmp = toCast->next;");
1216
                                m_helperCode.AppendLine("    free(toCast);");
1217
                                m_helperCode.AppendLine("    toCast = tmp;");
1218
                                m_helperCode.AppendLine("}");
1219
                                m_helperCode.AppendLine("    if (CALC_INVALID == 1)");
1220
                                m_helperCode.AppendLine(String.format("        printf(\"\\n\\nCalculation invalid: Cast to smaller list in %1$s\\n\\n\");", result));
1221

    
1222

    
1223
                                m_helperCode.AppendLine(String.format("int counter;"));
1224
                                m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= result.length; counter--) {", toType.maxNumberOfElements() - 1));
1225
                                m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
1226
                                                CadpType.enumString, CadpIdentifier.GetIdentifierString(toType.innerType().identifier()), CadpType.lowString));
1227
                                m_helperCode.AppendLine("return result; }");
1228

    
1229

    
1230
                                break;
1231
                        default:
1232
                                // no cast
1233
                                return "";
1234
                        }
1235
                        emittedOperations.add(result);
1236
                        return result;
1237

    
1238

    
1239
                }
1240
                else
1241
                {
1242
                        final String childTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.child().type().identifier());
1243
                        final String resultTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier());
1244
                        final String result = String.format("op_cast_%1$s_%2$s", childTypeName, resultTypeName);
1245

    
1246
                        if (emittedOperations.contains(result))
1247
                                return result;
1248

    
1249
                        // emit target type
1250
                        CadpType.EmitType(unaryOperator.type());
1251

    
1252
                        switch (unaryOperator.type().kind())
1253
                        {
1254
                        case ListType:
1255
                                final ListType toType = (ListType)unaryOperator.type();
1256
                                final ListType fromType = (ListType)unaryOperator.child().type();
1257
                                if (!(fromType.innerType().kind() == TypeKind.Null || CADPCastEquivalent(fromType.innerType(), toType.innerType())))
1258
                                        throw new UnsupportedOperationException(String.format("CADP Target does not support this type of cast: '%1$s' to '%2$s'", fromType.innerType().toString(), toType.innerType().toString()));
1259
                                m_helperCode.AppendLine(String.format("%3$s %2$s(%1$s toCast){", childTypeName, result, resultTypeName));
1260
                                m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
1261
                                m_helperCode.AppendLine(String.format("if (toCast.length > %1$s) { printf(\"Cast to smaller list! %2$s\\n\"); ", toType.maxNumberOfElements(), result));
1262
                                m_helperCode.AppendLine(String.format("%1$s%2$s(stdout, toCast); fflush(stdout); CALC_INVALID=1; result.length = %3$s;} else", CadpType.printString, childTypeName, toType.maxNumberOfElements()));
1263
                                m_helperCode.AppendLine(String.format("result.length = toCast.length;"));
1264
                                m_helperCode.AppendLine(String.format("if (result.length > 0)"));
1265
                                m_helperCode.AppendLine(String.format("memcpy(result.elements,toCast.elements,result.length * sizeof(%1$s));", CadpType.DumpType(toType.innerType())));
1266
                                m_helperCode.AppendLine(String.format("int counter;"));
1267
                                m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= result.length; counter--) {", toType.maxNumberOfElements() - 1));
1268
                                m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
1269
                                                CadpType.enumString, CadpIdentifier.GetIdentifierString(toType.innerType().identifier()), CadpType.lowString));
1270
                                m_helperCode.AppendLine("return result; }");
1271

    
1272

    
1273
                                break;
1274
                        case OoActionSystemType:
1275
                                if (unaryOperator.child().kind() == ExpressionKind.Value &&
1276
                                (unaryOperator.child() instanceof ValueExpression<?>) &&
1277
                                ((ValueExpression<?>)unaryOperator.child()).value() == null)
1278
                                {
1279
                                        m_emitter.Append(String.format("NULL_%1$s", CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier())));
1280
                                        doSub.value = false;
1281
                                }
1282
                                else
1283
                                {
1284
                                        doSub.value = true;
1285
                                        final CadpType targetType = new CadpType();
1286
                                        unaryOperator.type().Accept(targetType);
1287
                                        final CadpType sourceType = new CadpType();
1288
                                        unaryOperator.child().type().Accept(sourceType);
1289
                                        if (!(Type.Covariance((OoActionSystemType)unaryOperator.child().type(), (OoActionSystemType)unaryOperator.type())))
1290
                                        {
1291
                                                // cast result type (unaryOperator.type) not a sub-type of unaryOperator.child.type
1292
                                                return String.format("/* up-cast: %1$s as %2$s */ *(%2$s*)&", sourceType.ToString(), targetType.ToString());
1293
                                        }
1294
                                        else
1295
                                        {
1296
                                                return String.format(" /* down-cast: %1$s as %2$s */ *(%2$s*)&", sourceType.ToString(), targetType.ToString());
1297
                                        }
1298

    
1299
                                }
1300
                                return "";
1301
                        default:
1302
                                // no cast
1303
                                return "";
1304
                        }
1305
                        emittedOperations.add(result);
1306
                        return result;
1307
                }
1308
        }
1309

    
1310
        private String EmitTailOperation(UnaryOperator unaryOperator)
1311
        {
1312
                final String childTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.child().type().identifier());
1313
                final String result = String.format("op_tail_%1$s", childTypeName);
1314
                if (emittedOperations.contains(result))
1315
                        return result;
1316

    
1317
                final ListType alist = (ListType)unaryOperator.child().type();
1318
                CadpType.EmitType(unaryOperator.type());
1319
                final String resultType = CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier());
1320
                final ListType resultList = (ListType)unaryOperator.type();
1321

    
1322
                // -- tail constructor
1323
                m_helperCode.AppendLine(String.format("%3$s %2$s(%1$s toCopy){", childTypeName, result, resultType));
1324
                m_helperCode.AppendLine(String.format("%1$s result;", resultType));
1325
                m_helperCode.AppendLine(String.format("if (toCopy.length == 0) { printf(\"Tail from empty list! %1$s\\n\"); abort();}", childTypeName));
1326
                m_helperCode.AppendLine(String.format("result.length = toCopy.length - 1;"));
1327
                m_helperCode.AppendLine(String.format("if (result.length == 0)"));
1328
                m_helperCode.AppendLine(String.format("memset(&result,0,sizeof(%1$s));", resultType));
1329
                m_helperCode.AppendLine(String.format("else"));
1330
                m_helperCode.AppendLine(String.format("memcpy(&result.elements[0],&toCopy.elements[1],result.length * sizeof(%1$s));", CadpType.DumpType(alist.innerType()), alist.maxNumberOfElements() - 1));
1331

    
1332
                // in case our resulttype was set wider..
1333
                m_helperCode.AppendLine(String.format("int counter;"));
1334
                m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= result.length; counter--) {", resultList.maxNumberOfElements() - 1));
1335
                m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
1336
                                CadpType.enumString, CadpIdentifier.GetIdentifierString(alist.innerType().identifier()), CadpType.lowString));
1337

    
1338

    
1339
                m_helperCode.AppendLine("return result; }");
1340

    
1341

    
1342
                emittedOperations.add(result);
1343
                return result;
1344
        }
1345

    
1346
        public String VariableDeclarations()
1347
        {
1348
                return varDecl.toString();
1349
        }
1350

    
1351
        @Override
1352
        public  String toString()
1353
        {
1354
                return m_emitter.toString();
1355
        }
1356

    
1357
        public static String GetHelperCode()
1358
        {
1359
                final StringBuilder result = new StringBuilder(m_helperCode.toString());
1360
                result.append("void Model_Reset() {");
1361
                result.append(System.lineSeparator());
1362
                result.append(m_resetCode.toString());
1363
                result.append("}");
1364
                result.append(System.lineSeparator());
1365
                return result.toString();
1366
        }
1367

    
1368
        public CadpExpression(CadpActionInfo aProcInfo)
1369
        {
1370
                if (aProcInfo == null)
1371
                        throw new IllegalArgumentException();
1372
                m_procInfo = aProcInfo;
1373
        }
1374

    
1375

    
1376
        public CadpExpression(CadpActionInfo aProcInfo, HashSet<Identifier> varDecls)
1377
        {
1378
                if (aProcInfo == null)
1379
                        throw new IllegalArgumentException();
1380
                m_procInfo = aProcInfo;
1381
                emittedVariabes.addAll(varDecls);
1382
        }
1383
}