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:155
027     * @production AddExpr : {@link AdditiveExpr};
028    
029     */
030    public class AddExpr extends AdditiveExpr implements Cloneable {
031      /**
032       * @aspect TypeCheck
033       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:204
034       */
035      public void typeCheck() {
036        TypeDecl left = getLeftOperand().type();
037        TypeDecl right = getRightOperand().type();
038        if (!left.isString() && !right.isString()) {
039          super.typeCheck();
040        } else if (left.isVoid()) {
041          error("The type void of the left hand side is not numeric");
042        } else if (right.isVoid()) {
043          error("The type void of the right hand side is not numeric");
044        }
045      }
046      /**
047       * @aspect CodeGenerationBinaryOperations
048       * @declaredat /home/jesper/git/extendj/java4/backend/CodeGeneration.jrag:662
049       */
050      void emitOperation(CodeGeneration gen) { type().add(gen); }
051      /**
052       * @aspect CreateBCode
053       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:984
054       */
055      public void createBCode(CodeGeneration gen) {
056        if (!type().isString()) {
057          super.createBCode(gen);
058        } else if (isConstant()) {
059          StringLiteral.push(gen, constant().stringValue());
060        } else {
061          TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer");
062          String classname = stringBuffer.constantPoolName();
063          String desc;
064          int index;
065          TypeDecl argumentType;
066          if (firstStringAddPart()) {
067            stringBuffer.emitNew(gen); // new StringBuffer
068            gen.emitDup();             // dup
069            desc = "()V";
070            index = gen.constantPool().addMethodref(classname, "<init>", desc);
071            gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer()
072            getLeftOperand().createBCode(gen); // left
073            argumentType = getLeftOperand().type().stringPromotion();
074            desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
075            index = gen.constantPool().addMethodref(classname, "append", desc);
076            gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
077          } else {
078            getLeftOperand().createBCode(gen);
079          }
080          getRightOperand().createBCode(gen); // right
081          argumentType = getRightOperand().type().stringPromotion();
082          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
083          index = gen.constantPool().addMethodref(classname, "append", desc);
084          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
085          if (lastStringAddPart()) {
086            desc = "()" + type().typeDescriptor();
087            index = gen.constantPool().addMethodref(classname, "toString", desc);
088            gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString
089          }
090        }
091      }
092      /**
093       * @declaredat ASTNode:1
094       */
095      public AddExpr() {
096        super();
097      }
098      /**
099       * Initializes the child array to the correct size.
100       * Initializes List and Opt nta children.
101       * @apilevel internal
102       * @ast method
103       * @declaredat ASTNode:10
104       */
105      public void init$Children() {
106        children = new ASTNode[2];
107      }
108      /**
109       * @declaredat ASTNode:13
110       */
111      public AddExpr(Expr p0, Expr p1) {
112        setChild(p0, 0);
113        setChild(p1, 1);
114      }
115      /**
116       * @apilevel low-level
117       * @declaredat ASTNode:20
118       */
119      protected int numChildren() {
120        return 2;
121      }
122      /**
123       * @apilevel internal
124       * @declaredat ASTNode:26
125       */
126      public boolean mayHaveRewrite() {
127        return false;
128      }
129      /**
130       * @apilevel internal
131       * @declaredat ASTNode:32
132       */
133      public void flushAttrCache() {
134        super.flushAttrCache();
135        type_reset();
136      }
137      /**
138       * @apilevel internal
139       * @declaredat ASTNode:39
140       */
141      public void flushCollectionCache() {
142        super.flushCollectionCache();
143      }
144      /**
145       * @apilevel internal
146       * @declaredat ASTNode:45
147       */
148      public void flushRewriteCache() {
149        super.flushRewriteCache();
150      }
151      /**
152       * @apilevel internal
153       * @declaredat ASTNode:51
154       */
155      public AddExpr clone() throws CloneNotSupportedException {
156        AddExpr node = (AddExpr) super.clone();
157        return node;
158      }
159      /**
160       * @apilevel internal
161       * @declaredat ASTNode:58
162       */
163      public AddExpr copy() {
164        try {
165          AddExpr node = (AddExpr) clone();
166          node.parent = null;
167          if (children != null) {
168            node.children = (ASTNode[]) children.clone();
169          }
170          return node;
171        } catch (CloneNotSupportedException e) {
172          throw new Error("Error: clone not supported for " + getClass().getName());
173        }
174      }
175      /**
176       * Create a deep copy of the AST subtree at this node.
177       * The copy is dangling, i.e. has no parent.
178       * @return dangling copy of the subtree at this node
179       * @apilevel low-level
180       * @deprecated Please use treeCopy or treeCopyNoTransform instead
181       * @declaredat ASTNode:77
182       */
183      @Deprecated
184      public AddExpr fullCopy() {
185        return treeCopyNoTransform();
186      }
187      /**
188       * Create a deep copy of the AST subtree at this node.
189       * The copy is dangling, i.e. has no parent.
190       * @return dangling copy of the subtree at this node
191       * @apilevel low-level
192       * @declaredat ASTNode:87
193       */
194      public AddExpr treeCopyNoTransform() {
195        AddExpr tree = (AddExpr) copy();
196        if (children != null) {
197          for (int i = 0; i < children.length; ++i) {
198            ASTNode child = (ASTNode) children[i];
199            if (child != null) {
200              child = child.treeCopyNoTransform();
201              tree.setChild(child, i);
202            }
203          }
204        }
205        return tree;
206      }
207      /**
208       * Create a deep copy of the AST subtree at this node.
209       * The subtree of this node is traversed to trigger rewrites before copy.
210       * The copy is dangling, i.e. has no parent.
211       * @return dangling copy of the subtree at this node
212       * @apilevel low-level
213       * @declaredat ASTNode:107
214       */
215      public AddExpr treeCopy() {
216        doFullTraversal();
217        return treeCopyNoTransform();
218      }
219      /**
220       * @apilevel internal
221       * @declaredat ASTNode:114
222       */
223      protected boolean is$Equal(ASTNode node) {
224        return super.is$Equal(node);    
225      }
226      /**
227       * Replaces the LeftOperand child.
228       * @param node The new node to replace the LeftOperand child.
229       * @apilevel high-level
230       */
231      public void setLeftOperand(Expr node) {
232        setChild(node, 0);
233      }
234      /**
235       * Retrieves the LeftOperand child.
236       * @return The current node used as the LeftOperand child.
237       * @apilevel high-level
238       */
239      @ASTNodeAnnotation.Child(name="LeftOperand")
240      public Expr getLeftOperand() {
241        return (Expr) getChild(0);
242      }
243      /**
244       * Retrieves the LeftOperand child.
245       * <p><em>This method does not invoke AST transformations.</em></p>
246       * @return The current node used as the LeftOperand child.
247       * @apilevel low-level
248       */
249      public Expr getLeftOperandNoTransform() {
250        return (Expr) getChildNoTransform(0);
251      }
252      /**
253       * Replaces the RightOperand child.
254       * @param node The new node to replace the RightOperand child.
255       * @apilevel high-level
256       */
257      public void setRightOperand(Expr node) {
258        setChild(node, 1);
259      }
260      /**
261       * Retrieves the RightOperand child.
262       * @return The current node used as the RightOperand child.
263       * @apilevel high-level
264       */
265      @ASTNodeAnnotation.Child(name="RightOperand")
266      public Expr getRightOperand() {
267        return (Expr) getChild(1);
268      }
269      /**
270       * Retrieves the RightOperand child.
271       * <p><em>This method does not invoke AST transformations.</em></p>
272       * @return The current node used as the RightOperand child.
273       * @apilevel low-level
274       */
275      public Expr getRightOperandNoTransform() {
276        return (Expr) getChildNoTransform(1);
277      }
278      /**
279       * @attribute syn
280       * @aspect ConstantExpression
281       * @declaredat /home/jesper/git/extendj/java4/frontend/ConstantExpression.jrag:32
282       */
283      @ASTNodeAnnotation.Attribute
284      public Constant constant() {
285        Constant constant_value = type().add(getLeftOperand().constant(), getRightOperand().constant());
286    
287        return constant_value;
288      }
289      /** The operator string used for pretty printing this expression. 
290       * @attribute syn
291       * @aspect PrettyPrintUtil
292       * @declaredat /home/jesper/git/extendj/java4/frontend/PrettyPrintUtil.jrag:270
293       */
294      @ASTNodeAnnotation.Attribute
295      public String printOp() {
296        String printOp_value = "+";
297    
298        return printOp_value;
299      }
300      /**
301       * @apilevel internal
302       */
303      protected boolean type_computed = false;
304      /**
305       * @apilevel internal
306       */
307      protected TypeDecl type_value;
308      /**
309       * @apilevel internal
310       */
311      private void type_reset() {
312        type_computed = false;
313        type_value = null;
314      }
315      /**
316       * @attribute syn
317       * @aspect TypeAnalysis
318       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeAnalysis.jrag:302
319       */
320      @ASTNodeAnnotation.Attribute
321      public TypeDecl type() {
322        ASTNode$State state = state();
323        if (type_computed) {
324          return type_value;
325        }
326        boolean intermediate = state.INTERMEDIATE_VALUE;
327        state.INTERMEDIATE_VALUE = false;
328        int num = state.boundariesCrossed;
329        boolean isFinal = this.is$Final();
330        type_value = type_compute();
331        if (isFinal && num == state().boundariesCrossed) {
332          type_computed = true;
333        } else {
334        }
335        state.INTERMEDIATE_VALUE |= intermediate;
336    
337        return type_value;
338      }
339      /**
340       * @apilevel internal
341       */
342      private TypeDecl type_compute() {
343          TypeDecl left = getLeftOperand().type();
344          TypeDecl right = getRightOperand().type();
345          if (!left.isString() && !right.isString()) {
346            return super.type();
347          } else {
348            if (left.isVoid() || right.isVoid()) {
349              return unknownType();
350            }
351            // pick the string type
352            return left.isString() ? left : right;
353          }
354        }
355      /**
356       * @attribute syn
357       * @aspect InnerClasses
358       * @declaredat /home/jesper/git/extendj/java4/backend/InnerClasses.jrag:119
359       */
360      @ASTNodeAnnotation.Attribute
361      public boolean isStringAdd() {
362        boolean isStringAdd_value = type().isString() && !isConstant();
363    
364        return isStringAdd_value;
365      }
366      /**
367       * @attribute syn
368       * @aspect InnerClasses
369       * @declaredat /home/jesper/git/extendj/java4/backend/InnerClasses.jrag:122
370       */
371      @ASTNodeAnnotation.Attribute
372      public boolean firstStringAddPart() {
373        boolean firstStringAddPart_value = type().isString() && !getLeftOperand().isStringAdd();
374    
375        return firstStringAddPart_value;
376      }
377      /**
378       * @attribute syn
379       * @aspect InnerClasses
380       * @declaredat /home/jesper/git/extendj/java4/backend/InnerClasses.jrag:123
381       */
382      @ASTNodeAnnotation.Attribute
383      public boolean lastStringAddPart() {
384        boolean lastStringAddPart_value = !getParent().isStringAdd();
385    
386        return lastStringAddPart_value;
387      }
388      /**
389       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:30
390       * @apilevel internal
391       */
392      public TypeDecl Define_targetType(ASTNode caller, ASTNode child) {
393        if (caller == getRightOperandNoTransform()) {
394          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:53
395          {
396              if (getRightOperand().stringContext()) {
397                return getLeftOperand().type();
398              } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
399                return type();
400              } else {
401                return targetType();
402              }
403            }
404        }
405        else if (caller == getLeftOperandNoTransform()) {
406          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:44
407          {
408              if (getLeftOperand().stringContext()) {
409                return getRightOperand().type();
410              } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
411                return type();
412              } else {
413                return targetType();
414              }
415            }
416        }
417        else {
418          return super.Define_targetType(caller, child);
419        }
420      }
421      protected boolean canDefine_targetType(ASTNode caller, ASTNode child) {
422        return true;
423      }
424      /**
425       * @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:199
426       * @apilevel internal
427       */
428      public boolean Define_stringContext(ASTNode caller, ASTNode child) {
429        if (caller == getRightOperandNoTransform()) {
430          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:234
431          {
432              if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) {
433                if (getLeftOperand().type().isString() && !getRightOperand().type().isString()) {
434                  return true;
435                }
436              }
437              return false;
438            }
439        }
440        else if (caller == getLeftOperandNoTransform()) {
441          // @declaredat /home/jesper/git/extendj/java8/frontend/TargetType.jrag:226
442          {
443              if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) {
444                if (getRightOperand().type().isString() && !getLeftOperand().type().isString()) {
445                  return true;
446                }
447              }
448              return false;
449            }
450        }
451        else {
452          return super.Define_stringContext(caller, child);
453        }
454      }
455      protected boolean canDefine_stringContext(ASTNode caller, ASTNode child) {
456        return true;
457      }
458      /**
459       * @apilevel internal
460       */
461      public ASTNode rewriteTo() {
462        return super.rewriteTo();
463      }
464    }