mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 20:47:43 +00:00
LibJS: Generate bytecode for array expressions
This commit is contained in:
parent
b8a5ea1f8d
commit
a1e5711a27
6 changed files with 71 additions and 0 deletions
|
@ -1070,6 +1070,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 void generate_bytecode(Bytecode::Generator&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<RefPtr<Expression>> m_elements;
|
Vector<RefPtr<Expression>> m_elements;
|
||||||
|
|
|
@ -342,6 +342,26 @@ void ObjectExpression::generate_bytecode(Bytecode::Generator& generator) const
|
||||||
TODO();
|
TODO();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArrayExpression::generate_bytecode(Bytecode::Generator& generator) const
|
||||||
|
{
|
||||||
|
Vector<Bytecode::Register> element_regs;
|
||||||
|
for (auto& element : m_elements) {
|
||||||
|
generator.emit<Bytecode::Op::LoadImmediate>(Value {});
|
||||||
|
if (element) {
|
||||||
|
element->generate_bytecode(generator);
|
||||||
|
|
||||||
|
if (is<SpreadExpression>(*element)) {
|
||||||
|
TODO();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto element_reg = generator.allocate_register();
|
||||||
|
generator.emit<Bytecode::Op::Store>(element_reg);
|
||||||
|
element_regs.append(element_reg);
|
||||||
|
}
|
||||||
|
generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(element_regs.size(), element_regs);
|
||||||
|
}
|
||||||
|
|
||||||
void MemberExpression::generate_bytecode(Bytecode::Generator& generator) const
|
void MemberExpression::generate_bytecode(Bytecode::Generator& generator) const
|
||||||
{
|
{
|
||||||
object().generate_bytecode(generator);
|
object().generate_bytecode(generator);
|
||||||
|
|
|
@ -29,6 +29,8 @@ size_t Instruction::length() const
|
||||||
{
|
{
|
||||||
if (type() == Type::Call)
|
if (type() == Type::Call)
|
||||||
return static_cast<Op::Call const&>(*this).length();
|
return static_cast<Op::Call const&>(*this).length();
|
||||||
|
else if (type() == Type::NewArray)
|
||||||
|
return static_cast<Op::NewArray const&>(*this).length();
|
||||||
|
|
||||||
#define __BYTECODE_OP(op) \
|
#define __BYTECODE_OP(op) \
|
||||||
case Type::op: \
|
case Type::op: \
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
O(TypedInequals) \
|
O(TypedInequals) \
|
||||||
O(TypedEquals) \
|
O(TypedEquals) \
|
||||||
O(NewBigInt) \
|
O(NewBigInt) \
|
||||||
|
O(NewArray) \
|
||||||
O(NewString) \
|
O(NewString) \
|
||||||
O(NewObject) \
|
O(NewObject) \
|
||||||
O(GetVariable) \
|
O(GetVariable) \
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <LibJS/AST.h>
|
#include <LibJS/AST.h>
|
||||||
#include <LibJS/Bytecode/Interpreter.h>
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
#include <LibJS/Bytecode/Op.h>
|
#include <LibJS/Bytecode/Op.h>
|
||||||
|
#include <LibJS/Runtime/Array.h>
|
||||||
#include <LibJS/Runtime/BigInt.h>
|
#include <LibJS/Runtime/BigInt.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/ScriptFunction.h>
|
#include <LibJS/Runtime/ScriptFunction.h>
|
||||||
|
@ -125,6 +126,15 @@ void NewBigInt::execute(Bytecode::Interpreter& interpreter) const
|
||||||
interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint);
|
interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NewArray::execute(Bytecode::Interpreter& interpreter) const
|
||||||
|
{
|
||||||
|
Vector<Value> elements;
|
||||||
|
elements.ensure_capacity(m_element_count);
|
||||||
|
for (size_t i = 0; i < m_element_count; i++)
|
||||||
|
elements.append(interpreter.reg(m_elements[i]));
|
||||||
|
interpreter.accumulator() = Array::create_from(interpreter.global_object(), elements);
|
||||||
|
}
|
||||||
|
|
||||||
void NewString::execute(Bytecode::Interpreter& interpreter) const
|
void NewString::execute(Bytecode::Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
interpreter.accumulator() = js_string(interpreter.vm(), m_string);
|
interpreter.accumulator() = js_string(interpreter.vm(), m_string);
|
||||||
|
@ -258,6 +268,22 @@ String NewBigInt::to_string() const
|
||||||
return String::formatted("NewBigInt bigint:\"{}\"", m_bigint.to_base10());
|
return String::formatted("NewBigInt bigint:\"{}\"", m_bigint.to_base10());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String NewArray::to_string() const
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append("NewArray");
|
||||||
|
if (m_element_count != 0) {
|
||||||
|
builder.append(", elements:[");
|
||||||
|
for (size_t i = 0; i < m_element_count; ++i) {
|
||||||
|
builder.appendff("{}", m_elements[i]);
|
||||||
|
if (i != m_element_count - 1)
|
||||||
|
builder.append(',');
|
||||||
|
}
|
||||||
|
builder.append(']');
|
||||||
|
}
|
||||||
|
return builder.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
String NewString::to_string() const
|
String NewString::to_string() const
|
||||||
{
|
{
|
||||||
return String::formatted("NewString string:\"{}\"", m_string);
|
return String::formatted("NewString string:\"{}\"", m_string);
|
||||||
|
|
|
@ -168,6 +168,27 @@ private:
|
||||||
Crypto::SignedBigInteger m_bigint;
|
Crypto::SignedBigInteger m_bigint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NOTE: This instruction is variable-width depending on the number of elements!
|
||||||
|
class NewArray final : public Instruction {
|
||||||
|
public:
|
||||||
|
NewArray(Vector<Register> const& elements)
|
||||||
|
: Instruction(Type::NewArray)
|
||||||
|
, m_element_count(elements.size())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_element_count; ++i)
|
||||||
|
m_elements[i] = elements[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(Bytecode::Interpreter&) const;
|
||||||
|
String to_string() const;
|
||||||
|
|
||||||
|
size_t length() const { return sizeof(*this) + sizeof(Register) * m_element_count; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_element_count { 0 };
|
||||||
|
Register m_elements[];
|
||||||
|
};
|
||||||
|
|
||||||
class ConcatString final : public Instruction {
|
class ConcatString final : public Instruction {
|
||||||
public:
|
public:
|
||||||
ConcatString(Register lhs)
|
ConcatString(Register lhs)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue