diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 5dc8e73911..b1f5332600 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -1300,6 +1300,7 @@ public: } virtual Value execute(Interpreter&, GlobalObject&) const override; + virtual Optional generate_bytecode(Bytecode::Generator&) const override; const FlyString& target_label() const { return m_target_label; } diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index e53658f2ca..6bb367186b 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -110,6 +110,7 @@ Optional AssignmentExpression::generate_bytecode(Bytecode::G Optional WhileStatement::generate_bytecode(Bytecode::Generator& generator) const { + generator.begin_continuable_scope(); auto test_label = generator.make_label(); auto test_result_reg = m_test->generate_bytecode(generator); VERIFY(test_result_reg.has_value()); @@ -117,13 +118,16 @@ Optional WhileStatement::generate_bytecode(Bytecode::Generat auto body_result_reg = m_body->generate_bytecode(generator); generator.emit(test_label); test_jump.set_target(generator.make_label()); + generator.end_continuable_scope(); return body_result_reg; } Optional DoWhileStatement::generate_bytecode(Bytecode::Generator& generator) const { + generator.begin_continuable_scope(); auto head_label = generator.make_label(); auto body_result_reg = m_body->generate_bytecode(generator); + generator.end_continuable_scope(); auto test_result_reg = m_test->generate_bytecode(generator); VERIFY(test_result_reg.has_value()); generator.emit(*test_result_reg, head_label); @@ -209,4 +213,10 @@ Optional IfStatement::generate_bytecode(Bytecode::Generator& return {}; } +Optional ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + generator.emit(generator.nearest_continuable_scope()); + return {}; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 824f9de063..8a58af5b09 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -47,4 +47,19 @@ Label Generator::make_label() const return Label { m_block->instructions().size() }; } +Label Generator::nearest_continuable_scope() const +{ + return m_continuable_scopes.last(); +} + +void Generator::begin_continuable_scope() +{ + m_continuable_scopes.append(make_label()); +} + +void Generator::end_continuable_scope() +{ + m_continuable_scopes.take_last(); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index e0b4ab8509..3a19525e47 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -29,6 +29,11 @@ public: Label make_label() const; + void begin_continuable_scope(); + void end_continuable_scope(); + + Label nearest_continuable_scope() const; + private: Generator(); ~Generator(); @@ -37,6 +42,7 @@ private: OwnPtr m_block; u32 m_next_register { 1 }; + Vector