LibJS: Implement update expressions

Note that currently only the non-prefixed variant is supported (i.e i++
not ++i), this variant returns the value of the argument before the
update.
This commit is contained in:
0xtechnobabble 2020-03-12 13:45:45 +02:00 committed by Andreas Kling
parent dc9a702aa8
commit 8557bc56f7
Notes: sideshowbarker 2024-07-19 08:20:54 +09:00
3 changed files with 69 additions and 1 deletions

View file

@ -442,6 +442,25 @@ Value AssignmentExpression::execute(Interpreter& interpreter) const
return rhs_result;
}
Value UpdateExpression::execute(Interpreter& interpreter) const
{
ASSERT(m_argument->is_identifier());
auto name = static_cast<const Identifier&>(*m_argument).string();
auto previous_value = interpreter.get_variable(name);
ASSERT(previous_value.is_number());
switch (m_op) {
case UpdateOp::Increment:
interpreter.set_variable(name, Value(previous_value.as_double() + 1));
break;
case UpdateOp::Decrement:
interpreter.set_variable(name, Value(previous_value.as_double() - 1));
}
return previous_value;
}
void AssignmentExpression::dump(int indent) const
{
const char* op_string = nullptr;
@ -470,6 +489,24 @@ void AssignmentExpression::dump(int indent) const
m_rhs->dump(indent + 1);
}
void UpdateExpression::dump(int indent) const
{
const char* op_string = nullptr;
switch (m_op) {
case UpdateOp::Increment:
op_string = "++";
break;
case UpdateOp::Decrement:
op_string = "--";
break;
}
ASTNode::dump(indent);
print_indent(indent + 1);
printf("%s\n", op_string);
m_argument->dump(indent + 1);
}
Value VariableDeclaration::execute(Interpreter& interpreter) const
{
interpreter.declare_variable(name().string(), m_declaration_type);

View file

@ -444,6 +444,29 @@ private:
NonnullOwnPtr<Expression> m_rhs;
};
enum class UpdateOp {
Increment,
Decrement,
};
class UpdateExpression : public Expression {
public:
UpdateExpression(UpdateOp op, NonnullOwnPtr<Expression> argument)
: m_op(op)
, m_argument(move(argument))
{
}
virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override;
private:
virtual const char* class_name() const override { return "UpdateExpression"; }
UpdateOp m_op;
NonnullOwnPtr<Identifier> m_argument;
};
enum class DeclarationType {
Var,
Let,

View file

@ -174,6 +174,12 @@ NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expre
case TokenType::Period:
consume();
return make<MemberExpression>(move(lhs), parse_expression());
case TokenType::PlusPlus:
consume();
return make<UpdateExpression>(UpdateOp::Increment, move(lhs));
case TokenType::MinusMinus:
consume();
return make<UpdateExpression>(UpdateOp::Decrement, move(lhs));
default:
m_has_errors = true;
expected("secondary expression (missing switch case)");
@ -352,7 +358,9 @@ bool Parser::match_secondary_expression() const
|| type == TokenType::LessThan
|| type == TokenType::LessThanEquals
|| type == TokenType::ParenOpen
|| type == TokenType::Period;
|| type == TokenType::Period
|| type == TokenType::PlusPlus
|| type == TokenType::MinusMinus;
}
bool Parser::match_statement() const