ExpressionValue SemanticEval::evaluateExpr(ExpressionValue& ev, RefPortugolAST unary_op) {
  ExpressionValue nulo;

  //não permitir TIPO_ALL em expressões binarias
  if(ev.primitiveType() == TIPO_ALL) {
    stringstream msg;
    msg << "Função interna não pode participar de expressão";
    ErrorHandler::self()->add(msg.str(), unary_op->getLine());
    return nulo;
  }

  switch(unary_op->getType()) {

    //operadores unarios para expressões numéricas (retorna o tipo da expressão 'expr')
    case SemanticWalkerTokenTypes::TI_UN_POS://+
    case SemanticWalkerTokenTypes::TI_UN_NEG://-    
      if(!ev.isNumeric()) {
        stringstream msg;
        msg <<  "Operador unário \"" << unary_op->getText()
            << "\" deve ser usado em termos numéricos";
        ErrorHandler::self()->add(msg.str(), unary_op->getLine());
        return nulo;
      } else {      
        return ev;
      }  
      break;
    case SemanticWalkerTokenTypes::TI_UN_BNOT://~
      if(!ev.isNumeric(true)) {
        stringstream msg;
        msg <<  "Operador unário \"" << unary_op->getText()
            << "\" deve ser usado em termos numéricos inteiros e compatíveis";
        ErrorHandler::self()->add(msg.str(), unary_op->getLine());
        return nulo;
      } else {      
        return ev;
      }  
      break;
      
    //operador "not", para todos os tipos. Retorna TIPO_LOGICO
    case SemanticWalkerTokenTypes::TI_UN_NOT:
      ev.setPrimitiveType(TIPO_LOGICO);
      return ev;
      break;
  }

  stringstream msg;
  msg << "Erro interno: operador não suportado: " << unary_op->getText() << "";
  ErrorHandler::self()->add(msg.str(), unary_op->getLine());
  return nulo;
}
void SemanticEval::evaluateNumericExpr(ExpressionValue& ev, int line) {
  if(!ev.isPrimitive() || !ev.isNumeric()) {
    stringstream err;
    err << "Esperando uma expressão numérica. Encontrado expressão \"" << ev.toString() << "\"";
    ErrorHandler::self()->add(err.str(), line);
  }
}
ExpressionValue SemanticEval::evaluateNumTypes(ExpressionValue& left, ExpressionValue& right) {
  ExpressionValue ret;

  if(!left.isNumeric() || !right.isNumeric()) return ret;

  //a ordem eh importante. Primeiro o tipo mais forte.

  if((left.primitiveType() == TIPO_REAL) || (right.primitiveType() == TIPO_REAL)) {
    ret.setPrimitiveType(TIPO_REAL); //promoted to real

  } else if((left.primitiveType() == TIPO_INTEIRO) || (right.primitiveType() == TIPO_INTEIRO)) {
    ret.setPrimitiveType(TIPO_INTEIRO); //promoted to int

  } else  if((left.primitiveType() == TIPO_CARACTERE) || (right.primitiveType() == TIPO_CARACTERE)) {
    ret.setPrimitiveType(TIPO_CARACTERE); //promoted to char

  } else if((left.primitiveType() == TIPO_LOGICO) || (right.primitiveType() == TIPO_LOGICO)) {
    ret.setPrimitiveType(TIPO_LOGICO); //promoted to bool
  }    

  return ret; //no number here...
}