1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 00:35:08 +00:00

LibJS: Implement bitwise assignment operators (&=, |=, ^=)

This commit is contained in:
Linus Groh 2020-05-04 22:34:45 +01:00 committed by Andreas Kling
parent 8e4301dea6
commit 3e754a15d4
8 changed files with 62 additions and 2 deletions

View file

@ -50,7 +50,6 @@ static TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenType type)
return { palette.syntax_string() }; return { palette.syntax_string() };
case JS::TokenType::BracketClose: case JS::TokenType::BracketClose:
case JS::TokenType::BracketOpen: case JS::TokenType::BracketOpen:
case JS::TokenType::Caret:
case JS::TokenType::Comma: case JS::TokenType::Comma:
case JS::TokenType::CurlyClose: case JS::TokenType::CurlyClose:
case JS::TokenType::CurlyOpen: case JS::TokenType::CurlyOpen:
@ -65,6 +64,8 @@ static TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenType type)
case JS::TokenType::Asterisk: case JS::TokenType::Asterisk:
case JS::TokenType::AsteriskAsteriskEquals: case JS::TokenType::AsteriskAsteriskEquals:
case JS::TokenType::AsteriskEquals: case JS::TokenType::AsteriskEquals:
case JS::TokenType::Caret:
case JS::TokenType::CaretEquals:
case JS::TokenType::DoubleAmpersand: case JS::TokenType::DoubleAmpersand:
case JS::TokenType::DoubleAsterisk: case JS::TokenType::DoubleAsterisk:
case JS::TokenType::DoublePipe: case JS::TokenType::DoublePipe:

View file

@ -850,6 +850,24 @@ Value AssignmentExpression::execute(Interpreter& interpreter) const
return {}; return {};
rhs_result = div(interpreter, lhs_result, rhs_result); rhs_result = div(interpreter, lhs_result, rhs_result);
break; break;
case AssignmentOp::BitwiseAndAssignment:
lhs_result = m_lhs->execute(interpreter);
if (interpreter.exception())
return {};
rhs_result = bitwise_and(interpreter, lhs_result, rhs_result);
break;
case AssignmentOp::BitwiseOrAssignment:
lhs_result = m_lhs->execute(interpreter);
if (interpreter.exception())
return {};
rhs_result = bitwise_or(interpreter, lhs_result, rhs_result);
break;
case AssignmentOp::BitwiseXorAssignment:
lhs_result = m_lhs->execute(interpreter);
if (interpreter.exception())
return {};
rhs_result = bitwise_xor(interpreter, lhs_result, rhs_result);
break;
case AssignmentOp::LeftShiftAssignment: case AssignmentOp::LeftShiftAssignment:
lhs_result = m_lhs->execute(interpreter); lhs_result = m_lhs->execute(interpreter);
if (interpreter.exception()) if (interpreter.exception())
@ -936,6 +954,15 @@ void AssignmentExpression::dump(int indent) const
case AssignmentOp::DivisionAssignment: case AssignmentOp::DivisionAssignment:
op_string = "/="; op_string = "/=";
break; break;
case AssignmentOp::BitwiseAndAssignment:
op_string = "&=";
break;
case AssignmentOp::BitwiseOrAssignment:
op_string = "|=";
break;
case AssignmentOp::BitwiseXorAssignment:
op_string = "^=";
break;
case AssignmentOp::LeftShiftAssignment: case AssignmentOp::LeftShiftAssignment:
op_string = "<<="; op_string = "<<=";
break; break;

View file

