From f2863b5a89abaa5b4569b23ea4e314aa93cee95e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 4 Jun 2021 12:20:44 +0200 Subject: [PATCH] LibJS: Generate bytecode for do...while statements :^) This was quite straightforward using the same label/jump machinery that we added for while statements. The main addition here is a new JumpIfTrue bytecode instruction. --- Userland/Libraries/LibJS/AST.h | 1 + .../Libraries/LibJS/Bytecode/ASTCodegen.cpp | 10 ++++++++++ Userland/Libraries/LibJS/Bytecode/Op.cpp | 15 +++++++++++++++ Userland/Libraries/LibJS/Bytecode/Op.h | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 175b2fd824..8a7c2cf1a9 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -391,6 +391,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual Optional generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 14dc55af66..b515870349 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -105,4 +105,14 @@ Optional WhileStatement::generate_bytecode(Bytecode::Generat return body_result_reg; } +Optional DoWhileStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + auto head_label = generator.make_label(); + auto body_result_reg = m_body->generate_bytecode(generator); + auto test_result_reg = m_test->generate_bytecode(generator); + VERIFY(test_result_reg.has_value()); + generator.emit(*test_result_reg, head_label); + return body_result_reg; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 560aedb5e5..51eba805ce 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -64,6 +64,14 @@ void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const interpreter.jump(m_target.value()); } +void JumpIfTrue::execute(Bytecode::Interpreter& interpreter) const +{ + VERIFY(m_target.has_value()); + auto result = interpreter.reg(m_result); + if (result.as_bool()) + interpreter.jump(m_target.value()); +} + String Load::to_string() const { return String::formatted("Load dst:{}, value:{}", m_dst, m_value.to_string_without_side_effects()); @@ -116,4 +124,11 @@ String JumpIfFalse::to_string() const return String::formatted("JumpIfFalse result:{}, target:", m_result); } +String JumpIfTrue::to_string() const +{ + if (m_target.has_value()) + return String::formatted("JumpIfTrue result:{}, target:{}", m_result, m_target.value()); + return String::formatted("JumpIfTrue result:{}, target:", m_result); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 393cc7f304..7b3c38bc17 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -193,4 +193,23 @@ private: Optional