mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 11:05:09 +00:00
LibJS: Implement bitwise assignment operators (&=, |=, ^=)
This commit is contained in:
parent
8e4301dea6
commit
3e754a15d4
8 changed files with 62 additions and 2 deletions
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -604,6 +604,9 @@ enum class AssignmentOp {
|
||||||
SubtractionAssignment,
|
SubtractionAssignment,
|
||||||
MultiplicationAssignment,
|
MultiplicationAssignment,
|
||||||
DivisionAssignment,
|
DivisionAssignment,
|
||||||
|
BitwiseAndAssignment,
|
||||||
|
BitwiseOrAssignment,
|
||||||
|
BitwiseXorAssignment,
|
||||||
LeftShiftAssignment,
|
LeftShiftAssignment,
|
||||||
RightShiftAssignment,
|
RightShiftAssignment,
|
||||||
UnsignedRightShiftAssignment,
|
UnsignedRightShiftAssignment,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue