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:113
027     * @production AssignPlusExpr : {@link AssignAdditiveExpr};
028    
029     */
030    public class AssignPlusExpr extends AssignAdditiveExpr implements Cloneable {
031      /**
032       * @aspect TypeCheck
033       * @declaredat /home/jesper/git/extendj/java4/frontend/TypeCheck.jrag:98
034       */
035      public void typeCheck() {
036        if (!getDest().isVariable()) {
037          error("left hand side is not a variable");
038        } else if (getSource().type().isUnknown() || getDest().type().isUnknown()) {
039          return;
040        } else if (getDest().type().isString() && !(getSource().type().isVoid())) {
041          return;
042        } else if (getSource().type().isBoolean() || getDest().type().isBoolean()) {
043          error("Operator + does not operate on boolean types");
044        } else if (getSource().type().isPrimitive() && getDest().type().isPrimitive()) {
045          return;
046        } else
047          errorf("can not assign %s of type %s a value of type %s",
048              getDest().prettyPrint(), getDest().type().typeName(), getSource().type().typeName());
049      }
050      /**
051       * @aspect CreateBCode
052       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:359
053       */
054      public void createBCode(CodeGeneration gen) {
055        TypeDecl dest = getDest().type();
056        TypeDecl source = getSource().type();
057        if (dest.isString()) {
058          getDest().createAssignLoadDest(gen);
059    
060          // new StringBuffer()
061          TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer");
062          String classname = stringBuffer.constantPoolName();
063          String desc;
064          int index;
065          TypeDecl argumentType;
066          stringBuffer.emitNew(gen); // new StringBuffer
067          gen.emitDup();             // dup
068          desc = "()V";
069          index = gen.constantPool().addMethodref(classname, "<init>", desc);
070          gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer()
071    
072          gen.emitSwap();
073    
074          // append
075          argumentType = dest.stringPromotion();
076          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
077          index = gen.constantPool().addMethodref(classname, "append", desc);
078          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
079    
080          getSource().createBCode(gen);
081    
082          // typed append
083          argumentType = source.stringPromotion();
084          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
085          index = gen.constantPool().addMethodref(classname, "append", desc);
086          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
087    
088          // toString
089          desc = "()" + type().typeDescriptor();
090          index = gen.constantPool().addMethodref(classname, "toString", desc);
091          gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString
092    
093          if (needsPush()) {
094            getDest().createPushAssignmentResult(gen);
095          }
096          getDest().emitStore(gen);
097        } else {
098          super.createBCode(gen);
099        }
100      }
101      /**
102       * @aspect CreateBCode
103       * @declaredat /home/jesper/git/extendj/java4/backend/CreateBCode.jrag:505
104       */
105      public void createAssignOp(CodeGeneration gen, TypeDecl type)    { type.add(gen); }
106      /**
107       * @declaredat ASTNode:1
108       */
109      public AssignPlusExpr() {
110        super();
111      }
112      /**
113       * Initializes the child array to the correct size.
114       * Initializes List and Opt nta children.
115       * @apilevel internal
116       * @ast method
117       * @declaredat ASTNode:10
118       */
119      public void init$Children() {
120        children = new ASTNode[2];
121      }
122      /**
123       * @declaredat ASTNode:13
124       */
125      public AssignPlusExpr(Expr p0, Expr p1) {
126        setChild(p0, 0);
127        setChild(p1, 1);
128      }
129      /**
130       * @apilevel low-level
131       * @declaredat ASTNode:20
132       */
133      protected int numChildren() {
134        return 2;
135      }
136      /**
137       * @apilevel internal
138       * @declaredat ASTNode:26
139       */
140      public boolean mayHaveRewrite() {
141        return false;
142      }
143      /**
144       * @apilevel internal
145       * @declaredat ASTNode:32
146       */
147      public void flushAttrCache() {
148        super.flushAttrCache();
149      }
150      /**
151       * @apilevel internal
152       * @declaredat ASTNode:38
153       */
154      public void flushCollectionCache() {
155        super.flushCollectionCache();
156      }
157      /**
158       * @apilevel internal
159       * @declaredat ASTNode:44
160       */
161      public void flushRewriteCache() {
162        super.flushRewriteCache();
163      }
164      /**
165       * @apilevel internal
166       * @declaredat ASTNode:50
167       */
168      public AssignPlusExpr clone() throws CloneNotSupportedException {
169        AssignPlusExpr node = (AssignPlusExpr) super.clone();
170        return node;
171      }
172      /**
173       * @apilevel internal
174       * @declaredat ASTNode:57
175       */
176      public AssignPlusExpr copy() {
177        try {
178          AssignPlusExpr node = (AssignPlusExpr) 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:76
195       */
196      @Deprecated
197      public AssignPlusExpr 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:86
206       */
207      public AssignPlusExpr treeCopyNoTransform() {
208        AssignPlusExpr tree = (AssignPlusExpr) copy();
209        if (children != null) {
210          for (int i = 0; i < children.length; ++i) {
211            ASTNode child = (ASTNode) children[i];
212            if (child != null) {
213              child = child.treeCopyNoTransform();
214              tree.setChild(child, i);
215            }
216          }
217        }
218        return tree;
219      }
220      /**
221       * Create a deep copy of the AST subtree at this node.
222       * The subtree of this node is traversed to trigger rewrites before copy.
223       * The copy is dangling, i.e. has no parent.
224       * @return dangling copy of the subtree at this node
225       * @apilevel low-level
226       * @declaredat ASTNode:106
227       */
228      public AssignPlusExpr treeCopy() {
229        doFullTraversal();
230        return treeCopyNoTransform();
231      }
232      /**
233       * @apilevel internal
234       * @declaredat ASTNode:113
235       */
236      protected boolean is$Equal(ASTNode node) {
237        return super.is$Equal(node);    
238      }
239      /**
240       * Replaces the Dest child.
241       * @param node The new node to replace the Dest child.
242       * @apilevel high-level
243       */
244      public void setDest(Expr node) {
245        setChild(node, 0);
246      }
247      /**
248       * Retrieves the Dest child.
249       * @return The current node used as the Dest child.
250       * @apilevel high-level
251       */
252      @ASTNodeAnnotation.Child(name="Dest")
253      public Expr getDest() {
254        return (Expr) getChild(0);
255      }
256      /**
257       * Retrieves the Dest child.
258       * <p><em>This method does not invoke AST transformations.</em></p>
259       * @return The current node used as the Dest child.
260       * @apilevel low-level
261       */
262      public Expr getDestNoTransform() {
263        return (Expr) getChildNoTransform(0);
264      }
265      /**
266       * Replaces the Source child.
267       * @param node The new node to replace the Source child.
268       * @apilevel high-level
269       */
270      public void setSource(Expr node) {
271        setChild(node, 1);
272      }
273      /**
274       * Retrieves the Source child.
275       * @return The current node used as the Source child.
276       * @apilevel high-level
277       */
278      @ASTNodeAnnotation.Child(name="Source")
279      public Expr getSource() {
280        return (Expr) getChild(1);
281      }
282      /**
283       * Retrieves the Source child.
284       * <p><em>This method does not invoke AST transformations.</em></p>
285       * @return The current node used as the Source child.
286       * @apilevel low-level
287       */
288      public Expr getSourceNoTransform() {
289        return (Expr) getChildNoTransform(1);
290      }
291      /** The operator string used for pretty printing this expression. 
292       * @attribute syn
293       * @aspect PrettyPrintUtil
294       * @declaredat /home/jesper/git/extendj/java4/frontend/PrettyPrintUtil.jrag:292
295       */
296      @ASTNodeAnnotation.Attribute
297      public String printOp() {
298        String printOp_value = "+=";
299    
300        return printOp_value;
301      }
302      /**
303       * @apilevel internal
304       */
305      public ASTNode rewriteTo() {
306        return super.rewriteTo();
307      }
308    }