1*0c56280aSSorin Basca /* 2*0c56280aSSorin Basca * Licensed to the Apache Software Foundation (ASF) under one or more 3*0c56280aSSorin Basca * contributor license agreements. See the NOTICE file distributed with 4*0c56280aSSorin Basca * this work for additional information regarding copyright ownership. 5*0c56280aSSorin Basca * The ASF licenses this file to You under the Apache License, Version 2.0 6*0c56280aSSorin Basca * (the "License"); you may not use this file except in compliance with 7*0c56280aSSorin Basca * the License. You may obtain a copy of the License at 8*0c56280aSSorin Basca * 9*0c56280aSSorin Basca * http://www.apache.org/licenses/LICENSE-2.0 10*0c56280aSSorin Basca * 11*0c56280aSSorin Basca * Unless required by applicable law or agreed to in writing, software 12*0c56280aSSorin Basca * distributed under the License is distributed on an "AS IS" BASIS, 13*0c56280aSSorin Basca * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*0c56280aSSorin Basca * See the License for the specific language governing permissions and 15*0c56280aSSorin Basca * limitations under the License. 16*0c56280aSSorin Basca * 17*0c56280aSSorin Basca */ 18*0c56280aSSorin Basca /* Generated By:JJTree: Do not edit this line. ASTExpr.java */ 19*0c56280aSSorin Basca /* JJT: 0.3pre1 */ 20*0c56280aSSorin Basca 21*0c56280aSSorin Basca package Mini; 22*0c56280aSSorin Basca import org.apache.bcel.generic.BranchHandle; 23*0c56280aSSorin Basca import org.apache.bcel.generic.ConstantPoolGen; 24*0c56280aSSorin Basca import org.apache.bcel.generic.GOTO; 25*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPEQ; 26*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPGE; 27*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPGT; 28*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPLE; 29*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPLT; 30*0c56280aSSorin Basca import org.apache.bcel.generic.IF_ICMPNE; 31*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionConstants; 32*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionList; 33*0c56280aSSorin Basca import org.apache.bcel.generic.MethodGen; 34*0c56280aSSorin Basca import org.apache.bcel.generic.PUSH; 35*0c56280aSSorin Basca 36*0c56280aSSorin Basca /** 37*0c56280aSSorin Basca * Represents arithmetic expressions such as `(a + 12 == b) OR c'. 38*0c56280aSSorin Basca * The parse tree is built initially by the parser and modified, i.e. 39*0c56280aSSorin Basca * compacted with `traverse()'. Each (Expr, Term, Factor) node 40*0c56280aSSorin Basca * with kind == -1 is replaced which its successor node, which is 41*0c56280aSSorin Basca * converted to type `Expr' 42*0c56280aSSorin Basca * 43*0c56280aSSorin Basca * A node with kind == -1 denotes the fact that this expression 44*0c56280aSSorin Basca * node has just one child branch and thus may be replaced by this 45*0c56280aSSorin Basca * branch (or leaf) directly without altering the expression 46*0c56280aSSorin Basca * semantics. Term and Factor nodes are used only to build the parse tree 47*0c56280aSSorin Basca * obeying the aritmetical precedences (* stronger than +, etc.) and 48*0c56280aSSorin Basca * are discarded in the first pass. 49*0c56280aSSorin Basca */ 50*0c56280aSSorin Basca public class ASTExpr extends SimpleNode 51*0c56280aSSorin Basca implements MiniParserConstants, MiniParserTreeConstants, org.apache.bcel.Constants { 52*0c56280aSSorin Basca protected int kind=-1; // Single twig to leaf? 53*0c56280aSSorin Basca private int unop=-1; // Special case: Unary operand applied 54*0c56280aSSorin Basca protected ASTExpr[] exprs; // Sub expressions 55*0c56280aSSorin Basca protected Environment env; // Needed in all passes 56*0c56280aSSorin Basca protected int line, column; 57*0c56280aSSorin Basca protected boolean is_simple; // true, if simple expression like `12 + f(a)' 58*0c56280aSSorin Basca 59*0c56280aSSorin Basca /* Not all children shall inherit this, exceptions are ASTIdent and ASTFunAppl, which 60*0c56280aSSorin Basca * look up the type in the corresponding environment entry. 61*0c56280aSSorin Basca */ 62*0c56280aSSorin Basca protected int type = T_UNKNOWN; 63*0c56280aSSorin Basca 64*0c56280aSSorin Basca // Generated methods ASTExpr(int id)65*0c56280aSSorin Basca ASTExpr(int id) { 66*0c56280aSSorin Basca super(id); 67*0c56280aSSorin Basca } 68*0c56280aSSorin Basca ASTExpr(MiniParser p, int id)69*0c56280aSSorin Basca ASTExpr(MiniParser p, int id) { 70*0c56280aSSorin Basca super(p, id); 71*0c56280aSSorin Basca } 72*0c56280aSSorin Basca jjtCreate(MiniParser p, int id)73*0c56280aSSorin Basca public static Node jjtCreate(MiniParser p, int id) { 74*0c56280aSSorin Basca return new ASTExpr(p, id); 75*0c56280aSSorin Basca } 76*0c56280aSSorin Basca ASTExpr(int line, int column, int id)77*0c56280aSSorin Basca ASTExpr(int line, int column, int id) { 78*0c56280aSSorin Basca super(id); 79*0c56280aSSorin Basca this.line = line; 80*0c56280aSSorin Basca this.column = column; 81*0c56280aSSorin Basca } 82*0c56280aSSorin Basca ASTExpr(int line, int column, int kind, int id)83*0c56280aSSorin Basca ASTExpr(int line, int column, int kind, int id) { 84*0c56280aSSorin Basca this(line, column, id); 85*0c56280aSSorin Basca this.kind = kind; 86*0c56280aSSorin Basca } 87*0c56280aSSorin Basca 88*0c56280aSSorin Basca /* Special constructor, called from ASTTerm.traverse() and 89*0c56280aSSorin Basca * ASTFactor.traverse(), when traverse()ing the parse tree replace 90*0c56280aSSorin Basca * themselves with Expr nodes. 91*0c56280aSSorin Basca */ ASTExpr(ASTExpr[] children, int kind, int line, int column)92*0c56280aSSorin Basca ASTExpr(ASTExpr[] children, int kind, int line, int column) { 93*0c56280aSSorin Basca this(line, column, kind, JJTEXPR); 94*0c56280aSSorin Basca exprs = children; 95*0c56280aSSorin Basca } 96*0c56280aSSorin Basca 97*0c56280aSSorin Basca /** 98*0c56280aSSorin Basca * @return name of node, its kind and the number of children. 99*0c56280aSSorin Basca */ 100*0c56280aSSorin Basca @Override toString()101*0c56280aSSorin Basca public String toString() { 102*0c56280aSSorin Basca String op=""; 103*0c56280aSSorin Basca int len = (children != null)? children.length : 0; 104*0c56280aSSorin Basca if(unop != -1) { 105*0c56280aSSorin Basca op = tokenImage[unop]; 106*0c56280aSSorin Basca } else if(kind != -1) { 107*0c56280aSSorin Basca op = tokenImage[kind]; 108*0c56280aSSorin Basca } 109*0c56280aSSorin Basca 110*0c56280aSSorin Basca return jjtNodeName[id] + "(" + op + ")[" + len + "]<" + 111*0c56280aSSorin Basca TYPE_NAMES[type] + "> @" + line + ", " + column; 112*0c56280aSSorin Basca } 113*0c56280aSSorin Basca 114*0c56280aSSorin Basca /** 115*0c56280aSSorin Basca * Overrides SimpleNode.closeNode(). Overridden by some subclasses. 116*0c56280aSSorin Basca * 117*0c56280aSSorin Basca * Called by the parser when the construction of this node is finished. 118*0c56280aSSorin Basca * Casts children Node[] to precise ASTExpr[] type. 119*0c56280aSSorin Basca */ 120*0c56280aSSorin Basca @Override closeNode()121*0c56280aSSorin Basca public void closeNode() { 122*0c56280aSSorin Basca if(children != null) { 123*0c56280aSSorin Basca exprs = new ASTExpr[children.length]; 124*0c56280aSSorin Basca System.arraycopy(children, 0, exprs, 0, children.length); 125*0c56280aSSorin Basca children=null; // Throw away old reference 126*0c56280aSSorin Basca } 127*0c56280aSSorin Basca } 128*0c56280aSSorin Basca 129*0c56280aSSorin Basca /** 130*0c56280aSSorin Basca * First pass 131*0c56280aSSorin Basca * Overridden by subclasses. Traverse the whole parse tree recursively and 132*0c56280aSSorin Basca * drop redundant nodes. 133*0c56280aSSorin Basca */ traverse(Environment env)134*0c56280aSSorin Basca public ASTExpr traverse(Environment env) { 135*0c56280aSSorin Basca this.env = env; 136*0c56280aSSorin Basca 137*0c56280aSSorin Basca if((kind == -1) && (unop == -1)) { 138*0c56280aSSorin Basca return exprs[0].traverse(env); // --> Replaced by successor 139*0c56280aSSorin Basca } else { 140*0c56280aSSorin Basca for(int i=0; i < exprs.length; i++) { 141*0c56280aSSorin Basca exprs[i] = exprs[i].traverse(env); // References may change 142*0c56280aSSorin Basca } 143*0c56280aSSorin Basca 144*0c56280aSSorin Basca return this; 145*0c56280aSSorin Basca } 146*0c56280aSSorin Basca } 147*0c56280aSSorin Basca 148*0c56280aSSorin Basca /** 149*0c56280aSSorin Basca * Second and third pass 150*0c56280aSSorin Basca * @return type of expression 151*0c56280aSSorin Basca * @param expected type 152*0c56280aSSorin Basca */ eval(int expected)153*0c56280aSSorin Basca public int eval(int expected) { 154*0c56280aSSorin Basca int child_type = T_UNKNOWN, t; 155*0c56280aSSorin Basca 156*0c56280aSSorin Basca is_simple = true; 157*0c56280aSSorin Basca 158*0c56280aSSorin Basca // Determine expected node type depending on used operator. 159*0c56280aSSorin Basca if(unop != -1) { 160*0c56280aSSorin Basca if(unop == MINUS) { 161*0c56280aSSorin Basca child_type = type = T_INT; // - 162*0c56280aSSorin Basca } else { 163*0c56280aSSorin Basca child_type = type = T_BOOLEAN; // ! 164*0c56280aSSorin Basca } 165*0c56280aSSorin Basca } 166*0c56280aSSorin Basca else { 167*0c56280aSSorin Basca // Compute expected type 168*0c56280aSSorin Basca if((kind == PLUS) || (kind == MINUS) || (kind == MULT) || 169*0c56280aSSorin Basca (kind == MOD) || (kind == DIV)) { 170*0c56280aSSorin Basca child_type = type = T_INT; 171*0c56280aSSorin Basca } else if((kind == AND) || (kind == OR)) { 172*0c56280aSSorin Basca child_type = type = T_BOOLEAN; 173*0c56280aSSorin Basca } else { // LEQ, GT, etc. 174*0c56280aSSorin Basca child_type = T_INT; 175*0c56280aSSorin Basca type = T_BOOLEAN; 176*0c56280aSSorin Basca } 177*0c56280aSSorin Basca } 178*0c56280aSSorin Basca 179*0c56280aSSorin Basca // Get type of subexpressions 180*0c56280aSSorin Basca for(int i=0; i < exprs.length; i++) { 181*0c56280aSSorin Basca t = exprs[i].eval(child_type); 182*0c56280aSSorin Basca 183*0c56280aSSorin Basca if(t != child_type) { 184*0c56280aSSorin Basca MiniC.addError(exprs[i].getLine(), exprs[i].getColumn(), 185*0c56280aSSorin Basca "Expression has not expected type " + TYPE_NAMES[child_type] + 186*0c56280aSSorin Basca " but " + TYPE_NAMES[t] + "."); 187*0c56280aSSorin Basca } 188*0c56280aSSorin Basca 189*0c56280aSSorin Basca is_simple = is_simple && exprs[i].isSimple(); 190*0c56280aSSorin Basca } 191*0c56280aSSorin Basca 192*0c56280aSSorin Basca return type; 193*0c56280aSSorin Basca } 194*0c56280aSSorin Basca toBool(String i)195*0c56280aSSorin Basca private static String toBool(String i) { 196*0c56280aSSorin Basca return "(" + i + " != 0)"; 197*0c56280aSSorin Basca } 198*0c56280aSSorin Basca toInt(String i)199*0c56280aSSorin Basca private static String toInt(String i) { 200*0c56280aSSorin Basca return "((" + i + ")? 1 : 0)"; 201*0c56280aSSorin Basca } 202*0c56280aSSorin Basca 203*0c56280aSSorin Basca /** 204*0c56280aSSorin Basca * Fourth pass, produce Java code. 205*0c56280aSSorin Basca */ code(StringBuffer buf)206*0c56280aSSorin Basca public void code(StringBuffer buf) { 207*0c56280aSSorin Basca if(unop != -1) { 208*0c56280aSSorin Basca exprs[0].code(buf); 209*0c56280aSSorin Basca String top = ASTFunDecl.pop(); 210*0c56280aSSorin Basca if(unop == MINUS) { 211*0c56280aSSorin Basca ASTFunDecl.push(buf, "-" + top); 212*0c56280aSSorin Basca } else { 213*0c56280aSSorin Basca ASTFunDecl.push(buf, "(" + top + " == 1)? 0 : 1)"); 214*0c56280aSSorin Basca } 215*0c56280aSSorin Basca } 216*0c56280aSSorin Basca else { 217*0c56280aSSorin Basca exprs[0].code(buf); 218*0c56280aSSorin Basca exprs[1].code(buf); 219*0c56280aSSorin Basca String _body_int2 = ASTFunDecl.pop(); 220*0c56280aSSorin Basca String _body_int = ASTFunDecl.pop(); 221*0c56280aSSorin Basca 222*0c56280aSSorin Basca switch(kind) { 223*0c56280aSSorin Basca case PLUS: ASTFunDecl.push(buf, _body_int + " + " + _body_int2); break; 224*0c56280aSSorin Basca case MINUS: ASTFunDecl.push(buf, _body_int + " - " + _body_int2); break; 225*0c56280aSSorin Basca case MULT: ASTFunDecl.push(buf, _body_int + " * " + _body_int2); break; 226*0c56280aSSorin Basca case DIV: ASTFunDecl.push(buf, _body_int + " / " + _body_int2); break; 227*0c56280aSSorin Basca 228*0c56280aSSorin Basca case AND: ASTFunDecl.push(buf, toInt(toBool(_body_int) + " && " + 229*0c56280aSSorin Basca toBool(_body_int2))); break; 230*0c56280aSSorin Basca case OR: ASTFunDecl.push(buf, toInt(toBool(_body_int) + " || " + 231*0c56280aSSorin Basca toBool(_body_int2))); break; 232*0c56280aSSorin Basca 233*0c56280aSSorin Basca case EQ: ASTFunDecl.push(buf, toInt(_body_int + " == " + _body_int2)); 234*0c56280aSSorin Basca break; 235*0c56280aSSorin Basca case LEQ: ASTFunDecl.push(buf, toInt(_body_int + " <= " + _body_int2)); 236*0c56280aSSorin Basca break; 237*0c56280aSSorin Basca case GEQ: ASTFunDecl.push(buf, toInt(_body_int + " >= " + _body_int2)); 238*0c56280aSSorin Basca break; 239*0c56280aSSorin Basca case NEQ: ASTFunDecl.push(buf, toInt(_body_int + " != " + _body_int2)); 240*0c56280aSSorin Basca break; 241*0c56280aSSorin Basca case LT: ASTFunDecl.push(buf, toInt(_body_int + " < " + _body_int2)); 242*0c56280aSSorin Basca break; 243*0c56280aSSorin Basca case GT: ASTFunDecl.push(buf, toInt(_body_int + " > " + _body_int2)); 244*0c56280aSSorin Basca break; 245*0c56280aSSorin Basca 246*0c56280aSSorin Basca default: System.err.println("Ooops"); 247*0c56280aSSorin Basca } 248*0c56280aSSorin Basca } 249*0c56280aSSorin Basca } 250*0c56280aSSorin Basca 251*0c56280aSSorin Basca /** 252*0c56280aSSorin Basca * Fifth pass, produce Java byte code. 253*0c56280aSSorin Basca */ byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp)254*0c56280aSSorin Basca public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) { 255*0c56280aSSorin Basca exprs[0].byte_code(il, method, cp); 256*0c56280aSSorin Basca 257*0c56280aSSorin Basca if(unop != -1) { // Apply unary operand 258*0c56280aSSorin Basca if(unop == MINUS) { 259*0c56280aSSorin Basca il.append(InstructionConstants.INEG); 260*0c56280aSSorin Basca } else { // == NOT 261*0c56280aSSorin Basca il.append(new PUSH(cp, 1)); ASTFunDecl.push(); // Push TRUE 262*0c56280aSSorin Basca il.append(InstructionConstants.IXOR); ASTFunDecl.pop(); 263*0c56280aSSorin Basca } 264*0c56280aSSorin Basca } 265*0c56280aSSorin Basca else { // Apply binary operand 266*0c56280aSSorin Basca BranchHandle bh=null; 267*0c56280aSSorin Basca 268*0c56280aSSorin Basca exprs[1].byte_code(il, method, cp); 269*0c56280aSSorin Basca 270*0c56280aSSorin Basca switch(kind) { 271*0c56280aSSorin Basca case PLUS: il.append(InstructionConstants.IADD); ASTFunDecl.pop(); break; 272*0c56280aSSorin Basca case MINUS: il.append(InstructionConstants.ISUB); ASTFunDecl.pop(); break; 273*0c56280aSSorin Basca case MULT: il.append(InstructionConstants.IMUL); ASTFunDecl.pop(); break; 274*0c56280aSSorin Basca case DIV: il.append(InstructionConstants.IDIV); ASTFunDecl.pop(); break; 275*0c56280aSSorin Basca case AND: il.append(InstructionConstants.IAND); ASTFunDecl.pop(); break; 276*0c56280aSSorin Basca case OR: il.append(InstructionConstants.IOR); ASTFunDecl.pop(); break; 277*0c56280aSSorin Basca 278*0c56280aSSorin Basca /* Use negated operands */ 279*0c56280aSSorin Basca case EQ: bh = il.append(new IF_ICMPNE(null)); ASTFunDecl.pop(2); break; 280*0c56280aSSorin Basca case LEQ: bh = il.append(new IF_ICMPGT(null)); ASTFunDecl.pop(2); break; 281*0c56280aSSorin Basca case GEQ: bh = il.append(new IF_ICMPLT(null)); ASTFunDecl.pop(2); break; 282*0c56280aSSorin Basca case NEQ: bh = il.append(new IF_ICMPEQ(null)); ASTFunDecl.pop(2); break; 283*0c56280aSSorin Basca case LT: bh = il.append(new IF_ICMPGE(null)); ASTFunDecl.pop(2); break; 284*0c56280aSSorin Basca case GT: bh = il.append(new IF_ICMPLE(null)); ASTFunDecl.pop(2); break; 285*0c56280aSSorin Basca default: System.err.println("Ooops"); 286*0c56280aSSorin Basca } 287*0c56280aSSorin Basca 288*0c56280aSSorin Basca switch(kind) { 289*0c56280aSSorin Basca case EQ: case LEQ: case GEQ: case NEQ: case LT: case GT: 290*0c56280aSSorin Basca BranchHandle g; 291*0c56280aSSorin Basca 292*0c56280aSSorin Basca il.append(new PUSH(cp, 1)); 293*0c56280aSSorin Basca g = il.append(new GOTO(null)); 294*0c56280aSSorin Basca bh.setTarget(il.append(new PUSH(cp, 0))); 295*0c56280aSSorin Basca g.setTarget(il.append(InstructionConstants.NOP)); // May be optimized away later 296*0c56280aSSorin Basca ASTFunDecl.push(); 297*0c56280aSSorin Basca break; 298*0c56280aSSorin Basca 299*0c56280aSSorin Basca default: break; 300*0c56280aSSorin Basca } 301*0c56280aSSorin Basca } 302*0c56280aSSorin Basca } 303*0c56280aSSorin Basca isSimple()304*0c56280aSSorin Basca public boolean isSimple() { return is_simple; } setType(int type)305*0c56280aSSorin Basca public void setType(int type) { this.type = type; } getType()306*0c56280aSSorin Basca public int getType() { return type; } setKind(int kind)307*0c56280aSSorin Basca public void setKind(int kind) { this.kind = kind; } getKind()308*0c56280aSSorin Basca public int getKind() { return kind; } setUnOp(int unop)309*0c56280aSSorin Basca public void setUnOp(int unop) { this.unop = unop; } getUnOp()310*0c56280aSSorin Basca public int getUnOp() { return unop; } setLine(int line)311*0c56280aSSorin Basca public void setLine(int line) { this.line = line; } getLine()312*0c56280aSSorin Basca public int getLine() { return line; } setColumn(int column)313*0c56280aSSorin Basca public void setColumn(int column) { this.column = column; } getColumn()314*0c56280aSSorin Basca public int getColumn() { return column; } setPosition(int line, int column)315*0c56280aSSorin Basca public void setPosition(int line, int column) { 316*0c56280aSSorin Basca this.line = line; 317*0c56280aSSorin Basca this.column = column; 318*0c56280aSSorin Basca } 319*0c56280aSSorin Basca 320*0c56280aSSorin Basca @Override dump(String prefix)321*0c56280aSSorin Basca public void dump(String prefix) { 322*0c56280aSSorin Basca System.out.println(toString(prefix)); 323*0c56280aSSorin Basca 324*0c56280aSSorin Basca if(exprs != null) { 325*0c56280aSSorin Basca for(int i=0; i < exprs.length; ++i) { 326*0c56280aSSorin Basca exprs[i].dump(prefix + " "); 327*0c56280aSSorin Basca } 328*0c56280aSSorin Basca } 329*0c56280aSSorin Basca } 330*0c56280aSSorin Basca } 331