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:
parent
2c10bd72f2
commit
93eae063a1
4 changed files with 34 additions and 5 deletions
|
@ -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
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue