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