diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index f35122cabb..2554792f5a 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -1070,6 +1070,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: Vector> m_elements; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index dd92c4a196..a7f79412d6 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -342,6 +342,26 @@ void ObjectExpression::generate_bytecode(Bytecode::Generator& generator) const TODO(); } +void ArrayExpression::generate_bytecode(Bytecode::Generator& generator) const +{ + Vector element_regs; + for (auto& element : m_elements) { + generator.emit(Value {}); + if (element) { + element->generate_bytecode(generator); + + if (is(*element)) { + TODO(); + continue; + } + } + auto element_reg = generator.allocate_register(); + generator.emit(element_reg); + element_regs.append(element_reg); + } + generator.emit_with_extra_register_slots(element_regs.size(), element_regs); +} + void MemberExpression::generate_bytecode(Bytecode::Generator& generator) const { object().generate_bytecode(generator); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.cpp b/Userland/Libraries/LibJS/Bytecode/Instruction.cpp index 899229607d..acbe0d7632 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.cpp @@ -29,6 +29,8 @@ size_t Instruction::length() const { if (type() == Type::Call) return static_cast(*this).length(); + else if (type() == Type::NewArray) + return static_cast(*this).length(); #define __BYTECODE_OP(op) \ case Type::op: \ diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 1b7286eea8..510c63783c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -28,6 +28,7 @@ O(TypedInequals) \ O(TypedEquals) \ O(NewBigInt) \ + O(NewArray) \ O(NewString) \ O(NewObject) \ O(GetVariable) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index ee21957f58..60733de8e2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -125,6 +126,15 @@ void NewBigInt::execute(Bytecode::Interpreter& interpreter) const interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint); } +void NewArray::execute(Bytecode::Interpreter& interpreter) const +{ + Vector 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 { 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()); } +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 { return String::formatted("NewString string:\"{}\"", m_string); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 73d6f837ba..95bb44220f 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -168,6 +168,27 @@ private: Crypto::SignedBigInteger m_bigint; }; +// NOTE: This instruction is variable-width depending on the number of elements! +class NewArray final : public Instruction { +public: + NewArray(Vector 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 { public: ConcatString(Register lhs)