Project

General

Profile

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

    
30
import java.util.ArrayList;
31
import java.util.HashMap;
32
import java.util.List;
33
import java.util.ListIterator;
34

    
35
import org.momut.ooas.ast.IScope;
36
import org.momut.ooas.ast.expressions.AccessExpression;
37
import org.momut.ooas.ast.expressions.BinaryOperator;
38
import org.momut.ooas.ast.expressions.CallExpression;
39
import org.momut.ooas.ast.expressions.ExistsQuantifier;
40
import org.momut.ooas.ast.expressions.Expression;
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.Quantifier;
47
import org.momut.ooas.ast.expressions.SetConstructor;
48
import org.momut.ooas.ast.expressions.TernaryOperator;
49
import org.momut.ooas.ast.expressions.TupleConstructor;
50
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
51
import org.momut.ooas.ast.expressions.TypeExpression;
52
import org.momut.ooas.ast.expressions.UnaryOperator;
53
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
54
import org.momut.ooas.ast.expressions.ValueExpression;
55
import org.momut.ooas.ast.identifiers.AttributeIdentifier;
56
import org.momut.ooas.ast.identifiers.EnumIdentifier;
57
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier;
58
import org.momut.ooas.ast.identifiers.Identifier;
59
import org.momut.ooas.ast.identifiers.IdentifierKind;
60
import org.momut.ooas.ast.identifiers.LocalVariableIdentifier;
61
import org.momut.ooas.ast.identifiers.MainModule;
62
import org.momut.ooas.ast.identifiers.MethodIdentifier;
63
import org.momut.ooas.ast.identifiers.Module;
64
import org.momut.ooas.ast.identifiers.NamedActionIdentifier;
65
import org.momut.ooas.ast.identifiers.NondetIdentifierList;
66
import org.momut.ooas.ast.identifiers.ParameterIdentifier;
67
import org.momut.ooas.ast.identifiers.PrioIdentifierList;
68
import org.momut.ooas.ast.identifiers.SeqIdentifierList;
69
import org.momut.ooas.ast.identifiers.TypeIdentifier;
70
import org.momut.ooas.ast.identifiers.UnspecIdentifierList;
71
import org.momut.ooas.ast.statements.AbortStatement;
72
import org.momut.ooas.ast.statements.Assignment;
73
import org.momut.ooas.ast.statements.Block;
74
import org.momut.ooas.ast.statements.Call;
75
import org.momut.ooas.ast.statements.GuardedCommand;
76
import org.momut.ooas.ast.statements.KillStatement;
77
import org.momut.ooas.ast.statements.NondetBlock;
78
import org.momut.ooas.ast.statements.PrioBlock;
79
import org.momut.ooas.ast.statements.SeqBlock;
80
import org.momut.ooas.ast.statements.SkipStatement;
81
import org.momut.ooas.ast.statements.Statement;
82
import org.momut.ooas.ast.types.AnyType;
83
import org.momut.ooas.ast.types.BoolType;
84
import org.momut.ooas.ast.types.CharType;
85
import org.momut.ooas.ast.types.EnumType;
86
import org.momut.ooas.ast.types.FloatType;
87
import org.momut.ooas.ast.types.FunctionType;
88
import org.momut.ooas.ast.types.IntType;
89
import org.momut.ooas.ast.types.ListType;
90
import org.momut.ooas.ast.types.MapType;
91
import org.momut.ooas.ast.types.NullType;
92
import org.momut.ooas.ast.types.OoActionSystemType;
93
import org.momut.ooas.ast.types.OpaqueType;
94
import org.momut.ooas.ast.types.TupleType;
95
import org.momut.ooas.parser.SymbolTable;
96
import org.momut.ooas.utils.OoasCompilerHashMap;
97
import org.momut.ooas.utils.exceptions.ArgumentException;
98
import org.momut.ooas.utils.exceptions.NotImplementedException;
99
import org.momut.ooas.utils.exceptions.InternalCompilerException;
100

    
101
public final class OoaDeepCloneVisitor extends OoaCompleteAstTraversalVisitor
102
{
103

    
104
        OoasCompilerHashMap<Object, Object> mapping;
105
        Identifier selfreplacement;
106

    
107
        public boolean quantifierState = false;
108

    
109
        /* we do not clone types */
110
        @Override
111
        public void visit(AnyType anyType)
112
        { throw new NotImplementedException(); }
113
        @Override
114
        public void visit(BoolType boolType)
115
        { throw new NotImplementedException(); }
116
        @Override
117
        public void visit(CharType charType)
118
        { throw new NotImplementedException(); }
119
        @Override
120
        public void visit(EnumType enumType)
121
        { throw new NotImplementedException(); }
122
        @Override
123
        public void visit(FloatType floatType)
124
        { throw new NotImplementedException(); }
125
        @Override
126
        public void visit(FunctionType functionType)
127
        { throw new NotImplementedException(); }
128
        @Override
129
        public void visit(IntType intType)
130
        { throw new NotImplementedException(); }
131
        @Override
132
        public void visit(ListType listType)
133
        { throw new NotImplementedException(); }
134
        @Override
135
        public void visit(MapType mapType)
136
        { throw new NotImplementedException(); }
137
        @Override
138
        public void visit(NullType nullType)
139
        { throw new NotImplementedException(); }
140
        @Override
141
        public void visit(OoActionSystemType ooActionSystemType)
142
        { throw new NotImplementedException(); }
143
        @Override
144
        public void visit(TupleType tupleType)
145
        { throw new NotImplementedException(); }
146
        @Override
147
        public void visit(EnumIdentifier enumIdentifier)
148
        { throw new NotImplementedException(); }
149
        @Override
150
        public void visit(ExpressionVariableIdentifier expressionVariableIdentifier)
151
        { throw new NotImplementedException(); }
152

    
153

    
154
        @Override
155
        public void visit(LocalVariableIdentifier localVariableIdentifier)
156
        {
157
                throw new NotImplementedException();
158
        }
159

    
160
        @Override
161
        public void visit(MainModule mainModule)
162
        {
163
                throw new NotImplementedException();
164
        }
165

    
166

    
167
        @Override
168
        public void visit(MapConstructor mapConstructor)
169
        {
170
                throw new NotImplementedException();
171
        }
172

    
173
        @Override
174
        public void visit(MethodIdentifier methodIdentifier)
175
        {
176
                throw new NotImplementedException();
177
        }
178

    
179
        @Override
180
        public void visit(NamedActionIdentifier namedActionIdentifier)
181
        {
182
                final Statement newBlock = SClone(namedActionIdentifier.body());
183
                namedActionIdentifier.SetBody(newBlock);
184
                // we do not clone the parameters..
185
        }
186

    
187
        @Override
188
        public void visit(Module module)
189
        {
190
                throw new NotImplementedException();
191
        }
192

    
193
        @Override
194
        public void visit(NondetIdentifierList nondetIdentifierList)
195
        {
196
                throw new NotImplementedException();
197
        }
198

    
199

    
200
        @Override
201
        public void visit(OpaqueType opaqueType)
202
        {
203
                throw new NotImplementedException(); // must not happen
204
        }
205

    
206
        @Override
207
        public void visit(ParameterIdentifier parameterIdentifier)
208
        {
209
                throw new NotImplementedException();
210
        }
211

    
212
        @Override
213
        public void visit(PrioIdentifierList prioIdentifierList)
214
        {
215
                throw new NotImplementedException();
216
        }
217

    
218
        @Override
219
        public void visit(ObjectConstructor objectConstructor)
220
        {
221
                //base.visit(objectConstructor);
222
        }
223

    
224
        private void UpdateScope(IScope aScope)
225
        {
226
                if (aScope.GetParentScope() != null && !mapping.containsKey(aScope.GetParentScope()))
227
                        throw new ArgumentException();
228
                else if (aScope.GetParentScope() != null)
229
                {
230
                        aScope.SetParentScope((IScope)mapping.get(aScope.GetParentScope()));
231
                }
232
        }
233

    
234
        private void CheckScope(IScope aScope) {
235
                if (aScope.GetParentScope() == null)
236
                        return;
237
                if (mapping.containsKey(aScope.GetParentScope()))
238
                        throw new InternalCompilerException("Internal Error. Scope check failed.");
239
        }
240

    
241
        private Expression EClone(Expression anExpr)
242
        {
243
                Expression result = null;
244
                if (anExpr != null)
245
                {
246
                        result = anExpr.Clone();
247

    
248
                        if (anExpr instanceof IScope)
249
                        {
250
                                mapping.putSafe(anExpr, result);
251
                                UpdateScope((IScope)result);
252
                        }
253

    
254
                        result.Accept(this);
255
                }
256
                return result;
257
        }
258

    
259
        private Statement SClone(Statement aStatement)
260
        {
261
                Statement result = null;
262
                if (aStatement != null)
263
                {
264
                        result = aStatement.Clone();
265

    
266
                        if (aStatement instanceof IScope)
267
                        {
268
                                mapping.putSafe(aStatement, result);
269
                                UpdateScope((IScope)result);
270
                        }
271

    
272
                        result.Accept(this);
273
                }
274
                return result;
275
        }
276

    
277
        // clones symbols found in symbol table
278
        private void SymTabClone(SymbolTable aTable)
279
        {
280
                if (aTable != null && aTable.symbolList().size() > 0)
281
                {
282
                        final List<Identifier> newList = new ArrayList<Identifier>();
283
                        for (final Identifier x: aTable.symbolList())
284
                        {
285
                                if (!mapping.containsKey(x))
286
                                {
287
                                        final Identifier newid = x.Clone();
288
                                        newList.add(newid);
289
                                        mapping.putSafe(x, newid);
290
                                }
291
                                else
292
                                        newList.add((Identifier)mapping.get(x));
293
                        }
294
                        aTable.SetSymbolList(newList);
295
                }
296
        }
297

    
298

    
299
        private void cloneExpressionList(ListIterator<Expression> anElem)
300
        {
301
                while (anElem.hasNext())
302
                {
303
                        final Expression clone = EClone(anElem.next());
304
                        anElem.remove();
305
                        anElem.add(clone);
306
                }
307
        }
308

    
309

    
310
        /*no need to clone leafs (they are already cloned and a shallow copy is sufficient*/
311
        @Override
312
        public void visit(AbortStatement abortStatement)
313
        { }
314
        @Override
315
        public <T> void visit(ValueExpression<T> valueExpression)
316
        { }
317

    
318

    
319
        /*clone a block*/
320
        public void cloneBlock(Block aBlock)
321
        {
322
                SymTabClone(aBlock.symbols());
323
                final ListIterator<Statement> stmnt = aBlock.statements().listIterator();
324
                while (stmnt.hasNext())
325
                {
326
                        final Statement clone = SClone(stmnt.next());
327
                        stmnt.remove();
328
                        stmnt.add(clone);
329
                }
330
        }
331
        @Override
332
        public void visit(NondetBlock nondetBlock)
333
        {
334
                cloneBlock(nondetBlock);
335
        }
336
        @Override
337
        public void visit(SeqBlock seqBlock)
338
        {
339
                seqBlock.SetFilter(EClone(seqBlock.filter()));
340
                cloneBlock(seqBlock);
341
        }
342
        @Override
343
        public void visit(PrioBlock prioBlock)
344
        {
345
                cloneBlock(prioBlock);
346
        }
347

    
348
        @Override
349
        public void visit(AccessExpression accessExpression)
350
        {
351
                visit((BinaryOperator)accessExpression);
352
        }
353
        @Override
354
        public void visit(BinaryOperator binaryOperator)
355
        {
356
                final Expression left = EClone(binaryOperator.left());
357
                final Expression right = EClone(binaryOperator.right());
358
                binaryOperator.SetLeftChild(left);
359
                binaryOperator.SetRightChild(right);
360
        }
361

    
362
        @Override
363
        public void visit(Assignment assignment)
364
        {
365
                SymTabClone(assignment.symbols());
366
                cloneExpressionList(assignment.places().listIterator());
367
                cloneExpressionList(assignment.values().listIterator());
368
                assignment.SetNondetExpression(EClone(assignment.nondetExpression()));
369
                CheckScope(assignment);
370
        }
371

    
372
        @Override
373
        public void visit(AttributeIdentifier attributeIdentifier)
374
        {
375
                final Expression initializer = EClone(attributeIdentifier.initializer());
376
                attributeIdentifier.SetInitializer(initializer);
377
        }
378
        @Override
379
        public void visit(Call call)
380
        {
381
                final Expression cExpr = EClone(call.callExpression());
382
                call.SetCallExpression(cExpr);
383
        }
384

    
385
        @Override
386
        public void visit(CallExpression callExpression)
387
        {
388
                final ArrayList<Expression> newargs = new ArrayList<Expression>();
389
                for (final Expression x: callExpression.arguments())
390
                {
391
                        newargs.add(EClone(x));
392
                }
393
                callExpression.SetArguments(newargs);
394

    
395
                visit((UnaryOperator)callExpression);
396
        }
397

    
398
        public void CloneQuantifier(Quantifier qf)
399
        {
400
                SymTabClone(qf.symbols());
401
                final boolean oldQunatifierState = quantifierState;
402
                quantifierState = true;
403
                visit(qf);
404
                quantifierState = oldQunatifierState;
405
        }
406
        @Override
407
        public void visit(ExistsQuantifier quantifier)
408
        {
409
                CloneQuantifier(quantifier);
410
        }
411
        @Override
412
        public void visit(ForallQuantifier quantifier)
413
        {
414
                CloneQuantifier(quantifier);
415
        }
416

    
417

    
418

    
419

    
420
        @Override
421
        public void visit(GuardedCommand guardedCommand)
422
        {
423
                final Statement newblock = SClone(guardedCommand.body());
424
                final Expression newguard = EClone(guardedCommand.guard());
425
                guardedCommand.SetBody(newblock);
426
                guardedCommand.SetGuard(newguard);
427
        }
428

    
429
        @Override
430
        public void visit(IdentifierExpression identifierExpression)
431
        {
432

    
433
                if (identifierExpression.isSelf())
434
                        identifierExpression.SetIdentifier(selfreplacement);
435
                else if (mapping.containsKey(identifierExpression.identifier())
436
                                && identifierExpression.identifier().kind() != IdentifierKind.MethodIdentifier)
437
                        /* we do NOT replace method calls here, since they are prefixed by self if it's a
438
                         * method in the current object or by some field/method access if it's another
439
                         * object.
440
                         */
441
                        identifierExpression.SetIdentifier((Identifier)mapping.get(identifierExpression.identifier()));
442
        }
443

    
444
        @Override
445
        public void visit(KillStatement killStatement)
446
        {
447
                if (mapping.containsKey(killStatement.someOne))
448
                        killStatement.SetIdentifier((Identifier)mapping.get(killStatement.someOne));
449
        }
450

    
451

    
452
        @Override
453
        public void visit(ListConstructor listConstructor)
454
        {
455
                SymTabClone(listConstructor.comprehensionVariables());
456

    
457
                final ArrayList<Expression> newelems = new ArrayList<Expression>();
458
                for (final Expression x: listConstructor.elements())
459
                        newelems.add(EClone(x));
460

    
461
                listConstructor.SetElements(newelems);
462
                listConstructor.SetComprehension(EClone(listConstructor.comprehension()));
463
        }
464

    
465
        @Override
466
        public void visit(SeqIdentifierList seqIdentifierList)
467
        {
468
                throw new NotImplementedException();
469
        }
470

    
471

    
472
        @Override
473
        public void visit(SetConstructor setConstructor)
474
        {
475
                SymTabClone(setConstructor.comprehensionVariables());
476
                final ArrayList<Expression> newelems = new ArrayList<Expression>();
477
                for (final Expression x: setConstructor.items())
478
                        newelems.add(EClone(x));
479

    
480
                setConstructor.SetItems(newelems);
481
                setConstructor.SetComprehension(EClone(setConstructor.comprehension()));
482
        }
483

    
484

    
485
        @Override
486
        public void visit(SkipStatement skipStatement)
487
        { }
488

    
489
        @Override
490
        public void visit(TernaryOperator ternaryOperator)
491
        {
492
                ternaryOperator.SetLeftChild(EClone(ternaryOperator.left()));
493
                ternaryOperator.SetMidChild(EClone(ternaryOperator.mid()));
494
                ternaryOperator.SetRightChild(EClone(ternaryOperator.right()));
495
        }
496

    
497
        @Override
498
        public void visit(TupleConstructor tupleConstructor)
499
        {
500
                final ArrayList<Expression> values = new ArrayList<Expression>();
501
                for (final Expression x: tupleConstructor.values())
502
                        values.add(EClone(x));
503
                tupleConstructor.SetTupleValues(values);
504
        }
505

    
506
        @Override
507
        public void visit(TupleMapAccessExpression tupleMapAccessExpression)
508
        {
509
                tupleMapAccessExpression.SetArgument(EClone(tupleMapAccessExpression.argument()));
510
                visit((UnaryOperator)tupleMapAccessExpression);
511
        }
512

    
513
        @Override
514
        public void visit(TypeExpression typeExpression)
515
        { /*we do not clone types*/ }
516

    
517

    
518
        @Override
519
        public void visit(TypeIdentifier typeIdentifier)
520
        {
521
                throw new NotImplementedException();
522
        }
523

    
524
        @Override
525
        public void visit(UnaryOperator unaryOperator)
526
        {
527
                final Expression child = EClone(unaryOperator.child());
528
                unaryOperator.SetChild(child);
529
        }
530

    
531

    
532
        @Override
533
        public void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
534
        {
535
                throw new NotImplementedException(); // must not occur
536
        }
537

    
538
        @Override
539
        public void visit(UnspecIdentifierList unspecIdentifierList)
540
        {
541
                throw new NotImplementedException();
542
        }
543

    
544
        public OoaDeepCloneVisitor(HashMap<Object, Object> initMapping, Identifier selfreplace)
545
        {
546
                super (null);
547
                mapping = new OoasCompilerHashMap<Object, Object>(initMapping);
548
                selfreplacement = selfreplace;
549
        }
550
}