mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:17:42 +00:00
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.
This commit is contained in:
parent
80b1604b0a
commit
79eac08f5b
4 changed files with 30 additions and 5 deletions
|
@ -351,6 +351,7 @@ public:
|
||||||
|
|
||||||
virtual Value execute(Interpreter&, GlobalObject&) const override;
|
virtual Value execute(Interpreter&, GlobalObject&) const override;
|
||||||
virtual void dump(int indent) const override;
|
virtual void dump(int indent) const override;
|
||||||
|
virtual Optional<Bytecode::Register> generate_bytecode(Bytecode::Generator&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NonnullRefPtr<Expression> m_predicate;
|
NonnullRefPtr<Expression> m_predicate;
|
||||||
|
|
|
@ -187,4 +187,26 @@ Optional<Bytecode::Register> ReturnStatement::generate_bytecode(Bytecode::Genera
|
||||||
return argument_reg;
|
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 {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ void PutById::execute(Bytecode::Interpreter& interpreter) const
|
||||||
|
|
||||||
void Jump::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
|
void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const
|
||||||
|
@ -196,7 +196,7 @@ String GetById::to_string() const
|
||||||
|
|
||||||
String Jump::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
|
String JumpIfFalse::to_string() const
|
||||||
|
|
|
@ -214,17 +214,19 @@ private:
|
||||||
|
|
||||||
class Jump final : public Instruction {
|
class Jump final : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit Jump(Label target)
|
explicit Jump(Optional<Label> target = {})
|
||||||
: m_target(target)
|
: m_target(move(target))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_target(Optional<Label> target) { m_target = move(target); }
|
||||||
|
|
||||||
virtual ~Jump() override { }
|
virtual ~Jump() override { }
|
||||||
virtual void execute(Bytecode::Interpreter&) const override;
|
virtual void execute(Bytecode::Interpreter&) const override;
|
||||||
virtual String to_string() const override;
|
virtual String to_string() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Label m_target;
|
Optional<Label> m_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JumpIfFalse final : public Instruction {
|
class JumpIfFalse final : public Instruction {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue