@ugo-studio/jspp 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/cli/args.js +22 -0
  2. package/dist/cli/compiler.js +53 -0
  3. package/dist/cli/index.js +43 -117
  4. package/dist/cli/pch.js +71 -0
  5. package/dist/cli/runner.js +23 -0
  6. package/dist/cli/spinner.js +27 -11
  7. package/dist/cli/transpiler.js +20 -0
  8. package/dist/cli/utils.js +25 -27
  9. package/dist/cli/wasm.js +70 -0
  10. package/dist/index.js +17 -6
  11. package/dist/{analysis → interpreter/analysis}/scope.js +34 -1
  12. package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +542 -3
  13. package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
  14. package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +2 -2
  15. package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +21 -9
  16. package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +3 -3
  17. package/dist/{core → interpreter/core}/codegen/expression-handlers.js +44 -61
  18. package/dist/{core → interpreter/core}/codegen/function-handlers.js +108 -61
  19. package/dist/{core → interpreter/core}/codegen/helpers.js +79 -11
  20. package/dist/interpreter/core/codegen/index.js +156 -0
  21. package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
  22. package/dist/{core → interpreter/core}/codegen/statement-handlers.js +39 -1
  23. package/package.json +6 -4
  24. package/scripts/precompile-headers.ts +63 -19
  25. package/scripts/setup-emsdk.ts +114 -0
  26. package/src/prelude/any_value.cpp +851 -599
  27. package/src/prelude/any_value.hpp +28 -30
  28. package/src/prelude/jspp.hpp +3 -1
  29. package/src/prelude/library/boolean.cpp +30 -0
  30. package/src/prelude/library/boolean.hpp +14 -0
  31. package/src/prelude/library/error.cpp +2 -2
  32. package/src/prelude/library/global.cpp +2 -0
  33. package/src/prelude/library/math.cpp +46 -43
  34. package/src/prelude/library/math.hpp +2 -0
  35. package/src/prelude/library/object.cpp +1 -1
  36. package/src/prelude/types.hpp +10 -9
  37. package/src/prelude/utils/access.hpp +2 -2
  38. package/src/prelude/utils/assignment_operators.hpp +40 -20
  39. package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
  40. package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
  41. package/src/prelude/utils/operators.hpp +87 -87
  42. package/src/prelude/utils/operators_native.hpp +349 -0
  43. package/src/prelude/utils/well_known_symbols.hpp +13 -13
  44. package/src/prelude/values/array.cpp +3 -3
  45. package/src/prelude/values/boolean.cpp +64 -0
  46. package/src/prelude/values/number.cpp +137 -92
  47. package/src/prelude/values/object.cpp +163 -122
  48. package/src/prelude/values/prototypes/boolean.hpp +24 -0
  49. package/src/prelude/values/prototypes/number.hpp +8 -1
  50. package/dist/cli/file-utils.js +0 -20
  51. package/dist/cli-utils/args.js +0 -59
  52. package/dist/cli-utils/colors.js +0 -9
  53. package/dist/cli-utils/file-utils.js +0 -20
  54. package/dist/cli-utils/spinner.js +0 -55
  55. package/dist/cli.js +0 -153
  56. package/dist/core/codegen/index.js +0 -88
  57. package/src/prelude/utils/operators_primitive.hpp +0 -337
  58. /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
  59. /package/dist/{ast → interpreter/ast}/types.js +0 -0
  60. /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
  61. /package/dist/{core → interpreter/core}/constants.js +0 -0
  62. /package/dist/{core → interpreter/core}/error.js +0 -0
  63. /package/dist/{core → interpreter/core}/parser.js +0 -0
  64. /package/dist/{core → interpreter/core}/traverser.js +0 -0
@@ -0,0 +1,349 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+ #include <cstdint> // For int32_t
6
+ #include <cmath> // For fmod, isnan, isinf, floor, abs, pow
7
+ #include <string> // For std::to_string, std::stod
8
+ #include <algorithm> // For std::all_of
9
+ #include <limits> // For numeric_limits
10
+
11
+ namespace jspp
12
+ {
13
+ // Private namespace for helper functions that implement JS type conversions.
14
+ namespace Operators_Private
15
+ {
16
+ // Implements the ToNumber abstract operation from ECMA-262.
17
+ inline double ToNumber(const AnyValue &val)
18
+ {
19
+ if (val.is_number())
20
+ return val.as_double();
21
+ if (val.is_null())
22
+ return 0.0;
23
+ if (val.is_undefined())
24
+ return std::numeric_limits<double>::quiet_NaN();
25
+ if (val.is_boolean())
26
+ return val.as_boolean() ? 1.0 : 0.0;
27
+ if (val.is_string())
28
+ {
29
+ const std::string &s = val.as_string()->value;
30
+ if (s.empty() || std::all_of(s.begin(), s.end(), [](unsigned char c)
31
+ { return std::isspace(c); }))
32
+ return 0.0;
33
+ try
34
+ {
35
+ size_t pos;
36
+ double num = std::stod(s, &pos);
37
+ while (pos < s.length() && std::isspace(static_cast<unsigned char>(s[pos])))
38
+ pos++;
39
+ if (pos != s.length())
40
+ return std::numeric_limits<double>::quiet_NaN();
41
+ return num;
42
+ }
43
+ catch (...)
44
+ {
45
+ return std::numeric_limits<double>::quiet_NaN();
46
+ }
47
+ }
48
+ if (val.is_uninitialized())
49
+ {
50
+ // THROW
51
+ Exception::throw_uninitialized_reference("#<Object>");
52
+ }
53
+ // Default to NaN
54
+ return std::numeric_limits<double>::quiet_NaN();
55
+ }
56
+ // Implements the ToInt32 abstract operation from ECMA-262.
57
+ inline int32_t ToInt32(const AnyValue &val)
58
+ {
59
+ double num = ToNumber(val);
60
+
61
+ if (std::isnan(num) || std::isinf(num) || num == 0)
62
+ return 0;
63
+
64
+ double posInt = std::signbit(num) ? -std::floor(std::abs(num)) : std::floor(std::abs(num));
65
+ double int32bit = fmod(posInt, 4294967296.0); // 2^32
66
+
67
+ if (int32bit >= 2147483648.0) // 2^31
68
+ return static_cast<int32_t>(int32bit - 4294967296.0);
69
+ else
70
+ return static_cast<int32_t>(int32bit);
71
+ }
72
+ // Implements the ToUint32 abstract operation from ECMA-262.
73
+ inline uint32_t ToUint32(const AnyValue &val)
74
+ {
75
+ double num = ToNumber(val);
76
+ if (std::isnan(num) || std::isinf(num) || num == 0)
77
+ return 0;
78
+ double posInt = std::signbit(num) ? -std::floor(std::abs(num)) : std::floor(std::abs(num));
79
+ uint32_t uint32bit = static_cast<uint32_t>(fmod(posInt, 4294967296.0));
80
+ return uint32bit;
81
+ }
82
+ }
83
+
84
+ // --- TRUTHY CHECKER ---
85
+ inline const bool is_truthy(const double &val) noexcept
86
+ {
87
+ return val != 0.0 && !std::isnan(val);
88
+ }
89
+ inline const bool is_truthy(const std::string &val) noexcept
90
+ {
91
+ return !val.empty();
92
+ }
93
+ inline const bool is_truthy(const AnyValue &val) noexcept
94
+ {
95
+ switch (val.get_type())
96
+ {
97
+ case JsType::Number:
98
+ return is_truthy(val.as_double());
99
+ case JsType::String:
100
+ return is_truthy(val.as_string()->value);
101
+ case JsType::Boolean:
102
+ return val.as_boolean();
103
+ case JsType::Null:
104
+ case JsType::Undefined:
105
+ case JsType::Uninitialized:
106
+ return false;
107
+ default:
108
+ return true;
109
+ }
110
+ }
111
+
112
+ // --- BASIC EQUALITY ---
113
+
114
+ // Operator === (returns primitive boolean)
115
+ inline const bool is_strictly_equal_to_native(const AnyValue &lhs, const double &rhs) noexcept
116
+ {
117
+ if (lhs.is_number())
118
+ return lhs.as_double() == rhs;
119
+ return false;
120
+ }
121
+ inline const bool is_strictly_equal_to_native(const double &lhs, const AnyValue &rhs) noexcept
122
+ {
123
+ if (rhs.is_number())
124
+ return lhs == rhs.as_double();
125
+ return false;
126
+ }
127
+ inline const bool is_strictly_equal_to_native(const double &lhs, const double &rhs) noexcept
128
+ {
129
+ return lhs == rhs;
130
+ }
131
+ inline const bool is_strictly_equal_to_native(const AnyValue &lhs, const AnyValue &rhs) noexcept
132
+ {
133
+ JsType type = lhs.get_type();
134
+ if (type != rhs.get_type())
135
+ return false;
136
+ switch (type)
137
+ {
138
+ case JsType::Boolean:
139
+ return lhs.as_boolean() == rhs.as_boolean();
140
+ case JsType::Number:
141
+ return lhs.as_double() == rhs.as_double();
142
+ case JsType::String:
143
+ return lhs.as_string()->value == rhs.as_string()->value;
144
+ case JsType::Array:
145
+ return lhs.as_array() == rhs.as_array();
146
+ case JsType::Object:
147
+ return lhs.as_object() == rhs.as_object();
148
+ case JsType::Function:
149
+ return lhs.as_function() == rhs.as_function();
150
+ case JsType::Iterator:
151
+ return lhs.as_iterator() == rhs.as_iterator();
152
+ case JsType::AsyncIterator:
153
+ return lhs.as_async_iterator() == rhs.as_async_iterator();
154
+ case JsType::Promise:
155
+ return lhs.as_promise() == rhs.as_promise();
156
+ case JsType::Symbol:
157
+ return lhs.as_symbol() == rhs.as_symbol();
158
+ case JsType::DataDescriptor:
159
+ return lhs.as_data_descriptor() == rhs.as_data_descriptor();
160
+ case JsType::AccessorDescriptor:
161
+ return lhs.as_accessor_descriptor() == rhs.as_accessor_descriptor();
162
+ default:
163
+ return true;
164
+ }
165
+ }
166
+
167
+ // Operator == (returns primitive boolean)
168
+ inline const bool is_equal_to_native(const AnyValue &lhs, const double &rhs) noexcept
169
+ {
170
+ return is_equal_to_native(lhs, AnyValue::make_number(rhs));
171
+ }
172
+ inline const bool is_equal_to_native(const double &lhs, const AnyValue &rhs) noexcept
173
+ {
174
+ return is_equal_to_native(AnyValue::make_number(lhs), rhs);
175
+ }
176
+ inline const bool is_equal_to_native(const double &lhs, const double &rhs) noexcept
177
+ {
178
+ return lhs == rhs;
179
+ }
180
+ inline const bool is_equal_to_native(const AnyValue &lhs, const AnyValue &rhs) noexcept
181
+ {
182
+ JsType lhs_type = lhs.get_type();
183
+ JsType rhs_type = rhs.get_type();
184
+ if (lhs_type == rhs_type)
185
+ {
186
+ return is_strictly_equal_to_native(lhs, rhs);
187
+ }
188
+ if ((lhs_type == JsType::Null && rhs_type == JsType::Undefined) || (lhs_type == JsType::Undefined && rhs_type == JsType::Null))
189
+ {
190
+ return true;
191
+ }
192
+ if (lhs_type == JsType::Number && rhs_type == JsType::String)
193
+ {
194
+ return lhs.as_double() == Operators_Private::ToNumber(rhs);
195
+ }
196
+ if (lhs_type == JsType::String && rhs_type == JsType::Number)
197
+ {
198
+ return Operators_Private::ToNumber(lhs) == rhs.as_double();
199
+ }
200
+ if (lhs_type == JsType::Boolean)
201
+ {
202
+ return is_equal_to_native(lhs.as_boolean() ? 1.0 : 0.0, rhs);
203
+ }
204
+ if (rhs_type == JsType::Boolean)
205
+ {
206
+ return is_equal_to_native(lhs, AnyValue::make_number(rhs.as_boolean() ? 1.0 : 0.0));
207
+ }
208
+ if ((lhs_type == JsType::Object || lhs_type == JsType::Array || lhs_type == JsType::Function || lhs_type == JsType::Promise || lhs_type == JsType::Iterator) &&
209
+ (rhs_type == JsType::String || rhs_type == JsType::Number || rhs_type == JsType::Symbol))
210
+ {
211
+ return is_equal_to_native(AnyValue::make_string(lhs.to_std_string()), rhs);
212
+ }
213
+ if ((rhs_type == JsType::Object || rhs_type == JsType::Array || rhs_type == JsType::Function || rhs_type == JsType::Promise || rhs_type == JsType::Iterator) &&
214
+ (lhs_type == JsType::String || lhs_type == JsType::Number || lhs_type == JsType::Symbol))
215
+ {
216
+ return is_equal_to_native(lhs, AnyValue::make_string(rhs.to_std_string()));
217
+ }
218
+ if (lhs_type == JsType::DataDescriptor || lhs_type == JsType::AccessorDescriptor)
219
+ {
220
+ return is_strictly_equal_to_native(lhs, rhs);
221
+ }
222
+ return false;
223
+ }
224
+
225
+ // Operator !== (returns primitive boolean)
226
+ inline const bool not_strictly_equal_to_native(const AnyValue &lhs, const double &rhs) noexcept { return !is_strictly_equal_to_native(lhs, rhs); }
227
+ inline const bool not_strictly_equal_to_native(const double &lhs, const AnyValue &rhs) noexcept { return !is_strictly_equal_to_native(lhs, rhs); }
228
+ inline const bool not_strictly_equal_to_native(const double &lhs, const double &rhs) noexcept { return !is_strictly_equal_to_native(lhs, rhs); }
229
+ inline const bool not_strictly_equal_to_native(const AnyValue &lhs, const AnyValue &rhs) noexcept { return !is_strictly_equal_to_native(lhs, rhs); }
230
+
231
+ // Operator != (returns primitive boolean)
232
+ inline const bool not_equal_to_native(const AnyValue &lhs, const double &rhs) noexcept { return !is_equal_to_native(lhs, rhs); }
233
+ inline const bool not_equal_to_native(const double &lhs, const AnyValue &rhs) noexcept { return !is_equal_to_native(lhs, rhs); }
234
+ inline const bool not_equal_to_native(const double &lhs, const double &rhs) noexcept { return !is_equal_to_native(lhs, rhs); }
235
+ inline const bool not_equal_to_native(const AnyValue &lhs, const AnyValue &rhs) noexcept { return !is_equal_to_native(lhs, rhs); }
236
+
237
+ // --- PRIMITIVE ARITHMETIC OPERATORS ---
238
+ inline double add_native(const double &lhs, const double &rhs) { return lhs + rhs; }
239
+ inline double add_native(const AnyValue &lhs, const AnyValue &rhs) { return Operators_Private::ToNumber(lhs) + Operators_Private::ToNumber(rhs); }
240
+ inline double add_native(const AnyValue &lhs, const double &rhs) { return Operators_Private::ToNumber(lhs) + rhs; }
241
+ inline double add_native(const double &lhs, const AnyValue &rhs) { return lhs + Operators_Private::ToNumber(rhs); }
242
+
243
+ inline double sub_native(const double &lhs, const double &rhs) { return lhs - rhs; }
244
+ inline double sub_native(const AnyValue &lhs, const AnyValue &rhs) { return Operators_Private::ToNumber(lhs) - Operators_Private::ToNumber(rhs); }
245
+ inline double sub_native(const AnyValue &lhs, const double &rhs) { return Operators_Private::ToNumber(lhs) - rhs; }
246
+ inline double sub_native(const double &lhs, const AnyValue &rhs) { return lhs - Operators_Private::ToNumber(rhs); }
247
+
248
+ inline double mul_native(const double &lhs, const double &rhs) { return lhs * rhs; }
249
+ inline double mul_native(const AnyValue &lhs, const AnyValue &rhs) { return Operators_Private::ToNumber(lhs) * Operators_Private::ToNumber(rhs); }
250
+ inline double mul_native(const AnyValue &lhs, const double &rhs) { return Operators_Private::ToNumber(lhs) * rhs; }
251
+ inline double mul_native(const double &lhs, const AnyValue &rhs) { return lhs * Operators_Private::ToNumber(rhs); }
252
+
253
+ inline double div_native(const double &lhs, const double &rhs) { return lhs / rhs; }
254
+ inline double div_native(const AnyValue &lhs, const AnyValue &rhs) { return Operators_Private::ToNumber(lhs) / Operators_Private::ToNumber(rhs); }
255
+ inline double div_native(const AnyValue &lhs, const double &rhs) { return Operators_Private::ToNumber(lhs) / rhs; }
256
+ inline double div_native(const double &lhs, const AnyValue &rhs) { return lhs / Operators_Private::ToNumber(rhs); }
257
+
258
+ inline double mod_native(const double &lhs, const double &rhs) { return std::fmod(lhs, rhs); }
259
+ inline double mod_native(const AnyValue &lhs, const AnyValue &rhs) { return std::fmod(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
260
+ inline double mod_native(const AnyValue &lhs, const double &rhs) { return std::fmod(Operators_Private::ToNumber(lhs), rhs); }
261
+ inline double mod_native(const double &lhs, const AnyValue &rhs) { return std::fmod(lhs, Operators_Private::ToNumber(rhs)); }
262
+
263
+ inline double pow_native(const double &lhs, const double &rhs) { return std::pow(lhs, rhs); }
264
+ inline double pow_native(const AnyValue &lhs, const AnyValue &rhs) { return std::pow(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
265
+ inline double pow_native(const AnyValue &lhs, const double &rhs) { return std::pow(Operators_Private::ToNumber(lhs), rhs); }
266
+ inline double pow_native(const double &lhs, const AnyValue &rhs) { return std::pow(lhs, Operators_Private::ToNumber(rhs)); }
267
+
268
+ // --- PRIMITIVE COMPARISON OPERATORS ---
269
+ inline bool less_than_native(const double &lhs, const double &rhs) { return lhs < rhs; }
270
+ inline bool less_than_native(const AnyValue &lhs, const AnyValue &rhs) { return less_than_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
271
+ inline bool less_than_native(const AnyValue &lhs, const double &rhs) { return less_than_native(Operators_Private::ToNumber(lhs), rhs); }
272
+ inline bool less_than_native(const double &lhs, const AnyValue &rhs) { return less_than_native(lhs, Operators_Private::ToNumber(rhs)); }
273
+
274
+ inline bool greater_than_native(const double &lhs, const double &rhs) { return lhs > rhs; }
275
+ inline bool greater_than_native(const AnyValue &lhs, const AnyValue &rhs) { return greater_than_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
276
+ inline bool greater_than_native(const AnyValue &lhs, const double &rhs) { return greater_than_native(Operators_Private::ToNumber(lhs), rhs); }
277
+ inline bool greater_than_native(const double &lhs, const AnyValue &rhs) { return greater_than_native(lhs, Operators_Private::ToNumber(rhs)); }
278
+
279
+ inline bool less_than_or_equal_native(const double &lhs, const double &rhs) { return lhs <= rhs; }
280
+ inline bool less_than_or_equal_native(const AnyValue &lhs, const AnyValue &rhs) { return less_than_or_equal_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
281
+ inline bool less_than_or_equal_native(const AnyValue &lhs, const double &rhs) { return less_than_or_equal_native(Operators_Private::ToNumber(lhs), rhs); }
282
+ inline bool less_than_or_equal_native(const double &lhs, const AnyValue &rhs) { return less_than_or_equal_native(lhs, Operators_Private::ToNumber(rhs)); }
283
+
284
+ inline bool greater_than_or_equal_native(const double &lhs, const double &rhs) { return lhs >= rhs; }
285
+ inline bool greater_than_or_equal_native(const AnyValue &lhs, const AnyValue &rhs) { return greater_than_or_equal_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
286
+ inline bool greater_than_or_equal_native(const AnyValue &lhs, const double &rhs) { return greater_than_or_equal_native(Operators_Private::ToNumber(lhs), rhs); }
287
+ inline bool greater_than_or_equal_native(const double &lhs, const AnyValue &rhs) { return greater_than_or_equal_native(lhs, Operators_Private::ToNumber(rhs)); }
288
+
289
+ inline bool equal_native(const double &lhs, const double &rhs) { return lhs == rhs; }
290
+ inline bool equal_native(const AnyValue &lhs, const AnyValue &rhs) { return equal_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
291
+ inline bool equal_native(const AnyValue &lhs, const double &rhs) { return equal_native(Operators_Private::ToNumber(lhs), rhs); }
292
+ inline bool equal_native(const double &lhs, const AnyValue &rhs) { return equal_native(lhs, Operators_Private::ToNumber(rhs)); }
293
+
294
+ inline bool not_equal_native(const double &lhs, const double &rhs) { return lhs != rhs; }
295
+ inline bool not_equal_native(const AnyValue &lhs, const AnyValue &rhs) { return not_equal_native(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)); }
296
+ inline bool not_equal_native(const AnyValue &lhs, const double &rhs) { return not_equal_native(Operators_Private::ToNumber(lhs), rhs); }
297
+ inline bool not_equal_native(const double &lhs, const AnyValue &rhs) { return not_equal_native(lhs, Operators_Private::ToNumber(rhs)); }
298
+
299
+ // --- PRIMITIVE BITWISE OPERATORS ---
300
+ inline double bitwise_and_native(const double &lhs, const double &rhs)
301
+ {
302
+ return static_cast<double>(static_cast<int32_t>(lhs) & static_cast<int32_t>(rhs));
303
+ }
304
+ inline double bitwise_and_native(const AnyValue &lhs, const AnyValue &rhs) { return bitwise_and_native(Operators_Private::ToInt32(lhs), Operators_Private::ToInt32(rhs)); }
305
+ inline double bitwise_and_native(const AnyValue &lhs, const double &rhs) { return bitwise_and_native(Operators_Private::ToInt32(lhs), rhs); }
306
+ inline double bitwise_and_native(const double &lhs, const AnyValue &rhs) { return bitwise_and_native(lhs, Operators_Private::ToInt32(rhs)); }
307
+
308
+ inline double bitwise_or_native(const double &lhs, const double &rhs)
309
+ {
310
+ return static_cast<double>(static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
311
+ }
312
+ inline double bitwise_or_native(const AnyValue &lhs, const AnyValue &rhs) { return bitwise_or_native(Operators_Private::ToInt32(lhs), Operators_Private::ToInt32(rhs)); }
313
+ inline double bitwise_or_native(const AnyValue &lhs, const double &rhs) { return bitwise_or_native(Operators_Private::ToInt32(lhs), rhs); }
314
+ inline double bitwise_or_native(const double &lhs, const AnyValue &rhs) { return bitwise_or_native(lhs, Operators_Private::ToInt32(rhs)); }
315
+
316
+ inline double bitwise_xor_native(const double &lhs, const double &rhs)
317
+ {
318
+ return static_cast<double>(static_cast<int32_t>(lhs) ^ static_cast<int32_t>(rhs));
319
+ }
320
+ inline double bitwise_xor_native(const AnyValue &lhs, const AnyValue &rhs) { return bitwise_xor_native(Operators_Private::ToInt32(lhs), Operators_Private::ToInt32(rhs)); }
321
+ inline double bitwise_xor_native(const AnyValue &lhs, const double &rhs) { return bitwise_xor_native(Operators_Private::ToInt32(lhs), rhs); }
322
+ inline double bitwise_xor_native(const double &lhs, const AnyValue &rhs) { return bitwise_xor_native(lhs, Operators_Private::ToInt32(rhs)); }
323
+
324
+ inline double left_shift_native(const double &lhs, const double &rhs)
325
+ {
326
+ return static_cast<double>(static_cast<int32_t>(lhs) << (static_cast<int32_t>(rhs) & 0x1F));
327
+ }
328
+ inline double left_shift_native(const AnyValue &lhs, const AnyValue &rhs) { return left_shift_native(Operators_Private::ToInt32(lhs), Operators_Private::ToInt32(rhs)); }
329
+ inline double left_shift_native(const AnyValue &lhs, const double &rhs) { return left_shift_native(Operators_Private::ToInt32(lhs), rhs); }
330
+ inline double left_shift_native(const double &lhs, const AnyValue &rhs) { return left_shift_native(lhs, Operators_Private::ToInt32(rhs)); }
331
+
332
+ inline double right_shift_native(const double &lhs, const double &rhs)
333
+ {
334
+ return static_cast<double>(static_cast<int32_t>(lhs) >> (static_cast<int32_t>(rhs) & 0x1F));
335
+ }
336
+ inline double right_shift_native(const AnyValue &lhs, const AnyValue &rhs) { return right_shift_native(Operators_Private::ToInt32(lhs), Operators_Private::ToInt32(rhs)); }
337
+ inline double right_shift_native(const AnyValue &lhs, const double &rhs) { return right_shift_native(Operators_Private::ToInt32(lhs), rhs); }
338
+ inline double right_shift_native(const double &lhs, const AnyValue &rhs) { return right_shift_native(lhs, Operators_Private::ToInt32(rhs)); }
339
+
340
+ inline double unsigned_right_shift_native(const double &lhs, const double &rhs)
341
+ {
342
+ uint32_t l = static_cast<uint32_t>(fmod(lhs, 4294967296.0));
343
+ return static_cast<double>(l >> (static_cast<int32_t>(rhs) & 0x1F));
344
+ }
345
+ inline double unsigned_right_shift_native(const AnyValue &lhs, const AnyValue &rhs) { return unsigned_right_shift_native(Operators_Private::ToUint32(lhs), Operators_Private::ToInt32(rhs)); }
346
+ inline double unsigned_right_shift_native(const AnyValue &lhs, const double &rhs) { return unsigned_right_shift_native(Operators_Private::ToUint32(lhs), rhs); }
347
+ inline double unsigned_right_shift_native(const double &lhs, const AnyValue &rhs) { return unsigned_right_shift_native(lhs, Operators_Private::ToInt32(rhs)); }
348
+
349
+ }
@@ -7,18 +7,18 @@ namespace jspp
7
7
  namespace WellKnownSymbols
8
8
  {
9
9
  // We use a specific prefix "@@" for well-known symbols to distinguish them from user symbols
10
- inline JsSymbol* iterator = new JsSymbol("Symbol.iterator", "@@iterator");
11
- inline JsSymbol* asyncIterator = new JsSymbol("Symbol.asyncIterator", "@@asyncIterator");
12
- inline JsSymbol* hasInstance = new JsSymbol("Symbol.hasInstance", "@@hasInstance");
13
- inline JsSymbol* isConcatSpreadable = new JsSymbol("Symbol.isConcatSpreadable", "@@isConcatSpreadable");
14
- inline JsSymbol* match = new JsSymbol("Symbol.match", "@@match");
15
- inline JsSymbol* matchAll = new JsSymbol("Symbol.matchAll", "@@matchAll");
16
- inline JsSymbol* replace = new JsSymbol("Symbol.replace", "@@replace");
17
- inline JsSymbol* search = new JsSymbol("Symbol.search", "@@search");
18
- inline JsSymbol* species = new JsSymbol("Symbol.species", "@@species");
19
- inline JsSymbol* split = new JsSymbol("Symbol.split", "@@split");
20
- inline JsSymbol* toPrimitive = new JsSymbol("Symbol.toPrimitive", "@@toPrimitive");
21
- inline JsSymbol* toStringTag = new JsSymbol("Symbol.toStringTag", "@@toStringTag");
22
- inline JsSymbol* unscopables = new JsSymbol("Symbol.unscopables", "@@unscopables");
10
+ inline JsSymbol *iterator = new JsSymbol("Symbol.iterator", "@@iterator");
11
+ inline JsSymbol *asyncIterator = new JsSymbol("Symbol.asyncIterator", "@@asyncIterator");
12
+ inline JsSymbol *hasInstance = new JsSymbol("Symbol.hasInstance", "@@hasInstance");
13
+ inline JsSymbol *isConcatSpreadable = new JsSymbol("Symbol.isConcatSpreadable", "@@isConcatSpreadable");
14
+ inline JsSymbol *match = new JsSymbol("Symbol.match", "@@match");
15
+ inline JsSymbol *matchAll = new JsSymbol("Symbol.matchAll", "@@matchAll");
16
+ inline JsSymbol *replace = new JsSymbol("Symbol.replace", "@@replace");
17
+ inline JsSymbol *search = new JsSymbol("Symbol.search", "@@search");
18
+ inline JsSymbol *species = new JsSymbol("Symbol.species", "@@species");
19
+ inline JsSymbol *split = new JsSymbol("Symbol.split", "@@split");
20
+ inline JsSymbol *toPrimitive = new JsSymbol("Symbol.toPrimitive", "@@toPrimitive");
21
+ inline JsSymbol *toStringTag = new JsSymbol("Symbol.toStringTag", "@@toStringTag");
22
+ inline JsSymbol *unscopables = new JsSymbol("Symbol.unscopables", "@@unscopables");
23
23
  }
24
24
  }
@@ -513,7 +513,7 @@ AnyValue &get_includes_fn()
513
513
  AnyValue element = self->get_property(static_cast<uint32_t>(i));
514
514
  // SameValueZero algorithm (includes handles NaN)
515
515
  if (element.is_number() && searchElement.is_number() && std::isnan(element.as_double()) && std::isnan(searchElement.as_double())) return Constants::TRUE;
516
- if (is_strictly_equal_to_primitive(element, searchElement)) return Constants::TRUE;
516
+ if (is_strictly_equal_to_native(element, searchElement)) return Constants::TRUE;
517
517
  }
518
518
  return Constants::FALSE; },
519
519
  "includes");
@@ -538,7 +538,7 @@ AnyValue &get_indexOf_fn()
538
538
  {
539
539
  if (self->has_property(std::to_string(i))) {
540
540
  AnyValue element = self->get_property(static_cast<uint32_t>(i));
541
- if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_number(i);
541
+ if (is_strictly_equal_to_native(element, searchElement)) return AnyValue::make_number(i);
542
542
  }
543
543
  }
544
544
  return AnyValue::make_number(-1); },
@@ -565,7 +565,7 @@ AnyValue &get_lastIndexOf_fn()
565
565
  {
566
566
  if (self->has_property(std::to_string(i))) {
567
567
  AnyValue element = self->get_property(static_cast<uint32_t>(i));
568
- if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_number(i);
568
+ if (is_strictly_equal_to_native(element, searchElement)) return AnyValue::make_number(i);
569
569
  }
570
570
  }
571
571
  return AnyValue::make_number(-1); },
@@ -0,0 +1,64 @@
1
+ #include "jspp.hpp"
2
+ #include "values/prototypes/boolean.hpp"
3
+
4
+ namespace jspp
5
+ {
6
+
7
+ // --- JsBoolean Implementation ---
8
+
9
+ namespace JsBoolean
10
+ {
11
+ std::string to_std_string(bool value)
12
+ {
13
+ return value ? "true" : "false";
14
+ }
15
+
16
+ std::string to_std_string(const AnyValue &value)
17
+ {
18
+ return to_std_string(value.as_boolean());
19
+ }
20
+
21
+ }
22
+
23
+ // --- BooleanPrototypes Implementation ---
24
+
25
+ namespace BooleanPrototypes
26
+ {
27
+
28
+ AnyValue &get_toString_fn()
29
+ {
30
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
31
+ { return AnyValue::make_string(JsBoolean::to_std_string(thisVal.as_boolean())); },
32
+ "toString");
33
+ return fn;
34
+ }
35
+
36
+ AnyValue &get_valueOf_fn()
37
+ {
38
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
39
+ { return AnyValue::make_boolean(thisVal.as_boolean()); },
40
+ "valueOf");
41
+ return fn;
42
+ }
43
+
44
+ std::optional<AnyValue> get(const std::string &key)
45
+ {
46
+ if (key == "toString")
47
+ return get_toString_fn();
48
+ if (key == "valueOf")
49
+ return get_valueOf_fn();
50
+ return std::nullopt;
51
+ }
52
+
53
+ std::optional<AnyValue> get(const AnyValue &key)
54
+ {
55
+ if (key == "toString")
56
+ return get_toString_fn();
57
+ if (key == "valueOf")
58
+ return get_valueOf_fn();
59
+ return std::nullopt;
60
+ }
61
+
62
+ } // namespace BooleanPrototypes
63
+
64
+ } // namespace jspp