/* Copyright (c) 2000 The Regents of the University of California. All rights reserved. Permission to use, copy, modify, and distribute this software for any purpose, without fee, and without written agreement is hereby granted, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ // This is a project skeleton file import java.io.PrintStream; import java.util.Vector; import java.util.Enumeration; /** This class is used for representing the inheritance tree during code generation. You will need to fill in some of its methods and potentially extend it in other useful ways. */ class CgenClassTable extends SymbolTable { /** All classes in the program, represented as CgenNode */ private Vector nds; /** This is the stream to which assembly instructions are output */ private PrintStream str; private int stringclasstag; private int intclasstag; private int boolclasstag; // The following methods emit code for constants and global // declarations. /** Emits code to start the .data segment and to * declare the global names. * */ private void codeGlobalData() { // The following global names must be defined first. str.print("\t.data\n" + CgenSupport.ALIGN); str.println(CgenSupport.GLOBAL + CgenSupport.CLASSNAMETAB); str.print(CgenSupport.GLOBAL); CgenSupport.emitProtObjRef(TreeConstants.Main, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitProtObjRef(TreeConstants.Int, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitProtObjRef(TreeConstants.Str, str); str.println(""); str.print(CgenSupport.GLOBAL); BoolConst.falsebool.codeRef(str); str.println(""); str.print(CgenSupport.GLOBAL); BoolConst.truebool.codeRef(str); str.println(""); str.println(CgenSupport.GLOBAL + CgenSupport.INTTAG); str.println(CgenSupport.GLOBAL + CgenSupport.BOOLTAG); str.println(CgenSupport.GLOBAL + CgenSupport.STRINGTAG); // We also need to know the tag of the Int, String, and Bool classes // during code generation. str.println(CgenSupport.INTTAG + CgenSupport.LABEL + CgenSupport.WORD + intclasstag); str.println(CgenSupport.BOOLTAG + CgenSupport.LABEL + CgenSupport.WORD + boolclasstag); str.println(CgenSupport.STRINGTAG + CgenSupport.LABEL + CgenSupport.WORD + stringclasstag); } /** Emits code to start the .text segment and to * declare the global names. * */ private void codeGlobalText() { str.println(CgenSupport.GLOBAL + CgenSupport.HEAP_START); str.print(CgenSupport.HEAP_START + CgenSupport.LABEL); str.println(CgenSupport.WORD + 0); str.println("\t.text"); str.print(CgenSupport.GLOBAL); CgenSupport.emitInitRef(TreeConstants.Main, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitInitRef(TreeConstants.Int, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitInitRef(TreeConstants.Str, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitInitRef(TreeConstants.Bool, str); str.println(""); str.print(CgenSupport.GLOBAL); CgenSupport.emitMethodRef(TreeConstants.Main, TreeConstants.main_meth, str); str.println(""); } /** Emits code definitions for boolean constants. */ private void codeBools(int classtag) { BoolConst.falsebool.codeDef(classtag, str); BoolConst.truebool.codeDef(classtag, str); } /** Generates GC choice constants (pointers to GC functions) */ private void codeSelectGc() { str.println(CgenSupport.GLOBAL + "_MemMgr_INITIALIZER"); str.println("_MemMgr_INITIALIZER:"); str.println(CgenSupport.WORD + CgenSupport.gcInitNames[Flags.cgen_Memmgr]); str.println(CgenSupport.GLOBAL + "_MemMgr_COLLECTOR"); str.println("_MemMgr_COLLECTOR:"); str.println(CgenSupport.WORD + CgenSupport.gcCollectNames[Flags.cgen_Memmgr]); str.println(CgenSupport.GLOBAL + "_MemMgr_TEST"); str.println("_MemMgr_TEST:"); str.println(CgenSupport.WORD + ((Flags.cgen_Memmgr_Test == Flags.GC_TEST) ? "1" : "0")); } /** Emits code to reserve space for and initialize all of the * constants. Class names should have been added to the string * table (in the supplied code, is is done during the construction * of the inheritance graph), and code for emitting string constants * as a side effect adds the string's length to the integer table. * The constants are emmitted by running through the stringtable and * inttable and producing code for each entry. */ private void codeConstants() { // Add constants that are required by the code generator. AbstractTable.stringtable.addString(""); AbstractTable.inttable.addString("0"); AbstractTable.stringtable.codeStringTable(stringclasstag, str); AbstractTable.inttable.codeStringTable(intclasstag, str); codeBools(boolclasstag); } /** Creates data structures representing basic Cool classes (Object, * IO, Int, Bool, String). Please note: as is this method does not * do anything useful; you will need to edit it to make if do what * you want. * */ private void installBasicClasses() { AbstractSymbol filename = AbstractTable.stringtable.addString(""); // A few special class names are installed in the lookup table // but not the class list. Thus, these classes exist, but are // not part of the inheritance hierarchy. No_class serves as // the parent of Object and the other special classes. // SELF_TYPE is the self class; it cannot be redefined or // inherited. prim_slot is a class known to the code generator. addId(TreeConstants.No_class, new CgenNode(new class_(0, TreeConstants.No_class, TreeConstants.No_class, new Features(0), filename), CgenNode.Basic, this)); addId(TreeConstants.SELF_TYPE, new CgenNode(new class_(0, TreeConstants.SELF_TYPE, TreeConstants.No_class, new Features(0), filename), CgenNode.Basic, this)); addId(TreeConstants.prim_slot, new CgenNode(new class_(0, TreeConstants.prim_slot, TreeConstants.No_class, new Features(0), filename), CgenNode.Basic, this)); // The Object class has no parent class. Its methods are // cool_abort() : Object aborts the program // type_name() : Str returns a string representation // of class name // copy() : SELF_TYPE returns a copy of the object class_ Object_class = new class_(0, TreeConstants.Object_, TreeConstants.No_class, new Features(0) .appendElement(new method(0, TreeConstants.cool_abort, new Formals(0), TreeConstants.Object_, new no_expr(0))) .appendElement(new method(0, TreeConstants.type_name, new Formals(0), TreeConstants.Str, new no_expr(0))) .appendElement(new method(0, TreeConstants.copy, new Formals(0), TreeConstants.SELF_TYPE, new no_expr(0))), filename); installClass(new CgenNode(Object_class, CgenNode.Basic, this)); // The IO class inherits from Object. Its methods are // out_string(Str) : SELF_TYPE writes a string to the output // out_int(Int) : SELF_TYPE " an int " " " // in_string() : Str reads a string from the input // in_int() : Int " an int " " " class_ IO_class = new class_(0, TreeConstants.IO, TreeConstants.Object_, new Features(0) .appendElement(new method(0, TreeConstants.out_string, new Formals(0) .appendElement(new formal(0, TreeConstants.arg, TreeConstants.Str)), TreeConstants.SELF_TYPE, new no_expr(0))) .appendElement(new method(0, TreeConstants.out_int, new Formals(0) .appendElement(new formal(0, TreeConstants.arg, TreeConstants.Int)), TreeConstants.SELF_TYPE, new no_expr(0))) .appendElement(new method(0, TreeConstants.in_string, new Formals(0), TreeConstants.Str, new no_expr(0))) .appendElement(new method(0, TreeConstants.in_int, new Formals(0), TreeConstants.Int, new no_expr(0))), filename); installClass(new CgenNode(IO_class, CgenNode.Basic, this)); // The Int class has no methods and only a single attribute, the // "val" for the integer. class_ Int_class = new class_(0, TreeConstants.Int, TreeConstants.Object_, new Features(0) .appendElement(new attr(0, TreeConstants.val, TreeConstants.prim_slot, new no_expr(0))), filename); installClass(new CgenNode(Int_class, CgenNode.Basic, this)); // Bool also has only the "val" slot. class_ Bool_class = new class_(0, TreeConstants.Bool, TreeConstants.Object_, new Features(0) .appendElement(new attr(0, TreeConstants.val, TreeConstants.prim_slot, new no_expr(0))), filename); installClass(new CgenNode(Bool_class, CgenNode.Basic, this)); // The class Str has a number of slots and operations: // val the length of the string // str_field the string itself // length() : Int returns length of the string // concat(arg: Str) : Str performs string concatenation // substr(arg: Int, arg2: Int): Str substring selection class_ Str_class = new class_(0, TreeConstants.Str, TreeConstants.Object_, new Features(0) .appendElement(new attr(0, TreeConstants.val, TreeConstants.Int, new no_expr(0))) .appendElement(new attr(0, TreeConstants.str_field, TreeConstants.prim_slot, new no_expr(0))) .appendElement(new method(0, TreeConstants.length, new Formals(0), TreeConstants.Int, new no_expr(0))) .appendElement(new method(0, TreeConstants.concat, new Formals(0) .appendElement(new formal(0, TreeConstants.arg, TreeConstants.Str)), TreeConstants.Str, new no_expr(0))) .appendElement(new method(0, TreeConstants.substr, new Formals(0) .appendElement(new formal(0, TreeConstants.arg, TreeConstants.Int)) .appendElement(new formal(0, TreeConstants.arg2, TreeConstants.Int)), TreeConstants.Str, new no_expr(0))), filename); installClass(new CgenNode(Str_class, CgenNode.Basic, this)); } // The following creates an inheritance graph from // a list of classes. The graph is implemented as // a tree of `CgenNode', and class names are placed // in the base class symbol table. private void installClass(CgenNode nd) { AbstractSymbol name = nd.getName(); if (probe(name) != null) return; nds.addElement(nd); addId(name, nd); } private void installClasses(Classes cs) { for (Enumeration e = cs.getElements(); e.hasMoreElements(); ) { installClass(new CgenNode((Class_)e.nextElement(), CgenNode.NotBasic, this)); } } private void buildInheritanceTree() { for (Enumeration e = nds.elements(); e.hasMoreElements(); ) { setRelations((CgenNode)e.nextElement()); } } private void setRelations(CgenNode nd) { CgenNode parent = (CgenNode)probe(nd.getParent()); nd.setParentNd(parent); parent.addChild(nd); } /** Constructs a new class table and invokes the code generator */ public CgenClassTable(Classes cls, PrintStream str) { nds = new Vector(); this.str = str; stringclasstag = 0 /* Change to your String class tag here */; intclasstag = 0 /* Change to your Int class tag here */; boolclasstag = 0 /* Change to your Bool class tag here */; enterScope(); if (Flags.cgen_debug) System.out.println("Building CgenClassTable"); installBasicClasses(); installClasses(cls); buildInheritanceTree(); code(); exitScope(); } /** This method is the meat of the code generator. It is to be filled in programming assignment 5 */ public void code() { if (Flags.cgen_debug) System.out.println("coding global data"); codeGlobalData(); if (Flags.cgen_debug) System.out.println("choosing gc"); codeSelectGc(); if (Flags.cgen_debug) System.out.println("coding constants"); codeConstants(); // Add your code to emit // - prototype objects // - class_nameTab // - dispatch tables if (Flags.cgen_debug) System.out.println("coding global text"); codeGlobalText(); // Add your code to emit // - object initializer // - the class methods // - etc... } /** Gets the root of the inheritance tree */ public CgenNode root() { return (CgenNode)probe(TreeConstants.Object_); } }