| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| /* Generated By:JJTree: Do not edit this line. ASTLetExpr.java */ |
| /* JJT: 0.3pre1 */ |
| |
| package Mini; |
| import org.apache.bcel.generic.BasicType; |
| import org.apache.bcel.generic.ConstantPoolGen; |
| import org.apache.bcel.generic.ISTORE; |
| import org.apache.bcel.generic.InstructionHandle; |
| import org.apache.bcel.generic.InstructionList; |
| import org.apache.bcel.generic.LocalVariableGen; |
| import org.apache.bcel.generic.MethodGen; |
| import org.apache.bcel.generic.Type; |
| |
| /** |
| * |
| * @version $Id$ |
| */ |
| public class ASTLetExpr extends ASTExpr implements org.apache.bcel.Constants { |
| private ASTIdent[] idents; |
| private ASTExpr[] exprs; |
| private ASTExpr body; |
| |
| // Generated methods |
| ASTLetExpr(int id) { |
| super(id); |
| } |
| |
| ASTLetExpr(MiniParser p, int id) { |
| super(p, id); |
| } |
| |
| public static Node jjtCreate(MiniParser p, int id) { |
| return new ASTLetExpr(p, id); |
| } |
| |
| |
| /** |
| * Overrides ASTExpr.closeNode() |
| * Cast children nodes to appropiate types. |
| */ |
| @Override |
| public void closeNode() { |
| int i, len_2 = children.length / 2; /* length must be a multiple of |
| * two (ident = expr) + 1 (body expr) */ |
| idents = new ASTIdent[len_2]; |
| exprs = new ASTExpr[len_2]; |
| |
| // At least one assignment is enforced by the grammar |
| for(i=0; i < len_2; i++) { |
| idents[i] = (ASTIdent)children[i * 2]; |
| exprs[i] = (ASTExpr)children[i * 2 + 1]; |
| } |
| |
| body = (ASTExpr)children[children.length - 1]; // Last expr is the body |
| children=null; // Throw away old reference |
| } |
| |
| /** |
| * Overrides ASTExpr.traverse() |
| */ |
| @Override |
| public ASTExpr traverse(Environment env) { |
| this.env = env; |
| |
| // Traverse RHS exprs first, so no references to LHS vars are allowed |
| for(int i=0; i < exprs.length; i++) { |
| exprs[i] = exprs[i].traverse((Environment)env.clone()); |
| } |
| |
| // Put argument names into hash table aka. environment |
| for(int i=0; i < idents.length; i++) { |
| ASTIdent id = idents[i]; |
| String name = id.getName(); |
| EnvEntry entry = env.get(name); |
| |
| if(entry != null) { |
| MiniC.addError(id.getLine(), id.getColumn(), |
| "Redeclaration of " + entry + "."); |
| } else { |
| env.put(new Variable(id)); |
| } |
| } |
| |
| body = body.traverse(env); |
| |
| return this; |
| } |
| |
| /** |
| * Second pass |
| * Overrides AstExpr.eval() |
| * @return type of expression |
| * @param expected type |
| */ |
| @Override |
| public int eval(int expected) { |
| //is_simple = true; |
| |
| for(int i=0; i < idents.length; i++) { |
| int t = exprs[i].eval(T_UNKNOWN); |
| |
| idents[i].setType(t); |
| // is_simple = is_simple && exprs[i].isSimple(); |
| } |
| |
| return type = body.eval(expected); |
| } |
| |
| /** |
| * Fifth pass, produce Java code. |
| */ |
| @Override |
| public void code(StringBuffer buf) { |
| for(int i = 0; i < idents.length; i++) { |
| String ident = idents[i].getName(); |
| int t = idents[i].getType(); // can only be int |
| |
| /* Idents have to be declared at start of function for later use. |
| * Each name is unique, so there shouldn't be a problem in application. |
| */ |
| exprs[i].code(buf); |
| |
| buf.append(" " + TYPE_NAMES[t] + " " + ident + " = " + |
| ASTFunDecl.pop() + ";\n"); |
| } |
| |
| body.code(buf); |
| } |
| |
| /** |
| * Fifth pass, produce Java byte code. |
| */ |
| @Override |
| public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) { |
| int size = idents.length; |
| LocalVariableGen[] l = new LocalVariableGen[size]; |
| |
| for(int i=0; i < size; i++) { |
| String ident = idents[i].getName(); |
| Variable entry = (Variable)env.get(ident); |
| Type t = BasicType.getType((byte)idents[i].getType()); |
| LocalVariableGen lg = method.addLocalVariable(ident, t, null, null); |
| int slot = lg.getIndex(); |
| |
| entry.setLocalVariable(lg); |
| InstructionHandle start = il.getEnd(); |
| exprs[i].byte_code(il, method, cp); |
| start = (start == null)? il.getStart() : start.getNext(); |
| lg.setStart(start); |
| il.append(new ISTORE(slot)); ASTFunDecl.pop(); |
| l[i] = lg; |
| } |
| |
| body.byte_code(il, method, cp); |
| InstructionHandle end = il.getEnd(); |
| for(int i=0; i < size; i++) { |
| l[i].setEnd(end); |
| } |
| } |
| |
| @Override |
| public void dump(String prefix) { |
| System.out.println(toString(prefix)); |
| |
| for(int i=0; i < idents.length; i++) { |
| idents[i].dump(prefix + " "); |
| exprs[i].dump(prefix + " "); |
| } |
| |
| body.dump(prefix + " "); |
| } |
| |
| } |