package typecheck; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import antlr4.QLParser; import ast.ASTNode; import ast.Visitor; import ast.errormsg.Error; import ast.evaluate.Bool; import ast.form.Block; import ast.form.Computedquest; import ast.form.Form; import ast.form.IfElse; import ast.form.Ifstate; import ast.form.Question; import ast.form.Statement; import ast.form.StatementList; import ast.literals.BoolLiteral; import ast.literals.IntLiteral; import ast.literals.StrLiteral; import ast.type.Booltype; import ast.type.Inttype; import ast.type.Strtype; import ast.type.Type; import expr.Expr; import expr.Ident; import expr.conditional.And; import expr.conditional.Or; import expr.operation.Add; import expr.operation.Div; import expr.operation.Mul; import expr.operation.Sub; import expr.relational.Eq; import expr.relational.GEq; import expr.relational.GT; import expr.relational.LEq; import expr.relational.LT; import expr.relational.NEq; import expr.unary.Neg; import expr.unary.Not; import expr.unary.Pos; public class Typecheck implements Visitor<Boolean>{ private final Map<Ident,Type> identifier; private Error errors; private List<String> labels ; public String get_errorList(){ return errors.toString(); } public void checkquestion(String label){ //System.out.println(label); if(labels.contains(label)){ errors.addWarning("Warning: Duplicate label at " + label); } labels.add(label); } public boolean checkId(ASTNode node, Map<Ident,Type> identifier, Error errors){ Typecheck tc = new Typecheck(identifier, errors); return node.accept(tc); } public Typecheck (Map<Ident,Type> identifier, Error errors) { this.identifier= identifier; this.errors = errors; labels = new ArrayList<String>(); } public boolean ValidExpression(Expr exp) { if(exp.getClass()==Ident.class){ return true; } return exp.accept(this); } public boolean ValidInteger(Expr operand, String side, String operator) { if (ValidExpression(operand)){ Type type = operand.typeof(identifier); if(type.isInt()){ return true; } errors.addError("Error: Invalid/Incompatible Type at " + side + " " + operator); } return false; } public boolean ValidInteger(Expr lhs, Expr rhs, String operator) { boolean Validop1 = ValidInteger(lhs, "left side", operator); boolean Validop2 = ValidInteger(rhs, "right side", operator); return (Validop1 && Validop2); } public boolean ValidString(Expr operand, String side, String operator) { if(ValidExpression(operand)) { Type optype = operand.typeof(identifier); if((optype!=null) && (optype.isStr())) { return true; } else { errors.addError("Error: Invalid Type at " + side + " " + operator); } } return false; } public boolean ValidString(Expr lhs, Expr rhs, String operator) { boolean Validop1 = ValidString(lhs, "left side", operator); boolean Validop2 = ValidString(rhs, "right side", operator); return (Validop1 && Validop2); } public boolean ValidBoolean(Expr operand, String side, String operator) { if(ValidExpression(operand)) { Type optype = operand.typeof(identifier); if((optype!=null) && (optype.isBool())) { return true; } else{ errors.addError("Error: Invalid Type at " + side + " " + operator); } } return false; } public boolean ValidBoolean(Expr lhs, Expr rhs, String operator) { boolean Validop1 = ValidBoolean(lhs, "left side", operator); boolean Validop2 = ValidBoolean(rhs, "right side", operator); return (Validop1 && Validop2); } public boolean Equaltypes(Expr lhs, Expr rhs, String operator){ boolean ValidLhs = ValidExpression(lhs); boolean ValidRhs = ValidExpression(rhs); if(ValidLhs && ValidRhs){ Type t1 = lhs.typeof(identifier); Type t2 = rhs.typeof(identifier); if(t1.istype(t2)){ return true; } errors.addError("Error: Incompataible types at " + operator); } return false; } @Override public Boolean visit(And node) { return ValidBoolean(node.getLhs(), node.getRhs(), "&&") ; } @Override public Boolean visit(Or node) { return ValidBoolean(node.getLhs(), node.getRhs(), "||"); } @Override public Boolean visit(Ident node) { if(identifier.containsKey(node)) { return true; } errors.addError("Error: Undefined identifier: " + node.getId()); return false; } @Override public Boolean visit(Form node) { return node.getStatements().accept(this); } @Override public Boolean visit(Question node) { checkquestion(node.getDescription()); return checkIdent(node.getId(), node.getType()); } public boolean checkIdent(Ident id, Type type) { HashMap<String, Ident> IdentKey = new HashMap<String, Ident>(); for(Ident key: identifier.keySet()) { IdentKey.put(key.id, key); } if(IdentKey.containsKey(id.id) && (identifier.get(IdentKey.get(id.id)).istype(type))) { errors.addError("Used Identifier " + id.getId()); return false; } else if(IdentKey.containsKey(id.id) && !(identifier.get(IdentKey.get(id.id)).istype(type))) { errors.addError("Used Identifier with Invalid type " + id.getId()); return false; } else { identifier.put(id, type); return true; } // for (Ident key: identifier.keySet()){ // // if(id.id.equals(key.id) && identifier.get(key).istype(type)) // { // errors.addError("Error: Used Identifier " + id.getId()); // return false; // } // // else if(id.id.equals(key.id) &&!(identifier.get(key).istype(type))) // { // errors.addError("Error: Used Identifier with Invalid type " + id.getId()); // return false; // } // // // } // identifier.put(id, type); // return true; // } @Override public Boolean visit(IfElse node) { labels.clear(); boolean validExpr = ValidBoolean(node.getExpr(), "", "else"); boolean validIfState = node.getStatements().accept(this); boolean validElseState = node.getStatement1().accept(this); return (validExpr && validIfState && validElseState ); } @Override public Boolean visit(Ifstate node) { labels.clear(); boolean validExpr = ValidBoolean(node.getExpr(), "", "if"); boolean validState = node.getStatements().accept(this); return (validExpr && validState); } @Override public Boolean visit(Add node) { return ValidInteger(node.getLhs(),node.getRhs(), "+"); } @Override public Boolean visit(Div node) { return ValidInteger(node.getLhs(),node.getRhs(), "/"); } @Override public Boolean visit(Mul node) { return ValidInteger(node.getLhs(),node.getRhs(), "*"); } @Override public Boolean visit(Sub node) { return ValidInteger(node.getLhs(),node.getRhs(), "-"); } @Override public Boolean visit(Eq node) { return Equaltypes(node.getLhs(),node.getRhs(), "=="); } @Override public Boolean visit(GEq node) { return Equaltypes(node.getLhs(),node.getRhs(), ">="); } @Override public Boolean visit(GT node) { return Equaltypes(node.getLhs(),node.getRhs(), ">"); } @Override public Boolean visit(LEq node) { return Equaltypes(node.getLhs(),node.getRhs(), "<="); } @Override public Boolean visit(LT node) { return Equaltypes(node.getLhs(),node.getRhs(),"<"); } @Override public Boolean visit(NEq node) { return Equaltypes(node.getLhs(),node.getRhs(),"!="); } @Override public Boolean visit(Booltype node) { return true; } @Override public Boolean visit(Inttype node) { return true; } @Override public Boolean visit(Strtype node) { return true; } @Override public Boolean visit(Neg node) { return ValidInteger(node.getOperand(), "", "-"); } @Override public Boolean visit(Not node) { return ValidBoolean(node.getOperand(), "", "!"); } @Override public Boolean visit(Pos node) { return ValidInteger(node.getOperand(), "", "+"); } @Override public Boolean visit(StatementList statementList) { boolean result = true; for(Statement statement: statementList.getList()) { if(!statement.accept(this)){ result = false; } } return result; } @Override public Boolean visit(Computedquest node) { boolean ValidId = checkIdent(node.getId(), node.getType()); boolean ValidExpr = ValidExpression(node.getExpr()); boolean ValidType = Validtype(node.getId(),node.getType()); //boolean ValidType = true; Type exprType = node.getExpr().typeof(identifier); if (!node.getType().istype(exprType)){ ValidType = false; errors.addError("Not a Valid type: "+ exprType); } return (ValidId && ValidExpr && ValidType); } public boolean Validtype(Ident id, Type type) { for (Ident key : identifier.keySet()) { if (id.id.equals(key.id)) { if (identifier.get(key).istype(type)) { return true; } } } errors.addError("Error: Invalid Type "); return false; } @Override public Boolean visit(BoolLiteral node) { return true; } @Override public Boolean visit(IntLiteral node) { return true; } @Override public Boolean visit(StrLiteral node) { return true; } @Override public Boolean visit(Block block) { return visit (block.getStatements()); } }