mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:47:43 +00:00
LibJS: Basic bytecode support for computed member expressions
Expressions like foo[1 + 2] now work, and you can assign to them as well! :^)
This commit is contained in:
parent
b47246ec70
commit
9ee5029bc5
4 changed files with 75 additions and 3 deletions
|
@ -375,14 +375,18 @@ void AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) con
|
||||||
generator.emit<Bytecode::Op::Store>(object_reg);
|
generator.emit<Bytecode::Op::Store>(object_reg);
|
||||||
|
|
||||||
if (expression.is_computed()) {
|
if (expression.is_computed()) {
|
||||||
TODO();
|
expression.property().generate_bytecode(generator);
|
||||||
|
auto property_reg = generator.allocate_register();
|
||||||
|
generator.emit<Bytecode::Op::Store>(property_reg);
|
||||||
|
m_rhs->generate_bytecode(generator);
|
||||||
|
generator.emit<Bytecode::Op::PutByValue>(object_reg, property_reg);
|
||||||
} else {
|
} else {
|
||||||
VERIFY(is<Identifier>(expression.property()));
|
VERIFY(is<Identifier>(expression.property()));
|
||||||
m_rhs->generate_bytecode(generator);
|
m_rhs->generate_bytecode(generator);
|
||||||
auto identifier_table_ref = generator.intern_string(static_cast<Identifier const&>(expression.property()).string());
|
auto identifier_table_ref = generator.intern_string(static_cast<Identifier const&>(expression.property()).string());
|
||||||
generator.emit<Bytecode::Op::PutById>(object_reg, identifier_table_ref);
|
generator.emit<Bytecode::Op::PutById>(object_reg, identifier_table_ref);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TODO();
|
TODO();
|
||||||
|
@ -585,7 +589,11 @@ void MemberExpression::generate_bytecode(Bytecode::Generator& generator) const
|
||||||
object().generate_bytecode(generator);
|
object().generate_bytecode(generator);
|
||||||
|
|
||||||
if (is_computed()) {
|
if (is_computed()) {
|
||||||
TODO();
|
auto object_reg = generator.allocate_register();
|
||||||
|
generator.emit<Bytecode::Op::Store>(object_reg);
|
||||||
|
|
||||||
|
property().generate_bytecode(generator);
|
||||||
|
generator.emit<Bytecode::Op::GetByValue>(object_reg);
|
||||||
} else {
|
} else {
|
||||||
VERIFY(is<Identifier>(property()));
|
VERIFY(is<Identifier>(property()));
|
||||||
auto identifier_table_ref = generator.intern_string(static_cast<Identifier const&>(property()).string());
|
auto identifier_table_ref = generator.intern_string(static_cast<Identifier const&>(property()).string());
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
O(SetVariable) \
|
O(SetVariable) \
|
||||||
O(PutById) \
|
O(PutById) \
|
||||||
O(GetById) \
|
O(GetById) \
|
||||||
|
O(PutByValue) \
|
||||||
|
O(GetByValue) \
|
||||||
O(Jump) \
|
O(Jump) \
|
||||||
O(JumpConditional) \
|
O(JumpConditional) \
|
||||||
O(JumpNullish) \
|
O(JumpNullish) \
|
||||||
|
|
|
@ -291,6 +291,26 @@ void Yield::execute(Bytecode::Interpreter& interpreter) const
|
||||||
interpreter.do_return(object);
|
interpreter.do_return(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetByValue::execute(Bytecode::Interpreter& interpreter) const
|
||||||
|
{
|
||||||
|
if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) {
|
||||||
|
auto property_key = interpreter.accumulator().to_property_key(interpreter.global_object());
|
||||||
|
if (interpreter.vm().exception())
|
||||||
|
return;
|
||||||
|
interpreter.accumulator() = object->get(property_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PutByValue::execute(Bytecode::Interpreter& interpreter) const
|
||||||
|
{
|
||||||
|
if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) {
|
||||||
|
auto property_key = interpreter.reg(m_property).to_property_key(interpreter.global_object());
|
||||||
|
if (interpreter.vm().exception())
|
||||||
|
return;
|
||||||
|
object->put(property_key, interpreter.accumulator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String Load::to_string(Bytecode::Executable const&) const
|
String Load::to_string(Bytecode::Executable const&) const
|
||||||
{
|
{
|
||||||
return String::formatted("Load {}", m_src);
|
return String::formatted("Load {}", m_src);
|
||||||
|
@ -463,4 +483,14 @@ String Yield::to_string(Bytecode::Executable const&) const
|
||||||
return String::formatted("Yield return");
|
return String::formatted("Yield return");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String GetByValue::to_string(const Bytecode::Executable&) const
|
||||||
|
{
|
||||||
|
return String::formatted("GetByValue base:{}", m_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
String PutByValue::to_string(const Bytecode::Executable&) const
|
||||||
|
{
|
||||||
|
return String::formatted("PutByValue base:{}, property:{}", m_base, m_property);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,6 +266,38 @@ private:
|
||||||
StringTableIndex m_property;
|
StringTableIndex m_property;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetByValue final : public Instruction {
|
||||||
|
public:
|
||||||
|
explicit GetByValue(Register base)
|
||||||
|
: Instruction(Type::GetByValue)
|
||||||
|
, m_base(base)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(Bytecode::Interpreter&) const;
|
||||||
|
String to_string(Bytecode::Executable const&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Register m_base;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PutByValue final : public Instruction {
|
||||||
|
public:
|
||||||
|
PutByValue(Register base, Register property)
|
||||||
|
: Instruction(Type::PutByValue)
|
||||||
|
, m_base(base)
|
||||||
|
, m_property(property)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(Bytecode::Interpreter&) const;
|
||||||
|
String to_string(Bytecode::Executable const&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Register m_base;
|
||||||
|
Register m_property;
|
||||||
|
};
|
||||||
|
|
||||||
class Jump : public Instruction {
|
class Jump : public Instruction {
|
||||||
public:
|
public:
|
||||||
constexpr static bool IsTerminator = true;
|
constexpr static bool IsTerminator = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue