@ugo-studio/jspp 0.1.4 → 0.1.6

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 (71) hide show
  1. package/dist/analysis/scope.js +17 -0
  2. package/dist/analysis/typeAnalyzer.js +7 -1
  3. package/dist/ast/symbols.js +32 -0
  4. package/dist/ast/types.js +0 -6
  5. package/dist/cli-utils/args.js +57 -0
  6. package/dist/cli-utils/colors.js +9 -0
  7. package/dist/cli-utils/file-utils.js +20 -0
  8. package/dist/cli-utils/spinner.js +55 -0
  9. package/dist/cli.js +105 -30
  10. package/dist/core/codegen/class-handlers.js +10 -6
  11. package/dist/core/codegen/control-flow-handlers.js +57 -28
  12. package/dist/core/codegen/declaration-handlers.js +10 -6
  13. package/dist/core/codegen/expression-handlers.js +206 -61
  14. package/dist/core/codegen/function-handlers.js +203 -76
  15. package/dist/core/codegen/helpers.js +125 -28
  16. package/dist/core/codegen/index.js +23 -15
  17. package/dist/core/codegen/literal-handlers.js +15 -6
  18. package/dist/core/codegen/statement-handlers.js +282 -84
  19. package/dist/core/codegen/visitor.js +3 -1
  20. package/package.json +1 -1
  21. package/src/prelude/any_value.hpp +221 -342
  22. package/src/prelude/any_value_access.hpp +168 -81
  23. package/src/prelude/any_value_defines.hpp +74 -35
  24. package/src/prelude/any_value_helpers.hpp +75 -180
  25. package/src/prelude/exception.hpp +1 -0
  26. package/src/prelude/exception_helpers.hpp +4 -4
  27. package/src/prelude/index.hpp +12 -2
  28. package/src/prelude/library/array.hpp +190 -0
  29. package/src/prelude/library/console.hpp +6 -5
  30. package/src/prelude/library/error.hpp +10 -8
  31. package/src/prelude/library/function.hpp +10 -0
  32. package/src/prelude/library/global.hpp +20 -0
  33. package/src/prelude/library/math.hpp +308 -0
  34. package/src/prelude/library/object.hpp +288 -0
  35. package/src/prelude/library/performance.hpp +1 -1
  36. package/src/prelude/library/process.hpp +39 -0
  37. package/src/prelude/library/promise.hpp +57 -55
  38. package/src/prelude/library/symbol.hpp +45 -57
  39. package/src/prelude/library/timer.hpp +6 -6
  40. package/src/prelude/types.hpp +54 -0
  41. package/src/prelude/utils/access.hpp +215 -11
  42. package/src/prelude/utils/assignment_operators.hpp +99 -0
  43. package/src/prelude/utils/log_any_value/array.hpp +8 -8
  44. package/src/prelude/utils/log_any_value/function.hpp +6 -4
  45. package/src/prelude/utils/log_any_value/object.hpp +41 -24
  46. package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
  47. package/src/prelude/utils/operators.hpp +750 -274
  48. package/src/prelude/utils/well_known_symbols.hpp +12 -0
  49. package/src/prelude/values/array.hpp +8 -6
  50. package/src/prelude/values/async_iterator.hpp +79 -0
  51. package/src/prelude/values/descriptors.hpp +2 -2
  52. package/src/prelude/values/function.hpp +72 -62
  53. package/src/prelude/values/helpers/array.hpp +64 -28
  54. package/src/prelude/values/helpers/async_iterator.hpp +275 -0
  55. package/src/prelude/values/helpers/function.hpp +81 -92
  56. package/src/prelude/values/helpers/iterator.hpp +3 -3
  57. package/src/prelude/values/helpers/object.hpp +54 -9
  58. package/src/prelude/values/helpers/promise.hpp +13 -6
  59. package/src/prelude/values/iterator.hpp +1 -1
  60. package/src/prelude/values/object.hpp +10 -3
  61. package/src/prelude/values/promise.hpp +7 -11
  62. package/src/prelude/values/prototypes/array.hpp +851 -12
  63. package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
  64. package/src/prelude/values/prototypes/function.hpp +2 -2
  65. package/src/prelude/values/prototypes/iterator.hpp +5 -5
  66. package/src/prelude/values/prototypes/number.hpp +153 -0
  67. package/src/prelude/values/prototypes/object.hpp +2 -2
  68. package/src/prelude/values/prototypes/promise.hpp +40 -30
  69. package/src/prelude/values/prototypes/string.hpp +28 -28
  70. package/src/prelude/values/prototypes/symbol.hpp +20 -3
  71. package/src/prelude/values/shape.hpp +52 -0
