Project

General

Profile

Revision 7

Added by Willibald K. over 8 years ago

changing java, cpp, hpp files to unix line endings

View differences:

CadpExpression.java
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
  */

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 26

  
27 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;
28
package org.momut.ooas.codegen.cadp;
34 29

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

  
35 35
import org.momut.ooas.ast.expressions.AccessExpression;
36 36
import org.momut.ooas.ast.expressions.BinaryOperator;
37 37
import org.momut.ooas.ast.expressions.CallExpression;
......
68 68
import org.momut.ooas.codegen.OoasCodeEmitter;
69 69
import org.momut.ooas.parser.SymbolTable;
70 70
import org.momut.ooas.visitors.OoaExpressionVisitor;
71

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

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

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

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

  
122

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

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

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

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

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

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

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

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

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

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

  
255

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

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

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

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

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

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

  
293

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

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

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

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

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

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

  
333

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

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

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

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

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

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

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

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

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

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

  
416
			// emit helper
417

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

  
436

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

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

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

  
470

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  
648

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

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

  
669

  
670

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

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

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

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

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

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

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

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

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

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

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

  
742

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

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

  
768
			m_emitter.Append(")");
769

  
770

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

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

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

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

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

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

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

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

  
818

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

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

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

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

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

  
881
		m_emitter.Append("(");
882
		m_emitter.Append(String.format("%3$s = %1$s(%2$s)", callstatement, parameter, tmpaftercallstates));
883
		m_emitter.Append(",");
884
		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("\"", "'")));
885
		if (!funtype.isPureFunction())
886
		{
887
			m_emitter.Append(",");
888
			m_emitter.Append(String.format(" elem = %1$s == NULL ? elem : (list_insert_list(%2$s, %1$s),%1$s)", tmpaftercallstates, m_procInfo.doneListString));
889
		}
890
		m_emitter.Append(",");
891
		m_emitter.Append(String.format("%1$s", tmpresult));
892
		m_emitter.Append(")");
893
	}
894

  
895

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

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

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

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

  
930

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

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

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

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

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

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

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

  
985

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

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

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

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

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

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

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

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

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

  
1050

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

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

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

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

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

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

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

  
1122
		// if same kind, make a rigorous check
1123
		switch (tk1)
1124
		{
1125
		case IntType:
1126
			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
1127
		case BoolType:
1128
			return true;
1129
		case FloatType:
1130
			throw new UnsupportedOperationException(); // float type instanceof not used. other than that, we could return true
1131
		case EnumeratedType:
1132
			return type1 == type2; // reference equals!
1133
		case ListType:
1134
			final ListType listt1 = (ListType)type1;
1135
			final ListType listt2 = (ListType)type2;
1136
			return CADPCastEquivalent(listt1.innerType(), listt2.innerType()) &&
1137
					listt1.maxNumberOfElements() == listt2.maxNumberOfElements();
1138
		case MapType:
1139
			final MapType mapt1 = (MapType)type1;
1140
			final MapType mapt2 = (MapType)type2;
1141
			return CADPCastEquivalent(mapt1.fromType(), mapt2.fromType()) &&
1142
					CADPCastEquivalent(mapt1.toType(), mapt2.toType()) &&
1143
					mapt1.maxNumberOfElements() == mapt2.maxNumberOfElements();
1144
		case QrType:
1145
			final QrType qr1 = (QrType)type1;
1146
			final QrType qr2 = (QrType)type2;
1147
			return qr1 == qr2; // ref eq.
1148
		case TupleType:
1149
			final TupleType tuplet1 = (TupleType)type1;
1150
			final TupleType tuplet2 = (TupleType)type2;
1151
			if (tuplet1.innerTypes().size() != tuplet2.innerTypes().size())
1152
				return false;
1153
			final Iterator<UlyssesType> innert1 = tuplet1.innerTypes().iterator();
1154
			final Iterator<UlyssesType> innert2 = tuplet2.innerTypes().iterator();
1155
			while (innert1.hasNext())
1156
			{
1157
				final UlyssesType innert1Value = innert1.next();
1158
				final UlyssesType innert2Value = innert2.next();
1159

  
1160
				if (!CADPCastEquivalent(innert1Value, innert2Value))
1161
					return false;
1162
			}
1163
			return true;
1164
		case OoActionSystemType:
1165
			return type1 == type2 /*ref. eq.*/ ||
1166
					UlyssesType.Covariance((OoActionSystemType)type2, (OoActionSystemType)type1);
1167
		case OpaqueType:
1168
			throw new IllegalArgumentException();
1169
		case Null:
1170
		case Any:
1171
			return true;
1172
		default:
1173
			throw new UnsupportedOperationException();
1174
		}
1175
	}
1176

  
1177

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

  
1189
			if (emittedOperations.contains(result))
1190
				return result;
1191

  
1192
			// emit target type
1193
			CadpType.EmitType(unaryOperator.type());
1194

  
1195
			switch (unaryOperator.type().kind())
1196
			{
1197
			case ListType:
1198
				final ListType toType = (ListType)unaryOperator.type();
1199
				final ListType fromType = (ListType)unaryOperator.child().type();
1200
				final String listStruct = String.format("struct struct_list_%1$s", CadpType.DumpType(fromType.innerType()).replaceAll(" ", "_"));
1201

  
1202
				if (!(fromType.innerType().kind() == TypeKind.Null || CADPCastEquivalent(fromType.innerType(), toType.innerType())))
1203
					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()));
1204
				m_helperCode.AppendLine(String.format("%3$s %2$s(%1$s *toCast){", listStruct, result, resultTypeName));
