mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:58:11 +00:00
LibJS: Add support for do..while statements
This commit is contained in:
parent
da0715aba9
commit
f8393b80e3
5 changed files with 74 additions and 0 deletions
|
@ -177,6 +177,20 @@ Value WhileStatement::execute(Interpreter& interpreter) const
|
||||||
return last_value;
|
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
|
Value ForStatement::execute(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
RefPtr<BlockStatement> wrapper;
|
RefPtr<BlockStatement> wrapper;
|
||||||
|
@ -568,6 +582,16 @@ void WhileStatement::dump(int indent) const
|
||||||
body().dump(indent + 1);
|
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
|
void ForStatement::dump(int indent) const
|
||||||
{
|
{
|
||||||
ASTNode::dump(indent);
|
ASTNode::dump(indent);
|
||||||
|
|
|
@ -257,6 +257,27 @@ private:
|
||||||
NonnullRefPtr<ScopeNode> m_body;
|
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 {
|
class ForStatement : public Statement {
|
||||||
public:
|
public:
|
||||||
ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<ScopeNode> body)
|
ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<ScopeNode> body)
|
||||||
|
|
|
@ -210,6 +210,8 @@ NonnullRefPtr<Statement> Parser::parse_statement()
|
||||||
return parse_break_statement();
|
return parse_break_statement();
|
||||||
case TokenType::Switch:
|
case TokenType::Switch:
|
||||||
return parse_switch_statement();
|
return parse_switch_statement();
|
||||||
|
case TokenType::Do:
|
||||||
|
return parse_do_while_statement();
|
||||||
default:
|
default:
|
||||||
if (match_expression())
|
if (match_expression())
|
||||||
return adopt(*new ExpressionStatement(parse_expression(0)));
|
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));
|
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()
|
NonnullRefPtr<SwitchStatement> Parser::parse_switch_statement()
|
||||||
{
|
{
|
||||||
consume(TokenType::Switch);
|
consume(TokenType::Switch);
|
||||||
|
|
|
@ -58,6 +58,7 @@ public:
|
||||||
NonnullRefPtr<SwitchStatement> parse_switch_statement();
|
NonnullRefPtr<SwitchStatement> parse_switch_statement();
|
||||||
NonnullRefPtr<SwitchCase> parse_switch_case();
|
NonnullRefPtr<SwitchCase> parse_switch_case();
|
||||||
NonnullRefPtr<BreakStatement> parse_break_statement();
|
NonnullRefPtr<BreakStatement> parse_break_statement();
|
||||||
|
NonnullRefPtr<DoWhileStatement> parse_do_while_statement();
|
||||||
NonnullRefPtr<ConditionalExpression> parse_conditional_expression(NonnullRefPtr<Expression> test);
|
NonnullRefPtr<ConditionalExpression> parse_conditional_expression(NonnullRefPtr<Expression> test);
|
||||||
|
|
||||||
NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right);
|
NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right);
|
||||||
|
|
17
Libraries/LibJS/Tests/do-while-basic.js
Normal file
17
Libraries/LibJS/Tests/do-while-basic.js
Normal 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);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue