Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / visitors / OoaDeepCloneVisitor.java @ 12

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
                // this requires parents to be added before their children
227
                if (aScope.GetParentScope() != null)
228
                {
229
                        if(!mapping.containsKey(aScope.GetParentScope()))
230
                                throw new ArgumentException();
231
                        else
232
                                aScope.SetParentScope((IScope)mapping.get(aScope.GetParentScope()));
233
                }
234
        }
235

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

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

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

    
256
                        result.Accept(this);
257
                }
258
                return result;
259
        }
260

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

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

    
274
                        result.Accept(this);
275
                }
276
                return result;
277
        }
278

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

    
300

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

    
311

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

    
320

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

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

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

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

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

    
397
                visit((UnaryOperator)callExpression);
398
        }
399

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

    
419

    
420

    
421

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

    
431
        @Override
432
        public void visit(IdentifierExpression identifierExpression)
433
        {
434

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

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

    
453

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

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

    
463
                listConstructor.SetElements(newelems);
464
                listConstructor.SetComprehension(EClone(listConstructor.comprehension()));
465
        }
466

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

    
473

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

    
482
                setConstructor.SetItems(newelems);
483
                setConstructor.SetComprehension(EClone(setConstructor.comprehension()));
484
        }
485

    
486

    
487
        @Override
488
        public void visit(SkipStatement skipStatement)
489
        { }
490

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

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

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

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

    
519

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

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

    
533

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

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

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