mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 12:05:15 +00:00
LibJS: Implement bitwise left shift operator (<<)
This commit is contained in:
parent
97366f4dd4
commit
f0e7404480
Notes:
sideshowbarker
2024-07-19 07:21:43 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/f0e7404480d Pull-request: https://github.com/SerenityOS/serenity/pull/1931 Reviewed-by: https://github.com/awesomekling
7 changed files with 95 additions and 1 deletions
|
@ -749,6 +749,12 @@ Value AssignmentExpression::execute(Interpreter& interpreter) const
|
|||
return {};
|
||||
rhs_result = div(interpreter, lhs_result, rhs_result);
|
||||
break;
|
||||
case AssignmentOp::LeftShiftAssignment:
|
||||
lhs_result = m_lhs->execute(interpreter);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
rhs_result = left_shift(interpreter, lhs_result, rhs_result);
|
||||
break;
|
||||
}
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
|
@ -816,6 +822,9 @@ void AssignmentExpression::dump(int indent) const
|
|||
case AssignmentOp::DivisionAssignment:
|
||||
op_string = "/=";
|
||||
break;
|
||||
case AssignmentOp::LeftShiftAssignment:
|
||||
op_string = "<<=";
|
||||
break;
|
||||
}
|
||||
|
||||
ASTNode::dump(indent);
|
||||
|
|
|
@ -567,6 +567,7 @@ enum class AssignmentOp {
|
|||
SubtractionAssignment,
|
||||
MultiplicationAssignment,
|
||||
DivisionAssignment,
|
||||
LeftShiftAssignment,
|
||||
};
|
||||
|
||||
class AssignmentExpression : public Expression {
|
||||
|
|
|
@ -577,6 +577,12 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
case TokenType::Caret:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::BitwiseXor, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::ShiftLeft:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::LeftShift, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::ShiftLeftEquals:
|
||||
consume();
|
||||
return create_ast_node<AssignmentExpression>(AssignmentOp::LeftShiftAssignment, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::ParenOpen:
|
||||
return parse_call_expression(move(lhs));
|
||||
case TokenType::Equals:
|
||||
|
@ -1062,6 +1068,8 @@ bool Parser::match_secondary_expression() const
|
|||
|| type == TokenType::Ampersand
|
||||
|| type == TokenType::Pipe
|
||||
|| type == TokenType::Caret
|
||||
|| type == TokenType::ShiftLeft
|
||||
|| type == TokenType::ShiftLeftEquals
|
||||
|| type == TokenType::DoubleAmpersand
|
||||
|| type == TokenType::DoublePipe
|
||||
|| type == TokenType::DoubleQuestionMark;
|
||||
|
|
|
@ -253,7 +253,13 @@ Value unary_minus(Interpreter&, Value lhs)
|
|||
|
||||
Value left_shift(Interpreter&, Value lhs, Value rhs)
|
||||
{
|
||||
return Value((i32)lhs.to_number().as_double() << (i32)rhs.to_number().as_double());
|
||||
auto lhs_number = lhs.to_number();
|
||||
if (!lhs_number.is_finite_number())
|
||||
return Value(0);
|
||||
auto rhs_number = rhs.to_number();
|
||||
if (!rhs_number.is_finite_number())
|
||||
return lhs_number;
|
||||
return Value((i32)lhs_number.as_double() << (i32)lhs_number.as_double());
|
||||
}
|
||||
|
||||
Value right_shift(Interpreter&, Value lhs, Value rhs)
|
||||
|
|
|
@ -57,6 +57,13 @@ public:
|
|||
|
||||
bool is_nan() const { return is_number() && __builtin_isnan(as_double()); }
|
||||
bool is_infinity() const { return is_number() && __builtin_isinf(as_double()); }
|
||||
bool is_finite_number() const
|
||||
{
|
||||
if (!is_number())
|
||||
return false;
|
||||
auto number = as_double();
|
||||
return !__builtin_isnan(number) && !__builtin_isinf(number);
|
||||
}
|
||||
|
||||
Value()
|
||||
: m_type(Type::Empty)
|
||||
|
|
63
Libraries/LibJS/Tests/binary-bitwise-left-shift.js
Normal file
63
Libraries/LibJS/Tests/binary-bitwise-left-shift.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
load("test-common.js");
|
||||
|
||||
try {
|
||||
assert((0 << 0) === 0);
|
||||
assert((0 << 1) === 0);
|
||||
assert((0 << 2) === 0);
|
||||
assert((0 << 3) === 0);
|
||||
assert((0 << 4) === 0);
|
||||
assert((0 << 5) === 0);
|
||||
|
||||
assert((1 << 0) === 1);
|
||||
assert((1 << 1) === 2);
|
||||
assert((1 << 2) === 4);
|
||||
assert((1 << 3) === 8);
|
||||
assert((1 << 4) === 16);
|
||||
assert((1 << 5) === 32);
|
||||
|
||||
assert((2 << 0) === 2);
|
||||
assert((2 << 1) === 4);
|
||||
assert((2 << 2) === 8);
|
||||
assert((2 << 3) === 16);
|
||||
assert((2 << 4) === 32);
|
||||
assert((2 << 5) === 64);
|
||||
|
||||
assert((3 << 0) === 3);
|
||||
assert((3 << 1) === 6);
|
||||
assert((3 << 2) === 12);
|
||||
assert((3 << 3) === 24);
|
||||
assert((3 << 4) === 48);
|
||||
assert((3 << 5) === 96);
|
||||
|
||||
assert((4 << 0) === 4);
|
||||
assert((4 << 1) === 8);
|
||||
assert((4 << 2) === 16);
|
||||
assert((4 << 3) === 32);
|
||||
assert((4 << 4) === 64);
|
||||
assert((4 << 5) === 128);
|
||||
|
||||
assert((5 << 0) === 5);
|
||||
assert((5 << 1) === 10);
|
||||
assert((5 << 2) === 20);
|
||||
assert((5 << 3) === 40);
|
||||
assert((5 << 4) === 80);
|
||||
assert((5 << 5) === 160);
|
||||
|
||||
var x = 3;
|
||||
var y = 7;
|
||||
assert(("42" << 6) === 2688);
|
||||
assert((x << y) === 384);
|
||||
assert((x << [[[[12]]]]) === 12288);
|
||||
assert((undefined << y) === 0);
|
||||
assert(("a" << "b") === 0);
|
||||
assert((null << null) === 0);
|
||||
assert((undefined << undefined) === 0);
|
||||
assert((NaN << NaN) === 0);
|
||||
assert((NaN << 6) === 0);
|
||||
assert((Infinity << Infinity) === 0);
|
||||
assert((-Infinity << Infinity) === 0);
|
||||
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL: " + e);
|
||||
}
|
Loading…
Add table
Reference in a new issue