001    /* This file was generated with JastAdd2 (http://jastadd.org) version 2.1.13-12-g880e696 */
002    package org.extendj.ast;
003    
004    import java.util.HashSet;
005    import java.io.File;
006    import java.util.Set;
007    import java.util.Collections;
008    import java.util.Collection;
009    import java.util.ArrayList;
010    import beaver.*;
011    import java.util.*;
012    import java.io.ByteArrayOutputStream;
013    import java.io.PrintStream;
014    import java.lang.reflect.InvocationTargetException;
015    import java.lang.reflect.Method;
016    import org.jastadd.util.*;
017    import java.util.zip.*;
018    import java.io.*;
019    import org.jastadd.util.PrettyPrintable;
020    import org.jastadd.util.PrettyPrinter;
021    import java.io.FileNotFoundException;
022    import java.io.BufferedInputStream;
023    import java.io.DataInputStream;
024    /**
025     * @ast node
026     * @declaredat /home/jesper/git/extendj/java4/grammar/Java.ast:213
027     * @production SynchronizedStmt : {@link Stmt} ::= <span class="component">{@link Expr}</span> <span class="component">{@link Block}</span> <span class="component">{@link MonitorExit}</span>;
028    
029     */
030    public class SynchronizedStmt extends Stmt implements Cloneable, FinallyHost {
031      /**
032       * @aspect DU
033       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1046
034       */
035      public Block getFinallyBlock() {
036        return getMonitorExit();
037      }
038      /**
039       * @aspect Java4PrettyPrint
040       * @declaredat /home/jesper/git/extendj/java4/frontend/PrettyPrint.jadd:202
041       */
042      public void prettyPrint(PrettyPrinter out) {
043        out.print("synchronized ");
044        out.print(getExpr());
045        out.print(" ");
046        out.print(getBlock());
047        if (!out.isNewLine()) {
048          out.println();
049        }
050      }
051      /**
052       * @aspect TypeCheck
053       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:424
054       */
055      public void typeCheck() {
056        TypeDecl type = getExpr().type();
057        if (!type.isReferenceType() || type.isNull()) {
058          error("*** The type of the expression must be a reference");
059        }
060      }
061      /**
062       * @aspect CreateBCode
063       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1793
064       */
065      public void emitMonitorEnter(CodeGeneration gen) {
066        gen.emitDup();
067        int num = localNum();
068        gen.emitStoreReference(num);
069        gen.emit(Bytecode.MONITORENTER);
070      }
071      /**
072       * @aspect CreateBCode
073       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1809
074       */
075      protected int monitorId = -1;
076      /**
077       * @aspect CreateBCode
078       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1811
079       */
080      public void createBCode(CodeGeneration gen) {
081        int lbl_start = gen.constantPool().newLabel();
082        super.createBCode(gen);
083        getExpr().createBCode(gen);
084    
085        monitorId = gen.monitorEnter(this);
086        gen.addLabel(lbl_start);
087        gen.monitorRangeStart(monitorId, lbl_start);
088    
089        getBlock().createBCode(gen);
090    
091        if (getBlock().canCompleteNormally()) {
092          getMonitorExit().createBCode(gen);
093          gen.emitGoto(label_end());
094        }
095    
096        gen.monitorExit();
097    
098        gen.addLabel(label_end());
099      }
100      /**
101       * @declaredat ASTNode:1
102       */
103      public SynchronizedStmt() {
104        super();
105      }
106      /**
107       * Initializes the child array to the correct size.
108       * Initializes List and Opt nta children.
109       * @apilevel internal
110       * @ast method
111       * @declaredat ASTNode:10
112       */
113      public void init$Children() {
114        children = new ASTNode[3];
115      }
116      /**
117       * @declaredat ASTNode:13
118       */
119      public SynchronizedStmt(Expr p0, Block p1) {
120        setChild(p0, 0);
121        setChild(p1, 1);
122      }
123      /**
124       * @apilevel low-level
125       * @declaredat ASTNode:20
126       */
127      protected int numChildren() {
128        return 2;
129      }
130      /**
131       * @apilevel internal
132       * @declaredat ASTNode:26
133       */
134      public boolean mayHaveRewrite() {
135        return false;
136      }
137      /**
138       * @apilevel internal
139       * @declaredat ASTNode:32
140       */
141      public void flushAttrCache() {
142        super.flushAttrCache();
143        isDAafter_Variable_reset();
144        isDUafter_Variable_reset();
145        getMonitorExit_reset();
146        canCompleteNormally_reset();
147        start_label_reset();
148        label_end_reset();
149      }
150      /**
151       * @apilevel internal
152       * @declaredat ASTNode:44
153       */
154      public void flushCollectionCache() {
155        super.flushCollectionCache();
156      }
157      /**
158       * @apilevel internal
159       * @declaredat ASTNode:50
160       */
161      public void flushRewriteCache() {
162        super.flushRewriteCache();
163      }
164      /**
165       * @apilevel internal
166       * @declaredat ASTNode:56
167       */
168      public SynchronizedStmt clone() throws CloneNotSupportedException {
169        SynchronizedStmt node = (SynchronizedStmt) super.clone();
170        return node;
171      }
172      /**
173       * @apilevel internal
174       * @declaredat ASTNode:63
175       */
176      public SynchronizedStmt copy() {
177        try {
178          SynchronizedStmt node = (SynchronizedStmt) clone();
179          node.parent = null;
180          if (children != null) {
181            node.children = (ASTNode[]) children.clone();
182          }
183          return node;
184        } catch (CloneNotSupportedException e) {
185          throw new Error("Error: clone not supported for " + getClass().getName());
186        }
187      }
188      /**
189       * Create a deep copy of the AST subtree at this node.
190       * The copy is dangling, i.e. has no parent.
191       * @return dangling copy of the subtree at this node
192       * @apilevel low-level
193       * @deprecated Please use treeCopy or treeCopyNoTransform instead
194       * @declaredat ASTNode:82
195       */
196      @Deprecated
197      public SynchronizedStmt fullCopy() {
198        return treeCopyNoTransform();
199      }
200      /**
201       * Create a deep copy of the AST subtree at this node.
202       * The copy is dangling, i.e. has no parent.
203       * @return dangling copy of the subtree at this node
204       * @apilevel low-level
205       * @declaredat ASTNode:92
206       */
207      public SynchronizedStmt treeCopyNoTransform() {
208        SynchronizedStmt tree = (SynchronizedStmt) copy();
209        if (children != null) {
210          for (int i = 0; i < children.length; ++i) {
211            switch (i) {
212            case 2:
213              tree.children[i] = null;
214              continue;
215            }
216            ASTNode child = (ASTNode) children[i];
217            if (child != null) {
218              child = child.treeCopyNoTransform();
219              tree.setChild(child, i);
220            }
221          }
222        }
223        return tree;
224      }
225      /**
226       * Create a deep copy of the AST subtree at this node.
227       * The subtree of this node is traversed to trigger rewrites before copy.
228       * The copy is dangling, i.e. has no parent.
229       * @return dangling copy of the subtree at this node
230       * @apilevel low-level
231       * @declaredat ASTNode:117
232       */
233      public SynchronizedStmt treeCopy() {
234        doFullTraversal();
235        return treeCopyNoTransform();
236      }
237      /**
238       * @apilevel internal
239       * @declaredat ASTNode:124
240       */
241      protected boolean is$Equal(ASTNode node) {
242        return super.is$Equal(node);    
243      }
244      /**
245       * Replaces the Expr child.
246       * @param node The new node to replace the Expr child.
247       * @apilevel high-level
248       */
249      public void setExpr(Expr node) {
250        setChild(node, 0);
251      }
252      /**
253       * Retrieves the Expr child.
254       * @return The current node used as the Expr child.
255       * @apilevel high-level
256       */
257      @ASTNodeAnnotation.Child(name="Expr")
258      public Expr getExpr() {
259        return (Expr) getChild(0);
260      }
261      /**
262       * Retrieves the Expr child.
263       * <p><em>This method does not invoke AST transformations.</em></p>
264       * @return The current node used as the Expr child.
265       * @apilevel low-level
266       */
267      public Expr getExprNoTransform() {
268        return (Expr) getChildNoTransform(0);
269      }
270      /**
271       * Replaces the Block child.
272       * @param node The new node to replace the Block child.
273       * @apilevel high-level
274       */
275      public void setBlock(Block node) {
276        setChild(node, 1);
277      }
278      /**
279       * Retrieves the Block child.
280       * @return The current node used as the Block child.
281       * @apilevel high-level
282       */
283      @ASTNodeAnnotation.Child(name="Block")
284      public Block getBlock() {
285        return (Block) getChild(1);
286      }
287      /**
288       * Retrieves the Block child.
289       * <p><em>This method does not invoke AST transformations.</em></p>
290       * @return The current node used as the Block child.
291       * @apilevel low-level
292       */
293      public Block getBlockNoTransform() {
294        return (Block) getChildNoTransform(1);
295      }
296      /**
297       * Retrieves the MonitorExit child.
298       * <p><em>This method does not invoke AST transformations.</em></p>
299       * @return The current node used as the MonitorExit child.
300       * @apilevel low-level
301       */
302      public MonitorExit getMonitorExitNoTransform() {
303        return (MonitorExit) getChildNoTransform(2);
304      }
305      /**
306       * Retrieves the child position of the optional child MonitorExit.
307       * @return The the child position of the optional child MonitorExit.
308       * @apilevel low-level
309       */
310      protected int getMonitorExitChildPosition() {
311        return 2;
312      }
313      /**
314       * @apilevel internal
315       */
316      protected java.util.Map isDAafter_Variable_values;
317      /**
318       * @apilevel internal
319       */
320      private void isDAafter_Variable_reset() {
321        isDAafter_Variable_values = null;
322      }
323      /**
324       * @attribute syn
325       * @aspect DA
326       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:257
327       */
328      @ASTNodeAnnotation.Attribute
329      public boolean isDAafter(Variable v) {
330        Object _parameters = v;
331        if (isDAafter_Variable_values == null) isDAafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
332        ASTNode$State state = state();
333        if (isDAafter_Variable_values.containsKey(_parameters)) {
334          return (Boolean) isDAafter_Variable_values.get(_parameters);
335        }
336        boolean intermediate = state.INTERMEDIATE_VALUE;
337        state.INTERMEDIATE_VALUE = false;
338        int num = state.boundariesCrossed;
339        boolean isFinal = this.is$Final();
340        boolean isDAafter_Variable_value = getBlock().isDAafter(v);
341        if (isFinal && num == state().boundariesCrossed) {
342          isDAafter_Variable_values.put(_parameters, isDAafter_Variable_value);
343        } else {
344        }
345        state.INTERMEDIATE_VALUE |= intermediate;
346    
347        return isDAafter_Variable_value;
348      }
349      /**
350       * @attribute syn
351       * @aspect DU
352       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1051
353       */
354      @ASTNodeAnnotation.Attribute
355      public boolean isDUafterFinally(Variable v) {
356        boolean isDUafterFinally_Variable_value = true;
357    
358        return isDUafterFinally_Variable_value;
359      }
360      /**
361       * @attribute syn
362       * @aspect DU
363       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1054
364       */
365      @ASTNodeAnnotation.Attribute
366      public boolean isDAafterFinally(Variable v) {
367        boolean isDAafterFinally_Variable_value = false;
368    
369        return isDAafterFinally_Variable_value;
370      }
371      /**
372       * @apilevel internal
373       */
374      protected java.util.Map isDUafter_Variable_values;
375      /**
376       * @apilevel internal
377       */
378      private void isDUafter_Variable_reset() {
379        isDUafter_Variable_values = null;
380      }
381      /**
382       * @attribute syn
383       * @aspect DU
384       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:781
385       */
386      @ASTNodeAnnotation.Attribute
387      public boolean isDUafter(Variable v) {
388        Object _parameters = v;
389        if (isDUafter_Variable_values == null) isDUafter_Variable_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
390        ASTNode$State state = state();
391        if (isDUafter_Variable_values.containsKey(_parameters)) {
392          return (Boolean) isDUafter_Variable_values.get(_parameters);
393        }
394        boolean intermediate = state.INTERMEDIATE_VALUE;
395        state.INTERMEDIATE_VALUE = false;
396        int num = state.boundariesCrossed;
397        boolean isFinal = this.is$Final();
398        boolean isDUafter_Variable_value = getBlock().isDUafter(v);
399        if (isFinal && num == state().boundariesCrossed) {
400          isDUafter_Variable_values.put(_parameters, isDUafter_Variable_value);
401        } else {
402        }
403        state.INTERMEDIATE_VALUE |= intermediate;
404    
405        return isDUafter_Variable_value;
406      }
407      /**
408       * @apilevel internal
409       */
410      protected boolean getMonitorExit_computed = false;
411      /**
412       * @apilevel internal
413       */
414      protected MonitorExit getMonitorExit_value;
415      /**
416       * @apilevel internal
417       */
418      private void getMonitorExit_reset() {
419        getMonitorExit_computed = false;
420        getMonitorExit_value = null;
421      }
422      /**
423       * @attribute syn nta
424       * @aspect MonitorExit
425       * @declaredat /home/jesper/git/extendj/java4/frontend/MonitorExit.jrag:32
426       */
427      @ASTNodeAnnotation.Attribute
428      public MonitorExit getMonitorExit() {
429        ASTNode$State state = state();
430        if (getMonitorExit_computed) {
431          return (MonitorExit) getChild(getMonitorExitChildPosition());
432        }
433        boolean intermediate = state.INTERMEDIATE_VALUE;
434        state.INTERMEDIATE_VALUE = false;
435        int num = state.boundariesCrossed;
436        boolean isFinal = this.is$Final();
437        getMonitorExit_value = new MonitorExit(this);
438        setChild(getMonitorExit_value, getMonitorExitChildPosition());
439        if (isFinal && num == state().boundariesCrossed) {
440          getMonitorExit_computed = true;
441        } else {
442        }
443        state.INTERMEDIATE_VALUE |= intermediate;
444    
445        MonitorExit node = (MonitorExit) this.getChild(getMonitorExitChildPosition());
446        return node;
447      }
448      /**
449       * @apilevel internal
450       */
451      protected boolean canCompleteNormally_computed = false;
452      /**
453       * @apilevel internal
454       */
455      protected boolean canCompleteNormally_value;
456      /**
457       * @apilevel internal
458       */
459      private void canCompleteNormally_reset() {
460        canCompleteNormally_computed = false;
461      }
462      /**
463       * @attribute syn
464       * @aspect UnreachableStatements
465       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:53
466       */
467      @ASTNodeAnnotation.Attribute
468      public boolean canCompleteNormally() {
469        ASTNode$State state = state();
470        if (canCompleteNormally_computed) {
471          return canCompleteNormally_value;
472        }
473        boolean intermediate = state.INTERMEDIATE_VALUE;
474        state.INTERMEDIATE_VALUE = false;
475        int num = state.boundariesCrossed;
476        boolean isFinal = this.is$Final();
477        canCompleteNormally_value = getBlock().canCompleteNormally();
478        if (isFinal && num == state().boundariesCrossed) {
479          canCompleteNormally_computed = true;
480        } else {
481        }
482        state.INTERMEDIATE_VALUE |= intermediate;
483    
484        return canCompleteNormally_value;
485      }
486      /**
487       * @apilevel internal
488       */
489      protected boolean start_label_computed = false;
490      /**
491       * @apilevel internal
492       */
493      protected int start_label_value;
494      /**
495       * @apilevel internal
496       */
497      private void start_label_reset() {
498        start_label_computed = false;
499      }
500      /**
501       * @attribute syn
502       * @aspect CreateBCode
503       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1630
504       */
505      @ASTNodeAnnotation.Attribute
506      public int start_label() {
507        ASTNode$State state = state();
508        if (start_label_computed) {
509          return start_label_value;
510        }
511        boolean intermediate = state.INTERMEDIATE_VALUE;
512        state.INTERMEDIATE_VALUE = false;
513        int num = state.boundariesCrossed;
514        boolean isFinal = this.is$Final();
515        start_label_value = hostType().constantPool().newLabel();
516        if (isFinal && num == state().boundariesCrossed) {
517          start_label_computed = true;
518        } else {
519        }
520        state.INTERMEDIATE_VALUE |= intermediate;
521    
522        return start_label_value;
523      }
524      /**
525       * @attribute syn
526       * @aspect PreciseRethrow
527       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:84
528       */
529      @ASTNodeAnnotation.Attribute
530      public boolean modifiedInScope(Variable var) {
531        boolean modifiedInScope_Variable_value = getBlock().modifiedInScope(var);
532    
533        return modifiedInScope_Variable_value;
534      }
535      /**
536       * @apilevel internal
537       */
538      protected boolean label_end_computed = false;
539      /**
540       * @apilevel internal
541       */
542      protected int label_end_value;
543      /**
544       * @apilevel internal
545       */
546      private void label_end_reset() {
547        label_end_computed = false;
548      }
549      /**
550       * @attribute syn
551       * @aspect NTAFinally
552       * @declaredat /home/jesper/git/extendj/java4/backend/NTAFinally.jrag:32
553       */
554      @ASTNodeAnnotation.Attribute
555      public int label_end() {
556        ASTNode$State state = state();
557        if (label_end_computed) {
558          return label_end_value;
559        }
560        boolean intermediate = state.INTERMEDIATE_VALUE;
561        state.INTERMEDIATE_VALUE = false;
562        int num = state.boundariesCrossed;
563        boolean isFinal = this.is$Final();
564        label_end_value = hostType().constantPool().newLabel();
565        if (isFinal && num == state().boundariesCrossed) {
566          label_end_computed = true;
567        } else {
568        }
569        state.INTERMEDIATE_VALUE |= intermediate;
570    
571        return label_end_value;
572      }
573      /**
574       * @declaredat /home/jesper/git/extendj/java4/frontend/BranchTarget.jrag:262
575       * @apilevel internal
576       */
577      public FinallyHost Define_enclosingFinally(ASTNode caller, ASTNode child, Stmt branch) {
578        if (caller == getMonitorExitNoTransform()) {
579          // @declaredat /home/jesper/git/extendj/java4/frontend/BranchTarget.jrag:273
580          return enclosingFinally(branch);
581        }
582        else {
583          int childIndex = this.getIndexOfChild(caller);
584          return this;
585        }
586      }
587      protected boolean canDefine_enclosingFinally(ASTNode caller, ASTNode child, Stmt branch) {
588        return true;
589      }
590      /**
591       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:255
592       * @apilevel internal
593       */
594      public boolean Define_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
595        if (caller == getBlockNoTransform()) {
596          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:739
597          return getExpr().isDAafter(v);
598        }
599        else if (caller == getExprNoTransform()) {
600          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:738
601          return isDAbefore(v);
602        }
603        else {
604          return getParent().Define_isDAbefore(this, caller, v);
605        }
606      }
607      protected boolean canDefine_isDAbefore(ASTNode caller, ASTNode child, Variable v) {
608        return true;
609      }
610      /**
611       * @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:779
612       * @apilevel internal
613       */
614      public boolean Define_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
615        if (caller == getBlockNoTransform()) {
616          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1358
617          return getExpr().isDUafter(v);
618        }
619        else if (caller == getExprNoTransform()) {
620          // @declaredat /home/jesper/git/extendj/java4/frontend/DefiniteAssignment.jrag:1357
621          return isDUbefore(v);
622        }
623        else {
624          return getParent().Define_isDUbefore(this, caller, v);
625        }
626      }
627      protected boolean canDefine_isDUbefore(ASTNode caller, ASTNode child, Variable v) {
628        return true;
629      }
630      /**
631       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:52
632       * @apilevel internal
633       */
634      public boolean Define_reachable(ASTNode caller, ASTNode child) {
635        if (caller == getBlockNoTransform()) {
636          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:168
637          return reachable();
638        }
639        else {
640          return getParent().Define_reachable(this, caller);
641        }
642      }
643      protected boolean canDefine_reachable(ASTNode caller, ASTNode child) {
644        return true;
645      }
646      /**
647       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:283
648       * @apilevel internal
649       */
650      public boolean Define_reportUnreachable(ASTNode caller, ASTNode child) {
651        if (caller == getBlockNoTransform()) {
652          // @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:219
653          return reachable();
654        }
655        else {
656          return getParent().Define_reportUnreachable(this, caller);
657        }
658      }
659      protected boolean canDefine_reportUnreachable(ASTNode caller, ASTNode child) {
660        return true;
661      }
662      /**
663       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:1836
664       * @apilevel internal
665       */
666      public boolean Define_leavesMonitor(ASTNode caller, ASTNode child, Stmt branch, SynchronizedStmt monitor) {
667        int childIndex = this.getIndexOfChild(caller);
668        {
669            if (monitor == this) {
670              return true;
671            } else {
672              return leavesMonitor(branch, monitor);
673            }
674          }
675      }
676      protected boolean canDefine_leavesMonitor(ASTNode caller, ASTNode child, Stmt branch, SynchronizedStmt monitor) {
677        return true;
678      }
679      /**
680       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:64
681       * @apilevel internal
682       */
683      public int Define_localNum(ASTNode caller, ASTNode child) {
684        if (caller == getBlockNoTransform()) {
685          // @declaredat /home/jesper/git/extendj/java4/backend/LocalNum.jrag:197
686          return localNum() + 3;
687        }
688        else {
689          return getParent().Define_localNum(this, caller);
690        }
691      }
692      protected boolean canDefine_localNum(ASTNode caller, ASTNode child) {
693        return true;
694      }
695      /**
696       * @apilevel internal
697       */
698      public ASTNode rewriteTo() {
699        return super.rewriteTo();
700      }
701    }