Value.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/String.h>
  27. #include <LibJS/Heap/Heap.h>
  28. #include <LibJS/Runtime/Object.h>
  29. #include <LibJS/Runtime/PrimitiveString.h>
  30. #include <LibJS/Runtime/StringObject.h>
  31. #include <LibJS/Runtime/Value.h>
  32. namespace JS {
  33. bool Value::is_array() const
  34. {
  35. return is_object() && as_object()->is_array();
  36. }
  37. String Value::to_string() const
  38. {
  39. if (is_boolean())
  40. return as_bool() ? "true" : "false";
  41. if (is_null())
  42. return "null";
  43. if (is_undefined())
  44. return "undefined";
  45. if (is_number())
  46. // FIXME: This needs improvement.
  47. return String::number((i32)as_double());
  48. if (is_object())
  49. return as_object()->to_primitive(Object::PreferredType::String).to_string();
  50. if (is_string())
  51. return m_value.as_string->string();
  52. ASSERT_NOT_REACHED();
  53. }
  54. bool Value::to_boolean() const
  55. {
  56. switch (m_type) {
  57. case Type::Boolean:
  58. return m_value.as_bool;
  59. case Type::Number:
  60. return !(m_value.as_double == 0 || m_value.as_double == -0);
  61. case Type::Null:
  62. case Type::Undefined:
  63. return false;
  64. case Type::String:
  65. return !as_string()->string().is_empty();
  66. case Type::Object:
  67. return true;
  68. default:
  69. ASSERT_NOT_REACHED();
  70. }
  71. }
  72. Value Value::to_object(Heap& heap) const
  73. {
  74. if (is_object())
  75. return const_cast<Object*>(as_object());
  76. if (is_string())
  77. return heap.allocate<StringObject>(m_value.as_string);
  78. ASSERT_NOT_REACHED();
  79. }
  80. Value Value::to_number() const
  81. {
  82. switch (m_type) {
  83. case Type::Boolean:
  84. return Value(m_value.as_bool ? 1 : 0);
  85. case Type::Number:
  86. return Value(m_value.as_double);
  87. case Type::Null:
  88. return Value(0);
  89. case Type::String: {
  90. bool ok;
  91. //FIXME: Parse in a better way
  92. auto parsed_int = as_string()->string().to_int(ok);
  93. if (ok)
  94. return Value(parsed_int);
  95. //FIXME: Implement 'NaN'
  96. ASSERT_NOT_REACHED();
  97. break;
  98. }
  99. case Type::Undefined:
  100. //FIXME: Implement 'NaN'
  101. ASSERT_NOT_REACHED();
  102. case Type::Object:
  103. return m_value.as_object->to_primitive(Object::PreferredType::Number).to_number();
  104. }
  105. ASSERT_NOT_REACHED();
  106. }
  107. i32 Value::to_i32() const
  108. {
  109. return static_cast<i32>(to_number().as_double());
  110. }
  111. Value greater_than(Value lhs, Value rhs)
  112. {
  113. return Value(lhs.to_number().as_double() > rhs.to_number().as_double());
  114. }
  115. Value greater_than_equals(Value lhs, Value rhs)
  116. {
  117. return Value(lhs.to_number().as_double() >= rhs.to_number().as_double());
  118. }
  119. Value less_than(Value lhs, Value rhs)
  120. {
  121. return Value(lhs.to_number().as_double() < rhs.to_number().as_double());
  122. }
  123. Value less_than_equals(Value lhs, Value rhs)
  124. {
  125. return Value(lhs.to_number().as_double() <= rhs.to_number().as_double());
  126. }
  127. Value bitwise_and(Value lhs, Value rhs)
  128. {
  129. return Value((i32)lhs.to_number().as_double() & (i32)rhs.to_number().as_double());
  130. }
  131. Value bitwise_or(Value lhs, Value rhs)
  132. {
  133. return Value((i32)lhs.to_number().as_double() | (i32)rhs.to_number().as_double());
  134. }
  135. Value bitwise_xor(Value lhs, Value rhs)
  136. {
  137. return Value((i32)lhs.to_number().as_double() ^ (i32)rhs.to_number().as_double());
  138. }
  139. Value bitwise_not(Value lhs)
  140. {
  141. return Value(~(i32)lhs.to_number().as_double());
  142. }
  143. Value left_shift(Value lhs, Value rhs)
  144. {
  145. return Value((i32)lhs.to_number().as_double() << (i32)rhs.to_number().as_double());
  146. }
  147. Value right_shift(Value lhs, Value rhs)
  148. {
  149. return Value((i32)lhs.to_number().as_double() >> (i32)rhs.to_number().as_double());
  150. }
  151. Value add(Value lhs, Value rhs)
  152. {
  153. if (lhs.is_string() || rhs.is_string())
  154. return js_string((lhs.is_string() ? lhs : rhs).as_string()->heap(), String::format("%s%s", lhs.to_string().characters(), rhs.to_string().characters()));
  155. return Value(lhs.to_number().as_double() + rhs.to_number().as_double());
  156. }
  157. Value sub(Value lhs, Value rhs)
  158. {
  159. return Value(lhs.to_number().as_double() - rhs.to_number().as_double());
  160. }
  161. Value mul(Value lhs, Value rhs)
  162. {
  163. return Value(lhs.to_number().as_double() * rhs.to_number().as_double());
  164. }
  165. Value div(Value lhs, Value rhs)
  166. {
  167. return Value(lhs.to_number().as_double() / rhs.to_number().as_double());
  168. }
  169. Value typed_eq(Value lhs, Value rhs)
  170. {
  171. if (rhs.type() != lhs.type())
  172. return Value(false);
  173. switch (lhs.type()) {
  174. case Value::Type::Undefined:
  175. return Value(true);
  176. case Value::Type::Null:
  177. return Value(true);
  178. case Value::Type::Number:
  179. return Value(lhs.as_double() == rhs.as_double());
  180. case Value::Type::String:
  181. return Value(lhs.as_string()->string() == rhs.as_string()->string());
  182. case Value::Type::Boolean:
  183. return Value(lhs.as_bool() == rhs.as_bool());
  184. case Value::Type::Object:
  185. return Value(lhs.as_object() == rhs.as_object());
  186. }
  187. ASSERT_NOT_REACHED();
  188. }
  189. Value eq(Value lhs, Value rhs)
  190. {
  191. if (lhs.type() == rhs.type())
  192. return typed_eq(lhs, rhs);
  193. if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
  194. return Value(true);
  195. if (lhs.is_object() && rhs.is_boolean())
  196. return eq(lhs.as_object()->to_primitive(), rhs.to_number());
  197. if (lhs.is_boolean() && rhs.is_object())
  198. return eq(lhs.to_number(), rhs.as_object()->to_primitive());
  199. if (lhs.is_object())
  200. return eq(lhs.as_object()->to_primitive(), rhs);
  201. if (rhs.is_object())
  202. return eq(lhs, rhs.as_object()->to_primitive());
  203. if (lhs.is_number() || rhs.is_number())
  204. return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
  205. if ((lhs.is_string() && rhs.is_boolean()) || (lhs.is_string() && rhs.is_boolean()))
  206. return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
  207. return Value(false);
  208. }
  209. const LogStream& operator<<(const LogStream& stream, const Value& value)
  210. {
  211. return stream << value.to_string();
  212. }
  213. }