001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010: //
011: //
012:
013: package de.uka.ilkd.key.rule.metaconstruct;
014:
015: import java.util.Stack;
016:
017: import de.uka.ilkd.key.java.*;
018: import de.uka.ilkd.key.java.annotation.Annotation;
019: import de.uka.ilkd.key.java.declaration.LocalVariableDeclaration;
020: import de.uka.ilkd.key.java.expression.ExpressionStatement;
021: import de.uka.ilkd.key.java.expression.operator.CopyAssignment;
022: import de.uka.ilkd.key.java.reference.IExecutionContext;
023: import de.uka.ilkd.key.java.statement.*;
024: import de.uka.ilkd.key.java.visitor.JavaASTVisitor;
025: import de.uka.ilkd.key.logic.ProgramElementName;
026: import de.uka.ilkd.key.logic.op.IProgramVariable;
027: import de.uka.ilkd.key.logic.op.SchemaVariable;
028: import de.uka.ilkd.key.rule.inst.SVInstantiations;
029: import de.uka.ilkd.key.util.Debug;
030: import de.uka.ilkd.key.util.ExtList;
031:
032: /** Walks through a java AST in depth-left-fist-order.
033: * This walker is used to transform a loop (not only
034: * while loops) according to the rules of the dynamic logic.
035: */
036: public class WhileLoopTransformation extends JavaASTVisitor {
037:
038: protected static final Boolean CHANGED = new Boolean(true);
039: /** the replacement element */
040: protected ProgramElement replacement;
041: /** break outerlabel */
042: protected Break breakOuterLabel;
043: /** break innerlabel */
044: protected Break breakInnerLabel;
045: /** */
046: protected ExtList labelList = new ExtList();
047: /** */
048: protected Stack stack = new Stack();
049: /** if there is a loop inside the loop the breaks of these inner loops have
050: * not to be replaced. The replaceBreakWithNoLabel counts the depth of the
051: * loop cascades. Replacements are only performed if the value of the
052: * variable is zero
053: */
054: protected int replaceBreakWithNoLabel = 0;
055: /** there are two modes the visitor can be run. The check and transformation
056: * mode. In the check mode it is only looked if there are unlabeled break
057: * and continues that needs to be replaced, the transformation mode performs
058: * the unwinding of the loop with all necessary replacements
059: */
060: protected static final int TRANSFORMATION = 0;
061: protected static final int CHECK = 1;
062: protected int runMode = TRANSFORMATION;
063: /** indicates if an unlabled break has been found and an outer
064: * label is needed
065: */
066: protected boolean needOuterLabel = false;
067: /** Indicates if an unlabled continue has been found or if a labelled
068: * continue with a label outside of the loop currently transformed has
069: * been found. Then an inner label is needed.
070: */
071: protected boolean needInnerLabel = false;
072: /** counts the number of labelled continues with an label outside the
073: * while loop that is transformed
074: */
075: protected int newLabels = 0;
076:
077: /** if run in check mode there are normally schemavaribles, so we need the
078: * instantiations of them
079: */
080: protected SVInstantiations instantiations = SVInstantiations.EMPTY_SVINSTANTIATIONS;
081:
082: /**
083: * the result of the transformation
084: */
085: protected ProgramElement result = null;
086:
087: protected Stack labelStack = new Stack();
088:
089: protected Stack methodStack = new Stack();
090:
091: /** creates the WhileLoopTransformation for the transformation mode
092: * @param root the ProgramElement where to begin
093: * @param outerLabel the ProgramElementName of the outer label
094: * @param innerLabel the ProgramElementName of the inner label
095: */
096: public WhileLoopTransformation(ProgramElement root,
097: ProgramElementName outerLabel, ProgramElementName innerLabel) {
098: super (root);
099: breakOuterLabel = (outerLabel == null ? null : new Break(
100: outerLabel));
101: breakInnerLabel = (innerLabel == null ? null : new Break(
102: innerLabel));
103: replaceBreakWithNoLabel = 0;
104: runMode = TRANSFORMATION;
105: }
106:
107: /** creates the WhileLoopTransformation for the check mode
108: * @param root the ProgramElement where to begin
109: * @param inst the SVInstantiations if available
110: */
111: public WhileLoopTransformation(ProgramElement root,
112: SVInstantiations inst) {
113: super (root);
114: instantiations = (inst == null ? SVInstantiations.EMPTY_SVINSTANTIATIONS
115: : inst);
116: replaceBreakWithNoLabel = 0;
117: runMode = CHECK;
118: }
119:
120: /** returns true if an inner label is needed */
121: public boolean innerLabelNeeded() {
122: return needInnerLabel;
123: }
124:
125: /** returns true if an outer label is needed */
126: public boolean outerLabelNeeded() {
127: return needOuterLabel;
128: }
129:
130: /** the action that is performed just before leaving the node the
131: * last time
132: */
133: protected void doAction(ProgramElement node) {
134: if (runMode == CHECK) {
135: // in check mode we look only for unlabeled breaks and continues
136: if (node instanceof Break || node instanceof Continue
137: || node instanceof SchemaVariable
138: || node instanceof Return) {
139: node.visit(this );
140: }
141: } else {
142: node.visit(this );
143: }
144: }
145:
146: /** starts the walker*/
147: public void start() {
148: replaceBreakWithNoLabel = -1;
149: stack.push(new ExtList());
150: walk(root());
151: if (runMode == TRANSFORMATION) {
152: ExtList el = (ExtList) stack.peek();
153: int i = (el.get(0) == CHANGED ? 1 : 0);
154: result = (ProgramElement) (el.get(i));
155: }
156: }
157:
158: public ProgramElement result() {
159: Debug.out("While-Loop-Tranform-Result: ", result);
160: return result;
161: }
162:
163: /** walks through the AST. While keeping track of the current node
164: * @param node the JavaProgramElement the walker is at
165: */
166: protected void walk(ProgramElement node) {
167: stack.push(new ExtList());
168: if ((node instanceof LoopStatement) || (node instanceof Switch)) {
169: replaceBreakWithNoLabel++;
170: }
171: if (node instanceof LabeledStatement) {
172: labelStack.push(((LabeledStatement) node).getLabel());
173: }
174: if (node instanceof MethodFrame) {
175: methodStack.push(node);
176: }
177:
178: super .walk(node);
179: if (runMode == CHECK) {
180: if (needOuterLabel && needInnerLabel) {
181: // both labels are needed so if we just look for the necessary
182: // schemavariables we can stop here
183: return;
184: }
185: }
186: if (node instanceof LoopStatement || node instanceof Switch) {
187: replaceBreakWithNoLabel--;
188: }
189: }
190:
191: public String toString() {
192: return stack.peek().toString();
193: }
194:
195: /** the implemented default action is called if a program element is,
196: * and if it has children all its children too are left unchanged
197: */
198: protected void doDefaultAction(SourceElement x) {
199: addChild(x);
200: }
201:
202: public void performActionOnSchemaVariable(SchemaVariable sv) {
203: Object buffer = instantiations.getInstantiation(sv);
204: if (buffer == null) {
205: // we cannont decide whether there are unlabeled breaks that is why
206: // both labeled are needed
207: needInnerLabel = true;
208: needOuterLabel = true;
209: } else {
210: if (buffer instanceof ArrayOfProgramElement) {
211: ArrayOfProgramElement aope = (ArrayOfProgramElement) buffer;
212: for (int iterate = 0; iterate < aope.size(); iterate++) {
213: ProgramElement pe = aope.getProgramElement(iterate);
214: if (pe != null) {
215: walk(pe);
216: }
217: }
218: } else {
219: walk((ProgramElement) buffer);
220: }
221: }
222:
223: /**This was the part handling only ProgramElements
224: ProgramElement pe = (ProgramElement)
225: instantiations.getInstantiation(sv);
226: if (pe != null) {
227: walk(pe);
228: } else {
229: // we cannont decide whether there are unlabeled breaks that is why
230: // both labeled are needed
231: needInnerLabel = true;
232: needOuterLabel = true;
233: }
234: */
235:
236: }
237:
238: public void performActionOnLocalVariableDeclaration(
239: LocalVariableDeclaration x) {
240: DefaultAction def = new DefaultAction() {
241: ProgramElement createNewElement(ExtList changeList) {
242: return new LocalVariableDeclaration(changeList);
243: }
244: };
245: def.doAction(x);
246: }
247:
248: public void performActionOnStatementBlock(StatementBlock x) {
249: DefaultAction def = new DefaultAction() {
250: ProgramElement createNewElement(ExtList changeList) {
251: return new StatementBlock(changeList);
252: }
253: };
254: def.doAction(x);
255: }
256:
257: protected boolean replaceJumpStatement(LabelJumpStatement x) {
258: if (replaceBreakWithNoLabel == 0
259: && x.getProgramElementName() == null) {
260: return true;
261: }
262: return labelList.contains(x.getProgramElementName());
263: }
264:
265: public void performActionOnBreak(Break x) {
266: if (replaceJumpStatement(x)) {
267: if (runMode == CHECK) {
268: needOuterLabel = true;
269: } else {
270: addChild(breakOuterLabel);
271: changed();
272: }
273: } else {
274: doDefaultAction(x);
275: }
276: }
277:
278: public void performActionOnContinue(Continue x) {
279: if (replaceJumpStatement(x)) {
280: if (runMode == CHECK) {
281: needInnerLabel = true;
282: } else {
283: addChild(breakInnerLabel);
284: changed();
285: }
286: } else if ((x.getLabel() != null)
287: && (labelStack.search(x.getLabel()) == -1)) {
288: if (runMode == CHECK) {
289: needInnerLabel = true;
290: } else if (runMode == TRANSFORMATION) {
291: addChild(new Break(breakInnerLabel.getLabel()));
292: changed();
293: }
294: } else {
295: doDefaultAction(x);
296: }
297: }
298:
299: /**
300: *
301: * public void performActionOnFor(For x) {
302: * ExtList changeList = (ExtList)stack.peek();
303: * if (replaceBreakWithNoLabel==0){
304: * //most outer for loop
305: * if (changeList.getFirst() == CHANGED)
306: * changeList.removeFirst();
307: *
308: * LoopInitializer init[] = new
309: * LoopInitializer[x.getInitializers().size()];
310: *
311: * Expression[] updates = new
312: * Expression[x.getUpdates().size()];
313: *
314: * //the unchanged updates need to be extracted to initialize the
315: * //remainding 'for' statement
316: * Expression[] unchangedUpdates = new
317: * Expression[x.getUpdates().size()];
318: *
319: * Expression guard = null;
320: * Statement body = null;
321: * ProgramElement element =
322: * (ProgramElement) (changeList.isEmpty() ?
323: * null :
324: * changeList.removeFirst());
325: * // get loop initializers
326: * int foundInitializers = 0;
327: * while (element instanceof LoopInitializer) {
328: * init[foundInitializers] = (LoopInitializer) element;
329: * element = (ProgramElement) (changeList.isEmpty() ?
330: * null :
331: * changeList.removeFirst());
332: * foundInitializers++;
333: * }
334: * de.uka.ilkd.key.util.Debug.assertTrue
335: * (init.length == x.getInitializers().size(),
336: * "Critical Error: not all initializers found. "+
337: * "performActionOnFor in WhileLoopTransformation.");
338: * // get guard
339: * if (x.getGuard() != null) {
340: * guard = (Expression)element;
341: * }
342: *
343: * // getUpdates
344: * int foundUpdates = 0;
345: * element = (ProgramElement) (changeList.isEmpty() ?
346: * null :
347: * changeList.removeFirst());
348: * while (element instanceof Expression && foundUpdates<x.getUpdates().size()) {
349: * updates[foundUpdates] = (Expression) element;
350: * element = (ProgramElement) (changeList.isEmpty() ?
351: * null :
352: * changeList.removeFirst());
353: * unchangedUpdates[foundUpdates] = x.getUpdates().getExpression(foundUpdates);
354: * foundUpdates++;
355: * }
356: * de.uka.ilkd.key.util.Debug.assertTrue
357: * (updates.length == x.getUpdates().size(),
358: * "Critical Error: not all updates found. "+
359: * "performActionOnFor in WhileLoopTransformation.");
360: *
361: * // getBody
362: * body = (Statement) element;
363: *
364: * For remainder = new For(null, x.getGuard(), unchangedUpdates, x.getBody());
365: * if (breakInnerLabel!=null)
366: * body = (Statement) new LabeledStatement(breakInnerLabel.getLabel(), body);
367: *
368: *
369: * Statement innerBlockStatements[] = new Statement[updates.length+2];
370: * innerBlockStatements[0] = body;
371: * for (int copyStatements=0; copyStatements<updates.length;copyStatements++)
372: * innerBlockStatements[copyStatements+1] = (ExpressionStatement) updates[copyStatements];
373: * innerBlockStatements[updates.length+1] = remainder;
374: *
375: * Statement outerBlockStatements[] = new Statement[init.length+1];
376: * for (int copyStatements=0; copyStatements<init.length;copyStatements++)
377: * outerBlockStatements[copyStatements] = init[copyStatements];
378: * outerBlockStatements[init.length] = new If(guard ,new Then(new StatementBlock(new ArrayOfStatement(innerBlockStatements))));
379: * //outerBlockStatements[init.length+1] = remainder;
380: *
381: * if (breakOuterLabel!=null)
382: * addChild(new LabeledStatement(breakOuterLabel.getLabel(), new StatementBlock(
383: * new ArrayOfStatement(outerBlockStatements))));
384: * else
385: * addChild(new StatementBlock(new ArrayOfStatement(outerBlockStatements)));
386: * changed();
387: * } else {
388: * if (changeList.getFirst() == CHANGED) {
389: * changeList.removeFirst();
390: *
391: * LoopInitializer init[] = new
392: * LoopInitializer[x.getInitializers().size()];
393: *
394: * Expression[] updates = new
395: * Expression[x.getUpdates().size()];
396: *
397: * Expression guard = null;
398: * Statement body = null;
399: * ProgramElement element =
400: * (ProgramElement) (changeList.isEmpty() ?
401: * null :
402: * changeList.removeFirst());
403: * // get loop initializers
404: * int foundInitializers = 0;
405: * while (element instanceof LoopInitializer) {
406: * init[foundInitializers] = (LoopInitializer) element;
407: * element = (ProgramElement) (changeList.isEmpty() ?
408: * null :
409: * changeList.removeFirst());
410: * foundInitializers++;
411: * }
412: * de.uka.ilkd.key.util.Debug.assertTrue
413: * (init.length == x.getInitializers().size(),
414: * "Critical Error: not all initializers found. "+
415: * "performActionOnFor in WhileLoopTransformation.");
416: * // get guard
417: * if (x.getGuard() != null) {
418: * guard = (Expression)element;
419: * }
420: *
421: * // getUpdates
422: * int foundUpdates = 0;
423: * element = (ProgramElement) (changeList.isEmpty() ?
424: * null :
425: * changeList.removeFirst());
426: * while (element instanceof Expression) {
427: * updates[foundUpdates] = (Expression) element;
428: * element = (ProgramElement) (changeList.isEmpty() ?
429: * null :
430: * changeList.removeFirst());
431: * foundUpdates++;
432: * }
433: * de.uka.ilkd.key.util.Debug.assertTrue
434: * (updates.length == x.getUpdates().size(),
435: * "Critical Error: not all updates found. "+
436: * "performActionOnFor in WhileLoopTransformation.");
437: *
438: * // getBody
439: * body = (Statement) element;
440: * addChild(new For(init, guard, updates, body));
441: * changed();
442: * } else {
443: * doDefaultAction(x);
444: * }
445: * }
446: * }
447: *
448: */
449: public void performActionOnFor(For x) {
450: ExtList changeList = (ExtList) stack.peek();
451: if (replaceBreakWithNoLabel == 0) {
452: //most outer for loop
453: if (changeList.getFirst() == CHANGED)
454: changeList.removeFirst();
455:
456: ILoopInit inits = null;
457:
458: IForUpdates updates = null;
459:
460: //the unchanged updates need to be extracted to initialize the
461: //remainding 'for' statement
462: IForUpdates unchangedUpdates = x.getIForUpdates();
463:
464: Guard guard = null;
465: Statement body = null;
466:
467: if (changeList.get(0) instanceof ILoopInit) {
468: inits = (ILoopInit) changeList.removeFirst();
469: }
470: if (x.getGuard() != null) {
471: guard = (Guard) changeList.removeFirst();
472: }
473: if (changeList.get(0) instanceof IForUpdates) {
474: updates = (IForUpdates) changeList.removeFirst();
475: }
476: body = (Statement) changeList.removeFirst();
477:
478: For remainder = new For(null, x.getGuard(),
479: unchangedUpdates, x.getBody());
480:
481: if (breakInnerLabel != null) {
482: body = new LabeledStatement(breakInnerLabel.getLabel(),
483: body);
484: }
485:
486: final int updateSize = (updates == null ? 0 : updates
487: .size());
488: Statement innerBlockStatements[] = new Statement[updateSize + 2];
489: innerBlockStatements[0] = body;
490: for (int copyStatements = 0; copyStatements < updateSize; copyStatements++) {
491: innerBlockStatements[copyStatements + 1] = (ExpressionStatement) updates
492: .getExpressionAt(copyStatements);
493: }
494: innerBlockStatements[updateSize + 1] = remainder;
495:
496: final int initSize = (inits == null ? 0 : inits.size());
497: Statement outerBlockStatements[] = new Statement[initSize + 1];
498:
499: for (int copyStatements = 0; copyStatements < initSize; copyStatements++) {
500: outerBlockStatements[copyStatements] = inits.getInits()
501: .getLoopInitializer(copyStatements);
502: }
503:
504: outerBlockStatements[initSize] = new If(guard
505: .getExpression(), new Then(new StatementBlock(
506: new ArrayOfStatement(innerBlockStatements))));
507:
508: if (breakOuterLabel != null) {
509: addChild(new LabeledStatement(breakOuterLabel
510: .getLabel(), new StatementBlock(
511: new ArrayOfStatement(outerBlockStatements))));
512: } else {
513: addChild(new StatementBlock(new ArrayOfStatement(
514: outerBlockStatements)));
515: }
516: changed();
517: } else {
518:
519: if (changeList.getFirst() == CHANGED) {
520: changeList.removeFirst();
521: addChild(new For(changeList));
522: changed();
523: } else {
524: doDefaultAction(x);
525: }
526: }
527: }
528:
529: public void performActionOnWhile(While x) {
530: ExtList changeList = (ExtList) stack.peek();
531: if (replaceBreakWithNoLabel == 0) {
532: // the most outer while loop
533: // get guard
534: if (changeList.getFirst() == CHANGED) {
535: changeList.removeFirst();
536: }
537:
538: Expression guard = ((Guard) changeList.removeFirst())
539: .getExpression();
540: Statement body = (Statement) (changeList.isEmpty() ? null
541: : changeList.removeFirst());
542: if (breakInnerLabel != null) {
543: // an unlabeled continue needs to be handled with (replaced)
544: body = new LabeledStatement(breakInnerLabel.getLabel(),
545: body);
546: }
547: Then then = null;
548: StatementBlock block = new StatementBlock(
549: new ArrayOfStatement(new Statement[] { body,
550: (Statement) root() }));
551: if (breakOuterLabel != null) {
552: // an unlabeled break occurs in the
553: // while loop therefore we need a labeled statement
554: then = new Then(new LabeledStatement(breakOuterLabel
555: .getLabel(), block));
556:
557: } else {
558: then = new Then(block);
559: }
560: addChild(new If(guard, then));
561: changed();
562: } else {
563: if (changeList.getFirst() == CHANGED) {
564: changeList.removeFirst();
565: // Expression guard = (Expression) changeList.removeFirst(); ????
566: Expression guard = ((Guard) changeList.removeFirst())
567: .getExpression();
568: Statement body = (Statement) (changeList.isEmpty() ? null
569: : changeList.removeFirst());
570: addChild(new While(guard, body, x.getPositionInfo(), x
571: .getAnnotations()));
572: changed();
573: } else {
574: doDefaultAction(x);
575: }
576: }
577: }
578:
579: public void performActionOnDo(Do x) {
580: ExtList changeList = (ExtList) stack.peek();
581: if (replaceBreakWithNoLabel == 0) {
582: // the most outer do loop
583: if (changeList.getFirst() == CHANGED) {
584: changeList.removeFirst();
585: }
586: Statement body = (Statement) (changeList.isEmpty() ? null
587: : changeList.removeFirst());
588: Expression guard = ((Guard) changeList.removeFirst())
589: .getExpression();
590: Statement unwindedBody = null;
591: if (breakInnerLabel != null) {
592: // an unlabeled continue needs to be handled with (replaced)
593: unwindedBody = new LabeledStatement(breakInnerLabel
594: .getLabel(), body);
595: } else {
596: unwindedBody = body;
597: }
598: Statement resultStatement = null;
599: StatementBlock block = new StatementBlock(
600: new ArrayOfStatement(new Statement[] {
601: unwindedBody,
602: new While(guard, x.getBody(), x
603: .getPositionInfo(), x
604: .getAnnotations()) }));
605:
606: if (breakOuterLabel != null) {
607: // an unlabeled break occurs in the
608: // body therefore we need a labeled statement
609: resultStatement = new LabeledStatement(breakOuterLabel
610: .getLabel(), block);
611: } else {
612: resultStatement = block;
613: }
614: addChild(resultStatement);
615: changed();
616: } else {
617: if (changeList.getFirst() == CHANGED) {
618: changeList.removeFirst();
619: Expression guard = (Expression) changeList
620: .removeFirst();
621: Statement body = (Statement) (changeList.isEmpty() ? null
622: : changeList.removeFirst());
623: addChild(new Do(guard, body, x.getPositionInfo(), x
624: .getAnnotations()));
625: changed();
626: } else {
627: doDefaultAction(x);
628: }
629: }
630: }
631:
632: protected void performActionOnAnnotationArray(Annotation[] a) {
633: //do nothing;
634: }
635:
636: public void performActionOnIf(If x) {
637: DefaultAction def = new DefaultAction() {
638: ProgramElement createNewElement(ExtList changeList) {
639: return new If(changeList);
640: }
641: };
642: def.doAction(x);
643: }
644:
645: public void performActionOnSwitch(Switch x) {
646: DefaultAction def = new DefaultAction() {
647: ProgramElement createNewElement(ExtList changeList) {
648: return new Switch(changeList);
649: }
650: };
651: def.doAction(x);
652: }
653:
654: public void performActionOnTry(Try x) {
655: DefaultAction def = new DefaultAction() {
656: ProgramElement createNewElement(ExtList changeList) {
657: return new Try(changeList);
658: }
659: };
660: def.doAction(x);
661: }
662:
663: public void performActionOnLabeledStatement(LabeledStatement x) {
664: Label l = null;
665: ExtList changeList = (ExtList) stack.peek();
666: if (changeList.getFirst() == CHANGED) {
667: changeList.removeFirst();
668: if (x.getLabel() != null) {
669: l = (Label) changeList.removeFirst();
670: }
671: addChild(new LabeledStatement(changeList, l, x
672: .getPositionInfo()));
673: changed();
674: } else {
675: doDefaultAction(x);
676: }
677: }
678:
679: public void performActionOnMethodFrame(MethodFrame x) {
680: ExtList changeList = (ExtList) stack.peek();
681: if (!changeList.isEmpty() && changeList.getFirst() == CHANGED) {
682: changeList.removeFirst();
683: if (x.getChildCount() == 3) {
684: addChild(new MethodFrame((IProgramVariable) changeList
685: .get(0), (IExecutionContext) changeList.get(1),
686: (StatementBlock) changeList.get(2), x
687: .getProgramMethod(),
688: PositionInfo.UNDEFINED));
689:
690: } else if (x.getChildCount() == 2) {
691: addChild(new MethodFrame(null,
692: (IExecutionContext) changeList.get(0),
693: (StatementBlock) changeList.get(1), x
694: .getProgramMethod(),
695: PositionInfo.UNDEFINED));
696: } else {
697: throw new IllegalStateException(
698: "Methodframe has not allowed number of children.");
699: }
700: changed();
701: } else {
702: doDefaultAction(x);
703: }
704: }
705:
706: public void performActionOnSynchronizedBlock(SynchronizedBlock x) {
707: DefaultAction def = new DefaultAction() {
708: ProgramElement createNewElement(ExtList changeList) {
709: return new SynchronizedBlock(changeList);
710: }
711: };
712: def.doAction(x);
713: }
714:
715: public void performActionOnCopyAssignment(CopyAssignment x) {
716: DefaultAction def = new DefaultAction() {
717: ProgramElement createNewElement(ExtList changeList) {
718: return new CopyAssignment(changeList);
719: }
720: };
721: def.doAction(x);
722: }
723:
724: public void performActionOnThen(Then x) {
725: DefaultAction def = new DefaultAction() {
726: ProgramElement createNewElement(ExtList changeList) {
727: return new Then(changeList);
728: }
729: };
730: def.doAction(x);
731: }
732:
733: public void performActionOnElse(Else x) {
734: DefaultAction def = new DefaultAction() {
735: ProgramElement createNewElement(ExtList changeList) {
736: return new Else(changeList);
737: }
738: };
739: def.doAction(x);
740: }
741:
742: public void performActionOnCase(Case x) {
743: Expression e = null;
744: ExtList changeList = (ExtList) stack.peek();
745: if (changeList.getFirst() == CHANGED) {
746: changeList.removeFirst();
747: if (x.getExpression() != null) {
748: e = (Expression) changeList.removeFirst();
749: }
750: addChild(new Case(changeList, e, x.getPositionInfo()));
751: changed();
752: } else {
753: doDefaultAction(x);
754: }
755: }
756:
757: public void performActionOnCatch(Catch x) {
758: DefaultAction def = new DefaultAction() {
759: ProgramElement createNewElement(ExtList changeList) {
760: return new Catch(changeList);
761: }
762: };
763: def.doAction(x);
764: }
765:
766: public void performActionOnDefault(Default x) {
767: DefaultAction def = new DefaultAction() {
768: ProgramElement createNewElement(ExtList changeList) {
769: return new Default(changeList);
770: }
771: };
772: def.doAction(x);
773: }
774:
775: public void performActionOnFinally(Finally x) {
776: DefaultAction def = new DefaultAction() {
777: ProgramElement createNewElement(ExtList changeList) {
778: return new Finally(changeList);
779: }
780: };
781: def.doAction(x);
782: }
783:
784: protected void changed() {
785: ExtList list = (ExtList) stack.peek();
786: if (list.getFirst() != CHANGED) {
787: list.addFirst(CHANGED);
788: }
789: }
790:
791: protected void addChild(SourceElement x) {
792: stack.pop();
793: ExtList list = (ExtList) stack.peek();
794: list.add(x);
795: }
796:
797: private abstract class DefaultAction {
798: abstract ProgramElement createNewElement(ExtList changeList);
799:
800: private void addNewChild(ExtList changeList) {
801: addChild(createNewElement(changeList));
802: changed();
803: }
804:
805: public void doAction(ProgramElement x) {
806: ExtList changeList = (ExtList) stack.peek();
807: if (changeList.size() > 0
808: && changeList.getFirst() == CHANGED) {
809: changeList.removeFirst();
810: addNewChild(changeList);
811: } else {
812: doDefaultAction(x);
813: }
814: }
815: }
816: }
|