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 }