Ejemplo n.º 1
0
ExpressionValue SemanticEval::evaluateFCall(RefPortugolAST f, list<ExpressionValue>& args) {
  ExpressionValue v;
  Symbol s;
  try {
    s = stable.getSymbol(SymbolTable::GlobalScope, f->getText());
    v.set(s.type);
  } catch(SymbolTableException& e) {
    stringstream msg;
    msg << "Função \"" << f->getText() << "\" não foi declarada";
    ErrorHandler::self()->add(msg.str(), f->getLine());      
    return v;
  }

  ParameterSig params = s.param;

  if(params.isVariable()) {
    //nao permitir 0 argumentos
    if(args.size() == 0) {
      stringstream msg;
      msg << "Pelo menos um argumento deve ser passado para a função \"" << f->getText() << "\"";
      ErrorHandler::self()->add(msg.str(), f->getLine());      
      return v;
    }
    //nao permitir matrizes como argumentos de funcoes com parametros variaveis
    int count = 1;
    for(list<ExpressionValue>::iterator it = args.begin();
        it != args.end(); ++it) {
      if(!(*it).isPrimitive()) {
        stringstream msg;
        msg << "Argumento " << count;
        msg << " da função \"" << f->getText() << "\" não pode ser matriz/conjunto";
        ErrorHandler::self()->add(msg.str(), f->getLine());      
        return v;
      }
      count++;
    }
    return v;
  }
  
  if(params.symbolList().size() != args.size()) {
    stringstream msg;
    msg << "Número de argumentos diferem do número de parâmetros da função \""
      << f->getText() << "\"";
    ErrorHandler::self()->add(msg.str(), f->getLine());      
    return v;
  }

  list< pair<string,SymbolType> >::iterator pit = params.symbolList().begin();
  list< pair<string,SymbolType> >::iterator pend = params.symbolList().end();

  list<ExpressionValue>::iterator ait = args.begin();
  list<ExpressionValue>::iterator aend = args.end();

  int count = 1;
  while((pit != pend) && (ait != aend)) {
    if(!(*ait).isCompatibleWidth((*pit).second)) {
      stringstream msg;
      msg << "Argumento " << count << " da função \"" << f->getText() << "\" deve ser do tipo \""
        << (*pit).second.toString() << "\"";
      ErrorHandler::self()->add(msg.str(), f->getLine());              
      return v;
    }    
    ++count;
    ++pit;
    ++ait;
  }
  return v;
}
Ejemplo n.º 2
0
ExpressionValue SemanticEval::evaluateLValue(RefPortugolAST id, list<ExpressionValue>& dim) {
/*
  1: lvalue (id) deve ter sido declarado no escopo global ou local
  2: o tipo do lvalue (id) deve ser o mesmo da declaracao (primitivo/dimensoes)
  3: as expressoes das dimensoes devem ser numericas inteiras. [1.2] ou ["aa"] ->erro
*/

  bool islocal;
  Symbol lvalue;
  ExpressionValue ret;

  try {
    lvalue = stable.getSymbol(currentScope, id->getText(), true);
    if(lvalue.scope == SymbolTable::GlobalScope) {
      islocal = false;
    } else {
      islocal = true;
    }
  } catch(SymbolTableException& e) {
    stringstream msg;    
    msg << "Variável \"" << id->getText() << "\" não foi declarada";
    ErrorHandler::self()->add(msg.str(), id->getLine());
    return ret;
  }

  ret.setPrimitiveType(lvalue.type.primitiveType());

  if(lvalue.isFunction) {
    stringstream msg;
    msg << "Função \"" << id->getText() << "\" não pode ser usada como variável";
    ErrorHandler::self()->add(msg.str(), id->getLine());
    return ret;    
  }

  if(lvalue.type.isPrimitive()) {
    ret.set(lvalue.type);
    if(dim.size() > 0) {
      stringstream msg;
      msg << "Variável \"" << id->getText() << "\" não é uma matriz/conjunto";
      ErrorHandler::self()->add(msg.str(), id->getLine());
      return ret;
    } else {
      return ret;
    }
  } else {//matriz/conjunto    

//     ret.setPrimitive(true);
//     ret.setPrimitiveType(lvalue.type.primitiveType());

    //checar expressoes dos subscritos
    list<ExpressionValue>::iterator it;
    for(it = dim.begin(); it != dim.end();++it) {
      if(!(*it).isNumeric(true)) {
        ErrorHandler::self()->add("Subscritos de conjuntos/matrizes devem ser valores numéricos inteiros ou equivalente", id->getLine());
      }
    }

    /* Nota: checar pelas dimensoes impede que 
       se passe matriz como parametros. Checar subscritos apenas 
       em atribuicoes.
    */

    //checar numero de dimensoes usado
    // - So eh permitido matrizes como lvalue sem subscritos, ou com todos os seus subscritos

    if(dim.size() > 0) {
      //matriz com seus subscritos, retorna apenas o tipo primitivo
      ret.setPrimitive(true);

      if(lvalue.type.dimensions().size() != dim.size()) {
        stringstream msg;
        msg << "Matriz/conjunto \"" << id->getText() << "\" possui " << lvalue.type.dimensions().size();
  
        if(dim.size() == 1) {
          msg << " dimensão";
        } else {
          msg << " dimensões";
        }
        msg << " Use " << lvalue.type.dimensions().size() << " subscrito(s)";
        ErrorHandler::self()->add(msg.str(), id->getLine());
      } 
    } else {
      //variavel matriz sem subscritos, retorna tipo matriz
      ret.setPrimitive(true);
      ret.setDimensions(lvalue.type.dimensions());
    }
    return ret;
  }
}