@ -604,6 +604,9 @@ enum class AssignmentOp {
SubtractionAssignment, SubtractionAssignment,
MultiplicationAssignment, MultiplicationAssignment,
DivisionAssignment, DivisionAssignment,
BitwiseAndAssignment,
BitwiseOrAssignment,
BitwiseXorAssignment,
LeftShiftAssignment, LeftShiftAssignment,
RightShiftAssignment, RightShiftAssignment,
UnsignedRightShiftAssignment, UnsignedRightShiftAssignment,

View file

@ -97,6 +97,7 @@ Lexer::Lexer(StringView source)
s_two_char_tokens.set("%=", TokenType::PercentEquals); s_two_char_tokens.set("%=", TokenType::PercentEquals);
s_two_char_tokens.set("&=", TokenType::AmpersandEquals); s_two_char_tokens.set("&=", TokenType::AmpersandEquals);
s_two_char_tokens.set("|=", TokenType::PipeEquals); s_two_char_tokens.set("|=", TokenType::PipeEquals);
s_two_char_tokens.set("^=", TokenType::CaretEquals);
s_two_char_tokens.set("&&", TokenType::DoubleAmpersand); s_two_char_tokens.set("&&", TokenType::DoubleAmpersand);
s_two_char_tokens.set("||", TokenType::DoublePipe); s_two_char_tokens.set("||", TokenType::DoublePipe);
s_two_char_tokens.set("??", TokenType::DoubleQuestionMark); s_two_char_tokens.set("??", TokenType::DoubleQuestionMark);

View file

@ -140,7 +140,9 @@ Parser::Parser(Lexer lexer)
g_operator_precedence.set(TokenType::ShiftLeftEquals, 3); g_operator_precedence.set(TokenType::ShiftLeftEquals, 3);
g_operator_precedence.set(TokenType::ShiftRightEquals, 3); g_operator_precedence.set(TokenType::ShiftRightEquals, 3);
g_operator_precedence.set(TokenType::UnsignedShiftRightEquals, 3); g_operator_precedence.set(TokenType::UnsignedShiftRightEquals, 3);
g_operator_precedence.set(TokenType::AmpersandEquals, 3);
g_operator_precedence.set(TokenType::PipeEquals, 3); g_operator_precedence.set(TokenType::PipeEquals, 3);
g_operator_precedence.set(TokenType::CaretEquals, 3);
g_operator_precedence.set(TokenType::Yield, 2); g_operator_precedence.set(TokenType::Yield, 2);
@ -668,12 +670,21 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
case TokenType::Ampersand: case TokenType::Ampersand:
consume(); consume();
return create_ast_node<BinaryExpression>(BinaryOp::BitwiseAnd, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::BitwiseAnd, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::AmpersandEquals:
consume();
return create_ast_node<AssignmentExpression>(AssignmentOp::BitwiseAndAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Pipe: case TokenType::Pipe:
consume(); consume();
return create_ast_node<BinaryExpression>(BinaryOp::BitwiseOr, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::BitwiseOr, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::PipeEquals:
consume();
return create_ast_node<AssignmentExpression>(AssignmentOp::BitwiseOrAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Caret: case TokenType::Caret:
consume(); consume();
return create_ast_node<BinaryExpression>(BinaryOp::BitwiseXor, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::BitwiseXor, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::CaretEquals:
consume();
return create_ast_node<AssignmentExpression>(AssignmentOp::BitwiseXorAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ShiftLeft: case TokenType::ShiftLeft:
consume(); consume();
return create_ast_node<BinaryExpression>(BinaryOp::LeftShift, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::LeftShift, move(lhs), parse_expression(min_precedence, associativity));
@ -1199,8 +1210,11 @@ bool Parser::match_secondary_expression() const
|| type == TokenType::Instanceof || type == TokenType::Instanceof
|| type == TokenType::QuestionMark || type == TokenType::QuestionMark
|| type == TokenType::Ampersand || type == TokenType::Ampersand
|| type == TokenType::AmpersandEquals
|| type == TokenType::Pipe || type == TokenType::Pipe
|| type == TokenType::PipeEquals
|| type == TokenType::Caret || type == TokenType::Caret
|| type == TokenType::CaretEquals
|| type == TokenType::ShiftLeft || type == TokenType::ShiftLeft
|| type == TokenType::ShiftLeftEquals || type == TokenType::ShiftLeftEquals
|| type == TokenType::ShiftRight || type == TokenType::ShiftRight

View file

@ -23,6 +23,18 @@ try {
assert((x /= 2) === 3); assert((x /= 2) === 3);
assert(x === 3); assert(x === 3);
x = 3;
assert((x &= 2) === 2);
assert(x === 2);
x = 3;
assert((x |= 4) === 7);
assert(x === 7);
x = 6;
assert((x ^= 2) === 4);
assert(x === 4);
x = 2; x = 2;
assert((x <<= 2) === 8); assert((x <<= 2) === 8);
assert(x === 8); assert(x === 8);

View file

@ -44,6 +44,7 @@ namespace JS {
__ENUMERATE_JS_TOKEN(BracketOpen) \ __ENUMERATE_JS_TOKEN(BracketOpen) \
__ENUMERATE_JS_TOKEN(Break) \ __ENUMERATE_JS_TOKEN(Break) \
__ENUMERATE_JS_TOKEN(Caret) \ __ENUMERATE_JS_TOKEN(Caret) \
__ENUMERATE_JS_TOKEN(CaretEquals) \
__ENUMERATE_JS_TOKEN(Case) \ __ENUMERATE_JS_TOKEN(Case) \
__ENUMERATE_JS_TOKEN(Catch) \ __ENUMERATE_JS_TOKEN(Catch) \
__ENUMERATE_JS_TOKEN(Class) \ __ENUMERATE_JS_TOKEN(Class) \

View file

@ -556,7 +556,6 @@ int main(int argc, char** argv)
break; break;
case JS::TokenType::BracketClose: case JS::TokenType::BracketClose:
case JS::TokenType::BracketOpen: case JS::TokenType::BracketOpen:
case JS::TokenType::Caret:
case JS::TokenType::Comma: case JS::TokenType::Comma:
case JS::TokenType::CurlyClose: case JS::TokenType::CurlyClose:
case JS::TokenType::CurlyOpen: case JS::TokenType::CurlyOpen:
@ -570,6 +569,8 @@ int main(int argc, char** argv)
case JS::TokenType::Asterisk: case JS::TokenType::Asterisk:
case JS::TokenType::AsteriskAsteriskEquals: case JS::TokenType::AsteriskAsteriskEquals:
case JS::TokenType::AsteriskEquals: case JS::TokenType::AsteriskEquals:
case JS::TokenType::Caret:
case JS::TokenType::CaretEquals:
case JS::TokenType::DoubleAmpersand: case JS::TokenType::DoubleAmpersand:
case JS::TokenType::DoubleAsterisk: case JS::TokenType::DoubleAsterisk:
case JS::TokenType::DoublePipe: case JS::TokenType::DoublePipe: