public bool CompareTypes(AST.Type t1, AST.Type t2) { if (t1.GetType() != t2.GetType()) { return(false); } if (t1 is ObjectType to1 && t2 is ObjectType to2) { if (to1.Name != to2.Name) { return(false); } } return(true); }
public bool TypeChecking(Node tree, string currentClass, string currentMethod) { switch (tree) { case MethodBody methodBody: { foreach (var stm in methodBody.Statements) { TypeChecking(stm, currentClass, currentMethod); } if (symbolTable.GetMethodReturnType(currentClass, currentMethod).GetType() != TypeOf(methodBody.ReturnExpression, currentClass, currentMethod).GetType()) { throw new Exception("Wrong return type"); } else { return(true); } } case BlockStatement blockStm: { bool result = false; foreach (var stm in blockStm.Statements) { result = TypeChecking(stm, currentClass, currentMethod); } return(result); } case IfElseBlock ifElse: { if (!(TypeOf(ifElse.Expression, currentClass, currentMethod) is AST.Boolean)) { throw new Exception("Sorry but an if statement awaits a boolean :("); } else { bool a = TypeChecking(ifElse.FalseBranch, currentClass, currentMethod); bool b = TypeChecking(ifElse.TrueBranch, currentClass, currentMethod); return(a && b); } } case WhileBlock whileBlock: { if (!(TypeOf(whileBlock.Expression, currentClass, currentMethod) is AST.Boolean)) { throw new Exception("While type stupid"); } else { return(TypeChecking(whileBlock.Statement, currentClass, currentMethod)); } } case VarAssignment varAss: { AST.Type varType = symbolTable.GetVarType(currentClass, currentMethod, varAss.Id); if (varType.GetType() != TypeOf(varAss.Expression, currentClass, currentMethod).GetType()) { throw new Exception("Variable Assignment type is shit"); } else { return(true); } } case ArrayAssignment arrAss: { if (!(TypeOf(arrAss.Index, currentClass, currentMethod) is Int) || !(TypeOf(arrAss.Value, currentClass, currentMethod) is Int)) { throw new Exception("???"); } else { return(true); } } case Print print: { if (TypeOf(print.Expression, currentClass, currentMethod) is AST.Int) { return(true); } else { return(false); } } case Write write: { if (TypeOf(write.Expression, currentClass, currentMethod) is AST.IntegerLit) { return(true); } else { //throw new Exception("Write is shit"); return(true); } } default: throw new Exception("No thingy matched"); } }
public AST.Type TypeOf(Expression exp, string currentClass, string currentMethod) { switch (exp) { case Identifier id: { return(symbolTable.GetVarType(currentClass, currentMethod, id.Name)); } case And and: { AST.Type left = TypeOf(and.Left, currentClass, currentMethod); AST.Type right = TypeOf(and.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case Plus plus: { AST.Type left = TypeOf(plus.Left, currentClass, currentMethod); AST.Type right = TypeOf(plus.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Minus minus: { AST.Type left = TypeOf(minus.Left, currentClass, currentMethod); AST.Type right = TypeOf(minus.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Times times: { AST.Type left = TypeOf(times.Left, currentClass, currentMethod); AST.Type right = TypeOf(times.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Division division: { AST.Type left = TypeOf(division.Left, currentClass, currentMethod); AST.Type right = TypeOf(division.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case LessThan lt: { AST.Type left = TypeOf(lt.Left, currentClass, currentMethod); AST.Type right = TypeOf(lt.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case GreaterThan gt: { AST.Type left = TypeOf(gt.Left, currentClass, currentMethod); AST.Type right = TypeOf(gt.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case ArrayAccess arrAcc: { return(TypeOf(arrAcc.Val, currentClass, currentMethod)); } case ArrayLength arrlength: { if (!(TypeOf(arrlength.Exp, currentClass, currentMethod) is IntArray)) { throw new Exception(arrlength.Exp + " is not an array"); } else { return(new Int()); } } case MethodCall methodCall: { ObjectType expType; if (TypeOf(methodCall.Exp, currentClass, currentMethod) is ObjectType ot) { expType = ot; } else { throw new Exception("This method does not exist... Sorry bro"); } if (!symbolTable.ExistsMethod(expType.Name, methodCall.MethodName)) { throw new Exception("Method does not exist"); } AST.Type[] paramTypes = symbolTable.GetMethodParam(expType.Name, methodCall.MethodName); int i = 0; if (methodCall.Parameters == null) { return(symbolTable.GetMethodReturnType(expType.Name, methodCall.MethodName)); } foreach (var par in methodCall.Parameters) { if (!CompareTypes(TypeOf(par, currentClass, currentMethod), paramTypes[i])) { throw new Exception("Parameters type error"); } i++; } methodCall.EnhancedName = expType.Name + "$" + methodCall.MethodName; return(symbolTable.GetMethodReturnType(expType.Name, methodCall.MethodName)); } case Read read: { return(new AST.Boolean()); } case BooleanLit booleanLit: { return(new AST.Boolean()); } case IntegerLit intLit: { return(new Int()); } case This th: { return(new ObjectType(currentClass)); // TODO } case ArrayInstantiation arrInst: { TypeOf(arrInst.Length, currentClass, currentMethod); return(new AST.IntArray()); } case ObjectInstantiation objInst: { return(new ObjectType(objInst.ObjectId)); } case Not not: { TypeOf(not.Exp, currentClass, currentMethod); return(new AST.Boolean()); } case Parent par: { return(TypeOf(par.Exp, currentClass, currentMethod)); } } return(null); }