1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 22:17:42 +00:00

LibJS: Make sure that if expressions yield the correct value

When evaluated as an expression "if (true) { 3 } else { 5 }"
should yield 3. This updates the bytecode interpreter to make
it so.
This commit is contained in:
Gunnar Beutner 2021-06-07 22:05:09 +02:00 committed by Andreas Kling
parent 2c10bd72f2
commit 93eae063a1
4 changed files with 34 additions and 5 deletions

View file

@ -344,24 +344,25 @@ Optional<Bytecode::Register> ReturnStatement::generate_bytecode(Bytecode::Genera
Optional<Bytecode::Register> IfStatement::generate_bytecode(Bytecode::Generator& generator) const Optional<Bytecode::Register> IfStatement::generate_bytecode(Bytecode::Generator& generator) const
{ {
auto result_reg = generator.allocate_register();
auto predicate_reg = m_predicate->generate_bytecode(generator); auto predicate_reg = m_predicate->generate_bytecode(generator);
auto& if_jump = generator.emit<Bytecode::Op::JumpIfTrue>(*predicate_reg); auto& if_jump = generator.emit<Bytecode::Op::JumpIfTrue>(*predicate_reg);
auto& else_jump = generator.emit<Bytecode::Op::JumpIfFalse>(*predicate_reg); auto& else_jump = generator.emit<Bytecode::Op::JumpIfFalse>(*predicate_reg);
if_jump.set_target(generator.make_label()); if_jump.set_target(generator.make_label());
(void)m_consequent->generate_bytecode(generator); auto consequent_reg = m_consequent->generate_bytecode(generator);
generator.emit<Bytecode::Op::LoadRegister>(result_reg, *consequent_reg);
auto& end_jump = generator.emit<Bytecode::Op::Jump>(); auto& end_jump = generator.emit<Bytecode::Op::Jump>();
else_jump.set_target(generator.make_label()); else_jump.set_target(generator.make_label());
if (m_alternate) { if (m_alternate) {
(void)m_alternate->generate_bytecode(generator); auto alternative_reg = m_alternate->generate_bytecode(generator);
generator.emit<Bytecode::Op::LoadRegister>(result_reg, *alternative_reg);
} }
end_jump.set_target(generator.make_label()); end_jump.set_target(generator.make_label());
// FIXME: Do we need IfStatement to return the consequent/alternate result value? return result_reg;
// (That's what the AST interpreter currently does)
return {};
} }
Optional<Bytecode::Register> ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const Optional<Bytecode::Register> ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const

View file

@ -11,6 +11,7 @@
#define ENUMERATE_BYTECODE_OPS(O) \ #define ENUMERATE_BYTECODE_OPS(O) \
O(Load) \ O(Load) \
O(LoadRegister) \
O(Add) \ O(Add) \
O(Sub) \ O(Sub) \
O(Mul) \ O(Mul) \

View file

@ -52,6 +52,11 @@ void Load::execute(Bytecode::Interpreter& interpreter) const
interpreter.reg(m_dst) = m_value; interpreter.reg(m_dst) = m_value;
} }
void LoadRegister::execute(Bytecode::Interpreter& interpreter) const
{
interpreter.reg(m_dst) = interpreter.reg(m_src);
}
void Add::execute(Bytecode::Interpreter& interpreter) const void Add::execute(Bytecode::Interpreter& interpreter) const
{ {
interpreter.reg(m_dst) = add(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); interpreter.reg(m_dst) = add(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
@ -284,6 +289,11 @@ String Load::to_string() const
return String::formatted("Load dst:{}, value:{}", m_dst, m_value.to_string_without_side_effects()); return String::formatted("Load dst:{}, value:{}", m_dst, m_value.to_string_without_side_effects());
} }
String LoadRegister::to_string() const
{
return String::formatted("LoadRegister dst:{}, src:{}", m_dst, m_src);
}
String Add::to_string() const String Add::to_string() const
{ {
return String::formatted("Add dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); return String::formatted("Add dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);

View file

@ -32,6 +32,23 @@ private:
Value m_value; Value m_value;
}; };
class LoadRegister final : public Instruction {
public:
LoadRegister(Register dst, Register src)
: Instruction(Type::LoadRegister)
, m_dst(dst)
, m_src(src)
{
}
void execute(Bytecode::Interpreter&) const;
String to_string() const;
private:
Register m_dst;
Register m_src;
};
class Add final : public Instruction { class Add final : public Instruction {
public: public:
Add(Register dst, Register src1, Register src2) Add(Register dst, Register src1, Register src2)