int Expr::evaluateAsInteger(){ if (isIntExpr()){ return ((IntExpr*)this)->getValue(); } if (isBinaryExpr()){ BinaryExpr* binExpr = (BinaryExpr*)this; int e1 = binExpr->getE1()->evaluateAsInteger(); int e2 = binExpr->getE1()->evaluateAsInteger(); BinaryOp* op = binExpr->getOp(); switch(op->getType()){ case BinaryOp::TIMES: return e1*e2; break; case BinaryOp::MINUS: return e1-e2; break; case BinaryOp::PLUS: return e1+e2; break; default : cerr << "Unsupported binary expression for evaluation" << endl; exit(1); } } cerr << "Can't evaluate this expression"; exit(1); }
double Evaluator::eval(BinaryOp &e) { double left = e.getLeft()->eval(*this); double right = e.getRight()->eval(*this); if (right == 0 && (e.getType() == Operator::DIV_OP || e.getType() == Operator::MOD_OP)) { LOG_ERROR(e.getLocation() << ": Divide by zero"); return 0; } switch (e.getType()) { case Operator::EXP_OP: return pow(left, right); case Operator::MUL_OP: return left * right; case Operator::DIV_OP: return left / right; case Operator::MOD_OP: return fmod(left, right); case Operator::ADD_OP: return left + right; case Operator::SUB_OP: return left - right; case Operator::EQ_OP: return left == right; case Operator::NE_OP: return left != right; case Operator::GT_OP: return left > right; case Operator::GE_OP: return left >= right; case Operator::LT_OP: return left < right; case Operator::LE_OP: return left <= right; case Operator::AND_OP: return left && right; case Operator::OR_OP: return left || right; case Operator::XOR_OP: return (bool)left ^ (bool)right; default: THROWS(e.getLocation() << " Invalid binary operator"); } }
double Evaluator::eval(BinaryOp &e) { double left = e.getLeft()->eval(*this); double right = e.getRight()->eval(*this); if (right == 0 && (e.getType() == Operator::DIV_OP || e.getType() == Operator::MOD_OP)) { LOG_ERROR(e.getLocation() << ": Divide by zero"); return 0; } // NOTE, LinuxCNC handles floating-point equality differently. // See ``Equality and floating-point values``. switch (e.getType()) { case Operator::EXP_OP: return pow(left, right); case Operator::MUL_OP: return left * right; case Operator::DIV_OP: return left / right; case Operator::MOD_OP: return fmod(left, right); case Operator::ADD_OP: return left + right; case Operator::SUB_OP: return left - right; case Operator::EQ_OP: return left == right; case Operator::NE_OP: return left != right; case Operator::GT_OP: return left > right; case Operator::GE_OP: return left >= right; case Operator::LT_OP: return left < right; case Operator::LE_OP: return left <= right; case Operator::AND_OP: return left && right; case Operator::OR_OP: return left || right; case Operator::XOR_OP: return (bool)left ^ (bool)right; default: THROW(e.getLocation() << " Invalid binary operator"); } }
std::string BinopToString(std::ostream &os, const BinaryOp &x) { std::string left = RvalueToString(os, x.left()); std::string right = RvalueToString(os, x.right()); std::string op; switch (x.op()) { case BinaryOp::PLUS: op = "add"; break; case BinaryOp::MINUS: op = "sub"; break; case BinaryOp::MUL: op = "mul"; break; case BinaryOp::XOR: op = "xor"; break; case BinaryOp::AND: op = "and"; break; case BinaryOp::OR: op = "or"; break; // Support for Boolean operators will be added later case BinaryOp::EQ: case BinaryOp::NE: case BinaryOp::LE: case BinaryOp::GE: case BinaryOp::LT: case BinaryOp::GT: op = "add"; break; } std::string val_var = get_var(); os << val_var << " = " << op << " i32 " << left << ", " << right << "\n"; return val_var; }