1205
				m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
1206
				m_helperCode.AppendLine(String.format("%1$s *tmp = toCast;", listStruct));
1207
				m_helperCode.AppendLine(String.format("int len = 0;"));
1208
				m_helperCode.AppendLine(String.format("result.length = 0;"));
1209

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

  
1227

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

  
1234

  
1235
				break;
1236
			default:
1237
				// no cast
1238
				return "";
1239
			}
1240
			emittedOperations.add(result);
1241
			return result;
1242

  
1243

  
1244
		}
1245
		else
1246
		{
1247
			final String childTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.child().type().identifier());
1248
			final String resultTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier());
1249
			final String result = String.format("op_cast_%1$s_%2$s", childTypeName, resultTypeName);
1250

  
1251
			if (emittedOperations.contains(result))
1252
				return result;
1253

  
1254
			// emit target type
1255
			CadpType.EmitType(unaryOperator.type());
1256

  
1257
			switch (unaryOperator.type().kind())
1258
			{
1259
			case ListType:
1260
				final ListType toType = (ListType)unaryOperator.type();
1261
				final ListType fromType = (ListType)unaryOperator.child().type();
1262
				if (!(fromType.innerType().kind() == TypeKind.Null || CADPCastEquivalent(fromType.innerType(), toType.innerType())))
1263
					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()));
1264
				m_helperCode.AppendLine(String.format("%3$s %2$s(%1$s toCast){", childTypeName, result, resultTypeName));
1265
				m_helperCode.AppendLine(String.format("%1$s result;", resultTypeName));
1266
				m_helperCode.AppendLine(String.format("if (toCast.length > %1$s) { printf(\"Cast to smaller list! %2$s\\n\"); ", toType.maxNumberOfElements(), result));
1267
				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()));
1268
				m_helperCode.AppendLine(String.format("result.length = toCast.length;"));
1269
				m_helperCode.AppendLine(String.format("if (result.length > 0)"));
1270
				m_helperCode.AppendLine(String.format("memcpy(result.elements,toCast.elements,result.length * sizeof(%1$s));", CadpType.DumpType(toType.innerType())));
1271
				m_helperCode.AppendLine(String.format("int counter;"));
1272
				m_helperCode.AppendLine(String.format("for (counter = %1$s; counter >= result.length; counter--) {", toType.maxNumberOfElements() - 1));
1273
				m_helperCode.AppendLine(String.format("result.elements[counter] = %1$s%2$s(%3$s%2$s());}",
1274
						CadpType.enumString, CadpIdentifier.GetIdentifierString(toType.innerType().identifier()), CadpType.lowString));
1275
				m_helperCode.AppendLine("return result; }");
1276

  
1277

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

  
1304
				}
1305
				return "";
1306
			default:
1307
				// no cast
1308
				return "";
1309
			}
1310
			emittedOperations.add(result);
1311
			return result;
1312
		}
1313
	}
1314

  
1315
	private String EmitTailOperation(UnaryOperator unaryOperator)
1316
	{
1317
		final String childTypeName = CadpIdentifier.GetIdentifierString(unaryOperator.child().type().identifier());
1318
		final String result = String.format("op_tail_%1$s", childTypeName);
1319
		if (emittedOperations.contains(result))
1320
			return result;
1321

  
1322
		final ListType alist = (ListType)unaryOperator.child().type();
1323
		CadpType.EmitType(unaryOperator.type());
1324
		final String resultType = CadpIdentifier.GetIdentifierString(unaryOperator.type().identifier());
1325
		final ListType resultList = (ListType)unaryOperator.type();
1326

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

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

  
1343

  
1344
		m_helperCode.AppendLine("return result; }");
1345

  
1346

  
1347
		emittedOperations.add(result);
1348
		return result;
1349
	}
1350

  
1351
	public String VariableDeclarations()
1352
	{
1353
		return varDecl.toString();
1354
	}
1355

  
1356
	@Override
1357
	public  String toString()
1358
	{
1359
		return m_emitter.toString();
1360
	}
1361

  
1362
	public static String GetHelperCode()
1363
	{
1364
		final StringBuilder result = new StringBuilder(m_helperCode.toString());
1365
		result.append("void Model_Reset() {");
1366
		result.append(System.lineSeparator());
1367
		result.append(m_resetCode.toString());
1368
		result.append("}");
1369
		result.append(System.lineSeparator());
1370
		return result.toString();
1371
	}
1372

  
1373
	public CadpExpression(CadpActionInfo aProcInfo)
1374
	{
1375
		if (aProcInfo == null)
1376
			throw new IllegalArgumentException();
1377
		m_procInfo = aProcInfo;
1378
	}
1379

  
1380

  
1381
	public CadpExpression(CadpActionInfo aProcInfo, HashSet<Identifier> varDecls)
1382
	{
1383
		if (aProcInfo == null)
1384
			throw new IllegalArgumentException();
1385
		m_procInfo = aProcInfo;
1386
		emittedVariabes.addAll(varDecls);
1387
	}
1388
}
71

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

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

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

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

  
122

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

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

  
161
		default:
162
			return expression.kind().toString();
163
		}
164
	}
165
	@Override
166
	public <T>void visit(ValueExpression<T> valueExpression)
167
	{
168
		if (valueExpression.value() == null)
169
		{
170
			m_emitter.Append("NULL");
171
		}
172
		else if (valueExpression.valueType() == LeafTypeEnum.bool)
173
		{
174
			// bad hack..
175
			final boolean aboolval = (Boolean)valueExpression.value();
176
			m_emitter.AppendLine(aboolval ? "1" : "0");
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff