001    /* This file was generated with JastAdd2 (http://jastadd.org) version R20130213 */
002    package AST;
003    
004    import java.util.HashSet;
005    import java.io.File;
006    import java.util.*;
007    import beaver.*;
008    import java.util.ArrayList;
009    import java.util.zip.*;
010    import java.io.*;
011    import java.io.FileNotFoundException;
012    import java.util.Collection;
013    /**
014     * @production AddExpr : {@link AdditiveExpr};
015     * @ast node
016     * @declaredat /home/jesper/svn/JastAddJ/Java1.4Frontend/java.ast:158
017     */
018    public class AddExpr extends AdditiveExpr implements Cloneable {
019      /**
020       * @apilevel low-level
021       */
022      public void flushCache() {
023      }
024      /**
025       * @apilevel internal
026       */
027      public void flushCollectionCache() {
028      }
029      /**
030       * @apilevel internal
031       */
032      @SuppressWarnings({"unchecked", "cast"})
033      public AddExpr clone() throws CloneNotSupportedException {
034        AddExpr node = (AddExpr)super.clone();
035        node.type_computed = false;
036        node.type_value = null;
037        node.in$Circle(false);
038        node.is$Final(false);
039        return node;
040      }
041    /**
042     * @apilevel internal
043     */
044      @SuppressWarnings({"unchecked", "cast"})
045    public AddExpr copy() {
046      
047      try {
048        AddExpr node = (AddExpr) clone();
049        node.parent = null;
050        if(children != null)
051          node.children = (ASTNode[]) children.clone();
052        
053        return node;
054      } catch (CloneNotSupportedException e) {
055        throw new Error("Error: clone not supported for " + getClass().getName());
056      }
057      
058    }/**
059     * Create a deep copy of the AST subtree at this node.
060     * The copy is dangling, i.e. has no parent.
061     * @return dangling copy of the subtree at this node
062     * @apilevel low-level
063     */
064      @SuppressWarnings({"unchecked", "cast"})
065    public AddExpr fullCopy() {
066      
067      AddExpr tree = (AddExpr) copy();
068      if (children != null) {
069        for (int i = 0; i < children.length; ++i) {
070          
071          ASTNode child = (ASTNode) children[i];
072          if(child != null) {
073            child = child.fullCopy();
074            tree.setChild(child, i);
075          }
076        }
077      }
078      return tree;
079      
080    }  /**
081       * @ast method 
082       * @aspect TypeCheck
083       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Frontend/TypeCheck.jrag:172
084       */
085      public void typeCheck() {
086        TypeDecl left = getLeftOperand().type();
087        TypeDecl right = getRightOperand().type();
088        if(!left.isString() && !right.isString())
089          super.typeCheck();
090        else if(left.isVoid())
091          error("The type void of the left hand side is not numeric");
092        else if(right.isVoid())
093          error("The type void of the right hand side is not numeric");
094      }
095      /**
096       * @ast method 
097       * @aspect CodeGenerationBinaryOperations
098       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Backend/CodeGeneration.jrag:1024
099       */
100      void emitOperation(CodeGeneration gen) { type().add(gen); }
101      /**
102       * @ast method 
103       * @aspect CreateBCode
104       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Backend/CreateBCode.jrag:900
105       */
106      public void createBCode(CodeGeneration gen) {
107        if(!type().isString())
108          super.createBCode(gen);
109        else if(isConstant()) {
110          StringLiteral.push(gen, constant().stringValue());
111        }
112        else {
113          TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer");
114          String classname = stringBuffer.constantPoolName();
115          String desc;
116          int index;
117          TypeDecl argumentType;
118          if(firstStringAddPart()) {
119            stringBuffer.emitNew(gen); // new StringBuffer
120            gen.emitDup();             // dup
121            desc = "()V";
122            index = gen.constantPool().addMethodref(classname, "<init>", desc);
123            gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer()
124            getLeftOperand().createBCode(gen); // left
125            argumentType = getLeftOperand().type().stringPromotion();
126            desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
127            index = gen.constantPool().addMethodref(classname, "append", desc);
128            gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
129          }
130          else {
131            getLeftOperand().createBCode(gen);
132          }
133          getRightOperand().createBCode(gen); // right
134          argumentType = getRightOperand().type().stringPromotion();
135          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
136          index = gen.constantPool().addMethodref(classname, "append", desc);
137          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
138          if(lastStringAddPart()) {
139            desc = "()" + type().typeDescriptor();
140            index = gen.constantPool().addMethodref(classname, "toString", desc);
141            gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString
142          }
143        }
144      }
145      /**
146       * @ast method 
147       * 
148       */
149      public AddExpr() {
150        super();
151    
152    
153      }
154      /**
155       * Initializes the child array to the correct size.
156       * Initializes List and Opt nta children.
157       * @apilevel internal
158       * @ast method
159       * @ast method 
160       * 
161       */
162      public void init$Children() {
163        children = new ASTNode[2];
164      }
165      /**
166       * @ast method 
167       * 
168       */
169      public AddExpr(Expr p0, Expr p1) {
170        setChild(p0, 0);
171        setChild(p1, 1);
172      }
173      /**
174       * @apilevel low-level
175       * @ast method 
176       * 
177       */
178      protected int numChildren() {
179        return 2;
180      }
181      /**
182       * @apilevel internal
183       * @ast method 
184       * 
185       */
186      public boolean mayHaveRewrite() {
187        return false;
188      }
189      /**
190       * Replaces the LeftOperand child.
191       * @param node The new node to replace the LeftOperand child.
192       * @apilevel high-level
193       * @ast method 
194       * 
195       */
196      public void setLeftOperand(Expr node) {
197        setChild(node, 0);
198      }
199      /**
200       * Retrieves the LeftOperand child.
201       * @return The current node used as the LeftOperand child.
202       * @apilevel high-level
203       * @ast method 
204       * 
205       */
206      public Expr getLeftOperand() {
207        return (Expr)getChild(0);
208      }
209      /**
210       * Retrieves the LeftOperand child.
211       * <p><em>This method does not invoke AST transformations.</em></p>
212       * @return The current node used as the LeftOperand child.
213       * @apilevel low-level
214       * @ast method 
215       * 
216       */
217      public Expr getLeftOperandNoTransform() {
218        return (Expr)getChildNoTransform(0);
219      }
220      /**
221       * Replaces the RightOperand child.
222       * @param node The new node to replace the RightOperand child.
223       * @apilevel high-level
224       * @ast method 
225       * 
226       */
227      public void setRightOperand(Expr node) {
228        setChild(node, 1);
229      }
230      /**
231       * Retrieves the RightOperand child.
232       * @return The current node used as the RightOperand child.
233       * @apilevel high-level
234       * @ast method 
235       * 
236       */
237      public Expr getRightOperand() {
238        return (Expr)getChild(1);
239      }
240      /**
241       * Retrieves the RightOperand child.
242       * <p><em>This method does not invoke AST transformations.</em></p>
243       * @return The current node used as the RightOperand child.
244       * @apilevel low-level
245       * @ast method 
246       * 
247       */
248      public Expr getRightOperandNoTransform() {
249        return (Expr)getChildNoTransform(1);
250      }
251      /**
252       * @attribute syn
253       * @aspect ConstantExpression
254       * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/ConstantExpression.jrag:91
255       */
256      public Constant constant() {
257        ASTNode$State state = state();
258        try {  return type().add(getLeftOperand().constant(), getRightOperand().constant());  }
259        finally {
260        }
261      }
262      /**
263       * @attribute syn
264       * @aspect PrettyPrint
265       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Frontend/PrettyPrint.jadd:400
266       */
267      public String printOp() {
268        ASTNode$State state = state();
269        try {  return " + ";  }
270        finally {
271        }
272      }
273      /**
274       * @apilevel internal
275       */
276      protected boolean type_computed = false;
277      /**
278       * @apilevel internal
279       */
280      protected TypeDecl type_value;
281      /**
282       * @attribute syn
283       * @aspect TypeAnalysis
284       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Frontend/TypeAnalysis.jrag:327
285       */
286      @SuppressWarnings({"unchecked", "cast"})
287      public TypeDecl type() {
288        if(type_computed) {
289          return type_value;
290        }
291          ASTNode$State state = state();
292      int num = state.boundariesCrossed;
293      boolean isFinal = this.is$Final();
294        type_value = type_compute();
295      if(isFinal && num == state().boundariesCrossed){ type_computed = true; }
296            return type_value;
297      }
298      /**
299       * @apilevel internal
300       */
301      private TypeDecl type_compute() {
302        TypeDecl left = getLeftOperand().type();
303        TypeDecl right = getRightOperand().type();
304        if(!left.isString() && !right.isString())
305          return super.type();
306        else {
307          if(left.isVoid() || right.isVoid())
308            return unknownType();
309          // pick the string type
310          return left.isString() ? left : right;
311        }
312      }
313      /**
314       * @attribute syn
315       * @aspect InnerClasses
316       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Backend/InnerClasses.jrag:88
317       */
318      public boolean isStringAdd() {
319        ASTNode$State state = state();
320        try {  return type().isString() && !isConstant();  }
321        finally {
322        }
323      }
324      /**
325       * @attribute syn
326       * @aspect InnerClasses
327       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Backend/InnerClasses.jrag:91
328       */
329      public boolean firstStringAddPart() {
330        ASTNode$State state = state();
331        try {  return type().isString() && !getLeftOperand().isStringAdd();  }
332        finally {
333        }
334      }
335      /**
336       * @attribute syn
337       * @aspect InnerClasses
338       * @declaredat /home/jesper/svn/JastAddJ/Java1.4Backend/InnerClasses.jrag:92
339       */
340      public boolean lastStringAddPart() {
341        ASTNode$State state = state();
342        try {  return !getParent().isStringAdd();  }
343        finally {
344        }
345      }
346      /**
347       * @apilevel internal
348       */
349      public ASTNode rewriteTo() {
350        return super.rewriteTo();
351      }
352    }