@@ -7,7 +7,7 @@
7
7
  #include "exception.hpp"
8
8
 
9
9
  // setTimeout(callback, delay, ...args)
10
- inline auto setTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
10
+ inline auto setTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
11
11
  if (args.empty() || !args[0].is_function()) {
12
12
  throw jspp::Exception::make_exception("Callback must be a function", "TypeError");
13
13
  }
@@ -26,7 +26,7 @@ inline auto setTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue&
26
26
 
27
27
  auto task = [callback, callArgs]() {
28
28
  try {
29
- callback.as_function()->call(jspp::AnyValue::make_undefined(), callArgs);
29
+ callback.call(jspp::Constants::UNDEFINED, std::span<const jspp::AnyValue>(callArgs));
30
30
  } catch (const jspp::Exception& e) {
31
31
  std::cerr << "Uncaught exception in setTimeout: " << e.what() << "\n";
32
32
  } catch (const std::exception& e) {
@@ -41,7 +41,7 @@ inline auto setTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue&
41
41
  }, "setTimeout");
42
42
 
43
43
  // clearTimeout(id)
44
- inline auto clearTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
44
+ inline auto clearTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
45
45
  if (!args.empty() && args[0].is_number()) {
46
46
  size_t id = static_cast<size_t>(args[0].as_double());
47
47
  jspp::Scheduler::instance().clear_timer(id);
@@ -50,7 +50,7 @@ inline auto clearTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue
50
50
  }, "clearTimeout");
51
51
 
52
52
  // setInterval(callback, delay, ...args)
53
- inline auto setInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
53
+ inline auto setInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
54
54
  if (args.empty() || !args[0].is_function()) {
55
55
  throw jspp::Exception::make_exception("Callback must be a function", "TypeError");
56
56
  }
