LibJS: Add support for do..while statements

This commit is contained in:
Andreas Kling 2020-04-04 21:29:23 +02:00
parent da0715aba9
commit f8393b80e3
Notes: sideshowbarker 2024-07-19 07:55:56 +09:00
5 changed files with 74 additions and 0 deletions

View file

@ -177,6 +177,20 @@ Value WhileStatement::execute(Interpreter& interpreter) const
return last_value;
}
Value DoWhileStatement::execute(Interpreter& interpreter) const
{
Value last_value = js_undefined();
do {
if (interpreter.exception())
return {};
last_value = interpreter.run(*m_body);
if (interpreter.exception())
return {};
} while (m_test->execute(interpreter).to_boolean());
return last_value;
}
Value ForStatement::execute(Interpreter& interpreter) const
{
RefPtr<BlockStatement> wrapper;
@ -568,6 +582,16 @@ void WhileStatement::dump(int indent) const
body().dump(indent + 1);
}
void DoWhileStatement::dump(int indent) const
{
ASTNode::dump(indent);
print_indent(indent);
printf("DoWhile\n");
test().dump(indent + 1);
body().dump(indent + 1);
}
void ForStatement::dump(int indent) const
{
ASTNode::dump(indent);

View file

@ -257,6 +257,27 @@ private:
NonnullRefPtr<ScopeNode> m_body;
};
class DoWhileStatement : public Statement {
public:
DoWhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<ScopeNode> body)
: m_test(move(test))
, m_body(move(body))
{
}
const Expression& test() const { return *m_test; }
const ScopeNode& body() const { return *m_body; }
virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override;
private:
virtual const char* class_name() const override { return "DoWhileStatement"; }
NonnullRefPtr<Expression> m_test;
NonnullRefPtr<ScopeNode> m_body;
};
class ForStatement : public Statement {
public:
ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<ScopeNode> body)

View file

@ -210,6 +210,8 @@ NonnullRefPtr<Statement> Parser::parse_statement()
return parse_break_statement();
case TokenType::Switch:
return parse_switch_statement();
case TokenType::Do:
return parse_do_while_statement();
default:
if (match_expression())
return adopt(*new ExpressionStatement(parse_expression(0)));
@ -702,6 +704,15 @@ NonnullRefPtr<TryStatement> Parser::parse_try_statement()
return create_ast_node<TryStatement>(move(block), move(handler), move(finalizer));
}
NonnullRefPtr<DoWhileStatement> Parser::parse_do_while_statement()
{
consume(TokenType::Do);
auto body = parse_statement();
consume(TokenType::While);
auto test = parse_expression(0);
return create_ast_node<DoWhileStatement>(move(test), move(body));
}
NonnullRefPtr<SwitchStatement> Parser::parse_switch_statement()
{
consume(TokenType::Switch);

View file

@ -58,6 +58,7 @@ public:
NonnullRefPtr<SwitchStatement> parse_switch_statement();
NonnullRefPtr<SwitchCase> parse_switch_case();
NonnullRefPtr<BreakStatement> parse_break_statement();
NonnullRefPtr<DoWhileStatement> parse_do_while_statement();
NonnullRefPtr<ConditionalExpression> parse_conditional_expression(NonnullRefPtr<Expression> test);
NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right);

View file

@ -0,0 +1,17 @@
function assert(x) { if (!x) throw 1; }
try {
var number = 0;
do {
number++;
} while (number < 9);
assert(number === 9);
number = 0;
do number++; while(number < 3);
assert(number === 3);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}