| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | #include <LibJS/AST.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Bytecode/Interpreter.h>
 | 
					
						
							|  |  |  | #include <LibJS/Bytecode/Op.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | #include <LibJS/Runtime/GlobalObject.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | #include <LibJS/Runtime/ScriptFunction.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Runtime/Value.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace JS::Bytecode::Op { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Load::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = m_value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Add::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = add(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:32:33 +02:00
										 |  |  | void Sub::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = sub(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:03:57 +02:00
										 |  |  | void LessThan::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = less_than(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:18:06 +02:00
										 |  |  | void AbstractInequals::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = Value(!abstract_eq(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | void NewString::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = js_string(interpreter.vm(), m_string); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:30:23 +02:00
										 |  |  | void NewObject::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = Object::create_empty(interpreter.global_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | void GetVariable::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.reg(m_dst) = interpreter.vm().get_variable(m_identifier, interpreter.global_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SetVariable::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.vm().set_variable(m_identifier, interpreter.reg(m_src), interpreter.global_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  | void GetById::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) | 
					
						
							|  |  |  |         interpreter.reg(m_dst) = object->get(m_property); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  | void PutById::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) | 
					
						
							|  |  |  |         object->put(m_property, interpreter.reg(m_src)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  | void Jump::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     interpreter.jump(m_target); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VERIFY(m_target.has_value()); | 
					
						
							|  |  |  |     auto result = interpreter.reg(m_result); | 
					
						
							|  |  |  |     if (!result.as_bool()) | 
					
						
							|  |  |  |         interpreter.jump(m_target.value()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:20:44 +02:00
										 |  |  | void JumpIfTrue::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VERIFY(m_target.has_value()); | 
					
						
							|  |  |  |     auto result = interpreter.reg(m_result); | 
					
						
							|  |  |  |     if (result.as_bool()) | 
					
						
							|  |  |  |         interpreter.jump(m_target.value()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | void EnterScope::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& vm = interpreter.vm(); | 
					
						
							|  |  |  |     auto& global_object = interpreter.global_object(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& declaration : m_scope_node.functions()) | 
					
						
							|  |  |  |         vm.current_scope()->put_to_scope(declaration.name(), { js_undefined(), DeclarationKind::Var }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& declaration : m_scope_node.functions()) { | 
					
						
							|  |  |  |         auto* function = ScriptFunction::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), vm.current_scope(), declaration.is_strict_mode()); | 
					
						
							|  |  |  |         vm.set_variable(declaration.name(), function, global_object); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // FIXME: Process variable declarations.
 | 
					
						
							|  |  |  |     // FIXME: Whatever else JS::Interpreter::enter_scope() does.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | String Load::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 18:29:30 +02:00
										 |  |  |     return String::formatted("Load dst:{}, value:{}", m_dst, m_value.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String Add::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 18:29:30 +02:00
										 |  |  |     return String::formatted("Add dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:32:33 +02:00
										 |  |  | String Sub::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("Sub dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:03:57 +02:00
										 |  |  | String LessThan::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("LessThan dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:18:06 +02:00
										 |  |  | String AbstractInequals::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("AbstractInequals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | String NewString::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 18:29:30 +02:00
										 |  |  |     return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string); | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:30:23 +02:00
										 |  |  | String NewObject::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("NewObject dst:{}", m_dst); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | String GetVariable::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 18:29:30 +02:00
										 |  |  |     return String::formatted("GetVariable dst:{}, identifier:{}", m_dst, m_identifier); | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String SetVariable::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 18:29:30 +02:00
										 |  |  |     return String::formatted("SetVariable identifier:{}, src:{}", m_identifier, m_src); | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  | String PutById::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("PutById base:{}, property:{}, src:{}", m_base, m_property, m_src); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  | String GetById::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("GetById dst:{}, base:{}, property:{}", m_dst, m_base, m_property); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  | String Jump::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return String::formatted("Jump {}", m_target); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String JumpIfFalse::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_target.has_value()) | 
					
						
							|  |  |  |         return String::formatted("JumpIfFalse result:{}, target:{}", m_result, m_target.value()); | 
					
						
							|  |  |  |     return String::formatted("JumpIfFalse result:{}, target:<empty>", m_result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:20:44 +02:00
										 |  |  | String JumpIfTrue::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_target.has_value()) | 
					
						
							|  |  |  |         return String::formatted("JumpIfTrue result:{}, target:{}", m_result, m_target.value()); | 
					
						
							|  |  |  |     return String::formatted("JumpIfTrue result:{}, target:<empty>", m_result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | String EnterScope::to_string() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return "EnterScope"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | } |