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