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. ASTLetExpr.java */ 19 /* JJT: 0.3pre1 */ 20 21 package Mini; 22 import org.apache.bcel.generic.BasicType; 23 import org.apache.bcel.generic.ConstantPoolGen; 24 import org.apache.bcel.generic.ISTORE; 25 import org.apache.bcel.generic.InstructionHandle; 26 import org.apache.bcel.generic.InstructionList; 27 import org.apache.bcel.generic.LocalVariableGen; 28 import org.apache.bcel.generic.MethodGen; 29 import org.apache.bcel.generic.Type; 30 31 /** 32 * 33 * @version $Id$ 34 */ 35 public class ASTLetExpr extends ASTExpr implements org.apache.bcel.Constants { 36 private ASTIdent[] idents; 37 private ASTExpr[] exprs; 38 private ASTExpr body; 39 40 // Generated methods 41 ASTLetExpr(int id) { 42 super(id); 43 } 44 45 ASTLetExpr(MiniParser p, int id) { 46 super(p, id); 47 } 48 49 public static Node jjtCreate(MiniParser p, int id) { 50 return new ASTLetExpr(p, id); 51 } 52 53 54 /** 55 * Overrides ASTExpr.closeNode() 56 * Cast children nodes to appropiate types. 57 */ 58 @Override 59 public void closeNode() { 60 int i, len_2 = children.length / 2; /* length must be a multiple of 61 * two (ident = expr) + 1 (body expr) */ 62 idents = new ASTIdent[len_2]; 63 exprs = new ASTExpr[len_2]; 64 65 // At least one assignment is enforced by the grammar 66 for(i=0; i < len_2; i++) { 67 idents[i] = (ASTIdent)children[i * 2]; 68 exprs[i] = (ASTExpr)children[i * 2 + 1]; 69 } 70 71 body = (ASTExpr)children[children.length - 1]; // Last expr is the body 72 children=null; // Throw away old reference 73 } 74 75 /** 76 * Overrides ASTExpr.traverse() 77 */ 78 @Override 79 public ASTExpr traverse(Environment env) { 80 this.env = env; 81 82 // Traverse RHS exprs first, so no references to LHS vars are allowed 83 for(int i=0; i < exprs.length; i++) { 84 exprs[i] = exprs[i].traverse((Environment)env.clone()); 85 } 86 87 // Put argument names into hash table aka. environment 88 for(int i=0; i < idents.length; i++) { 89 ASTIdent id = idents[i]; 90 String name = id.getName(); 91 EnvEntry entry = env.get(name); 92 93 if(entry != null) { 94 MiniC.addError(id.getLine(), id.getColumn(), 95 "Redeclaration of " + entry + "."); 96 } else { 97 env.put(new Variable(id)); 98 } 99 } 100 101 body = body.traverse(env); 102 103 return this; 104 } 105 106 /** 107 * Second pass 108 * Overrides AstExpr.eval() 109 * @return type of expression 110 * @param expected type 111 */ 112 @Override 113 public int eval(int expected) { 114 //is_simple = true; 115 116 for(int i=0; i < idents.length; i++) { 117 int t = exprs[i].eval(T_UNKNOWN); 118 119 idents[i].setType(t); 120 // is_simple = is_simple && exprs[i].isSimple(); 121 } 122 123 return type = body.eval(expected); 124 } 125 126 /** 127 * Fifth pass, produce Java code. 128 */ 129 @Override 130 public void code(StringBuffer buf) { 131 for(int i = 0; i < idents.length; i++) { 132 String ident = idents[i].getName(); 133 int t = idents[i].getType(); // can only be int 134 135 /* Idents have to be declared at start of function for later use. 136 * Each name is unique, so there shouldn't be a problem in application. 137 */ 138 exprs[i].code(buf); 139 140 buf.append(" " + TYPE_NAMES[t] + " " + ident + " = " + 141 ASTFunDecl.pop() + ";\n"); 142 } 143 144 body.code(buf); 145 } 146 147 /** 148 * Fifth pass, produce Java byte code. 149 */ 150 @Override 151 public void byte_code(InstructionList il, MethodGen method, ConstantPoolGen cp) { 152 int size = idents.length; 153 LocalVariableGen[] l = new LocalVariableGen[size]; 154 155 for(int i=0; i < size; i++) { 156 String ident = idents[i].getName(); 157 Variable entry = (Variable)env.get(ident); 158 Type t = BasicType.getType((byte)idents[i].getType()); 159 LocalVariableGen lg = method.addLocalVariable(ident, t, null, null); 160 int slot = lg.getIndex(); 161 162 entry.setLocalVariable(lg); 163 InstructionHandle start = il.getEnd(); 164 exprs[i].byte_code(il, method, cp); 165 start = (start == null)? il.getStart() : start.getNext(); 166 lg.setStart(start); 167 il.append(new ISTORE(slot)); ASTFunDecl.pop(); 168 l[i] = lg; 169 } 170 171 body.byte_code(il, method, cp); 172 InstructionHandle end = il.getEnd(); 173 for(int i=0; i < size; i++) { 174 l[i].setEnd(end); 175 } 176 } 177 178 @Override 179 public void dump(String prefix) { 180 System.out.println(toString(prefix)); 181 182 for(int i=0; i < idents.length; i++) { 183 idents[i].dump(prefix + " "); 184 exprs[i].dump(prefix + " "); 185 } 186 187 body.dump(prefix + " "); 188 } 189 190 } 191