summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-06-06 13:26:50 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-07 18:11:59 +0200
commit79eac08f5bc9850749a3280d517649a1d0c9933a (patch)
treed1ab742b71e5df578f7549ef15d69a9fa505c737 /Userland
parent80b1604b0a90b85f1fbdfecfcffcbf73e5b485bc (diff)
downloadserenity-79eac08f5bc9850749a3280d517649a1d0c9933a.zip
LibJS: Add basic "if" statement support to the bytecode VM :^)
This also required making Bytecode::Op::Jump support lazy linking to a target label. I left a FIXME here about having the "if" statement return the result value from the taken branch statement. That's what the AST interpreter does but I'm not sure if it's actually required.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/AST.h1
-rw-r--r--Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp22
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.cpp4
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.h8
4 files changed, 30 insertions, 5 deletions
diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h
index 4e156ef655..5dc8e73911 100644
--- a/Userland/Libraries/LibJS/AST.h
+++ b/Userland/Libraries/LibJS/AST.h
@@ -351,6 +351,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_predicate;
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
index 18d4e24700..e53658f2ca 100644
--- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
@@ -187,4 +187,26 @@ Optional<Bytecode::Register> ReturnStatement::generate_bytecode(Bytecode::Genera
return argument_reg;
}
+Optional<Bytecode::Register> IfStatement::generate_bytecode(Bytecode::Generator& generator) const
+{
+ auto predicate_reg = m_predicate->generate_bytecode(generator);
+ auto& if_jump = generator.emit<Bytecode::Op::JumpIfTrue>(*predicate_reg);
+ auto& else_jump = generator.emit<Bytecode::Op::JumpIfFalse>(*predicate_reg);
+
+ if_jump.set_target(generator.make_label());
+ (void)m_consequent->generate_bytecode(generator);
+ auto& end_jump = generator.emit<Bytecode::Op::Jump>();
+
+ else_jump.set_target(generator.make_label());
+ if (m_alternate) {
+ (void)m_alternate->generate_bytecode(generator);
+ }
+
+ end_jump.set_target(generator.make_label());
+
+ // FIXME: Do we need IfStatement to return the consequent/alternate result value?
+ // (That's what the AST interpreter currently does)
+ return {};
+}
+
}
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp
index 869dd169ce..0297533b11 100644
--- a/Userland/Libraries/LibJS/Bytecode/Op.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp
@@ -72,7 +72,7 @@ void PutById::execute(Bytecode::Interpreter& interpreter) const
void Jump::execute(Bytecode::Interpreter& interpreter) const
{
- interpreter.jump(m_target);
+ interpreter.jump(*m_target);
}
void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const
@@ -196,7 +196,7 @@ String GetById::to_string() const
String Jump::to_string() const
{
- return String::formatted("Jump {}", m_target);
+ return String::formatted("Jump {}", *m_target);
}
String JumpIfFalse::to_string() const
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h
index 1d57fed10b..9769a6b5a6 100644
--- a/Userland/Libraries/LibJS/Bytecode/Op.h
+++ b/Userland/Libraries/LibJS/Bytecode/Op.h
@@ -214,17 +214,19 @@ private:
class Jump final : public Instruction {
public:
- explicit Jump(Label target)
- : m_target(target)
+ explicit Jump(Optional<Label> target = {})
+ : m_target(move(target))
{
}
+ void set_target(Optional<Label> target) { m_target = move(target); }
+
virtual ~Jump() override { }
virtual void execute(Bytecode::Interpreter&) const override;
virtual String to_string() const override;
private:
- Label m_target;
+ Optional<Label> m_target;
};
class JumpIfFalse final : public Instruction {