ExprResult CondNode::eval() { ExprResult result; ExprResult left = mLeft->eval(); ExprResult right = mRight->eval(); // @TODO Realizar cast automático para string nos casos necessários if (left.isNumeric() && right.isNumeric()) { result.setType("bool"); if (left.isInteger()) { long leftVal = left.getIntegerValue(); if (right.isInteger()) { long rightVal = right.getIntegerValue(); result.setValue((Val*)new BoolVal(compare(leftVal, rightVal))); } else { double rightVal = right.getFloatValue(); result.setValue((Val*)new BoolVal(compare(leftVal, rightVal))); } } else { double leftVal = left.getFloatValue(); if (right.isInteger()) { long rightVal = right.getIntegerValue(); result.setValue((Val*)new BoolVal(compare(leftVal, rightVal))); } else { double rightVal = right.getFloatValue(); result.setValue((Val*)new BoolVal(compare(leftVal, rightVal))); } } } else if (left.getType() == "string" && right.getType() == "string") { result.setType("bool"); std::string leftVal = ((StringVal*)left.getValue())->getValue(); std::string rightVal = ((StringVal*)right.getValue())->getValue(); result.setValue((Val*)new BoolVal(compare(leftVal, rightVal))); } if (result.getType() == "void") { Log::fatal("Tipos incompatíveis para comparação"); } return result; }
/* @TODO Implementar melhor, copy paste de SumNode com poucas diferenças */ ExprResult ModNode::eval() { ExprResult result; ExprResult left = mLeft->eval(); ExprResult right = mRight->eval(); if (left.isNumeric() && right.isNumeric()) { if (left.isInteger()) { long leftValue = left.getIntegerValue(); long resultValue; if (right.isInteger()) { long rightValue = right.getIntegerValue(); resultValue = leftValue % rightValue; result.setValue("long", resultValue); } else if (right.isFloat()) { long rightValue = (long)right.getFloatValue(); resultValue = leftValue % rightValue; result.setValue("long", resultValue); } } else if (left.isFloat()) { long leftValue = (long)left.getFloatValue(); long resultValue; if (right.isInteger()) { long rightValue = right.getIntegerValue(); resultValue = leftValue % rightValue; } else if (right.isFloat()) { long rightValue = (long)right.getFloatValue(); resultValue = leftValue % rightValue; } result.setValue("long", resultValue); } } // Nenhuma operação pode ser realizada if (result.getType() == "void") { Log::fatal("Uso de módulo com valores não numéricos"); } return result; }
ExprResult SumNode::eval() { ExprResult result; ExprResult left = mLeft->eval(); ExprResult right = mRight->eval(); if (left.isNumeric() && right.isNumeric()) { if (left.isInteger()) { long leftValue = left.getIntegerValue(); if (right.isInteger()) { long rightValue = right.getIntegerValue(); long resultValue = leftValue + rightValue; result.setValue(result.getLargerType(left, right), resultValue); } else if (right.isFloat()) { double rightValue = right.getFloatValue(); double resultValue = leftValue + rightValue; result.setValue(result.getLargerType(left, right), resultValue); } } else if (left.isFloat()) { double leftValue = left.getFloatValue(); double resultValue = leftValue; if (right.isInteger()) { long rightValue = right.getIntegerValue(); resultValue += rightValue; } else if (right.isFloat()) { double rightValue = right.getFloatValue(); resultValue += rightValue; } result.setValue(result.getLargerType(left, right), resultValue); } } // Nenhuma operação pode ser realizada if (result.getType() == "void") { Log::fatal("Uso de soma com valores não numéricos"); } return result; }
ExprResult IdentifierNode::eval() { ExprResult result; ActivationReg* areg = ActivationReg::getInstance(); SymbolTable* table = areg->top(); Symbol* sym = table->get(mName); if (sym != NULL && sym->isVar()) { result.setType(sym->getType()); result.setValue(sym->getValue()); } else { Log::fatal("Uso de identificador não definido"); } return result; }