diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index b8e9c4a2c9..45380bc975 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -584,6 +584,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual Optional generate_bytecode(Bytecode::Generator&) const override; private: UnaryOp m_op; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 6b5c2511c8..0230c526f5 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -93,6 +93,38 @@ Optional BinaryExpression::generate_bytecode(Bytecode::Gener } } +Optional UnaryExpression::generate_bytecode(Bytecode::Generator& generator) const +{ + auto lhs_reg = m_lhs->generate_bytecode(generator); + + VERIFY(lhs_reg.has_value()); + + auto dst_reg = generator.allocate_register(); + + switch (m_op) { + case UnaryOp::BitwiseNot: + generator.emit(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Not: + generator.emit(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Plus: + generator.emit(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Minus: + generator.emit(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Typeof: + generator.emit(dst_reg, *lhs_reg); + return dst_reg; + case UnaryOp::Void: + generator.emit(dst_reg, js_undefined()); + return dst_reg; + default: + TODO(); + } +} + Optional NumericLiteral::generate_bytecode(Bytecode::Generator& generator) const { auto dst = generator.allocate_register(); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index ccf58871e0..84471e80e2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -37,7 +37,12 @@ O(Return) \ O(BitwiseAnd) \ O(BitwiseOr) \ - O(BitwiseXor) + O(BitwiseXor) \ + O(BitwiseNot) \ + O(Not) \ + O(UnaryPlus) \ + O(UnaryMinus) \ + O(Typeof) namespace JS::Bytecode { diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 58be18b91e..73703d1027 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -127,6 +127,32 @@ void BitwiseXor::execute(Bytecode::Interpreter& interpreter) const interpreter.reg(m_dst) = bitwise_xor(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); } +void BitwiseNot::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = bitwise_not(interpreter.global_object(), interpreter.reg(m_src)); +} + +void Not::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(!interpreter.reg(m_src).to_boolean()); +} + +void UnaryPlus::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(unary_plus(interpreter.global_object(), interpreter.reg(m_src))); +} + +void UnaryMinus::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = Value(unary_minus(interpreter.global_object(), interpreter.reg(m_src))); +} + +void Typeof::execute(Bytecode::Interpreter& interpreter) const +{ + auto& vm = interpreter.global_object().vm(); + interpreter.reg(m_dst) = Value(js_string(vm, interpreter.reg(m_src).typeof())); +} + void NewString::execute(Bytecode::Interpreter& interpreter) const { interpreter.reg(m_dst) = js_string(interpreter.vm(), m_string); @@ -308,6 +334,31 @@ String BitwiseXor::to_string() const return String::formatted("BitwiseXor dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); } +String BitwiseNot::to_string() const +{ + return String::formatted("BitwiseNot dst:{}, src:{}", m_dst, m_src); +} + +String Not::to_string() const +{ + return String::formatted("Not dst:{}, src:{}", m_dst, m_src); +} + +String UnaryPlus::to_string() const +{ + return String::formatted("UnaryPlus dst:{}, src:{}", m_dst, m_src); +} + +String UnaryMinus::to_string() const +{ + return String::formatted("UnaryMinus dst:{}, src:{}", m_dst, m_src); +} + +String Typeof::to_string() const +{ + return String::formatted("Typeof dst:{}, src:{}", m_dst, m_src); +} + String NewString::to_string() const { return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 070856a4bb..17f96d135e 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -317,6 +317,91 @@ private: Register m_src2; }; +class BitwiseNot final : public Instruction { +public: + BitwiseNot(Register dst, Register src) + : Instruction(Type::BitwiseNot) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class Not final : public Instruction { +public: + Not(Register dst, Register src) + : Instruction(Type::Not) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class UnaryPlus final : public Instruction { +public: + UnaryPlus(Register dst, Register src) + : Instruction(Type::UnaryPlus) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class UnaryMinus final : public Instruction { +public: + UnaryMinus(Register dst, Register src) + : Instruction(Type::UnaryMinus) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + +class Typeof final : public Instruction { +public: + Typeof(Register dst, Register src) + : Instruction(Type::Typeof) + , m_dst(dst) + , m_src(src) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; + Register m_src; +}; + class NewString final : public Instruction { public: NewString(Register dst, String string)