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. ASTProgram.java */ 19*0c56280aSSorin Basca /* JJT: 0.3pre1 */ 20*0c56280aSSorin Basca 21*0c56280aSSorin Basca package Mini; 22*0c56280aSSorin Basca import java.io.PrintWriter; 23*0c56280aSSorin Basca 24*0c56280aSSorin Basca import org.apache.bcel.classfile.Field; 25*0c56280aSSorin Basca import org.apache.bcel.generic.ALOAD; 26*0c56280aSSorin Basca import org.apache.bcel.generic.ClassGen; 27*0c56280aSSorin Basca import org.apache.bcel.generic.ConstantPoolGen; 28*0c56280aSSorin Basca import org.apache.bcel.generic.GETSTATIC; 29*0c56280aSSorin Basca import org.apache.bcel.generic.ILOAD; 30*0c56280aSSorin Basca import org.apache.bcel.generic.INVOKESPECIAL; 31*0c56280aSSorin Basca import org.apache.bcel.generic.INVOKESTATIC; 32*0c56280aSSorin Basca import org.apache.bcel.generic.INVOKEVIRTUAL; 33*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionConstants; 34*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionList; 35*0c56280aSSorin Basca import org.apache.bcel.generic.MethodGen; 36*0c56280aSSorin Basca import org.apache.bcel.generic.NEW; 37*0c56280aSSorin Basca import org.apache.bcel.generic.PUSH; 38*0c56280aSSorin Basca import org.apache.bcel.generic.PUTSTATIC; 39*0c56280aSSorin Basca import org.apache.bcel.generic.RETURN; 40*0c56280aSSorin Basca import org.apache.bcel.generic.Type; 41*0c56280aSSorin Basca 42*0c56280aSSorin Basca /** 43*0c56280aSSorin Basca * Root node of everything, direct children are nodes of type FunDecl 44*0c56280aSSorin Basca * 45*0c56280aSSorin Basca * @version $Id$ 46*0c56280aSSorin Basca */ 47*0c56280aSSorin Basca public class ASTProgram extends SimpleNode 48*0c56280aSSorin Basca implements MiniParserConstants, MiniParserTreeConstants, org.apache.bcel.Constants { 49*0c56280aSSorin Basca private ASTFunDecl[] fun_decls; // Children: Function declarations 50*0c56280aSSorin Basca private Environment env; // Environment contains variables and functions 51*0c56280aSSorin Basca ASTProgram(int id)52*0c56280aSSorin Basca ASTProgram(int id) { 53*0c56280aSSorin Basca super(id); 54*0c56280aSSorin Basca 55*0c56280aSSorin Basca env = new Environment(); 56*0c56280aSSorin Basca 57*0c56280aSSorin Basca /* Add predefined functions WRITE/READ. 58*0c56280aSSorin Basca * WRITE has one arg of type T_INT, both return T_INT. 59*0c56280aSSorin Basca */ 60*0c56280aSSorin Basca ASTIdent ident = new ASTIdent("WRITE", T_INT, -1, -1); 61*0c56280aSSorin Basca ASTIdent[] args = { new ASTIdent("", T_INT, -1, -1) }; 62*0c56280aSSorin Basca Function fun = new Function(ident, args, true); 63*0c56280aSSorin Basca env.put(fun); 64*0c56280aSSorin Basca 65*0c56280aSSorin Basca ident = new ASTIdent("READ", T_INT, -1, -1); 66*0c56280aSSorin Basca args = new ASTIdent[0]; 67*0c56280aSSorin Basca fun = new Function(ident, args, true); 68*0c56280aSSorin Basca env.put(fun); 69*0c56280aSSorin Basca 70*0c56280aSSorin Basca /* Add predefined idents TRUE/FALSE of type T_BOOLEAN 71*0c56280aSSorin Basca */ 72*0c56280aSSorin Basca ident = new ASTIdent("TRUE", T_BOOLEAN, -1, -1); 73*0c56280aSSorin Basca Variable var = new Variable(ident, true); 74*0c56280aSSorin Basca env.put(var); 75*0c56280aSSorin Basca 76*0c56280aSSorin Basca ident = new ASTIdent("FALSE", T_BOOLEAN, -1, -1); 77*0c56280aSSorin Basca var = new Variable(ident, true); 78*0c56280aSSorin Basca env.put(var); 79*0c56280aSSorin Basca } 80*0c56280aSSorin Basca ASTProgram(MiniParser p, int id)81*0c56280aSSorin Basca ASTProgram(MiniParser p, int id) { 82*0c56280aSSorin Basca super(p, id); 83*0c56280aSSorin Basca } 84*0c56280aSSorin Basca jjtCreate(MiniParser p, int id)85*0c56280aSSorin Basca public static Node jjtCreate(MiniParser p, int id) { 86*0c56280aSSorin Basca return new ASTProgram(p, id); 87*0c56280aSSorin Basca } 88*0c56280aSSorin Basca 89*0c56280aSSorin Basca /** 90*0c56280aSSorin Basca * Overrides SimpleNode.closeNode(). 91*0c56280aSSorin Basca * Cast children to appropiate type. 92*0c56280aSSorin Basca */ 93*0c56280aSSorin Basca @Override closeNode()94*0c56280aSSorin Basca public void closeNode() { 95*0c56280aSSorin Basca if(children != null) { // Non-empty program ? 96*0c56280aSSorin Basca fun_decls = new ASTFunDecl[children.length]; 97*0c56280aSSorin Basca System.arraycopy(children, 0, fun_decls, 0, children.length); 98*0c56280aSSorin Basca children=null; // Throw away old reference 99*0c56280aSSorin Basca } 100*0c56280aSSorin Basca } 101*0c56280aSSorin Basca 102*0c56280aSSorin Basca /** 103*0c56280aSSorin Basca * First pass of parse tree. 104*0c56280aSSorin Basca * 105*0c56280aSSorin Basca * Put everything into the environment, which is copied appropiately to each 106*0c56280aSSorin Basca * recursion level, i.e. each FunDecl gets its own copy that it can further 107*0c56280aSSorin Basca * manipulate. 108*0c56280aSSorin Basca * 109*0c56280aSSorin Basca * Checks for name clashes of function declarations. 110*0c56280aSSorin Basca */ traverse()111*0c56280aSSorin Basca public ASTProgram traverse() { 112*0c56280aSSorin Basca ASTFunDecl f; 113*0c56280aSSorin Basca ASTIdent name; 114*0c56280aSSorin Basca String fname; 115*0c56280aSSorin Basca EnvEntry fun; 116*0c56280aSSorin Basca Function main=null; 117*0c56280aSSorin Basca 118*0c56280aSSorin Basca if(fun_decls != null) { 119*0c56280aSSorin Basca // Put function names into hash table aka. environment 120*0c56280aSSorin Basca for(int i=0; i < fun_decls.length; i++) { 121*0c56280aSSorin Basca f = fun_decls[i]; 122*0c56280aSSorin Basca name = f.getName(); 123*0c56280aSSorin Basca fname = name.getName(); 124*0c56280aSSorin Basca fun = env.get(fname); // Lookup in env 125*0c56280aSSorin Basca 126*0c56280aSSorin Basca if(fun != null) { 127*0c56280aSSorin Basca MiniC.addError(f.getLine(), f.getColumn(), 128*0c56280aSSorin Basca "Redeclaration of " + fun + "."); 129*0c56280aSSorin Basca } else { 130*0c56280aSSorin Basca env.put(new Function(name, null)); // `args' will be set by FunDecl.traverse() 131*0c56280aSSorin Basca } 132*0c56280aSSorin Basca 133*0c56280aSSorin Basca 134*0c56280aSSorin Basca } 135*0c56280aSSorin Basca 136*0c56280aSSorin Basca // Go for it 137*0c56280aSSorin Basca for(int i=0; i < fun_decls.length; i++) { 138*0c56280aSSorin Basca fun_decls[i] = fun_decls[i].traverse((Environment)env.clone()); 139*0c56280aSSorin Basca 140*0c56280aSSorin Basca // Look for `main' routine 141*0c56280aSSorin Basca fname = fun_decls[i].getName().getName(); 142*0c56280aSSorin Basca if(fname.equals("main")) { 143*0c56280aSSorin Basca main = (Function)env.get(fname); 144*0c56280aSSorin Basca } 145*0c56280aSSorin Basca } 146*0c56280aSSorin Basca 147*0c56280aSSorin Basca if(main == null) { 148*0c56280aSSorin Basca MiniC.addError(0, 0, "You didn't declare a `main' function."); 149*0c56280aSSorin Basca } else if(main.getNoArgs() != 0) { 150*0c56280aSSorin Basca MiniC.addError(main.getLine(), main.getColumn(), 151*0c56280aSSorin Basca "Main function has too many arguments declared."); 152*0c56280aSSorin Basca } 153*0c56280aSSorin Basca } 154*0c56280aSSorin Basca 155*0c56280aSSorin Basca return this; 156*0c56280aSSorin Basca } 157*0c56280aSSorin Basca 158*0c56280aSSorin Basca /** 159*0c56280aSSorin Basca * Second pass, determine type of each node, if possible. 160*0c56280aSSorin Basca */ eval(int pass)161*0c56280aSSorin Basca public void eval(int pass) { 162*0c56280aSSorin Basca 163*0c56280aSSorin Basca for(int i=0; i < fun_decls.length; i++) { 164*0c56280aSSorin Basca fun_decls[i].eval(pass); 165*0c56280aSSorin Basca 166*0c56280aSSorin Basca if(pass == 3) { // Final check for unresolved types 167*0c56280aSSorin Basca ASTIdent name = fun_decls[i].getName(); 168*0c56280aSSorin Basca 169*0c56280aSSorin Basca if(name.getType() == T_UNKNOWN) { 170*0c56280aSSorin Basca MiniC.addError(name.getColumn(), name.getLine(), 171*0c56280aSSorin Basca "Type of function " + name.getName() + 172*0c56280aSSorin Basca " can not be determined (infinite recursion?)."); 173*0c56280aSSorin Basca } 174*0c56280aSSorin Basca } 175*0c56280aSSorin Basca } 176*0c56280aSSorin Basca } 177*0c56280aSSorin Basca 178*0c56280aSSorin Basca /** 179*0c56280aSSorin Basca * Fifth pass, produce Java code. 180*0c56280aSSorin Basca */ code(PrintWriter out, String name)181*0c56280aSSorin Basca public void code(PrintWriter out, String name) { 182*0c56280aSSorin Basca out.println("import java.io.BufferedReader;"); 183*0c56280aSSorin Basca out.println("import java.io.InputStreamReader;"); 184*0c56280aSSorin Basca out.println("import java.io.IOException;\n"); 185*0c56280aSSorin Basca 186*0c56280aSSorin Basca out.println("public final class " + name + " {"); 187*0c56280aSSorin Basca out.println(" private static BufferedReader _in = new BufferedReader" + 188*0c56280aSSorin Basca "(new InputStreamReader(System.in));\n"); 189*0c56280aSSorin Basca 190*0c56280aSSorin Basca out.println(" private static int _readInt() throws IOException {\n" + 191*0c56280aSSorin Basca " System.out.print(\"Please enter a number> \");\n" + 192*0c56280aSSorin Basca " return Integer.parseInt(_in.readLine());\n }\n"); 193*0c56280aSSorin Basca 194*0c56280aSSorin Basca out.println(" private static int _writeInt(int n) {\n" + 195*0c56280aSSorin Basca " System.out.println(\"Result: \" + n);\n return 0;\n }\n"); 196*0c56280aSSorin Basca 197*0c56280aSSorin Basca for(int i=0; i < fun_decls.length; i++) { 198*0c56280aSSorin Basca fun_decls[i].code(out); 199*0c56280aSSorin Basca } 200*0c56280aSSorin Basca 201*0c56280aSSorin Basca out.println("}"); 202*0c56280aSSorin Basca } 203*0c56280aSSorin Basca 204*0c56280aSSorin Basca /** 205*0c56280aSSorin Basca * Fifth pass, produce Java byte code. 206*0c56280aSSorin Basca */ byte_code(ClassGen class_gen, ConstantPoolGen cp)207*0c56280aSSorin Basca public void byte_code(ClassGen class_gen, ConstantPoolGen cp) { 208*0c56280aSSorin Basca /* private static BufferedReader _in; 209*0c56280aSSorin Basca */ 210*0c56280aSSorin Basca class_gen.addField(new Field(ACC_PRIVATE | ACC_STATIC, 211*0c56280aSSorin Basca cp.addUtf8("_in"), 212*0c56280aSSorin Basca cp.addUtf8("Ljava/io/BufferedReader;"), 213*0c56280aSSorin Basca null, cp.getConstantPool())); 214*0c56280aSSorin Basca 215*0c56280aSSorin Basca MethodGen method; 216*0c56280aSSorin Basca InstructionList il = new InstructionList(); 217*0c56280aSSorin Basca String class_name = class_gen.getClassName(); 218*0c56280aSSorin Basca 219*0c56280aSSorin Basca /* Often used constant pool entries 220*0c56280aSSorin Basca */ 221*0c56280aSSorin Basca int _in = cp.addFieldref(class_name, "_in", "Ljava/io/BufferedReader;"); 222*0c56280aSSorin Basca 223*0c56280aSSorin Basca int out = cp.addFieldref("java.lang.System", "out", 224*0c56280aSSorin Basca "Ljava/io/PrintStream;"); 225*0c56280aSSorin Basca 226*0c56280aSSorin Basca il.append(new GETSTATIC(out)); 227*0c56280aSSorin Basca il.append(new PUSH(cp, "Please enter a number> ")); 228*0c56280aSSorin Basca il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.PrintStream", 229*0c56280aSSorin Basca "print", 230*0c56280aSSorin Basca "(Ljava/lang/String;)V"))); 231*0c56280aSSorin Basca il.append(new GETSTATIC(_in)); 232*0c56280aSSorin Basca il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.BufferedReader", 233*0c56280aSSorin Basca "readLine", 234*0c56280aSSorin Basca "()Ljava/lang/String;"))); 235*0c56280aSSorin Basca il.append(new INVOKESTATIC(cp.addMethodref("java.lang.Integer", 236*0c56280aSSorin Basca "parseInt", 237*0c56280aSSorin Basca "(Ljava/lang/String;)I"))); 238*0c56280aSSorin Basca il.append(InstructionConstants.IRETURN); 239*0c56280aSSorin Basca 240*0c56280aSSorin Basca /* private static int _readInt() throws IOException 241*0c56280aSSorin Basca */ 242*0c56280aSSorin Basca method = new MethodGen(ACC_STATIC | ACC_PRIVATE | ACC_FINAL, 243*0c56280aSSorin Basca Type.INT, Type.NO_ARGS, null, 244*0c56280aSSorin Basca "_readInt", class_name, il, cp); 245*0c56280aSSorin Basca 246*0c56280aSSorin Basca method.addException("java.io.IOException"); 247*0c56280aSSorin Basca 248*0c56280aSSorin Basca method.setMaxStack(2); 249*0c56280aSSorin Basca class_gen.addMethod(method.getMethod()); 250*0c56280aSSorin Basca 251*0c56280aSSorin Basca /* private static int _writeInt(int i) throws IOException 252*0c56280aSSorin Basca */ 253*0c56280aSSorin Basca Type[] args = { Type.INT }; 254*0c56280aSSorin Basca String[] argv = { "i" } ; 255*0c56280aSSorin Basca il = new InstructionList(); 256*0c56280aSSorin Basca il.append(new GETSTATIC(out)); 257*0c56280aSSorin Basca il.append(new NEW(cp.addClass("java.lang.StringBuffer"))); 258*0c56280aSSorin Basca il.append(InstructionConstants.DUP); 259*0c56280aSSorin Basca il.append(new PUSH(cp, "Result: ")); 260*0c56280aSSorin Basca il.append(new INVOKESPECIAL(cp.addMethodref("java.lang.StringBuffer", 261*0c56280aSSorin Basca "<init>", 262*0c56280aSSorin Basca "(Ljava/lang/String;)V"))); 263*0c56280aSSorin Basca 264*0c56280aSSorin Basca il.append(new ILOAD(0)); 265*0c56280aSSorin Basca il.append(new INVOKEVIRTUAL(cp.addMethodref("java.lang.StringBuffer", 266*0c56280aSSorin Basca "append", 267*0c56280aSSorin Basca "(I)Ljava/lang/StringBuffer;"))); 268*0c56280aSSorin Basca 269*0c56280aSSorin Basca il.append(new INVOKEVIRTUAL(cp.addMethodref("java.lang.StringBuffer", 270*0c56280aSSorin Basca "toString", 271*0c56280aSSorin Basca "()Ljava/lang/String;"))); 272*0c56280aSSorin Basca 273*0c56280aSSorin Basca il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.PrintStream", 274*0c56280aSSorin Basca "println", 275*0c56280aSSorin Basca "(Ljava/lang/String;)V"))); 276*0c56280aSSorin Basca il.append(new PUSH(cp, 0)); 277*0c56280aSSorin Basca il.append(InstructionConstants.IRETURN); // Reuse objects, if possible 278*0c56280aSSorin Basca 279*0c56280aSSorin Basca method = new MethodGen(ACC_STATIC | ACC_PRIVATE | ACC_FINAL, 280*0c56280aSSorin Basca Type.INT, args, argv, 281*0c56280aSSorin Basca "_writeInt", class_name, il, cp); 282*0c56280aSSorin Basca 283*0c56280aSSorin Basca method.setMaxStack(4); 284*0c56280aSSorin Basca class_gen.addMethod(method.getMethod()); 285*0c56280aSSorin Basca 286*0c56280aSSorin Basca /* public <init> -- constructor 287*0c56280aSSorin Basca */ 288*0c56280aSSorin Basca il.dispose(); // Dispose instruction handles for better memory utilization 289*0c56280aSSorin Basca 290*0c56280aSSorin Basca il = new InstructionList(); 291*0c56280aSSorin Basca il.append(new ALOAD(0)); // Push `this' 292*0c56280aSSorin Basca il.append(new INVOKESPECIAL(cp.addMethodref("java.lang.Object", 293*0c56280aSSorin Basca "<init>", "()V"))); 294*0c56280aSSorin Basca il.append(new RETURN()); 295*0c56280aSSorin Basca 296*0c56280aSSorin Basca method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, null, 297*0c56280aSSorin Basca "<init>", class_name, il, cp); 298*0c56280aSSorin Basca 299*0c56280aSSorin Basca method.setMaxStack(1); 300*0c56280aSSorin Basca class_gen.addMethod(method.getMethod()); 301*0c56280aSSorin Basca 302*0c56280aSSorin Basca /* class initializer 303*0c56280aSSorin Basca */ 304*0c56280aSSorin Basca il.dispose(); // Dispose instruction handles for better memory utilization 305*0c56280aSSorin Basca il = new InstructionList(); 306*0c56280aSSorin Basca il.append(new NEW(cp.addClass("java.io.BufferedReader"))); 307*0c56280aSSorin Basca il.append(InstructionConstants.DUP); 308*0c56280aSSorin Basca il.append(new NEW(cp.addClass("java.io.InputStreamReader"))); 309*0c56280aSSorin Basca il.append(InstructionConstants.DUP); 310*0c56280aSSorin Basca il.append(new GETSTATIC(cp.addFieldref("java.lang.System", "in", 311*0c56280aSSorin Basca "Ljava/io/InputStream;"))); 312*0c56280aSSorin Basca il.append(new INVOKESPECIAL(cp.addMethodref("java.io.InputStreamReader", 313*0c56280aSSorin Basca "<init>", "(Ljava/io/InputStream;)V"))); 314*0c56280aSSorin Basca il.append(new INVOKESPECIAL(cp.addMethodref("java.io.BufferedReader", 315*0c56280aSSorin Basca "<init>", "(Ljava/io/Reader;)V"))); 316*0c56280aSSorin Basca il.append(new PUTSTATIC(_in)); 317*0c56280aSSorin Basca il.append(InstructionConstants.RETURN); // Reuse instruction constants 318*0c56280aSSorin Basca 319*0c56280aSSorin Basca method = new MethodGen(ACC_STATIC, Type.VOID, Type.NO_ARGS, null, 320*0c56280aSSorin Basca "<clinit>", class_name, il, cp); 321*0c56280aSSorin Basca 322*0c56280aSSorin Basca method.setMaxStack(5); 323*0c56280aSSorin Basca class_gen.addMethod(method.getMethod()); 324*0c56280aSSorin Basca 325*0c56280aSSorin Basca for(int i=0; i < fun_decls.length; i++) { 326*0c56280aSSorin Basca fun_decls[i].byte_code(class_gen, cp); 327*0c56280aSSorin Basca } 328*0c56280aSSorin Basca } 329*0c56280aSSorin Basca 330*0c56280aSSorin Basca @Override dump(String prefix)331*0c56280aSSorin Basca public void dump(String prefix) { 332*0c56280aSSorin Basca System.out.println(toString(prefix)); 333*0c56280aSSorin Basca 334*0c56280aSSorin Basca for(int i = 0; i < fun_decls.length; ++i) { 335*0c56280aSSorin Basca fun_decls[i].dump(prefix + " "); 336*0c56280aSSorin Basca } 337*0c56280aSSorin Basca } 338*0c56280aSSorin Basca } 339