diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 2554792f5a..76176fb771 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -937,6 +937,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: UpdateOp m_op; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 207c29eeac..a772ed82b2 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -638,4 +638,32 @@ void TemplateLiteral::generate_bytecode(Bytecode::Generator& generator) const } } } + +void UpdateExpression::generate_bytecode(Bytecode::Generator& generator) const +{ + if (is(*m_argument)) { + auto& identifier = static_cast(*m_argument); + generator.emit(identifier.string()); + + Optional previous_value_for_postfix_reg; + if (!m_prefixed) { + previous_value_for_postfix_reg = generator.allocate_register(); + generator.emit(*previous_value_for_postfix_reg); + } + + if (m_op == UpdateOp::Increment) + generator.emit(); + else + generator.emit(); + + generator.emit(identifier.string()); + + if (!m_prefixed) + generator.emit(*previous_value_for_postfix_reg); + return; + } + + TODO(); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 167e592ed5..c4467437c0 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -54,7 +54,9 @@ O(UnsignedRightShift) \ O(In) \ O(InstanceOf) \ - O(ConcatString) + O(ConcatString) \ + O(Increment) \ + O(Decrement) namespace JS::Bytecode { diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index ee074101f9..87ee3c8690 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -231,6 +231,30 @@ void Return::execute(Bytecode::Interpreter& interpreter) const interpreter.do_return(interpreter.accumulator().value_or(js_undefined())); } +void Increment::execute(Bytecode::Interpreter& interpreter) const +{ + auto old_value = interpreter.accumulator().to_numeric(interpreter.global_object()); + if (interpreter.vm().exception()) + return; + + if (old_value.is_number()) + interpreter.accumulator() = Value(old_value.as_double() + 1); + else + interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 })); +} + +void Decrement::execute(Bytecode::Interpreter& interpreter) const +{ + auto old_value = interpreter.accumulator().to_numeric(interpreter.global_object()); + if (interpreter.vm().exception()) + return; + + if (old_value.is_number()) + interpreter.accumulator() = Value(old_value.as_double() - 1); + else + interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 })); +} + String Load::to_string() const { return String::formatted("Load {}", m_src); @@ -349,4 +373,14 @@ String Return::to_string() const return "Return"; } +String Increment::to_string() const +{ + return "Increment"; +} + +String Decrement::to_string() const +{ + return "Decrement"; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index a431d823bb..59ce5f30c1 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -373,6 +373,28 @@ public: String to_string() const; }; +class Increment final : public Instruction { +public: + Increment() + : Instruction(Type::Increment) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; +}; + +class Decrement final : public Instruction { +public: + Decrement() + : Instruction(Type::Decrement) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; +}; + } namespace JS::Bytecode {