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