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; }
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; } }