1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 10:08:10 +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:
Andreas Kling 2021-06-06 13:26:50 +02:00
parent 80b1604b0a
commit 79eac08f5b
4 changed files with 30 additions and 5 deletions

View file

@ -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 {};
}
}

View file

@ -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

View file

@ -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 {