diff options
author | Andreas Kling <kling@serenityos.org> | 2021-06-04 12:20:44 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-07 18:11:59 +0200 |
commit | f2863b5a89abaa5b4569b23ea4e314aa93cee95e (patch) | |
tree | afdd9d100bcf672173bb431c37fab1ab0c89c45d /Userland/Libraries | |
parent | bd1a5e282a6355a4c5e7646da364b79153d757bd (diff) | |
download | serenity-f2863b5a89abaa5b4569b23ea4e314aa93cee95e.zip |
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.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/AST.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 15 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 19 |
4 files changed, 45 insertions, 0 deletions
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<Bytecode::Register> generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr<Expression> 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<Bytecode::Register> WhileStatement::generate_bytecode(Bytecode::Generat return body_result_reg; } +Optional<Bytecode::Register> 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<Bytecode::Op::JumpIfTrue>(*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:<empty>", 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:<empty>", 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<Label> m_target; }; +class JumpIfTrue final : public Instruction { +public: + explicit JumpIfTrue(Register result, Optional<Label> target = {}) + : m_result(result) + , m_target(move(target)) + { + } + + void set_target(Optional<Label> target) { m_target = move(target); } + + virtual ~JumpIfTrue() override { } + virtual void execute(Bytecode::Interpreter&) const override; + virtual String to_string() const override; + +private: + Register m_result; + Optional<Label> m_target; +}; + } |