/** * Handles the given compare-operator * * @param string $op the operator (==, !=, ===, ...) * @param PC_Obj_MultiType $e1 the first operand * @param PC_Obj_MultiType $e2 the second operand * @return PC_Obj_MultiType the result */ public function handle_cmp($op, $e1, $e2) { if (!$e1 instanceof PC_Obj_MultiType) { return $this->handle_error('$e1 is invalid'); } if (!$e2 instanceof PC_Obj_MultiType) { return $this->handle_error('$e2 is invalid'); } // if we don't know one of the types or values, try to determine the type by the operator // if we're in a loop, do that, too. if ($this->vars->is_in_loop() || $e1->is_val_unknown() || $e2->is_val_unknown()) { return $this->get_type_from_op($op, $e1, $e2); } // if we have an array-operation, just return bool, because we would have to do it ourself // and I think its not worth the effort. $e1arr = $e1->get_first()->get_type() == PC_Obj_Type::TARRAY; $e2arr = $e2->get_first()->get_type() == PC_Obj_Type::TARRAY; if ($e1arr && $e2arr || $e1arr && $e1->is_array_unknown() || $e2arr && $e2->is_array_unknown()) { return PC_Obj_MultiType::create_bool(); } $val = false; $f1 = $e1->get_first(); $f2 = $e2->get_first(); switch ($op) { // its not a good idea to use eval in this case because it might change the type case '===': $val = $f1->get_value_for_use() === $f2->get_value_for_use(); break; case '!==': $val = $f1->get_value_for_use() !== $f2->get_value_for_use(); break; case '?:': if ($f1->get_value_for_use() < $f2->get_value_for_use()) { $val = -1; } else { if ($f1->get_value_for_use() > $f2->get_value_for_use()) { $val = 1; } else { $val = 0; } } return PC_Obj_MultiType::create_int($val); case '==': case '!=': case '<': case '>': case '<=': case '>=': case '?:': eval('$val = ' . $f1->get_value_for_eval() . ' ' . $op . ' ' . $f2->get_value_for_eval() . ';'); break; } return PC_Obj_MultiType::create_bool($val); }