(*
*) type Id = string; (** Representing types for mini-Java **) datatype Basic = Bool | Int | Real; datatype Type = BasicType of Basic | ArrayType of Basic | ObjType of Id | VoidType; (* A slot of type (`x TC) is an option *) (* type. The parser places NONE there *) (* and the type-checker fills it in *) (* with (SOME x) when "x" is known *) type 'x TC = 'x option; (******** Representing Programs *******) datatype Op (* infix operators *) = ADD | SUB | MUL | DIV (* Arithmetic *) | AND | OR (* logical *) | EQ | NE | LT | LE | GT | GE (* relational *) datatype Constant (* Literal constants *) = Cint of int | Creal of string | Cbool of bool datatype Exp = Literal of Constant (* 5, 6.3, true *) | Binop of Op * Exp * Exp (* x + 3 *) | Relop of Op * Exp * Exp (* x < 7.7 *) | Not of Exp (* ! x *) | ArrayElm of Exp * Exp * (Basic TC) (* x[3] *) | ArrayLen of Exp (* x.length() *) | Call of Exp * Id *(Id TC)* Exp list (* x.f(1,z) *) | NewArray of Basic * Exp (* new int[3] *) | NewObject of Id (* new point() *) (* Coerce is used only in type checking *) | Coerce of Exp datatype Stmt = Block of Stmt list (* {x:5; print(2)} *) | Assign of Exp option * Id * Exp option * Exp (* p.x[2]=5 p.x=5 x=5 *) | CallStmt of Exp * Id * (Id TC)* Exp list (* x.f(1,z) *) | If of Exp * Stmt * Stmt (* if (p<2) x=5 else x=6 *) | While of Exp * Stmt (* while (p) s *) | PrintE of Exp (* System.out.println(x) *) | PrintT of string (* System.out.println("zbc") *) | Return of Exp option; (* return (x+3) *) datatype VarDecl = VarDecl of Type * Id * Exp option; datatype Formal = Formal of Type * Id; datatype MetDecl = MetDecl of Type * Id * Formal list * VarDecl list * Stmt list; datatype VarDecl = VarDecl of Type * Id * Exp datatype ClassDec = ClassDec of Id * Id * VarDecl list * MetDecl list; datatype Program = Program of ClassDec list; datatype CTab = Node of Id * (* Class Name *) (Id * Type)list * (* Class Variables *) (Id * Type list * Type)list * (* Class Methods *) CTab ref * (* Parent Class *) CTab list (* Sub Classes *) | NullClass; val root = Node("object",[],[],ref NullClass,[]); exception NoParent of string; fun newClass name vars methods parent NullClass = NullClass | newClass name vars methods parent (n as Node(nm,vs,ms,p,subs)) = if parent=nm then let val p1 = ref n val new = Node(name,vars,methods,p1,[]) val newP = Node(nm,vs,ms,p,new::subs) val _ = p1 := newP in newP end else Node(nm,vs,ms,p,map (newClass name vars methods parent) subs) val t1 = newClass "point" [] [] "object" root; val t2 = newClass "colorpoint" [] [] "point" t1; fun basiceq (x,y) = case (x,y) of (Real,Real) => true | (Int,Int) => true | (Bool,Bool) => true | (_,_) => false fun typeeq (x,y) = case (x,y) of (BasicType x,BasicType y) => basiceq(x,y) | (ArrayType x,ArrayType y) => basiceq(x,y) | (ObjType x,ObjType y) => x=y | (VoidType,VoidType) => true | (_,_) => false fun defines name NullClass = false | defines name (Node(n,vs,ms,p,ss)) = if name=n then true else List.exists (defines name) ss; fun useTree NullClass (x,y) = false | useTree (Node(nm,vs,ms,p,ss)) (x,y) = if nm = y then List.exists (defines x) ss else List.exists (fn t => useTree t (x,y)) ss fun subtype classH (x,y) = case (x,y) of (x,ObjType "object") => true | (BasicType Int,ObjType "numeric") => true | (BasicType Real,ObjType "numeric") => true | (ObjType x,ObjType y) => useTree classH (x,y) | (_,_) => typeeq(x,y) (**)