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/java7/grammar/BasicTWR.ast:1
027     * @production BasicTWR : {@link Stmt} ::= <span class="component">Resource:{@link ResourceDeclaration}</span> <span class="component">{@link Block}</span>;
028    
029     */
030    public class BasicTWR extends Stmt implements Cloneable, VariableScope {
031      /**
032       * The general structure of the basic try-with-resources:
033       * 
034       * <pre><code>
035       * RESOURCE
036       * BLOCK
037       * 
038       * Primary Exception Handler
039       * Automatic Closing of Resource
040       * Suppressed Exception Handler
041       * re-throw primary exception
042       * Automatic Closing of Resource
043       * </pre></code>
044       * 
045       * Pseudocode for basic try-with-resources:
046       * 
047       * <pre><code>
048       * 0  .resourceBegin
049       * 1  emit RESOURCE
050       * 0  store resource
051       * 0  .resourceEnd
052       * 
053       * 0  .blockBegin
054       * 0  emit BLOCK
055       * 0  .blockEnd
056       * 0  goto outerFinally
057       * 
058       * 1  .resourceException
059       * 1  throw
060       * 
061       * #if BLOCK is not empty:
062       * 
063       * 1  .catchPrimary
064       * 0  store primary
065       * 
066       * 0  .tryCloseBegin
067       * 1  load resource
068       * 0  ifnull innerFinally
069       * 1  load resource
070       * 0  invoke java.lang.AutoCloseable.close()
071       * 0  .tryCloseEnd
072       * 
073       * 0  goto innerFinally
074       * 
075       * 1  .catchSuppressed
076       * 0  store suppressed
077       * 1  load primary
078       * 2  load suppressed
079       * 0  invoke java.lang.Throwable.addSuppressed(Throwable)
080       * 
081       * 0  .innerFinally
082       * 1  load primary
083       * 1  throw
084       * 
085       * #endif BLOCK is not empty
086       * 
087       * 0  .outerFinally
088       * 1  load resource
089       * 0  ifnull tryEnd
090       * 1  load resource
091       * 0  invoke java.lang.AutoCloseable.close()
092       * 
093       * 0  .tryEnd
094       * 
095       * Exception Table:
096       * resourceBegin .. resourceEnd : resourceException
097       * blockBegin .. blockEnd : catchPrimary
098       * tryCloseBegin .. tryCloseEnd : catchSuppressed
099       * </pre></code>
100       * 
101       * @aspect TryWithResources
102       * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:157
103       */
104      public void createBCode(CodeGeneration gen) {
105        ResourceDeclaration resource = getResource();
106    
107        int resourceBeginLbl = gen.constantPool().newLabel();
108        int resourceEndLbl = gen.constantPool().newLabel();
109        int blockBeginLbl = gen.constantPool().newLabel();
110        int blockEndLbl = gen.constantPool().newLabel();
111        int tryCloseBeginLbl = gen.constantPool().newLabel();
112        int tryCloseEndLbl = gen.constantPool().newLabel();
113    
114        int resourceExceptionLbl = gen.constantPool().newLabel();
115        int catchPrimaryLbl = gen.constantPool().newLabel();
116        int catchSuppressedLbl = gen.constantPool().newLabel();
117        int innerFinallyLbl = gen.constantPool().newLabel();
118        int outerFinallyLbl = gen.constantPool().newLabel();
119        int tryEndLbl = gen.constantPool().newLabel();
120    
121        TypeDecl throwableType = lookupType("java.lang", "Throwable");
122        TypeDecl resourceType = resource.type();
123        TypeDecl autoCloseableType = lookupType("java.lang", "AutoCloseable");
124    
125        gen.changeStackDepth(3);
126        int resourceIndex = resource.localNum();
127        int primaryIndex = resourceIndex+resourceType.variableSize();
128        int suppressedIndex = primaryIndex+throwableType.variableSize();
129    
130        // store the resource in local
131        gen.addLabel(resourceBeginLbl);
132        resource.createBCode(gen);
133        gen.addLabel(resourceEndLbl);
134        gen.emit(Bytecode.NOP);
135    
136        gen.addLabel(blockBeginLbl);
137        getBlock().createBCode(gen);
138        gen.addLabel(blockEndLbl);
139        gen.emitGoto(outerFinallyLbl);
140    
141        // If there was an exception when initializing the resource
142        // we need to directly rethrow the exception
143        gen.addLabel(resourceExceptionLbl);
144        gen.emitThrow();
145        gen.addException(
146          resourceBeginLbl,
147          resourceEndLbl,
148          resourceExceptionLbl,
149          CodeGeneration.ExceptionEntry.CATCH_ALL);
150    
151        if (gen.addressOf(blockBeginLbl) != gen.addressOf(blockEndLbl)) {
152    
153          // catch primary exception
154          // operand stack: .., #primary
155          gen.addLabel(catchPrimaryLbl);
156          throwableType.emitStoreLocal(gen, primaryIndex);
157    
158          // try-close resource
159          gen.addLabel(tryCloseBeginLbl);
160          {
161            // if resource != null
162            resourceType.emitLoadLocal(gen, resourceIndex);
163            gen.emitCompare(Bytecode.IFNULL, innerFinallyLbl);
164            resourceType.emitLoadLocal(gen, resourceIndex);
165            closeMethod().emitInvokeMethod(gen, autoCloseableType);
166          }
167          gen.addLabel(tryCloseEndLbl);
168          gen.emitGoto(innerFinallyLbl);
169    
170          // catch suppressed exception
171          // operand stack: .., #primary, #suppressed
172          gen.addLabel(catchSuppressedLbl);
173          throwableType.emitStoreLocal(gen, suppressedIndex);
174          throwableType.emitLoadLocal(gen, primaryIndex);
175          throwableType.emitLoadLocal(gen, suppressedIndex);
176          addSuppressedMethod().emitInvokeMethod(gen, throwableType);
177    
178          // inner finally
179          // operand stack: .., #primary
180          gen.addLabel(innerFinallyLbl);
181          throwableType.emitLoadLocal(gen, primaryIndex);
182          gen.emitThrow();
183    
184          // If there was an exception during the block of the try
185          // statement, then we should try to close the resource
186          gen.addException(
187            blockBeginLbl,
188            blockEndLbl,
189            catchPrimaryLbl,
190            CodeGeneration.ExceptionEntry.CATCH_ALL);
191    
192          // If an exception occurrs during the automatic closing
193          // of a resource after an exception in the try block...
194          gen.addException(
195            tryCloseBeginLbl,
196            tryCloseEndLbl,
197            catchSuppressedLbl,
198            CodeGeneration.ExceptionEntry.CATCH_ALL);
199        }
200    
201        // outer finally
202        gen.addLabel(outerFinallyLbl);
203        {
204          // if resource != null
205          resourceType.emitLoadLocal(gen, resourceIndex);
206          gen.emitCompare(Bytecode.IFNULL, tryEndLbl);
207          resourceType.emitLoadLocal(gen, resourceIndex);
208          closeMethod().emitInvokeMethod(gen, autoCloseableType);
209        }
210    
211        gen.addLabel(tryEndLbl);
212        gen.emit(Bytecode.NOP);
213      }
214      /**
215       * Lookup the java.lang.Throwable.close() method.
216       * @aspect TryWithResources
217       * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:271
218       */
219      private MethodDecl closeMethod() {
220        TypeDecl autoCloseableType = lookupType("java.lang", "AutoCloseable");
221        if (autoCloseableType.isUnknown()) {
222          throw new Error("Could not find java.lang.AutoCloseable");
223        }
224        for (MethodDecl method : (Collection<MethodDecl>)
225            autoCloseableType.memberMethods("close")) {
226          if (method.getNumParameter() == 0) {
227            return method;
228          }
229        }
230        throw new Error("Could not find java.lang.AutoCloseable.close()");
231      }
232      /**
233       * Lookup the java.lang.Throwable.addSuppressed(Throwable) method.
234       * @aspect TryWithResources
235       * @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:288
236       */
237      private MethodDecl addSuppressedMethod() {
238        TypeDecl throwableType = lookupType("java.lang", "Throwable");
239        if (throwableType.isUnknown()) {
240          throw new Error("Could not find java.lang.Throwable");
241        }
242        for (MethodDecl method : (Collection<MethodDecl>)
243            throwableType.memberMethods("addSuppressed")) {
244          if (method.getNumParameter() == 1 &&
245              method.getParameter(0).getTypeAccess().type() == throwableType) {
246            return method;
247          }
248        }
249        throw new Error("Could not find java.lang.Throwable.addSuppressed()");
250      }
251      /**
252       * @declaredat ASTNode:1
253       */
254      public BasicTWR() {
255        super();
256      }
257      /**
258       * Initializes the child array to the correct size.
259       * Initializes List and Opt nta children.
260       * @apilevel internal
261       * @ast method
262       * @declaredat ASTNode:10
263       */
264      public void init$Children() {
265        children = new ASTNode[2];
266      }
267      /**
268       * @declaredat ASTNode:13
269       */
270      public BasicTWR(ResourceDeclaration p0, Block p1) {
271        setChild(p0, 0);
272        setChild(p1, 1);
273      }
274      /**
275       * @apilevel low-level
276       * @declaredat ASTNode:20
277       */
278      protected int numChildren() {
279        return 2;
280      }
281      /**
282       * @apilevel internal
283       * @declaredat ASTNode:26
284       */
285      public boolean mayHaveRewrite() {
286        return false;
287      }
288      /**
289       * @apilevel internal
290       * @declaredat ASTNode:32
291       */
292      public void flushAttrCache() {
293        super.flushAttrCache();
294        localLookup_String_reset();
295        localVariableDeclaration_String_reset();
296        lookupVariable_String_reset();
297      }
298      /**
299       * @apilevel internal
300       * @declaredat ASTNode:41
301       */
302      public void flushCollectionCache() {
303        super.flushCollectionCache();
304      }
305      /**
306       * @apilevel internal
307       * @declaredat ASTNode:47
308       */
309      public void flushRewriteCache() {
310        super.flushRewriteCache();
311      }
312      /**
313       * @apilevel internal
314       * @declaredat ASTNode:53
315       */
316      public BasicTWR clone() throws CloneNotSupportedException {
317        BasicTWR node = (BasicTWR) super.clone();
318        return node;
319      }
320      /**
321       * @apilevel internal
322       * @declaredat ASTNode:60
323       */
324      public BasicTWR copy() {
325        try {
326          BasicTWR node = (BasicTWR) clone();
327          node.parent = null;
328          if (children != null) {
329            node.children = (ASTNode[]) children.clone();
330          }
331          return node;
332        } catch (CloneNotSupportedException e) {
333          throw new Error("Error: clone not supported for " + getClass().getName());
334        }
335      }
336      /**
337       * Create a deep copy of the AST subtree at this node.
338       * The copy is dangling, i.e. has no parent.
339       * @return dangling copy of the subtree at this node
340       * @apilevel low-level
341       * @deprecated Please use treeCopy or treeCopyNoTransform instead
342       * @declaredat ASTNode:79
343       */
344      @Deprecated
345      public BasicTWR fullCopy() {
346        return treeCopyNoTransform();
347      }
348      /**
349       * Create a deep copy of the AST subtree at this node.
350       * The copy is dangling, i.e. has no parent.
351       * @return dangling copy of the subtree at this node
352       * @apilevel low-level
353       * @declaredat ASTNode:89
354       */
355      public BasicTWR treeCopyNoTransform() {
356        BasicTWR tree = (BasicTWR) copy();
357        if (children != null) {
358          for (int i = 0; i < children.length; ++i) {
359            ASTNode child = (ASTNode) children[i];
360            if (child != null) {
361              child = child.treeCopyNoTransform();
362              tree.setChild(child, i);
363            }
364          }
365        }
366        return tree;
367      }
368      /**
369       * Create a deep copy of the AST subtree at this node.
370       * The subtree of this node is traversed to trigger rewrites before copy.
371       * The copy is dangling, i.e. has no parent.
372       * @return dangling copy of the subtree at this node
373       * @apilevel low-level
374       * @declaredat ASTNode:109
375       */
376      public BasicTWR treeCopy() {
377        doFullTraversal();
378        return treeCopyNoTransform();
379      }
380      /**
381       * @apilevel internal
382       * @declaredat ASTNode:116
383       */
384      protected boolean is$Equal(ASTNode node) {
385        return super.is$Equal(node);    
386      }
387      /**
388       * Replaces the Resource child.
389       * @param node The new node to replace the Resource child.
390       * @apilevel high-level
391       */
392      public void setResource(ResourceDeclaration node) {
393        setChild(node, 0);
394      }
395      /**
396       * Retrieves the Resource child.
397       * @return The current node used as the Resource child.
398       * @apilevel high-level
399       */
400      @ASTNodeAnnotation.Child(name="Resource")
401      public ResourceDeclaration getResource() {
402        return (ResourceDeclaration) getChild(0);
403      }
404      /**
405       * Retrieves the Resource child.
406       * <p><em>This method does not invoke AST transformations.</em></p>
407       * @return The current node used as the Resource child.
408       * @apilevel low-level
409       */
410      public ResourceDeclaration getResourceNoTransform() {
411        return (ResourceDeclaration) getChildNoTransform(0);
412      }
413      /**
414       * Replaces the Block child.
415       * @param node The new node to replace the Block child.
416       * @apilevel high-level
417       */
418      public void setBlock(Block node) {
419        setChild(node, 1);
420      }
421      /**
422       * Retrieves the Block child.
423       * @return The current node used as the Block child.
424       * @apilevel high-level
425       */
426      @ASTNodeAnnotation.Child(name="Block")
427      public Block getBlock() {
428        return (Block) getChild(1);
429      }
430      /**
431       * Retrieves the Block child.
432       * <p><em>This method does not invoke AST transformations.</em></p>
433       * @return The current node used as the Block child.
434       * @apilevel low-level
435       */
436      public Block getBlockNoTransform() {
437        return (Block) getChildNoTransform(1);
438      }
439      /**
440       * @apilevel internal
441       */
442      protected java.util.Map localLookup_String_values;
443      /**
444       * @apilevel internal
445       */
446      private void localLookup_String_reset() {
447        localLookup_String_values = null;
448      }
449      /**
450       * @attribute syn
451       * @aspect MultiCatch
452       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:100
453       */
454      @ASTNodeAnnotation.Attribute
455      public SimpleSet localLookup(String name) {
456        Object _parameters = name;
457        if (localLookup_String_values == null) localLookup_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
458        ASTNode$State state = state();
459        if (localLookup_String_values.containsKey(_parameters)) {
460          return (SimpleSet) localLookup_String_values.get(_parameters);
461        }
462        boolean intermediate = state.INTERMEDIATE_VALUE;
463        state.INTERMEDIATE_VALUE = false;
464        int num = state.boundariesCrossed;
465        boolean isFinal = this.is$Final();
466        SimpleSet localLookup_String_value = localLookup_compute(name);
467        if (isFinal && num == state().boundariesCrossed) {
468          localLookup_String_values.put(_parameters, localLookup_String_value);
469        } else {
470        }
471        state.INTERMEDIATE_VALUE |= intermediate;
472    
473        return localLookup_String_value;
474      }
475      /**
476       * @apilevel internal
477       */
478      private SimpleSet localLookup_compute(String name) {
479          VariableDeclaration v = localVariableDeclaration(name);
480          if (v != null) {
481            return v;
482          }
483          return lookupVariable(name);
484        }
485      /**
486       * @apilevel internal
487       */
488      protected java.util.Map localVariableDeclaration_String_values;
489      /**
490       * @apilevel internal
491       */
492      private void localVariableDeclaration_String_reset() {
493        localVariableDeclaration_String_values = null;
494      }
495      /**
496       * @attribute syn
497       * @aspect MultiCatch
498       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:107
499       */
500      @ASTNodeAnnotation.Attribute
501      public VariableDeclaration localVariableDeclaration(String name) {
502        Object _parameters = name;
503        if (localVariableDeclaration_String_values == null) localVariableDeclaration_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
504        ASTNode$State state = state();
505        if (localVariableDeclaration_String_values.containsKey(_parameters)) {
506          return (VariableDeclaration) localVariableDeclaration_String_values.get(_parameters);
507        }
508        boolean intermediate = state.INTERMEDIATE_VALUE;
509        state.INTERMEDIATE_VALUE = false;
510        int num = state.boundariesCrossed;
511        boolean isFinal = this.is$Final();
512        VariableDeclaration localVariableDeclaration_String_value = getResource().declaresVariable(name) ? getResource() : null;
513        if (isFinal && num == state().boundariesCrossed) {
514          localVariableDeclaration_String_values.put(_parameters, localVariableDeclaration_String_value);
515        } else {
516        }
517        state.INTERMEDIATE_VALUE |= intermediate;
518    
519        return localVariableDeclaration_String_value;
520      }
521      /**
522       * @attribute syn
523       * @aspect PreciseRethrow
524       * @declaredat /home/jesper/git/extendj/java7/frontend/PreciseRethrow.jrag:84
525       */
526      @ASTNodeAnnotation.Attribute
527      public boolean modifiedInScope(Variable var) {
528        boolean modifiedInScope_Variable_value = getBlock().modifiedInScope(var);
529    
530        return modifiedInScope_Variable_value;
531      }
532      /**
533       * @attribute inh
534       * @aspect MultiCatch
535       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:111
536       */
537      /**
538       * @attribute inh
539       * @aspect MultiCatch
540       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:111
541       */
542      @ASTNodeAnnotation.Attribute
543      public SimpleSet lookupVariable(String name) {
544        Object _parameters = name;
545        if (lookupVariable_String_values == null) lookupVariable_String_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
546        ASTNode$State state = state();
547        if (lookupVariable_String_values.containsKey(_parameters)) {
548          return (SimpleSet) lookupVariable_String_values.get(_parameters);
549        }
550        boolean intermediate = state.INTERMEDIATE_VALUE;
551        state.INTERMEDIATE_VALUE = false;
552        int num = state.boundariesCrossed;
553        boolean isFinal = this.is$Final();
554        SimpleSet lookupVariable_String_value = getParent().Define_lookupVariable(this, null, name);
555        if (isFinal && num == state().boundariesCrossed) {
556          lookupVariable_String_values.put(_parameters, lookupVariable_String_value);
557        } else {
558        }
559        state.INTERMEDIATE_VALUE |= intermediate;
560    
561        return lookupVariable_String_value;
562      }
563      /**
564       * @apilevel internal
565       */
566      protected java.util.Map lookupVariable_String_values;
567      /**
568       * @apilevel internal
569       */
570      private void lookupVariable_String_reset() {
571        lookupVariable_String_values = null;
572      }
573      /**
574       * @declaredat /home/jesper/git/extendj/java8/frontend/LookupVariable.jrag:30
575       * @apilevel internal
576       */
577      public SimpleSet Define_lookupVariable(ASTNode caller, ASTNode child, String name) {
578        if (caller == getBlockNoTransform()) {
579          // @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:99
580          return localLookup(name);
581        }
582        else {
583          return getParent().Define_lookupVariable(this, caller, name);
584        }
585      }
586      protected boolean canDefine_lookupVariable(ASTNode caller, ASTNode child, String name) {
587        return true;
588      }
589      /**
590       * @declaredat /home/jesper/git/extendj/java7/backend/MultiCatch.jrag:64
591       * @apilevel internal
592       */
593      public int Define_localNum(ASTNode caller, ASTNode child) {
594        if (caller == getBlockNoTransform()) {
595          // @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:315
596          return getResource().localNum()
597                + getResource().type().variableSize()
598                + 2 * lookupType("java.lang", "Throwable").variableSize();
599        }
600        else if (caller == getResourceNoTransform()) {
601          // @declaredat /home/jesper/git/extendj/java7/backend/TryWithResources.jrag:306
602          return localNum();
603        }
604        else {
605          return getParent().Define_localNum(this, caller);
606        }
607      }
608      protected boolean canDefine_localNum(ASTNode caller, ASTNode child) {
609        return true;
610      }
611      /**
612       * @apilevel internal
613       */
614      public ASTNode rewriteTo() {
615        return super.rewriteTo();
616      }
617    }