xref: /aosp_15_r20/external/apache-commons-bcel/src/examples/Mini/ASTExpr.java (revision 0c56280ab0842982c46a149f7b9eaa497e31e292)
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