void SemanticEval::evaluateReturnCmd(ExpressionValue& ev, int line) { if(currentScope == SymbolTable::GlobalScope) { //tentando retornar no bloco principal ErrorHandler::self()->add("Bloco principal não deve ter retorno", line); } else { //currentScope eh o nome da funcao atual try { SymbolType sctype = stable.getSymbol(SymbolTable::GlobalScope, currentScope).type; if(!ev.isCompatibleWidth(sctype)) { stringstream msg; msg << "Expressão de retorno deve ser compatível com o tipo \"" << sctype.toString() << "\""; ErrorHandler::self()->add(msg.str(), line); } //else ok! } catch(SymbolTableException& e) { cerr << "Erro interno: SemanticEval::evaluateReturnCmd exception\n"; } } }
void SemanticEval::evaluateAttribution(ExpressionValue& lv, ExpressionValue& rv, int line) { //lvalue e rvalue devem ter tipos compativeis // -numericos (inteiro, logico, real, caractere) sao compativeis entre si. stringstream msg; if(!lv.isPrimitive()) { msg << "Apenas variáveis de tipos primitivos podem receber valores"; ErrorHandler::self()->add(msg.str(), line); return; } if(rv.primitiveType() == TIPO_NULO) { msg << "Expressão não retorna resultado para variável"; ErrorHandler::self()->add(msg.str(), line); } else if(!lv.isCompatibleWidth(rv)) { msg << "Variável não pode receber valores do tipo '" << rv.toString() << "'"; ErrorHandler::self()->add(msg.str(), line); } }
ExpressionValue SemanticEval::evaluateExpr(ExpressionValue& left, ExpressionValue& right, RefPortugolAST op) { //analisa expressoes binarias ExpressionValue ret, nulo; //operadores suportam apenas primitivos // if(!left.isPrimitive() || !right.isPrimitive()) { // return ret; // } //não permitir TIPO_ALL em expressões binarias if((left.primitiveType() == TIPO_ALL) || (right.primitiveType() == TIPO_ALL)) { stringstream msg; msg << "Função interna não pode participar de expressão"; ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; } switch(op->getType()) { //qualquer tipo, contanto que left e right sejam compativeis case SemanticWalkerTokenTypes::T_IGUAL: case SemanticWalkerTokenTypes::T_DIFERENTE: //nota sobre literais: // operacoes aplicadas sobre o length() do literal case SemanticWalkerTokenTypes::T_MAIOR: case SemanticWalkerTokenTypes::T_MENOR: case SemanticWalkerTokenTypes::T_MAIOR_EQ: case SemanticWalkerTokenTypes::T_MENOR_EQ: case SemanticWalkerTokenTypes::T_KW_OU: case SemanticWalkerTokenTypes::T_KW_E: if(left.isCompatibleWidth(right)) { ret.setPrimitiveType(TIPO_LOGICO); return ret; } else { stringstream msg; msg << "Operador \"" << op->getText() << "\" não pode ser usado em expressões no formato " << "'" << left.toString() << " " << op->getText() << " " << right.toString() << "'"; ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; } break; //qualquer numerico não-real (inteiro, caractere, lógico) case SemanticWalkerTokenTypes::T_BIT_OU: case SemanticWalkerTokenTypes::T_BIT_XOU: case SemanticWalkerTokenTypes::T_BIT_E: ret = evaluateNumTypes(left, right); if((ret.primitiveType() == TIPO_REAL) || (ret.primitiveType() == TIPO_NULO)) { stringstream msg; msg << "Operador \"" << op->getText() << "\" só pode ser usado com termos númericos não-reais"; ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; } else { return ret; } break; //qualquer numérico case SemanticWalkerTokenTypes::T_MAIS: case SemanticWalkerTokenTypes::T_MENOS: case SemanticWalkerTokenTypes::T_DIV: case SemanticWalkerTokenTypes::T_MULTIP: ret = evaluateNumTypes(left, right); if(!ret.isNumeric()) { stringstream msg; msg << "Operador \"" << op->getText() << "\" só pode ser usado com termos numéricos"; ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; } else { return ret; } break; case SemanticWalkerTokenTypes::T_MOD: ret = evaluateNumTypes(left, right); if(!ret.isNumeric(true)) { stringstream msg; msg << "Operador \"" << op->getText() << "\" não pode ser usado com termos " << "numéricos inteiros e compatíveis"; ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; } else { return ret; } break; } stringstream msg; msg << "Erro interno: operador não suportado: " << op->getText(); ErrorHandler::self()->add(msg.str(), op->getLine()); return nulo; }