// TypeCheckVisitor.java

package semant;

import syntaxtree.*;

import java.util.Vector;

import java.util.StringTokenizer;

 

public class TypeCheckVisitor extends visitor.TypeDepthFirstVisitor {

// By extending TypeDepthFirstVisitor, we only have to override those

// methods that differ from the generic visitor.

 

private errormsg.ErrorMsg errorMsg;

private SymbolTable classTable;

private ClassInfo currClass;

private MethodInfo currMethod;

public int errCounter;

private boolean T;

private String[] primitives = {"int","boolean","class", "int[]"};

// Type constants

final IntegerType INTTY = new IntegerType();

final IntArrayType INTARRTY = new IntArrayType();

final BooleanType BOOLTY = new BooleanType();

public TypeCheckVisitor(errormsg.ErrorMsg e, SymbolTable s){

errorMsg = e;

classTable = s;

currClass = null;

currMethod = null;

T = false;

}

 

 

// Identifier i1,i2;

// Statement s;

public Type visit(MainClass n)

{

String id = n.i1.toString();

currClass = classTable.get(id);

T = true;

n.i2.accept(this);

n.s.accept(this);

T = false;

return new IdentifierType(currClass.getName());

}

 

// MainClass m;

// ClassDeclList cl;

public Type visit(Program n) {

n.m.accept(this);

for (int i = 0; i < n.cl.size()-1; i++)

{

n.cl.elementAt(i).accept(this);

}

return null;

}

 

// Identifier i;

// List vl;

// MethodDeclList ml;

public Type visit(ClassDeclSimple n) {

String iX = n.i.toString();

currClass = classTable.get(iX);

for(int i=0; i<n.vl.size();i++) {

n.vl.elementAt(i).accept(this);

}

for(int i=0; i<n.ml.size();i++){

n.ml.elementAt(i).accept(this);

}

n.i.accept(this);

return new IdentifierType(currClass.getName());

}

// Type t;

// Identifier i;

public Type visit(Formal n) {

n.t.accept(this);

n.i.accept(this);

return null;

}

 

// Exp e;

// Statement s1,s2;

public Type visit(If n) {

Type t = n.e.accept(this);

if (!equal(t,BOOLTY,BOOLTY)) {

errCounter++;

errorMsg.error(n.pos, "Err: Condition of if must be of type boolean");

}

n.s1.accept(this);

n.s2.accept(this);

return t;

}

 

// Exp e;

// Statement s;

public Type visit(While n) {

Type t = n.e.accept(this);

if (!equal(t,BOOLTY,BOOLTY)) {

errCounter++;

errorMsg.error(n.pos, "Err:Condition of while must be of type boolean");

}

n.s.accept(this);

return t;

}

 

// Exp e;

public Type visit(Print n) {

Type t = n.e.accept(this);

return t;

}

// Identifier i;

// Exp e;

public Type visit(Assign n){

Type eType = n.e.accept(this);

VariableInfo vi = null;

if(currMethod!=null){

vi = currMethod.getVar(n.i.toString());

if(vi!=null && (!equal(vi.type,eType,vi.type))){

errCounter++;

errorMsg.error(n.pos, "Err:"+eIncompTypes(eType.toString(),vi.type.toString()));

}

}

else{

vi = currClass.getField(n.i.toString());

if(vi!=null && (!equal(vi.type,eType,vi.type)) ){

errCounter++;

errorMsg.error(n.pos, "Err:"+eIncompTypes(eType.toString(),vi.type.toString()));

}

}

return eType;

}

 

// Identifier i;

// Exp e1,e2;

public Type visit(ArrayAssign n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

VariableInfo vi = currClass.getField(n.i.toString());

if(vi==null && currMethod!=null){

vi = currMethod.getVar(n.i.toString());

}

Type IdType = vi.type;

if ((!(t1 instanceof IntegerType))&& t1!=null) {

errCounter++;

errorMsg.error(n.e1.pos, "Err:"+eIncompTypes(t1.toString(),INTTY.toString()));

}

if ((!(t2 instanceof IntegerType)) && t2!=null) {

errCounter++;

errorMsg.error(n.e1.pos, "Err:"+eIncompTypes(t2.toString(),INTTY.toString()));

 

}

return IdType;

}

 

// Type t;

// Identifier i;

public Type visit(VarDecl n) {

n.t.accept(this);

n.i.accept(this);

VariableInfo vi=null;

Type tx=null;

if(currMethod!=null){

vi = currMethod.getVar(n.i.toString());

}

if(vi==null && currClass!=null){

vi=currClass.getField(n.i.toString());

}

if(vi!=null){

tx = vi.type;

}

if(tx==null){

errCounter++;

errorMsg.error(n.pos,"Err: Cannot resolve symbol "+n.i.toString());

}

else{

int c=0;

for(int i=0; i<4;i++){

if(!tx.toString().equals(primitives[i])){ c++;}

}

if(c==4 && ( classTable.get(tx.toString()) == null ) ){

errCounter++;

errorMsg.error(n.pos,"Err:\""+ tx.toString()+"\" is not a class or a type");

}

}

return tx;

}

 

// Type t;

// Identifier i;

// FormalList fl;

// VarDeclList vl;

// StatementList sl;

// Exp e;

public Type visit(MethodDecl n) {

String id = n.i.toString();

currMethod = currClass.getMethod(id);

Type eType = n.e.accept(this);

Type retType = currMethod.getReturnType();

for ( int i = 0; i < n.fl.size(); i++ ) {

n.fl.elementAt(i).accept(this);

}

for ( int i = 0; i < n.vl.size(); i++ ) {

n.vl.elementAt(i).accept(this);

}

for ( int i = 0; i < n.sl.size(); i++ ) {

n.sl.elementAt(i).accept(this);

}

//We have to compare the return type of the method

//with the actual returned parameter

//and report error when necessary

if(eType!=null){

if(!retType.toString().equals(eType.toString())){

errCounter++;

errorMsg.error(n.pos,errCounter+":"+eIncompTypes(eType.toString(),retType.toString()));

}

}

return retType;

}

 

 

 

public Type visit(And n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

 

if (!equal(t1, t2, BOOLTY)){

errCounter++;

errorMsg.error(n.pos,"Err:"+ eIncompBiop("&&", t1.toString(), t2.toString()));

}

return BOOLTY;

}

 

// Exp e1,e2;

public Type visit(LessThan n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

if (!equal(t1, t2, INTTY)){

errCounter++;

errorMsg.error(n.pos,"Err:"+ eIncompBiop("<", t1.toString(), t2.toString()));

}

return BOOLTY;

}

 

// Exp e1,e2;

public Type visit(Minus n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

 

if (!equal(t1, t2, INTTY)){

errCounter++;

errorMsg.error(n.pos,"Err:"+ eIncompBiop("-", t1.toString(), t2.toString()));

}

return INTTY;

}

 

// Exp e1,e2;

public Type visit(Times n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

 

if (!equal(t1, t2, INTTY)){

errCounter++;

errorMsg.error(n.pos,"Err:"+ eIncompBiop("*", t1.toString(), t2.toString()));

}

return INTTY;

}

 

// Exp e1,e2;

public Type visit(ArrayLookup n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

 

if(!(t2 instanceof IntegerType)){

errCounter++;

errorMsg.error(n.pos,"Err:"+eIncompTypes(t2.toString(),INTTY.toString() ));

}

return INTTY;

}

 

// Exp e;

public Type visit(ArrayLength n) {

Type t = n.e.accept(this);

if (t!=null && !(t instanceof IntArrayType) ) {

errCounter++;

errorMsg.error(n.e.pos, "Err: int required.");

}

return INTTY ;

}

 

// Exp e;

// Identifier i;

// ExpList el;

public Type visit(Call n) {

Type t = n.e.accept(this);

n.i.accept(this);

ClassInfo classInfo = classTable.get(t.toString());

if (classInfo==null){

errCounter++;

errorMsg.error(n.pos, "Err: Not a valid class or Object. ");

return null;

}

MethodInfo method = classInfo.getMethod(n.i.toString());

if (method==null){

errCounter++;

errorMsg.error(n.pos,"Err: Cannot resolve method "+n.i.toString());

return null;

}

//Fillout the fullname field

n.fullname = classInfo.getName()+"$"+method.getName();

Vector v = new Vector();

for(int i=0; i<n.el.size();i++){

Type type = n.el.elementAt(i).accept(this);

if (type != null)

v.add(type.toString());

else{

return null;

}

}

String formalsF = v.toString();

formalsF = "("+formalsF.substring(1,formalsF.length()-1)+")";

String formals = method.getFormalsTypes();

if(!(formals.equals(formalsF))){

errCounter++;

errorMsg.error(n.pos,"Err: Cannot apply "+classInfo.getName()+"."+

method.getName()+formals+ " to " + formalsF);

}

return null;

}

 

 

// int i;

public Type visit(IntegerLiteral n) {

return INTTY;

}

 

public Type visit(True n) {

return BOOLTY;

}

 

public Type visit(False n) {

return BOOLTY;

}

 

// String s;

public Type visit(IdentifierExp n) {

Type t;

VariableInfo vi = null;

if(currMethod!=null){

vi =currMethod.getVar(n.s.toString());

if(vi==null){

}

else{

}

}

if( vi == null && currClass!=null ){

vi = currClass.getField(n.s.toString());

}

if(vi!=null){

t= vi.type;

return t;

}

else{

errCounter++;

errorMsg.error(n.pos, "Err: Cannot resolve symbol "+n.s+ " in class " + currClass.getName());

}

return null;

}

 

public Type visit(This n) {

if(T){

errCounter++;

errorMsg.error(n.pos,"Err: non-static variable \"this\" cannot be referenced from a static context");

}

else{

if(currClass !=null){

return new IdentifierType(currClass.getName());

}

}

return null;

}

 

// Exp e;

public Type visit(NewArray n) {

Type t = n.e.accept(this);

if (! (t instanceof IntegerType) ) {

errCounter++;

errorMsg.error(n.e.pos, "Err: int required.");

}

return INTARRTY;

}

 

// Identifier i;

public Type visit(NewObject n) {

return new IdentifierType(n.i.s);

}

 

// Exp e;

public Type visit(Not n) {

Type t = n.e.accept(this);

if (! (t instanceof BooleanType) ) {

errCounter++;

errorMsg.error(n.e.pos, "Err: boolean required.");

}

return BOOLTY;

}

// Exp e1,e2;

public Type visit(Plus n) {

Type t1 = n.e1.accept(this);

Type t2 = n.e2.accept(this);

 

if (!equal(t1, t2, INTTY)){

errCounter++;

errorMsg.error(n.pos,"Err:"+ eIncompBiop("+", t1.toString(), t2.toString()));

}

return INTTY;

}

 

// Check whether t1 == t2 == target, but suppress error messages if

// either t1 or t2 is null.

private boolean equal(Type t1, Type t2, Type target) {

if ( t1 == null || t2 == null )

return true;

if (target == null){

throw new Error("target argument in method equal cannot be null");

}

 

if (target instanceof IdentifierType && t1 instanceof IdentifierType

&& t2 instanceof IdentifierType)

return ((IdentifierType) t1).s.equals(((IdentifierType) t2).s );

 

if (!(target instanceof IdentifierType) &&

t1.toString().equals(target.toString()) &&

t2.toString().equals(target.toString()))

return true;

 

return false;

}

 

// Methods for error reporting:

 

private String eIncompTypes(String t1, String t2) {

return "incompatible types \nfound : " + t1

+ "\nrequired: " + t2 ;

}

 

private String eIncompBiop(String op, String t1, String t2) {

return "operator \"" + op + "\" cannot be applied to " + t1 + "," + t2 ;

}

www.cpccci.com
www.cpcwebsolutions.com
www.cpcwebdevelopment.com