package pointless; import java.util.*; // Please direct questions to emily@cs.nyu.edu // Now we have added the components needed for type checking. All additions // are preceded by the key "//typechecker" for easy review. //typechecker //typechecker class TypeError extends Error{ TypeError(String dis){super(dis);} static void out(String x) {throw(new TypeError(x)); } } // these three interfaces can be implemented using one class. Presented as // three separate interfaces for type cleanliness //implements an association between variable names and the VarDeclNode //the name is referring to. interface VarEnv{ //you want the member currentOffset; here to be used by setVar int getCurrentOffset(); void setVar(VarDeclNode var); // adds the var.name, var pair to the VarEnv. // Should also set var's offset to currentOffset, and // add to currentOffset the amount of space toBeSet takes up. VarDeclNode getVar(String name); //returns the VarDeclNode associated with the String name. VarDeclNode lookupVar(String name); //returns the VarDeclNode associated with the String name //if none exists, returns the VarDeclNode associated with globalEnv. //if none exists, throws typeError. }; //implements an association between type names and the record //the name is referring to. interface RecordEnv{ void setRecord(RecordNode toBeSet); //adds the record to the RecordEnv RecordNode getRecord(String name); //gets the record from the RecordEnv }; //implements an association between function names and the FunctionNode //the name is referring to. interface FunctionEnv { void setFunction(FunctionNode toBeSet); //adds the function to the FunctionEnv; FunctionNode getFunction(String name); //gets the function from the FunctionEnv; }; //possible implementation using just one class, feel free to ignore class SymbolTable extends HashMap implements FunctionEnv,RecordEnv,VarEnv{ int curOffset = 0; public void setFunction(FunctionNode toBeSet) {} public FunctionNode getFunction(String name) {return null;} //combines common functionality of setFunction,setRecord, and setVar void set(NamedNode x) {} public void setRecord(RecordNode toBeSet) {} public RecordNode getRecord(String name) {return null;} public int getCurrentOffset() {return curOffset;} public void setVar(VarDeclNode toBeSet){} public VarDeclNode getVar(String name) {return null;} public VarDeclNode lookupVar(String name) { return null; }} class Type{ String name; int array_index = -1; RecordNode base; Type(String x){name = x;} Type(String x, String ai){name = x; array_index = new Integer(ai).intValue();} public String toString(){ if(array_index >= 0) return name + "[" + String.valueOf(array_index) + "]"; else return name;} RecordNode getBaseType(){ //returns RecordNode associated with the type return null;} boolean equals(Type other){ //checks to see if two types are equal return false; } int getSpace() { //space required by values of this type. Used to calculate the //offset needed by variable declarations return 0; } VarDeclNode getField(String name) { //gets the VarDeclNode associated with the Field name //throws a TypeError if there is no such field. return null;} boolean isArray(){ //returns whether this is an Array type return false; } } class Node { Vector children = new Vector(); Node getChild(int i) {return (Node) (children.get(i));} String label; Type type = null; VarEnv curEnv; Node() {label = "unknown";} Node(String x){label = x;} static Node root = new Node("root"); void printme(int level) {} static void tab_in(int level){ System.out.println(""); for(int i = 0; i < level; i++) System.out.print(" ");} void print(int level){ tab_in(level); System.out.print(label + ":");printme(level); if(type != null) System.out.print(" <" + type + ">"); for(int i = 0; i < children.size(); i++) getChild(i).print(level + 1);} //typechecker //this can either be a class or an interface, presented as //a class here in case people just want to use this definition //special Env's needed for the typeChecker static VarEnv globalEnv = new SymbolTable(); static FunctionEnv functionEnv = new SymbolTable(); static RecordEnv recordEnv = new SymbolTable(); //constants needed to represent Int,Bool,String static Type intType = new Type("Int"); static Type stringType = new Type("String"); static Type boolType = new Type("Bool"); static Type voidType = new Type("Void"); //Void functions can have either this type //or a null type field depending on how you did it. static FunctionNode currentFunction; //needed to typecheck return statements static void typeCheck(){ typeCheckInit(); VarEnv curEnv = new SymbolTable(); Node.root.typeCheck(curEnv); } static void typeCheckInit(){ //calls init on all records, functions, and global variables which: // a) adds all records to recordEnv // b) adds all functions to functionEnv. // c) adds all global variables to the globalEnv } void init(){} //here to prevent Java type errors Type typeCheck(VarEnv x){ //some node types will need to override this function, however here is //a good base definition. for(int i = 0; i < children.size();i++) getChild(i).typeCheck(x); typeCheckAux(x); curEnv = x; return type;} void typeCheckAux(VarEnv x){ //this will need to be overwritten by almost every function; } } class NamedNode extends Node{ String name; void printme(int level) { System.out.print(name); } } class FunctionNode extends NamedNode{ public boolean pure = false; FunctionNode() {label = "function";} void printme(int level) { if (pure) System.out.print("pure " + name); else System.out.print(" " + name); } void init(){} //adds the function to the functionEnv } class RecordNode extends NamedNode{ int space = 0; RecordNode() { label = "record_decl";} RecordNode(String x) { label = "record_decl";name = x;} //typechecker void init() { /* calculate how much space the RecordNode takes up. hint: create a new curEnv and add all the field VarDeclNode's to it. at the end the value for getCurrentOffset() is exactly the space taken up by the RecordNode. Add the RecordNode to the RecordEnv. */ } } class VarDeclNode extends NamedNode{ //typechecker int offset = -1; void printme(int level) { System.out.print(name); if(offset >= 0) System.out.print("(" + offset + ")");} } class DispatchNode extends NamedNode{ DispatchNode(Vector v) {label = "dispatch"; v.add(this);} } class ArrayRefNode extends Node{ } class RefNode extends NamedNode{ //typechecker VarDeclNode ref; } class AssignNode extends Node { } class BlockNode extends Node{ } class IntConstNode extends Node { int value; } class ReturnNode extends Node { } class BoolConstNode extends Node { } class StringConstNode extends Node { } class IfNode extends Node { } class MemberNode extends NamedNode { } class IfClauseNode extends Node { } class ForNode extends Node { } class WhileNode extends Node { } class OpNode extends NamedNode{ }