mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 01:08:11 +00:00
LibJS: Implement abstract equality and inequality
This commit is contained in:
parent
4d22a142f7
commit
dfbaa8e543
6 changed files with 64 additions and 2 deletions
12
Base/home/anon/js/type-play.js
Normal file
12
Base/home/anon/js/type-play.js
Normal 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]");
|
|
@ -155,7 +155,11 @@ Value BinaryExpression::execute(Interpreter& interpreter) const
|
||||||
case BinaryOp::TypedEquals:
|
case BinaryOp::TypedEquals:
|
||||||
return typed_eq(lhs_result, rhs_result);
|
return typed_eq(lhs_result, rhs_result);
|
||||||
case BinaryOp::TypedInequals:
|
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:
|
case BinaryOp::GreaterThan:
|
||||||
return greater_than(lhs_result, rhs_result);
|
return greater_than(lhs_result, rhs_result);
|
||||||
case BinaryOp::GreaterThanEquals:
|
case BinaryOp::GreaterThanEquals:
|
||||||
|
@ -247,6 +251,12 @@ void BinaryExpression::dump(int indent) const
|
||||||
case BinaryOp::TypedInequals:
|
case BinaryOp::TypedInequals:
|
||||||
op_string = "!==";
|
op_string = "!==";
|
||||||
break;
|
break;
|
||||||
|
case BinaryOp::AbstractEquals:
|
||||||
|
op_string = "==";
|
||||||
|
break;
|
||||||
|
case BinaryOp::AbstractInequals:
|
||||||
|
op_string = "!=";
|
||||||
|
break;
|
||||||
case BinaryOp::GreaterThan:
|
case BinaryOp::GreaterThan:
|
||||||
op_string = ">";
|
op_string = ">";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -248,6 +248,8 @@ enum class BinaryOp {
|
||||||
Slash,
|
Slash,
|
||||||
TypedEquals,
|
TypedEquals,
|
||||||
TypedInequals,
|
TypedInequals,
|
||||||
|
AbstractEquals,
|
||||||
|
AbstractInequals,
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
GreaterThanEquals,
|
GreaterThanEquals,
|
||||||
LessThan,
|
LessThan,
|
||||||
|
|
|
@ -334,6 +334,12 @@ NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expre
|
||||||
case TokenType::ExclamationMarkEqualsEquals:
|
case TokenType::ExclamationMarkEqualsEquals:
|
||||||
consume();
|
consume();
|
||||||
return make<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression(min_precedence, associativity));
|
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:
|
case TokenType::ParenOpen:
|
||||||
return parse_call_expression(move(lhs));
|
return parse_call_expression(move(lhs));
|
||||||
case TokenType::Equals:
|
case TokenType::Equals:
|
||||||
|
@ -543,6 +549,8 @@ bool Parser::match_secondary_expression() const
|
||||||
|| type == TokenType::Equals
|
|| type == TokenType::Equals
|
||||||
|| type == TokenType::EqualsEqualsEquals
|
|| type == TokenType::EqualsEqualsEquals
|
||||||
|| type == TokenType::ExclamationMarkEqualsEquals
|
|| type == TokenType::ExclamationMarkEqualsEquals
|
||||||
|
|| type == TokenType::EqualsEquals
|
||||||
|
|| type == TokenType::ExclamationMarkEquals
|
||||||
|| type == TokenType::GreaterThan
|
|| type == TokenType::GreaterThan
|
||||||
|| type == TokenType::GreaterThanEquals
|
|| type == TokenType::GreaterThanEquals
|
||||||
|| type == TokenType::LessThan
|
|| type == TokenType::LessThan
|
||||||
|
|
|
@ -209,7 +209,7 @@ Value typed_eq(Value lhs, Value rhs)
|
||||||
case Value::Type::Number:
|
case Value::Type::Number:
|
||||||
return Value(lhs.as_double() == rhs.as_double());
|
return Value(lhs.as_double() == rhs.as_double());
|
||||||
case Value::Type::String:
|
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:
|
case Value::Type::Boolean:
|
||||||
return Value(lhs.as_bool() == rhs.as_bool());
|
return Value(lhs.as_bool() == rhs.as_bool());
|
||||||
case Value::Type::Object:
|
case Value::Type::Object:
|
||||||
|
@ -219,6 +219,35 @@ Value typed_eq(Value lhs, Value rhs)
|
||||||
ASSERT_NOT_REACHED();
|
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)
|
const LogStream& operator<<(const LogStream& stream, const Value& value)
|
||||||
{
|
{
|
||||||
return stream << value.to_string();
|
return stream << value.to_string();
|
||||||
|
|
|
@ -174,6 +174,7 @@ Value add(Value lhs, Value rhs);
|
||||||
Value sub(Value lhs, Value rhs);
|
Value sub(Value lhs, Value rhs);
|
||||||
Value mul(Value lhs, Value rhs);
|
Value mul(Value lhs, Value rhs);
|
||||||
Value div(Value lhs, Value rhs);
|
Value div(Value lhs, Value rhs);
|
||||||
|
Value eq(Value lhs, Value rhs);
|
||||||
Value typed_eq(Value lhs, Value rhs);
|
Value typed_eq(Value lhs, Value rhs);
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream&, const Value&);
|
const LogStream& operator<<(const LogStream&, const Value&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue