Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}