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