public function process(Vertex $vertex, Digraph $graph) { if ($vertex instanceof JitBinaryOp && $vertex->getA() instanceof Constant && $vertex->getB() instanceof Constant) { $ret = null; switch ($vertex->getKind()) { case JitBinaryOp::CONCAT: $ret = $vertex->getA()->getValue() . $vertex->getB()->getValue(); break; case JitBinaryOp::PLUS: $ret = $vertex->getA()->getValue() + $vertex->getB()->getValue(); break; case JitBinaryOp::MINUS: $ret = $vertex->getA()->getValue() - $vertex->getB()->getValue(); break; case JitBinaryOp::MUL: $ret = $vertex->getA()->getValue() * $vertex->getB()->getValue(); break; case JitBinaryOp::DIV: $ret = $vertex->getA()->getValue() / $vertex->getB()->getValue(); break; case JitBinaryOp::MOD: $ret = $vertex->getA()->getValue() % $vertex->getB()->getValue(); break; case JitBinaryOp::EQUAL: $ret = $vertex->getA()->getValue() == $vertex->getB()->getValue(); break; case JitBinaryOp::NOT_EQUAL: $ret = $vertex->getA()->getValue() != $vertex->getB()->getValue(); break; case JitBinaryOp::IDENTICAL: $ret = $vertex->getA()->getValue() == $vertex->getB()->getValue(); break; case JitBinaryOp::NOT_IDENTICAL: $ret = $vertex->getA()->getValue() !== $vertex->getB()->getValue(); break; case JitBinaryOp::GREATER: $ret = $vertex->getA()->getValue() > $vertex->getB()->getValue(); break; case JitBinaryOp::GREATER_EQUAL: $ret = $vertex->getA()->getValue() >= $vertex->getB()->getValue(); break; case JitBinaryOp::SMALLER: $ret = $vertex->getA()->getValue() < $vertex->getB()->getValue(); break; case JitBinaryOp::SMALLER_EQUAL: $ret = $vertex->getA()->getValue() <= $vertex->getB()->getValue(); break; case JitBinaryOp::BITWISE_AND: $ret = $vertex->getA()->getValue() & $vertex->getB()->getValue(); break; case JitBinaryOp::BITWISE_OR: $ret = $vertex->getA()->getValue() | $vertex->getB()->getValue(); break; case JitBinaryOp::BITWISE_XOR: $ret = $vertex->getA()->getValue() ^ $vertex->getB()->getValue(); break; case JitBinaryOp::SHIFT_LEFT: $ret = $vertex->getA()->getValue() << $vertex->getB()->getValue(); break; case JitBinaryOp::SHIFT_RIGHT: $ret = $vertex->getA()->getValue() >> $vertex->getB()->getValue(); break; } // replace binary op with assign op Helper::replace($vertex, new JitAssign(new Constant($ret), $vertex->getResult()), $graph); return true; } return false; }
public function process(Vertex $vertex, Digraph $graph) { if ($vertex->getName() !== 'BinaryOp') { return false; } $result = $vertex->getResult(); $rType = $result->getType(); if ($rType->isUnknown() || $rType->getType() === Type::TYPE_NUMERIC) { $typePair = [$vertex->getA()->getType()->getType(), $vertex->getB()->getType()->getType()]; $newType = Type::TYPE_UNKNOWN; switch ($vertex->getKind()) { case JitBinaryOp::PLUS: case JitBinaryOp::MINUS: case JitBinaryOp::MUL: switch ($typePair) { case [Type::TYPE_LONG, Type::TYPE_LONG]: $newType = Type::TYPE_NUMERIC; break; case [Type::TYPE_DOUBLE, Type::TYPE_LONG]: case [Type::TYPE_LONG, Type::TYPE_DOUBLE]: case [Type::TYPE_DOUBLE, Type::TYPE_NUMERIC]: case [Type::TYPE_NUMERIC, Type::TYPE_DOUBLE]: case [Type::TYPE_DOUBLE, Type::TYPE_DOUBLE]: $newType = Type::TYPE_DOUBLE; break; case [Type::TYPE_NUMERIC, Type::TYPE_NUMERIC]: case [Type::TYPE_NUMERIC, Type::TYPE_LONG]: case [Type::TYPE_LONG, Type::TYPE_NUMERIC]: $newType = Type::TYPE_NUMERIC; break; default: if (in_array(Type::TYPE_DOUBLE, $typePair)) { $newType = Type::TYPE_DOUBLE; } else { $newType = Type::TYPE_NUMERIC; } } break; case JitBinaryOp::DIV: $newType = Type::TYPE_DOUBLE; break; case JitBinaryOp::EQUAL: case JitBinaryOp::NOT_EQUAL: case JitBinaryOp::IDENTICAL: case JitBinaryOp::NOT_IDENTICAL: case JitBinaryOp::GREATER: case JitBinaryOp::GREATER_EQUAL: case JitBinaryOp::SMALLER: case JitBinaryOp::SMALLER_EQUAL: $newType = Type::TYPE_BOOLEAN; break; case JitBinaryOp::BITWISE_AND: case JitBinaryOp::BITWISE_OR: case JitBinaryOp::BITWISE_XOR: if ($typePair === [Type::TYPE_STRING, Type::TYPE_STRING]) { $newType = Type::TYPE_STRING; break; } // Fallthrough intentional // Fallthrough intentional case JitBinaryOp::SHIFT_LEFT: case JitBinaryOp::SHIFT_RIGHT: $newType = Type::TYPE_LONG; break; } if ($newType !== Type::TYPE_UNKNOWN && $newType !== $rType->getType()) { $result->setType(new Type($newType)); return true; } } return false; }