bool CAstBinaryOp::TypeCheck(CToken *t, string *msg) const { EOperation oper = GetOperation(); CAstExpression *left = GetLeft(); CAstExpression *right = GetRight(); if(!left->TypeCheck(t, msg)) return false; if(!right->TypeCheck(t, msg)) return false; switch(oper) { case opAdd: case opSub: case opMul: case opDiv: if(left->GetType() != CTypeManager::Get()->GetInt() || right->GetType() != CTypeManager::Get()->GetInt()) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "Operand types should be integer for '+','-','*',or '/'."; return false; } break; case opAnd: case opOr: if(left->GetType() != CTypeManager::Get()->GetBool() || right->GetType() != CTypeManager::Get()->GetBool()) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "Operand types should be boolean for '&&',or '||'."; return false; } break; case opEqual: case opNotEqual: if(left->GetType() != right->GetType()) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "Operand types should be same for '=',or '#'."; return false; } else if(left->GetType() == CTypeManager::Get()->GetNull()) { // left and right has same type, so we only check left type if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "Operand types should not be NULL."; return false; } break; case opLessThan: case opLessEqual: case opBiggerThan: case opBiggerEqual: if(left->GetType() != CTypeManager::Get()->GetInt() || right->GetType() != CTypeManager::Get()->GetInt()) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "Operand types should be integer for '<','<=','>',or '>='."; return false; } break; } return true; }
bool CAstArrayDesignator::TypeCheck(CToken *t, string *msg) const { bool result = true; assert(_done); if(!GetType()) { // if GetType is NULL then it is an invalid array expression if(t != NULL) *t = GetToken(); if(msg != NULL) *msg = "invalid array expression."; return false; } int i; for(i = 0; i < GetNIndices(); i++) { CAstExpression *e = GetIndex(i); if(!e->TypeCheck(t, msg)) return false; // Do TypeCheck on indexing expression if(!e->GetType()->IsInt()) { // The indexing expression should be Int type if(t != NULL) *t = e->GetToken(); if(msg != NULL) *msg = "invalid array index expression."; return false; } } return result; }
bool CAstStatIf::TypeCheck(CToken *t, string *msg) const { CAstExpression *cond = GetCondition(); bool result = true; if (!cond->TypeCheck(t, msg)) return false; if (cond->GetType() != CTypeManager::Get()->GetBool()) { if (t != NULL) *t = cond->GetToken(); if (msg != NULL) *msg = "boolean expression expected."; return false; } try { CAstStatement *ifBody = GetIfBody(); CAstStatement *elseBody = GetElseBody(); while (result && (ifBody != NULL)) { result = ifBody->TypeCheck(t, msg); ifBody = ifBody->GetNext(); } while (result && (elseBody != NULL)) { result = elseBody->TypeCheck(t, msg); elseBody = elseBody->GetNext(); } } catch (...) { result = false; } return result; }
bool CAstStatReturn::TypeCheck(CToken *t, string *msg) const { const CType *st = GetScope()->GetType(); CAstExpression *e = GetExpression(); if (st->Match(CTypeManager::Get()->GetNull())) { if (e != NULL) { if (t != NULL) *t = e->GetToken(); if (msg != NULL) *msg = "superfluous expression after return."; return false; } } else { if (e == NULL) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "expression expected after return."; return false; } if (!e->TypeCheck(t, msg)) return false; if (!st->Match(e->GetType())) { if (t != NULL) *t = e->GetToken(); if (msg != NULL) *msg = "return type mismatch."; return false; } } return true; }
bool CAstFunctionCall::TypeCheck(CToken *t, string *msg) const { const CSymProc *symbol = GetSymbol(); // check the number of procedure/function arguments. if (GetNArgs() != symbol->GetNParams()) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "the number of arguments mismatch."; return false; } // first, type check for expression of arguments. // then, check the types of procedure/function arguments. // in this project, arguments type is only integer. for (int i = 0; i < GetNArgs(); i++) { CAstExpression *arg = GetArg(i); if (!arg->TypeCheck(t, msg)) return false; if (arg->GetType() != symbol->GetParam(i)->GetDataType()) { if (t != NULL) *t = arg->GetToken(); if (msg != NULL) *msg = "the type of arguments mismatch."; return false; } } return true; }
bool CAstStatAssign::TypeCheck(CToken *t, string *msg) const { CAstDesignator *id = GetLHS(); CAstExpression *e = GetRHS(); if (!id->TypeCheck(t, msg)) return false; if (!e->TypeCheck(t, msg)) return false; if (!id->GetType()->Match(e->GetType())) { if (t != NULL) *t = e->GetToken(); if (msg != NULL) *msg = "assignment type mismatch."; return false; } return true; }
bool CAstUnaryOp::TypeCheck(CToken *t, string *msg) const { CAstExpression *e = GetOperand(); if (!e->TypeCheck(t, msg)) return false; if( ((GetOperation() == opPos || GetOperation() == opNeg) && (e->GetType() != CTypeManager::Get()->GetInt())) || ((GetOperation() == opNot) && (e->GetType() != CTypeManager::Get()->GetBool())) ) { if (t != NULL) *t = GetToken(); if (msg != NULL) *msg = "unary operation type mismatch."; return false; } return true; }