@@ -68,7 +68,7 @@ inline auto setInterval = jspp::AnyValue::make_function([](const jspp::AnyValue&
68
68
 
69
69
  auto task = [callback, callArgs]() {
70
70
  try {
71
- callback.as_function()->call(jspp::AnyValue::make_undefined(), callArgs);
71
+ callback.call(jspp::Constants::UNDEFINED, std::span<const jspp::AnyValue>(callArgs));
72
72
  } catch (const jspp::Exception& e) {
73
73
  std::cerr << "Uncaught exception in setInterval: " << e.what() << "\n";
74
74
  } catch (const std::exception& e) {
@@ -83,7 +83,7 @@ inline auto setInterval = jspp::AnyValue::make_function([](const jspp::AnyValue&
83
83
  }, "setInterval");
84
84
 
85
85
  // clearInterval(id)
86
- inline auto clearInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
86
+ inline auto clearInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
87
87
  if (!args.empty() && args[0].is_number()) {
88
88
  size_t id = static_cast<size_t>(args[0].as_double());
89
89
  jspp::Scheduler::instance().clear_timer(id);
@@ -14,6 +14,7 @@
14
14
  #include <set>
15
15
  #include <cmath>
16
16
  #include <optional>
17
+ #include <span>
17
18
 
18
19
  // JSPP standard library
19
20
  namespace jspp
@@ -32,6 +33,9 @@ namespace jspp
32
33
  template <typename T>
33
34
  class JsIterator; // can set property
34
35
 
36
+ template <typename T>
37
+ class JsAsyncIterator; // can set property
38
+
35
39
  // Object property configuration forward declarations
36
40
  struct DataDescriptor;
37
41
  struct AccessorDescriptor;
@@ -42,7 +46,53 @@ namespace jspp
42
46
  // Dynamic AnyValue
43
47
  class AnyValue;
44
48
 
49
+ // Awaiter for AnyValue
50
+ struct AnyValueAwaiter;
51
+
52
+ // Truthiness checker
53
+ const bool is_truthy(const double &val) noexcept;
54
+ const bool is_truthy(const std::string &val) noexcept;
55
+ const bool is_truthy(const AnyValue &val) noexcept;
56
+
57
+ // Basic equality operators
58
+ inline const bool is_strictly_equal_to_primitive(const AnyValue &lhs, const double &rhs) noexcept;
59
+ inline const bool is_strictly_equal_to_primitive(const double &lhs, const AnyValue &rhs) noexcept;
60
+ inline const bool is_strictly_equal_to_primitive(const double &lhs, const double &rhs) noexcept;
61
+ inline const bool is_strictly_equal_to_primitive(const AnyValue &lhs, const AnyValue &rhs) noexcept;
62
+
63
+ inline const bool is_equal_to_primitive(const AnyValue &lhs, const double &rhs) noexcept;
64
+ inline const bool is_equal_to_primitive(const double &lhs, const AnyValue &rhs) noexcept;
65
+ inline const bool is_equal_to_primitive(const double &lhs, const double &rhs) noexcept;
66
+ inline const bool is_equal_to_primitive(const AnyValue &lhs, const AnyValue &rhs) noexcept;
67
+
68
+ inline const AnyValue is_strictly_equal_to(const AnyValue &lhs, const double &rhs) noexcept;
69
+ inline const AnyValue is_strictly_equal_to(const double &lhs, const AnyValue &rhs) noexcept;
70
+ inline const AnyValue is_strictly_equal_to(const double &lhs, const double &rhs) noexcept;
71
+ inline const AnyValue is_strictly_equal_to(const AnyValue &lhs, const AnyValue &rhs) noexcept;
72
+
73
+ inline const AnyValue is_equal_to(const AnyValue &lhs, const double &rhs) noexcept;
74
+ inline const AnyValue is_equal_to(const double &lhs, const AnyValue &rhs) noexcept;
75
+ inline const AnyValue is_equal_to(const double &lhs, const double &rhs) noexcept;
76
+ inline const AnyValue is_equal_to(const AnyValue &lhs, const AnyValue &rhs) noexcept;
77
+
78
+ inline const AnyValue not_strictly_equal_to(const AnyValue &lhs, const double &rhs) noexcept;
79
+ inline const AnyValue not_strictly_equal_to(const double &lhs, const AnyValue &rhs) noexcept;
80
+ inline const AnyValue not_strictly_equal_to(const double &lhs, const double &rhs) noexcept;
81
+ inline const AnyValue not_strictly_equal_to(const AnyValue &lhs, const AnyValue &rhs) noexcept;
82
+
83
+ inline const AnyValue not_equal_to(const AnyValue &lhs, const double &rhs) noexcept;
84
+ inline const AnyValue not_equal_to(const double &lhs, const AnyValue &rhs) noexcept;
85
+ inline const AnyValue not_equal_to(const AnyValue &lhs, const AnyValue &rhs) noexcept;
86
+
87
+ // Bitwise operators
88
+ inline AnyValue unsigned_right_shift(const AnyValue &lhs, const AnyValue &rhs);
89
+ inline AnyValue unsigned_right_shift(const AnyValue &lhs, const double &rhs);
90
+ inline AnyValue unsigned_right_shift(const double &lhs, const AnyValue &rhs);
91
+
45
92
  // Arithemetic operators
93
+
94
+ inline AnyValue pow(const double &lhs, const double &rhs);
95
+ inline AnyValue pow(const AnyValue &lhs, const double &rhs);
46
96
  inline AnyValue pow(const AnyValue &lhs, const AnyValue &rhs);
47
97
 
48
98
  // AnyValue prototypes
@@ -54,6 +104,10 @@ namespace jspp
54
104
  {
55
105
  inline std::optional<AnyValue> get(const std::string &key, JsString *self);
56
106
  }
107
+ namespace NumberPrototypes
108
+ {
109
+ inline std::optional<AnyValue> get(const std::string &key, double self);
110
+ }
57
111
  namespace ArrayPrototypes
58
112
  {
59
113
  inline std::optional<AnyValue> get(const std::string &key, JsArray *self);
@@ -64,9 +64,12 @@ namespace jspp
64
64
  return var;
65
65
  }
66
66
 
67
- inline AnyValue typeof(const AnyValue &val)
67
+ inline const AnyValue type_of(const std::optional<AnyValue> &val = std::nullopt)
68
68
  {
69
- switch (val.get_type())
69
+ if (!val.has_value())
70
+ return AnyValue::make_string("undefined");
71
+
72
+ switch (val.value().get_type())
70
73
  {
71
74
  case JsType::Undefined:
72
75
  return AnyValue::make_string("undefined");
@@ -83,17 +86,17 @@ namespace jspp
83
86
  case JsType::Function:
84
87
  return AnyValue::make_string("function");
85
88
  case JsType::Object:
89
+ return AnyValue::make_string("object");
86
90
  case JsType::Array:
91
+ return AnyValue::make_string("object");
87
92
  case JsType::Iterator:
88
93
  return AnyValue::make_string("object");
94
+ case JsType::AsyncIterator:
95
+ return AnyValue::make_string("object");
89
96
  default:
90
97
  return AnyValue::make_string("undefined");
91
98
  }
92
99
  }
93
- inline AnyValue typeof() // for undeclared variables
94
- {
95
- return AnyValue::make_string("undefined");
96
- }
97
100
 
98
101
  // Helper function to get enumerable own property keys/values of an object
99
102
  inline std::vector<std::string> get_object_keys(const AnyValue &obj)
@@ -103,10 +106,35 @@ namespace jspp
103
106
  if (obj.is_object())
104
107
  {
105
108
  auto ptr = obj.as_object();
106
- for (const auto &pair : ptr->props)
109
+ // Use shape's property_names for stable iteration order
110
+ for (const auto &key : ptr->shape->property_names)
107
111
  {
108
- if (!JsSymbol::is_internal_key(pair.first))
109
- keys.push_back(pair.first);
112
+ if (ptr->deleted_keys.count(key))
113
+ continue;
114
+
115
+ if (JsSymbol::is_internal_key(key))
116
+ continue;
117
+
118
+ auto offset_opt = ptr->shape->get_offset(key);
119
+ if (!offset_opt.has_value())
120
+ continue;
121
+
122
+ const auto &val = ptr->storage[offset_opt.value()];
123
+
124
+ if (val.is_data_descriptor())
125
+ {
126
+ if (val.as_data_descriptor()->enumerable)
127
+ keys.push_back(key);
128
+ }
129
+ else if (val.is_accessor_descriptor())
130
+ {
131
+ if (val.as_accessor_descriptor()->enumerable)
132
+ keys.push_back(key);
133
+ }
134
+ else
135
+ {
136
+ keys.push_back(key);
137
+ }
110
138
  }
111
139
  }
112
140
  if (obj.is_function())
@@ -143,6 +171,7 @@ namespace jspp
143
171
 
144
172
  return keys;
145
173
  }
174
+
146
175
  inline AnyValue get_object_value_iterator(const AnyValue &obj, const std::string &name)
147
176
  {
148
177
  if (obj.is_iterator())
@@ -153,7 +182,7 @@ namespace jspp
153
182
  auto gen_fn = obj.get_own_property(WellKnownSymbols::iterator->key);
154
183
  if (gen_fn.is_function())
155
184
  {
156
- auto iter = gen_fn.as_function()->call(gen_fn, {});
185
+ auto iter = gen_fn.call(obj, {}, WellKnownSymbols::iterator->key);
157
186
  if (iter.is_iterator())
158
187
  {
159
188
  return iter;
@@ -170,5 +199,180 @@ namespace jspp
170
199
 
171
200
  throw jspp::Exception::make_exception(name + " is not iterable", "TypeError");
172
201
  }
202
+
203
+ inline AnyValue get_async_object_value_iterator(const AnyValue &obj, const std::string &name)
204
+ {
205
+ if (obj.is_async_iterator())
206
+ return obj;
207
+
208
+ // 1. Try Symbol.asyncIterator
209
+ auto method = obj.get_own_property(WellKnownSymbols::asyncIterator->key);
210
+ if (method.is_function())
211
+ {
212
+ auto iter = method.call(obj, {}, WellKnownSymbols::asyncIterator->key);
213
+ if (iter.is_object() || iter.is_async_iterator() || iter.is_iterator())
214
+ return iter;
215
+ }
216
+
217
+ // 2. Try Symbol.iterator (sync fallback)
218
+ auto syncMethod = obj.get_own_property(WellKnownSymbols::iterator->key);
219
+ if (syncMethod.is_function())
220
+ {
221
+ auto iter = syncMethod.call(obj, {}, WellKnownSymbols::iterator->key);
222
+ if (iter.is_object() || iter.is_iterator())
223
+ return iter;
224
+ }
225
+
226
+ throw jspp::Exception::make_exception(name + " is not async iterable", "TypeError");
227
+ }
228
+
229
+ inline AnyValue in(const AnyValue &lhs, const AnyValue &rhs)
230
+ {
231
+ if (!rhs.is_object() && !rhs.is_array() && !rhs.is_function() && !rhs.is_promise() && !rhs.is_iterator())
232
+ {
233
+ throw jspp::Exception::make_exception("Cannot use 'in' operator to search for '" + lhs.to_std_string() + "' in " + rhs.to_std_string(), "TypeError");
234
+ }
235
+ return AnyValue::make_boolean(rhs.has_property(lhs.to_std_string()));
236
+ }
237
+
238
+ inline AnyValue instance_of(const AnyValue &lhs, const AnyValue &rhs)
239
+ {
240
+ if (!rhs.is_function())
241
+ {
242
+ throw jspp::Exception::make_exception("Right-hand side of 'instanceof' is not callable", "TypeError");
243
+ }
244
+ if (!lhs.is_object() && !lhs.is_array() && !lhs.is_function() && !lhs.is_promise() && !lhs.is_iterator() && !lhs.is_async_iterator())
245
+ {
246
+ return Constants::FALSE;
247
+ }
248
+ AnyValue targetProto = rhs.get_own_property("prototype");
249
+ if (!targetProto.is_object() && !targetProto.is_array() && !targetProto.is_function())
250
+ {
251
+ throw jspp::Exception::make_exception("Function has non-object prototype in instanceof check", "TypeError");
252
+ }
253
+ // Walk prototype chain of lhs
254
+ AnyValue current = lhs;
255
+
256
+ while (true)
257
+ {
258
+ AnyValue proto;
259
+ if (current.is_object())
260
+ {
261
+ auto p = current.as_object()->proto;
262
+ if (p)
263
+ proto = *p;
264
+ else
265
+ break;
266
+ }
267
+ else if (current.is_array())
268
+ {
269
+ auto p = current.as_array()->proto;
270
+ if (p)
271
+ proto = *p;
272
+ else
273
+ break;
274
+ }
275
+ else if (current.is_function())
276
+ {
277
+ auto p = current.as_function()->proto;
278
+ if (p)
279
+ proto = *p;
280
+ else
281
+ break;
282
+ }
283
+ else if (current.is_promise())
284
+ {
285
+ // Promises don't store explicit proto yet in our impl
286
+ break;
287
+ }
288
+ else if (current.is_async_iterator())
289
+ {
290
+ // AsyncIterators don't store explicit proto yet in our impl
291
+ break;
292
+ }
293
+ else
294
+ {
295
+ break;
296
+ }
297
+ if (proto.is_null() || proto.is_undefined())
298
+ break;
299
+ if (is_strictly_equal_to_primitive(proto, targetProto))
300
+ return Constants::TRUE;
301
+ current = proto;
302
+ }
303
+ return Constants::FALSE;
304
+ }
305
+
306
+ inline AnyValue delete_property(const AnyValue &obj, const AnyValue &key)
307
+ {
308
+ if (obj.is_object())
309
+ {
310
+ auto ptr = obj.as_object();
311
+ std::string key_str = key.to_std_string();
312
+ if (ptr->shape->get_offset(key_str).has_value())
313
+ {
314
+ ptr->deleted_keys.insert(key_str);
315
+ }
316
+ return Constants::TRUE;
317
+ }
318
+ if (obj.is_array())
319
+ {
320
+ auto ptr = obj.as_array();
321
+ std::string key_str = key.to_std_string();
322
+ if (JsArray::is_array_index(key_str))
323
+ {
324
+ uint32_t idx = static_cast<uint32_t>(std::stoull(key_str));
325
+ if (idx < ptr->dense.size())
326
+ {
327
+ ptr->dense[idx] = Constants::UNINITIALIZED;
328
+ }
329
+ else
330
+ {
331
+ ptr->sparse.erase(idx);
332
+ }
333
+ }
334
+ else
335
+ {
336
+ ptr->props.erase(key_str);
337
+ }
338
+ return Constants::TRUE;
339
+ }
340
+ if (obj.is_function())
341
+ {
342
+ auto ptr = obj.as_function();
343
+ ptr->props.erase(key.to_std_string());
344
+ return Constants::TRUE;
345
+ }
346
+ return Constants::TRUE;
347
+ }
348
+
349
+ inline AnyValue optional_get_property(const AnyValue &obj, const std::string &key)
350
+ {
351
+ if (obj.is_null() || obj.is_undefined())
352
+ return Constants::UNDEFINED;
353
+ return obj.get_own_property(key);
354
+ }
355
+
356
+ inline AnyValue optional_get_element(const AnyValue &obj, const AnyValue &key)
357
+ {
358
+ if (obj.is_null() || obj.is_undefined())
359
+ return Constants::UNDEFINED;
360
+ return obj.get_own_property(key);
361
+ }
362
+
363
+ inline AnyValue optional_get_element(const AnyValue &obj, const double &key)
364
+ {
365
+ if (obj.is_null() || obj.is_undefined())
366
+ return Constants::UNDEFINED;
367
+ return obj.get_own_property(static_cast<uint32_t>(key));
368
+ }
369
+
370
+ inline AnyValue optional_call(const AnyValue &fn, const AnyValue &thisVal, std::span<const AnyValue> args, const std::optional<std::string> &name = std::nullopt)
371
+ {
372
+ if (fn.is_null() || fn.is_undefined())
373
+ return Constants::UNDEFINED;
374
+ return fn.call(thisVal, args, name);
375
+ }
376
+
173
377
  }
174
- }
378
+ }
@@ -0,0 +1,99 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+ #include "utils/operators.hpp"
6
+
7
+ namespace jspp {
8
+
9
+ // --- FRIEND IMPLEMENTATIONS ---
10
+
11
+ inline AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs) {
12
+ lhs = lhs + rhs;
13
+ return lhs;
14
+ }
15
+
16
+ inline AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs) {
17
+ lhs = lhs - rhs;
18
+ return lhs;
19
+ }
20
+
21
+ inline AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs) {
22
+ lhs = lhs * rhs;
23
+ return lhs;
24
+ }
25
+
26
+ inline AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs) {
27
+ lhs = lhs / rhs;
28
+ return lhs;
29
+ }
30
+
31
+ inline AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs) {
32
+ lhs = lhs % rhs;
33
+ return lhs;
34
+ }
35
+
36
+ inline AnyValue &operator++(AnyValue &val) {
37
+ val = val + 1.0;
38
+ return val;
39
+ }
40
+
41
+ inline AnyValue operator++(AnyValue &val, int) {
42
+ AnyValue temp = val;
43
+ val = val + 1.0;
44
+ return temp;
45
+ }
46
+
47
+ inline AnyValue &operator--(AnyValue &val) {
48
+ val = val - 1.0;
49
+ return val;
50
+ }
51
+
52
+ inline AnyValue operator--(AnyValue &val, int) {
53
+ AnyValue temp = val;
54
+ val = val - 1.0;
55
+ return temp;
56
+ }
57
+
58
+ // --- OVERLOADS FOR PRIMITIVES ---
59
+
60
+ inline AnyValue &operator+=(AnyValue &lhs, const double &rhs) {
61
+ lhs = lhs + rhs;
62
+ return lhs;
63
+ }
64
+ inline AnyValue &operator+=(AnyValue &lhs, const int &rhs) {
65
+ return lhs += static_cast<double>(rhs);
66
+ }
67
+
68
+ inline AnyValue &operator-=(AnyValue &lhs, const double &rhs) {
69
+ lhs = lhs - rhs;
70
+ return lhs;
71
+ }
72
+ inline AnyValue &operator-=(AnyValue &lhs, const int &rhs) {
73
+ return lhs -= static_cast<double>(rhs);
74
+ }
75
+
76
+ inline AnyValue &operator*=(AnyValue &lhs, const double &rhs) {
77
+ lhs = lhs * rhs;
78
+ return lhs;
79
+ }
80
+ inline AnyValue &operator*=(AnyValue &lhs, const int &rhs) {
81
+ return lhs *= static_cast<double>(rhs);
82
+ }
83
+
84
+ inline AnyValue &operator/=(AnyValue &lhs, const double &rhs) {
85
+ lhs = lhs / rhs;
86
+ return lhs;
87
+ }
88
+ inline AnyValue &operator/=(AnyValue &lhs, const int &rhs) {
89
+ return lhs /= static_cast<double>(rhs);
90
+ }
91
+
92
+ inline AnyValue &operator%=(AnyValue &lhs, const double &rhs) {
93
+ lhs = lhs % rhs;
94
+ return lhs;
95
+ }
96
+ inline AnyValue &operator%=(AnyValue &lhs, const int &rhs) {
97
+ return lhs %= static_cast<double>(rhs);
98
+ }
99
+ }
@@ -45,7 +45,7 @@ namespace jspp
45
45
  {
46
46
  for (size_t i = 0; i < item_count; ++i)
47
47
  {
48
- std::optional<AnyValue> itemVal;
48
+ AnyValue itemVal = AnyValue::make_uninitialized();
49
49
  if (i < arr->dense.size())
50
50
  {
51
51
  itemVal = arr->dense[i];
@@ -58,7 +58,7 @@ namespace jspp
58
58
  itemVal = it->second;
59
59
  }
60
60
  }
61
- if (itemVal.has_value() && !is_simple_value(itemVal.value()))
61
+ if (!itemVal.is_uninitialized() && !is_simple_value(itemVal))
62
62
  {
63
63
  use_horizontal_layout = false;
64
64
  break;
@@ -74,7 +74,7 @@ namespace jspp
74
74
 
75
75
  for (size_t i = 0; i < item_count; ++i)
76
76
  {
77
- std::optional<AnyValue> itemVal;
77
+ AnyValue itemVal = AnyValue::make_uninitialized();
78
78
  if (i < arr->dense.size())
79
79
  {
80
80
  itemVal = arr->dense[i];
@@ -88,7 +88,7 @@ namespace jspp
88
88
  }
89
89
  }
90
90
 
91
- if (itemVal.has_value())
91
+ if (!itemVal.is_uninitialized())
92
92
  {
93
93
  if (empty_count > 0)
94
94
  {
@@ -100,7 +100,7 @@ namespace jspp
100
100
  }
101
101
  if (needs_comma)
102
102
  ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
103
- ss << to_log_string(itemVal.value(), visited, depth + 1);
103
+ ss << to_log_string(itemVal, visited, depth + 1);
104
104
  needs_comma = true;
105
105
  }
106
106
  else
@@ -154,7 +154,7 @@ namespace jspp
154
154
 
155
155
  for (size_t i = 0; i < items_to_show; ++i)
156
156
  {
157
- std::optional<AnyValue> itemVal;
157
+ AnyValue itemVal = AnyValue::make_uninitialized();
158
158
  if (i < arr->dense.size())
159
159
  {
160
160
  itemVal = arr->dense[i];
@@ -168,7 +168,7 @@ namespace jspp
168
168
  }
169
169
  }
170
170
 
171
- if (itemVal.has_value())
171
+ if (!itemVal.is_uninitialized())
172
172
  {
173
173
  if (empty_count > 0)
174
174
  {
@@ -182,7 +182,7 @@ namespace jspp
182
182
  if (first_item_printed)
183
183
  ss << Color::BRIGHT_BLACK << ",\n"
184
184
  << Color::RESET;
185
- ss << next_indent << to_log_string(itemVal.value(), visited, depth + 1);
185
+ ss << next_indent << to_log_string(itemVal, visited, depth + 1);
186
186
  first_item_printed = true;
187
187
  }
188
188
  else
@@ -20,17 +20,19 @@ namespace jspp
20
20
  if (fn->proto->is_function())
21
21
  {
22
22
  auto parent = fn->proto->as_function();
23
- if (!parent->name.empty())
23
+ std::string name = parent->name.value_or("");
24
+ if (!name.empty())
24
25
  {
25
- extends_part = " extends " + parent->name;
26
+ extends_part = " extends " + name;
26
27
  }
27
28
  }
28
29
  }
29
- return Color::CYAN + std::string("[class ") + (fn->name.empty() ? "(anonymous)" : fn->name) + extends_part + "]" + Color::RESET;
30
+ std::string name = fn->name.value_or("");
31
+ return Color::CYAN + std::string("[class ") + (name.empty() ? "(anonymous)" : name) + extends_part + "]" + Color::RESET;
30
32
  }
31
33
 
32
34
  auto type_part = fn->is_generator ? "GeneratorFunction" : "Function";
33
- auto name_part = fn->name.size() > 0 ? ": " + fn->name : " (anonymous)";
35
+ auto name_part = fn->name.has_value() ? ": " + fn->name.value() : " (anonymous)";
34
36
  return Color::CYAN + "[" + type_part + name_part + "]" + Color::RESET;
35
37
  }
36
38
  }