LibJS: Implement abstract equality and inequality

This commit is contained in:
0xtechnobabble 2020-03-16 00:23:38 +02:00 committed by Andreas Kling
parent 4d22a142f7
commit dfbaa8e543
Notes: sideshowbarker 2024-07-19 08:16:45 +09:00
6 changed files with 64 additions and 2 deletions

View File

@ -0,0 +1,12 @@
const object = {};
print(true == 1);
print(null == undefined);
print("12" == 12);
print(1 + "12");
print(12 / "12" == true);
print(2 * "12");
print(~"24");
print(~true);
print(2*2 + "4");
print(object == "[object Object]");

View File

@ -155,7 +155,11 @@ Value BinaryExpression::execute(Interpreter& interpreter) const
case BinaryOp::TypedEquals:
return typed_eq(lhs_result, rhs_result);
case BinaryOp::TypedInequals:
return Value(!typed_eq(lhs_result, rhs_result).to_boolean());
return Value(!typed_eq(lhs_result, rhs_result).as_bool());
case BinaryOp::AbstractEquals:
return eq(lhs_result, rhs_result);
case BinaryOp::AbstractInequals:
return Value(!eq(lhs_result, rhs_result).as_bool());
case BinaryOp::GreaterThan:
return greater_than(lhs_result, rhs_result);
case BinaryOp::GreaterThanEquals:
@ -247,6 +251,12 @@ void BinaryExpression::dump(int indent) const
case BinaryOp::TypedInequals:
op_string = "!==";
break;
case BinaryOp::AbstractEquals:
op_string = "==";
break;
case BinaryOp::AbstractInequals:
op_string = "!=";
break;
case BinaryOp::GreaterThan:
op_string = ">";
break;

View File

@ -248,6 +248,8 @@ enum class BinaryOp {
Slash,
TypedEquals,
TypedInequals,
AbstractEquals,
AbstractInequals,
GreaterThan,
GreaterThanEquals,
LessThan,

View File

@ -334,6 +334,12 @@ NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expre
case TokenType::ExclamationMarkEqualsEquals:
consume();
return make<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::EqualsEquals:
consume();
return make<BinaryExpression>(BinaryOp::AbstractEquals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ExclamationMarkEquals:
consume();
return make<BinaryExpression>(BinaryOp::AbstractInequals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ParenOpen:
return parse_call_expression(move(lhs));
case TokenType::Equals:
@ -543,6 +549,8 @@ bool Parser::match_secondary_expression() const
|| type == TokenType::Equals
|| type == TokenType::EqualsEqualsEquals
|| type == TokenType::ExclamationMarkEqualsEquals
|| type == TokenType::EqualsEquals
|| type == TokenType::ExclamationMarkEquals
|| type == TokenType::GreaterThan
|| type == TokenType::GreaterThanEquals
|| type == TokenType::LessThan

View File

@ -209,7 +209,7 @@ Value typed_eq(Value lhs, Value rhs)
case Value::Type::Number:
return Value(lhs.as_double() == rhs.as_double());
case Value::Type::String:
return Value(lhs.as_string() == rhs.as_string());
return Value(lhs.as_string()->string() == rhs.as_string()->string());
case Value::Type::Boolean:
return Value(lhs.as_bool() == rhs.as_bool());
case Value::Type::Object:
@ -219,6 +219,35 @@ Value typed_eq(Value lhs, Value rhs)
ASSERT_NOT_REACHED();
}
Value eq(Value lhs, Value rhs)
{
if (lhs.type() == rhs.type())
return typed_eq(lhs, rhs);
if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
return Value(true);
if (lhs.is_object() && rhs.is_boolean())
return eq(lhs.as_object()->to_primitive(), rhs.to_number());
if (lhs.is_boolean() && rhs.is_object())
return eq(lhs.to_number(), rhs.as_object()->to_primitive());
if (lhs.is_object())
return eq(lhs.as_object()->to_primitive(), rhs);
if (rhs.is_object())
return eq(lhs, rhs.as_object()->to_primitive());
if (lhs.is_number() || rhs.is_number())
return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
if ((lhs.is_string() && rhs.is_boolean()) || (lhs.is_string() && rhs.is_boolean()))
return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
return Value(false);
}
const LogStream& operator<<(const LogStream& stream, const Value& value)
{
return stream << value.to_string();

View File

@ -174,6 +174,7 @@ Value add(Value lhs, Value rhs);
Value sub(Value lhs, Value rhs);
Value mul(Value lhs, Value rhs);
Value div(Value lhs, Value rhs);
Value eq(Value lhs, Value rhs);
Value typed_eq(Value lhs, Value rhs);
const LogStream& operator<<(const LogStream&, const Value&);