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/java8/grammar/Lambda.ast:12
027     * @production BlockLambdaBody : {@link LambdaBody} ::= <span class="component">{@link Block}</span>;
028    
029     */
030    public class BlockLambdaBody extends LambdaBody implements Cloneable {
031      /**
032       * @aspect ReturnCompatible
033       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:57
034       */
035      public boolean noReturnsHasResult() {
036        ArrayList<ReturnStmt> returnList = lambdaReturns();
037        for (int i = 0; i < returnList.size(); i++) {
038          if (returnList.get(i).hasResult()) {
039            return false;
040          }
041        }
042        return true;
043      }
044      /**
045       * @aspect ReturnCompatible
046       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:67
047       */
048      public boolean allReturnsHasResult() {
049        ArrayList<ReturnStmt> returnList = lambdaReturns();
050        for (int i = 0; i < returnList.size(); i++) {
051          if (!returnList.get(i).hasResult()) {
052            return false;
053          }
054        }
055        return true;
056      }
057      /**
058       * @aspect Java8PrettyPrint
059       * @declaredat /home/jesper/git/extendj/java8/frontend/PrettyPrint.jadd:51
060       */
061      public void prettyPrint(PrettyPrinter out) {
062        out.print(getBlock());
063      }
064      /**
065       * @aspect TypeCheck
066       * @declaredat /home/jesper/git/extendj/java8/frontend/TypeCheck.jrag:189
067       */
068      public void typeCheck() {
069        // 15.27.2
070        if (!voidCompatible() && !valueCompatible()) {
071          error("Block lambda bodies must be either void or value compatible");
072        }
073      }
074      /**
075       * @declaredat ASTNode:1
076       */
077      public BlockLambdaBody() {
078        super();
079      }
080      /**
081       * Initializes the child array to the correct size.
082       * Initializes List and Opt nta children.
083       * @apilevel internal
084       * @ast method
085       * @declaredat ASTNode:10
086       */
087      public void init$Children() {
088        children = new ASTNode[1];
089      }
090      /**
091       * @declaredat ASTNode:13
092       */
093      public BlockLambdaBody(Block p0) {
094        setChild(p0, 0);
095      }
096      /**
097       * @apilevel low-level
098       * @declaredat ASTNode:19
099       */
100      protected int numChildren() {
101        return 1;
102      }
103      /**
104       * @apilevel internal
105       * @declaredat ASTNode:25
106       */
107      public boolean mayHaveRewrite() {
108        return false;
109      }
110      /**
111       * @apilevel internal
112       * @declaredat ASTNode:31
113       */
114      public void flushAttrCache() {
115        super.flushAttrCache();
116        isBlockBody_reset();
117        isExprBody_reset();
118        voidCompatible_reset();
119        valueCompatible_reset();
120        congruentTo_FunctionDescriptor_reset();
121        toBlock_reset();
122      }
123      /**
124       * @apilevel internal
125       * @declaredat ASTNode:43
126       */
127      public void flushCollectionCache() {
128        super.flushCollectionCache();
129        BlockLambdaBody_lambdaReturns_computed = false;
130        BlockLambdaBody_lambdaReturns_value = null;
131        BlockLambdaBody_lambdaReturns_contributors = null;
132      }
133      /**
134       * @apilevel internal
135       * @declaredat ASTNode:52
136       */
137      public void flushRewriteCache() {
138        super.flushRewriteCache();
139      }
140      /**
141       * @apilevel internal
142       * @declaredat ASTNode:58
143       */
144      public BlockLambdaBody clone() throws CloneNotSupportedException {
145        BlockLambdaBody node = (BlockLambdaBody) super.clone();
146        return node;
147      }
148      /**
149       * @apilevel internal
150       * @declaredat ASTNode:65
151       */
152      public BlockLambdaBody copy() {
153        try {
154          BlockLambdaBody node = (BlockLambdaBody) clone();
155          node.parent = null;
156          if (children != null) {
157            node.children = (ASTNode[]) children.clone();
158          }
159          return node;
160        } catch (CloneNotSupportedException e) {
161          throw new Error("Error: clone not supported for " + getClass().getName());
162        }
163      }
164      /**
165       * Create a deep copy of the AST subtree at this node.
166       * The copy is dangling, i.e. has no parent.
167       * @return dangling copy of the subtree at this node
168       * @apilevel low-level
169       * @deprecated Please use treeCopy or treeCopyNoTransform instead
170       * @declaredat ASTNode:84
171       */
172      @Deprecated
173      public BlockLambdaBody fullCopy() {
174        return treeCopyNoTransform();
175      }
176      /**
177       * Create a deep copy of the AST subtree at this node.
178       * The copy is dangling, i.e. has no parent.
179       * @return dangling copy of the subtree at this node
180       * @apilevel low-level
181       * @declaredat ASTNode:94
182       */
183      public BlockLambdaBody treeCopyNoTransform() {
184        BlockLambdaBody tree = (BlockLambdaBody) copy();
185        if (children != null) {
186          for (int i = 0; i < children.length; ++i) {
187            ASTNode child = (ASTNode) children[i];
188            if (child != null) {
189              child = child.treeCopyNoTransform();
190              tree.setChild(child, i);
191            }
192          }
193        }
194        return tree;
195      }
196      /**
197       * Create a deep copy of the AST subtree at this node.
198       * The subtree of this node is traversed to trigger rewrites before copy.
199       * The copy is dangling, i.e. has no parent.
200       * @return dangling copy of the subtree at this node
201       * @apilevel low-level
202       * @declaredat ASTNode:114
203       */
204      public BlockLambdaBody treeCopy() {
205        doFullTraversal();
206        return treeCopyNoTransform();
207      }
208      /**
209       * @apilevel internal
210       * @declaredat ASTNode:121
211       */
212      protected boolean is$Equal(ASTNode node) {
213        return super.is$Equal(node);    
214      }
215      /**
216       * Replaces the Block child.
217       * @param node The new node to replace the Block child.
218       * @apilevel high-level
219       */
220      public void setBlock(Block node) {
221        setChild(node, 0);
222      }
223      /**
224       * Retrieves the Block child.
225       * @return The current node used as the Block child.
226       * @apilevel high-level
227       */
228      @ASTNodeAnnotation.Child(name="Block")
229      public Block getBlock() {
230        return (Block) getChild(0);
231      }
232      /**
233       * Retrieves the Block child.
234       * <p><em>This method does not invoke AST transformations.</em></p>
235       * @return The current node used as the Block child.
236       * @apilevel low-level
237       */
238      public Block getBlockNoTransform() {
239        return (Block) getChildNoTransform(0);
240      }
241      /**
242       * @attribute syn
243       * @aspect PreciseRethrow
244       * @declaredat /home/jesper/git/extendj/java8/frontend/EffectivelyFinal.jrag:43
245       */
246      @ASTNodeAnnotation.Attribute
247      public boolean modifiedInScope(Variable var) {
248        boolean modifiedInScope_Variable_value = getBlock().modifiedInScope(var);
249    
250        return modifiedInScope_Variable_value;
251      }
252      /**
253       * @apilevel internal
254       */
255      protected boolean isBlockBody_computed = false;
256      /**
257       * @apilevel internal
258       */
259      protected boolean isBlockBody_value;
260      /**
261       * @apilevel internal
262       */
263      private void isBlockBody_reset() {
264        isBlockBody_computed = false;
265      }
266      /**
267       * @attribute syn
268       * @aspect LambdaBody
269       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:29
270       */
271      @ASTNodeAnnotation.Attribute
272      public boolean isBlockBody() {
273        ASTNode$State state = state();
274        if (isBlockBody_computed) {
275          return isBlockBody_value;
276        }
277        boolean intermediate = state.INTERMEDIATE_VALUE;
278        state.INTERMEDIATE_VALUE = false;
279        int num = state.boundariesCrossed;
280        boolean isFinal = this.is$Final();
281        isBlockBody_value = true;
282        if (isFinal && num == state().boundariesCrossed) {
283          isBlockBody_computed = true;
284        } else {
285        }
286        state.INTERMEDIATE_VALUE |= intermediate;
287    
288        return isBlockBody_value;
289      }
290      /**
291       * @apilevel internal
292       */
293      protected boolean isExprBody_computed = false;
294      /**
295       * @apilevel internal
296       */
297      protected boolean isExprBody_value;
298      /**
299       * @apilevel internal
300       */
301      private void isExprBody_reset() {
302        isExprBody_computed = false;
303      }
304      /**
305       * @attribute syn
306       * @aspect LambdaBody
307       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:30
308       */
309      @ASTNodeAnnotation.Attribute
310      public boolean isExprBody() {
311        ASTNode$State state = state();
312        if (isExprBody_computed) {
313          return isExprBody_value;
314        }
315        boolean intermediate = state.INTERMEDIATE_VALUE;
316        state.INTERMEDIATE_VALUE = false;
317        int num = state.boundariesCrossed;
318        boolean isFinal = this.is$Final();
319        isExprBody_value = false;
320        if (isFinal && num == state().boundariesCrossed) {
321          isExprBody_computed = true;
322        } else {
323        }
324        state.INTERMEDIATE_VALUE |= intermediate;
325    
326        return isExprBody_value;
327      }
328      /**
329       * @apilevel internal
330       */
331      protected boolean voidCompatible_computed = false;
332      /**
333       * @apilevel internal
334       */
335      protected boolean voidCompatible_value;
336      /**
337       * @apilevel internal
338       */
339      private void voidCompatible_reset() {
340        voidCompatible_computed = false;
341      }
342      /**
343       * @attribute syn
344       * @aspect ReturnCompatible
345       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:40
346       */
347      @ASTNodeAnnotation.Attribute
348      public boolean voidCompatible() {
349        ASTNode$State state = state();
350        if (voidCompatible_computed) {
351          return voidCompatible_value;
352        }
353        boolean intermediate = state.INTERMEDIATE_VALUE;
354        state.INTERMEDIATE_VALUE = false;
355        int num = state.boundariesCrossed;
356        boolean isFinal = this.is$Final();
357        voidCompatible_value = noReturnsHasResult();
358        if (isFinal && num == state().boundariesCrossed) {
359          voidCompatible_computed = true;
360        } else {
361        }
362        state.INTERMEDIATE_VALUE |= intermediate;
363    
364        return voidCompatible_value;
365      }
366      /**
367       * @apilevel internal
368       */
369      protected boolean valueCompatible_computed = false;
370      /**
371       * @apilevel internal
372       */
373      protected boolean valueCompatible_value;
374      /**
375       * @apilevel internal
376       */
377      private void valueCompatible_reset() {
378        valueCompatible_computed = false;
379      }
380      /**
381       * @attribute syn
382       * @aspect ReturnCompatible
383       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:41
384       */
385      @ASTNodeAnnotation.Attribute
386      public boolean valueCompatible() {
387        ASTNode$State state = state();
388        if (valueCompatible_computed) {
389          return valueCompatible_value;
390        }
391        boolean intermediate = state.INTERMEDIATE_VALUE;
392        state.INTERMEDIATE_VALUE = false;
393        int num = state.boundariesCrossed;
394        boolean isFinal = this.is$Final();
395        valueCompatible_value = allReturnsHasResult() && !getBlock().canCompleteNormally();
396        if (isFinal && num == state().boundariesCrossed) {
397          valueCompatible_computed = true;
398        } else {
399        }
400        state.INTERMEDIATE_VALUE |= intermediate;
401    
402        return valueCompatible_value;
403      }
404      /**
405       * @apilevel internal
406       */
407      protected java.util.Map congruentTo_FunctionDescriptor_values;
408      /**
409       * @apilevel internal
410       */
411      private void congruentTo_FunctionDescriptor_reset() {
412        congruentTo_FunctionDescriptor_values = null;
413      }
414      /**
415       * @attribute syn
416       * @aspect LambdaExpr
417       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaExpr.jrag:71
418       */
419      @ASTNodeAnnotation.Attribute
420      public boolean congruentTo(FunctionDescriptor f) {
421        Object _parameters = f;
422        if (congruentTo_FunctionDescriptor_values == null) congruentTo_FunctionDescriptor_values = new org.jastadd.util.RobustMap(new java.util.HashMap());
423        ASTNode$State state = state();
424        if (congruentTo_FunctionDescriptor_values.containsKey(_parameters)) {
425          return (Boolean) congruentTo_FunctionDescriptor_values.get(_parameters);
426        }
427        boolean intermediate = state.INTERMEDIATE_VALUE;
428        state.INTERMEDIATE_VALUE = false;
429        int num = state.boundariesCrossed;
430        boolean isFinal = this.is$Final();
431        boolean congruentTo_FunctionDescriptor_value = congruentTo_compute(f);
432        if (isFinal && num == state().boundariesCrossed) {
433          congruentTo_FunctionDescriptor_values.put(_parameters, congruentTo_FunctionDescriptor_value);
434        } else {
435        }
436        state.INTERMEDIATE_VALUE |= intermediate;
437    
438        return congruentTo_FunctionDescriptor_value;
439      }
440      /**
441       * @apilevel internal
442       */
443      private boolean congruentTo_compute(FunctionDescriptor f) {
444          if (f.method.type().isVoid()) {
445            return voidCompatible();
446          } else {
447            if (!valueCompatible()) {
448              return false;
449            }
450            for (ReturnStmt returnStmt : lambdaReturns()) {
451              if (!returnStmt.getResult().assignConversionTo(f.method.type())) {
452                return false;
453              }
454            }
455            return true;
456          }
457        }
458      /**
459       * @apilevel internal
460       */
461      protected boolean toBlock_computed = false;
462      /**
463       * @apilevel internal
464       */
465      protected Block toBlock_value;
466      /**
467       * @apilevel internal
468       */
469      private void toBlock_reset() {
470        toBlock_computed = false;
471        toBlock_value = null;
472      }
473      /**
474       * @attribute syn
475       * @aspect LambdaToClass
476       * @declaredat /home/jesper/git/extendj/java8/backend/LambdaToClass.jrag:68
477       */
478      @ASTNodeAnnotation.Attribute
479      public Block toBlock() {
480        ASTNode$State state = state();
481        if (toBlock_computed) {
482          return toBlock_value;
483        }
484        boolean intermediate = state.INTERMEDIATE_VALUE;
485        state.INTERMEDIATE_VALUE = false;
486        int num = state.boundariesCrossed;
487        boolean isFinal = this.is$Final();
488        toBlock_value = toBlock_compute();
489        if (isFinal && num == state().boundariesCrossed) {
490          toBlock_computed = true;
491        } else {
492        }
493        state.INTERMEDIATE_VALUE |= intermediate;
494    
495        return toBlock_value;
496      }
497      /**
498       * @apilevel internal
499       */
500      private Block toBlock_compute() {
501          Block b = getBlock();
502          setChild(new Block(), 0);
503          b.flushCaches();
504          return b;
505        }
506      /**
507       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:196
508       * @apilevel internal
509       */
510      public boolean Define_assignmentContext(ASTNode caller, ASTNode child) {
511        if (caller == getBlockNoTransform()) {
512          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:214
513          return false;
514        }
515        else {
516          return getParent().Define_assignmentContext(this, caller);
517        }
518      }
519      protected boolean canDefine_assignmentContext(ASTNode caller, ASTNode child) {
520        return true;
521      }
522      /**
523       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:197
524       * @apilevel internal
525       */
526      public boolean Define_invocationContext(ASTNode caller, ASTNode child) {
527        if (caller == getBlockNoTransform()) {
528          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:215
529          return false;
530        }
531        else {
532          return getParent().Define_invocationContext(this, caller);
533        }
534      }
535      protected boolean canDefine_invocationContext(ASTNode caller, ASTNode child) {
536        return true;
537      }
538      /**
539       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:198
540       * @apilevel internal
541       */
542      public boolean Define_castContext(ASTNode caller, ASTNode child) {
543        if (caller == getBlockNoTransform()) {
544          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:216
545          return false;
546        }
547        else {
548          return getParent().Define_castContext(this, caller);
549        }
550      }
551      protected boolean canDefine_castContext(ASTNode caller, ASTNode child) {
552        return true;
553      }
554      /**
555       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:199
556       * @apilevel internal
557       */
558      public boolean Define_stringContext(ASTNode caller, ASTNode child) {
559        if (caller == getBlockNoTransform()) {
560          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:217
561          return false;
562        }
563        else {
564          return getParent().Define_stringContext(this, caller);
565        }
566      }
567      protected boolean canDefine_stringContext(ASTNode caller, ASTNode child) {
568        return true;
569      }
570      /**
571       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:200
572       * @apilevel internal
573       */
574      public boolean Define_numericContext(ASTNode caller, ASTNode child) {
575        if (caller == getBlockNoTransform()) {
576          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:218
577          return false;
578        }
579        else {
580          return getParent().Define_numericContext(this, caller);
581        }
582      }
583      protected boolean canDefine_numericContext(ASTNode caller, ASTNode child) {
584        return true;
585      }
586      /**
587       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:472
588       * @apilevel internal
589       */
590      public TypeDecl Define_returnType(ASTNode caller, ASTNode child) {
591        if (caller == getBlockNoTransform()) {
592          // @declaredat /home/jesper/git/extendj/java8/frontend/TypeCheck.jrag:38
593          {
594              TypeDecl decl = enclosingLambda().targetType();
595              if (decl == null) {
596                return unknownType();
597              } else if (!(decl instanceof InterfaceDecl)) {
598                return unknownType();
599              } else {
600                InterfaceDecl iDecl = (InterfaceDecl)decl;
601                if (!iDecl.isFunctional()) {
602                  return unknownType();
603                } else {
604                  return iDecl.functionDescriptor().method.type();
605                }
606              }
607            }
608        }
609        else {
610          return getParent().Define_returnType(this, caller);
611        }
612      }
613      protected boolean canDefine_returnType(ASTNode caller, ASTNode child) {
614        return true;
615      }
616      /**
617       * @declaredat /home/jesper/git/extendj/java4/frontend/UnreachableStatements.jrag:52
618       * @apilevel internal
619       */
620      public boolean Define_reachable(ASTNode caller, ASTNode child) {
621        if (caller == getBlockNoTransform()) {
622          // @declaredat /home/jesper/git/extendj/java8/frontend/UnreachableStatements.jrag:29
623          return true;
624        }
625        else {
626          return getParent().Define_reachable(this, caller);
627        }
628      }
629      protected boolean canDefine_reachable(ASTNode caller, ASTNode child) {
630        return true;
631      }
632      /**
633       * @apilevel internal
634       */
635      public ASTNode rewriteTo() {
636        return super.rewriteTo();
637      }
638      /**
639       * @attribute coll
640       * @aspect ReturnCompatible
641       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:47
642       */
643      /**
644       * @attribute coll
645       * @aspect ReturnCompatible
646       * @declaredat /home/jesper/git/extendj/java8/frontend/LambdaBody.jrag:47
647       */
648      @ASTNodeAnnotation.Attribute
649      public ArrayList<ReturnStmt> lambdaReturns() {
650        ASTNode$State state = state();
651        if (BlockLambdaBody_lambdaReturns_computed) {
652          return BlockLambdaBody_lambdaReturns_value;
653        }
654        boolean intermediate = state.INTERMEDIATE_VALUE;
655        state.INTERMEDIATE_VALUE = false;
656        int num = state.boundariesCrossed;
657        boolean isFinal = this.is$Final();
658        BlockLambdaBody_lambdaReturns_value = lambdaReturns_compute();
659        if (isFinal && num == state().boundariesCrossed) {
660          BlockLambdaBody_lambdaReturns_computed = true;
661        } else {
662        }
663        state.INTERMEDIATE_VALUE |= intermediate;
664    
665        return BlockLambdaBody_lambdaReturns_value;
666      }
667      java.util.Collection BlockLambdaBody_lambdaReturns_contributors;
668    
669      /**
670       * @apilevel internal
671       * @return the contributor set for lambdaReturns
672       */
673      public java.util.Collection BlockLambdaBody_lambdaReturns_contributors() {
674        if (BlockLambdaBody_lambdaReturns_contributors == null)
675          BlockLambdaBody_lambdaReturns_contributors  = new java.util.LinkedList();
676        return BlockLambdaBody_lambdaReturns_contributors;
677      }
678    
679      /**
680       * @apilevel internal
681       */
682      private ArrayList<ReturnStmt> lambdaReturns_compute() {
683        ASTNode node = this;
684        while(node.getParent() != null && !(node instanceof Program)) {
685          node = node.getParent();
686        }
687        Program root = (Program) node;
688        root.collect_contributors_BlockLambdaBody_lambdaReturns();
689        BlockLambdaBody_lambdaReturns_value = new ArrayList<ReturnStmt>();
690        if (BlockLambdaBody_lambdaReturns_contributors != null) {
691          for (java.util.Iterator iter = BlockLambdaBody_lambdaReturns_contributors.iterator(); iter.hasNext(); ) {
692            ASTNode contributor = (ASTNode) iter.next();
693            contributor.contributeTo_BlockLambdaBody_BlockLambdaBody_lambdaReturns(BlockLambdaBody_lambdaReturns_value);
694          }
695        }
696        // TODO: disabled temporarily since collections may not be cached
697        //BlockLambdaBody_lambdaReturns_contributors = null;
698        return BlockLambdaBody_lambdaReturns_value;
699      }
700      /**
701       * @apilevel internal
702       */
703      protected boolean BlockLambdaBody_lambdaReturns_computed = false;
704      /**
705       * @apilevel internal
706       */
707      protected ArrayList<ReturnStmt> BlockLambdaBody_lambdaReturns_value;
708      /**
709       * @apilevel internal
710       */
711      private void BlockLambdaBody_lambdaReturns_reset() {
712        BlockLambdaBody_lambdaReturns_computed = false;
713        BlockLambdaBody_lambdaReturns_value = null;
714      }
715    }