@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
@@ -17,6 +17,7 @@
17
17
  #include <cmath>
18
18
  #include <optional>
19
19
  #include <coroutine>
20
+ #include <variant>
20
21
 
21
22
  #include "types.hpp"
22
23
  #include "values/non_values.hpp"
@@ -27,8 +28,8 @@
27
28
  #include "values/promise.hpp"
28
29
  #include "values/symbol.hpp"
29
30
  #include "values/string.hpp"
30
- #include "exception.hpp"
31
31
  #include "values/descriptors.hpp"
32
+ #include "exception.hpp"
32
33
  #include "utils/well_known_symbols.hpp"
33
34
 
34
35
  namespace jspp
@@ -49,445 +50,308 @@ namespace jspp
49
50
  Promise = 11,
50
51
  DataDescriptor = 12,
51
52
  AccessorDescriptor = 13,
53
+ AsyncIterator = 14,
52
54
  };
53
55
 
54
- // Tagged storage with a union for payload
55
- struct TaggedValue
56
- {
57
- JsType type;
58
- union
59
- {
60
- JsUndefined undefined;
61
- JsNull null;
62
- JsUninitialized uninitialized;
63
- bool boolean;
64
- double number;
65
- std::shared_ptr<JsString> str;
66
- std::shared_ptr<JsObject> object;
67
- std::shared_ptr<JsArray> array;
68
- std::shared_ptr<JsFunction> function;
69
- std::shared_ptr<JsIterator<AnyValue>> iterator;
70
- std::shared_ptr<JsSymbol> symbol;
71
- std::shared_ptr<JsPromise> promise;
72
- std::shared_ptr<DataDescriptor> data_desc;
73
- std::shared_ptr<AccessorDescriptor> accessor_desc;
74
- };
75
-
76
- TaggedValue() noexcept : type(JsType::Undefined), undefined{} {}
77
- ~TaggedValue() {}
78
- };
56
+ // The variant order MUST match JsType
57
+ using AnyValueVariant = std::variant<
58
+ JsUndefined,
59
+ JsNull,
60
+ JsUninitialized,
61
+ bool,
62
+ double,
63
+ std::shared_ptr<JsString>,
64
+ std::shared_ptr<JsObject>,
65
+ std::shared_ptr<JsArray>,
66
+ std::shared_ptr<JsFunction>,
67
+ std::shared_ptr<JsIterator<AnyValue>>,
68
+ std::shared_ptr<JsSymbol>,
69
+ std::shared_ptr<JsPromise>,
70
+ std::shared_ptr<DataDescriptor>,
71
+ std::shared_ptr<AccessorDescriptor>,
72
+ std::shared_ptr<JsAsyncIterator<AnyValue>>>;
79
73
 
80
74
  class AnyValue
81
75
  {
82
76
  private:
83
- TaggedValue storage;
84
-
85
- void destroy_value() noexcept
86
- {
87
- switch (storage.type)
88
- {
89
- case JsType::String:
90
- storage.str.~shared_ptr();
91
- break;
92
- case JsType::Object:
93
- storage.object.~shared_ptr();
94
- break;
95
- case JsType::Array:
96
- storage.array.~shared_ptr();
97
- break;
98
- case JsType::Function:
99
- storage.function.~shared_ptr();
100
- break;
101
- case JsType::Iterator:
102
- storage.iterator.~shared_ptr();
103
- break;
104
- case JsType::Symbol:
105
- storage.symbol.~shared_ptr();
106
- break;
107
- case JsType::Promise:
108
- storage.promise.~shared_ptr();
109
- break;
110
- case JsType::DataDescriptor:
111
- storage.data_desc.~shared_ptr();
112
- break;
113
- case JsType::AccessorDescriptor:
114
- storage.accessor_desc.~shared_ptr();
115
- break;
116
- default:
117
- break;
118
- }
119
- }
120
-
121
- void reset_to_undefined() noexcept
122
- {
123
- destroy_value();
124
- storage.type = JsType::Undefined;
125
- storage.undefined = JsUndefined{};
126
- }
127
-
128
- void move_from(AnyValue &other) noexcept
129
- {
130
- storage.type = other.storage.type;
131
- switch (other.storage.type)
132
- {
133
- case JsType::Undefined:
134
- storage.undefined = JsUndefined{};
135
- break;
136
- case JsType::Null:
137
- storage.null = JsNull{};
138
- break;
139
- case JsType::Uninitialized:
140
- storage.uninitialized = JsUninitialized{};
141
- break;
142
- case JsType::Boolean:
143
- storage.boolean = other.storage.boolean;
144
- break;
145
- case JsType::Number:
146
- storage.number = other.storage.number;
147
- break;
148
- case JsType::String:
149
- new (&storage.str) std::shared_ptr<JsString>(std::move(other.storage.str));
150
- break;
151
- case JsType::Object:
152
- new (&storage.object) std::shared_ptr<JsObject>(std::move(other.storage.object));
153
- break;
154
- case JsType::Array:
155
- new (&storage.array) std::shared_ptr<JsArray>(std::move(other.storage.array));
156
- break;
157
- case JsType::Function:
158
- new (&storage.function) std::shared_ptr<JsFunction>(std::move(other.storage.function));
159
- break;
160
- case JsType::Iterator:
161
- new (&storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(std::move(other.storage.iterator));
162
- break;
163
- case JsType::Symbol:
164
- new (&storage.symbol) std::shared_ptr<JsSymbol>(std::move(other.storage.symbol));
165
- break;
166
- case JsType::Promise:
167
- new (&storage.promise) std::shared_ptr<JsPromise>(std::move(other.storage.promise));
168
- break;
169
- case JsType::DataDescriptor:
170
- new (&storage.data_desc) std::shared_ptr<DataDescriptor>(std::move(other.storage.data_desc));
171
- break;
172
- case JsType::AccessorDescriptor:
173
- new (&storage.accessor_desc) std::shared_ptr<AccessorDescriptor>(std::move(other.storage.accessor_desc));
174
- break;
175
- }
176
- }
177
-
178
- void copy_from(const AnyValue &other)
179
- {
180
- storage.type = other.storage.type;
181
- switch (other.storage.type)
182
- {
183
- case JsType::Undefined:
184
- storage.undefined = JsUndefined{};
185
- break;
186
- case JsType::Null:
187
- storage.null = JsNull{};
188
- break;
189
- case JsType::Uninitialized:
190
- storage.uninitialized = JsUninitialized{};
191
- break;
192
- case JsType::Boolean:
193
- storage.boolean = other.storage.boolean;
194
- break;
195
- case JsType::Number:
196
- storage.number = other.storage.number;
197
- break;
198
- case JsType::String:
199
- new (&storage.str) std::shared_ptr<JsString>(std::make_shared<JsString>(*other.storage.str));
200
- break;
201
- case JsType::Object:
202
- new (&storage.object) std::shared_ptr<JsObject>(other.storage.object); // shallow copy
203
- break;
204
- case JsType::Array:
205
- new (&storage.array) std::shared_ptr<JsArray>(other.storage.array); // shallow copy
206
- break;
207
- case JsType::Function:
208
- new (&storage.function) std::shared_ptr<JsFunction>(other.storage.function); // shallow copy
209
- break;
210
- case JsType::Iterator:
211
- new (&storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(other.storage.iterator); // shallow copy
212
- break;
213
- case JsType::Symbol:
214
- new (&storage.symbol) std::shared_ptr<JsSymbol>(other.storage.symbol); // shallow copy (shared)
215
- break;
216
- case JsType::Promise:
217
- new (&storage.promise) std::shared_ptr<JsPromise>(other.storage.promise); // shallow copy
218
- break;
219
- case JsType::DataDescriptor:
220
- new (&storage.data_desc) std::shared_ptr<DataDescriptor>(other.storage.data_desc); // shallow copy
221
- break;
222
- case JsType::AccessorDescriptor:
223
- new (&storage.accessor_desc) std::shared_ptr<AccessorDescriptor>(other.storage.accessor_desc); // shallow copy
224
- break;
225
- }
226
- }
77
+ AnyValueVariant storage;
227
78
 
228
79
  public:
229
80
  // default ctor (Undefined)
230
- AnyValue() noexcept
231
- {
232
- storage.type = JsType::Undefined;
233
- storage.undefined = JsUndefined{};
234
- }
81
+ AnyValue() noexcept = default;
235
82
 
236
- // 1. Destructor
237
- ~AnyValue() noexcept
238
- {
239
- destroy_value();
240
- }
83
+ // Copy/Move handled by std::variant
84
+ AnyValue(const AnyValue &) = default;
85
+ AnyValue(AnyValue &&) noexcept = default;
86
+ AnyValue &operator=(const AnyValue &) = default;
87
+ AnyValue &operator=(AnyValue &&) noexcept = default;
241
88
 
242
- // 2. Copy Constructor (deep copy)
243
- AnyValue(const AnyValue &other)
244
- {
245
- copy_from(other);
246
- }
89
+ ~AnyValue() = default;
247
90
 
248
- // 3. Copy Assignment Operator
249
- AnyValue &operator=(const AnyValue &other)
91
+ // Assignments
92
+ AnyValue &operator=(const double &val)
250
93
  {
251
- if (this != &other)
252
- {
253
- destroy_value();
254
- copy_from(other);
255
- }
94
+ storage = val;
256
95
  return *this;
257
- }
258
-
259
- // 4. Move Constructor
260
- AnyValue(AnyValue &&other) noexcept
261
- {
262
- storage.type = JsType::Undefined;
263
- storage.undefined = JsUndefined{};
264
- move_from(other);
265
- other.reset_to_undefined();
266
- }
267
-
268
- // 5. Move Assignment Operator
269
- AnyValue &operator=(AnyValue &&other) noexcept
270
- {
271
- if (this != &other)
272
- {
273
- destroy_value();
274
- move_from(other);
275
- other.reset_to_undefined();
276
- }
277
- return *this;
278
- }
96
+ };
279
97
 
280
98
  friend void swap(AnyValue &a, AnyValue &b) noexcept
281
99
  {
282
- AnyValue tmp(std::move(a));
283
- a = std::move(b);
284
- b = std::move(tmp);
100
+ std::swap(a.storage, b.storage);
285
101
  }
286
102
 
103
+ // --- FRIENDS for Optimized Operators
104
+ friend AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs);
105
+ friend AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs);
106
+ friend AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs);
107
+ friend AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs);
108
+ friend AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs);
109
+ friend AnyValue &operator++(AnyValue &val);
110
+ friend AnyValue operator++(AnyValue &val, int);
111
+ friend AnyValue &operator--(AnyValue &val);
112
+ friend AnyValue operator--(AnyValue &val, int);
113
+
287
114
  // factories -------------------------------------------------------
288
115
  static AnyValue make_number(double d) noexcept
289
116
  {
290
117
  AnyValue v;
291
- v.storage.type = JsType::Number;
292
- v.storage.number = d;
118
+ v.storage = d;
293
119
  return v;
294
120
  }
295
121
  static AnyValue make_nan() noexcept
296
122
  {
297
123
  AnyValue v;
298
- v.storage.type = JsType::Number;
299
- v.storage.number = std::numeric_limits<double>::quiet_NaN();
124
+ v.storage = std::numeric_limits<double>::quiet_NaN();
300
125
  return v;
301
126
  }
302
127
  static AnyValue make_uninitialized() noexcept
303
128
  {
304
129
  AnyValue v;
305
- v.storage.type = JsType::Uninitialized;
306
- v.storage.uninitialized = JsUninitialized{};
130
+ v.storage = JsUninitialized{};
307
131
  return v;
308
132
  }
309
133
  static AnyValue make_undefined() noexcept
310
134
  {
311
135
  AnyValue v;
312
- v.storage.type = JsType::Undefined;
313
- v.storage.undefined = JsUndefined{};
136
+ v.storage = JsUndefined{};
314
137
  return v;
315
138
  }
316
139
  static AnyValue make_null() noexcept
317
140
  {
318
141
  AnyValue v;
319
- v.storage.type = JsType::Null;
320
- v.storage.null = JsNull{};
142
+ v.storage = JsNull{};
321
143
  return v;
322
144
  }
323
145
  static AnyValue make_boolean(bool b) noexcept
324
146
  {
325
147
  AnyValue v;
326
- v.storage.type = JsType::Boolean;
327
- v.storage.boolean = b;
148
+ v.storage = b;
328
149
  return v;
329
150
  }
330
151
  static AnyValue make_string(const std::string &raw_s) noexcept
331
152
  {
332
153
  AnyValue v;
333
- v.storage.type = JsType::String;
334
- new (&v.storage.str) std::shared_ptr<JsString>(std::make_shared<JsString>(raw_s));
154
+ v.storage = std::make_shared<JsString>(raw_s);
155
+ return v;
156
+ }
157
+ static AnyValue make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept
158
+ {
159
+ AnyValue v;
160
+ v.storage = std::make_shared<JsObject>(props);
335
161
  return v;
336
162
  }
337
163
  static AnyValue make_object(const std::map<std::string, AnyValue> &props) noexcept
338
164
  {
339
165
  AnyValue v;
340
- v.storage.type = JsType::Object;
341
- new (&v.storage.object) std::shared_ptr<JsObject>(std::make_shared<JsObject>(props));
166
+ v.storage = std::make_shared<JsObject>(props);
167
+ return v;
168
+ }
169
+ static AnyValue make_object_with_proto(std::initializer_list<std::pair<std::string, AnyValue>> props, const AnyValue &proto) noexcept
170
+ {
171
+ AnyValue v;
172
+ auto protoPtr = std::make_shared<AnyValue>(proto);
173
+ v.storage = std::make_shared<JsObject>(props, protoPtr);
342
174
  return v;
343
175
  }
344
176
  static AnyValue make_object_with_proto(const std::map<std::string, AnyValue> &props, const AnyValue &proto) noexcept
345
177
  {
346
178
  AnyValue v;
347
- v.storage.type = JsType::Object;
348
179
  auto protoPtr = std::make_shared<AnyValue>(proto);
349
- new (&v.storage.object) std::shared_ptr<JsObject>(std::make_shared<JsObject>(props, protoPtr));
180
+ v.storage = std::make_shared<JsObject>(props, protoPtr);
181
+ return v;
182
+ }
183
+ static AnyValue make_array(std::span<const AnyValue> dense) noexcept
184
+ {
185
+ AnyValue v;
186
+ std::vector<AnyValue> vec;
187
+ vec.reserve(dense.size());
188
+ for (const auto &item : dense)
189
+ vec.push_back(item);
190
+ v.storage = std::make_shared<JsArray>(std::move(vec));
191
+ return v;
192
+ }
193
+ static AnyValue make_array(const std::vector<AnyValue> &dense) noexcept
194
+ {
195
+ AnyValue v;
196
+ v.storage = std::make_shared<JsArray>(dense);
197
+ return v;
198
+ }
199
+ static AnyValue make_array(std::vector<AnyValue> &&dense) noexcept
200
+ {
201
+ AnyValue v;
202
+ v.storage = std::make_shared<JsArray>(std::move(dense));
350
203
  return v;
351
204
  }
352
- static AnyValue make_array(const std::vector<std::optional<AnyValue>> &dense) noexcept
205
+ static AnyValue make_array_with_proto(std::span<const AnyValue> dense, const AnyValue &proto) noexcept
353
206
  {
354
207
  AnyValue v;
355
- v.storage.type = JsType::Array;
356
- new (&v.storage.array) std::shared_ptr<JsArray>(std::make_shared<JsArray>(dense));
208
+ std::vector<AnyValue> vec;
209
+ vec.reserve(dense.size());
210
+ for (const auto &item : dense)
211
+ vec.push_back(item);
212
+ v.storage = std::make_shared<JsArray>(std::move(vec));
213
+ std::get<std::shared_ptr<JsArray>>(v.storage)->proto = std::make_shared<AnyValue>(proto);
357
214
  return v;
358
215
  }
359
- static AnyValue make_array(std::vector<std::optional<AnyValue>> &&dense) noexcept
216
+ static AnyValue make_array_with_proto(const std::vector<AnyValue> &dense, const AnyValue &proto) noexcept
360
217
  {
361
218
  AnyValue v;
362
- v.storage.type = JsType::Array;
363
- new (&v.storage.array) std::shared_ptr<JsArray>(std::make_shared<JsArray>(std::move(dense)));
219
+ v.storage = std::make_shared<JsArray>(dense);
220
+ std::get<std::shared_ptr<JsArray>>(v.storage)->proto = std::make_shared<AnyValue>(proto);
364
221
  return v;
365
222
  }
366
- static AnyValue make_function(const JsFunctionCallable &call, const std::string &name) noexcept
223
+ static AnyValue make_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt, bool is_constructor = true) noexcept
367
224
  {
368
225
  AnyValue v;
369
- v.storage.type = JsType::Function;
370
- new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, name));
226
+ v.storage = std::make_shared<JsFunction>(call, name, std::unordered_map<std::string, AnyValue>{}, false, is_constructor);
371
227
 
372
228
  auto proto = make_object({});
373
- proto.set_own_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
374
- v.set_own_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
229
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
230
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
375
231
 
376
232
  return v;
377
233
  }
378
- static AnyValue make_class(const JsFunctionCallable &call, const std::string &name) noexcept
234
+ static AnyValue make_class(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept
379
235
  {
380
236
  AnyValue v;
381
- v.storage.type = JsType::Function;
382
237
  // use Constructor A with is_cls = true
383
- new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, name, std::unordered_map<std::string, AnyValue>{}, true));
238
+ v.storage = std::make_shared<JsFunction>(call, name, std::unordered_map<std::string, AnyValue>{}, true);
384
239
 
385
240
  auto proto = make_object({});
386
- proto.set_own_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
387
- v.set_own_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
241
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
242
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
388
243
 
389
244
  return v;
390
245
  }
391
- static AnyValue make_generator(const JsFunctionCallable &call, const std::string &name) noexcept
246
+ static AnyValue make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept
392
247
  {
393
248
  AnyValue v;
394
- v.storage.type = JsType::Function;
395
249
  // use Constructor B with is_gen = true
396
- new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, true, name));
250
+ v.storage = std::make_shared<JsFunction>(call, true, name);
397
251
 
398
252
  auto proto = make_object({});
399
- proto.set_own_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
400
- v.set_own_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
253
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
254
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
401
255
 
402
256
  return v;
403
257
  }
404
- static AnyValue make_async_function(const JsFunctionCallable &call, const std::string &name) noexcept
258
+ static AnyValue make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept
405
259
  {
406
260
  AnyValue v;
407
- v.storage.type = JsType::Function;
408
261
  // use Constructor C with is_async_func = true
409
- new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, false, true, name));
262
+ v.storage = std::make_shared<JsFunction>(call, false, true, name);
263
+
264
+ auto proto = make_object({});
265
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
266
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
267
+
268
+ return v;
269
+ }
270
+ static AnyValue make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept
271
+ {
272
+ AnyValue v;
273
+ // use Constructor C with is_gen = true and is_async_func = true
274
+ v.storage = std::make_shared<JsFunction>(call, true, true, name);
410
275
 
411
276
  auto proto = make_object({});
412
- proto.set_own_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
413
- v.set_own_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
277
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
278
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
414
279
 
415
280
  return v;
416
281
  }
417
282
  static AnyValue make_symbol(const std::string &description = "") noexcept
418
283
  {
419
284
  AnyValue v;
420
- v.storage.type = JsType::Symbol;
421
- new (&v.storage.symbol) std::shared_ptr<JsSymbol>(std::make_shared<JsSymbol>(description));
285
+ v.storage = std::make_shared<JsSymbol>(description);
422
286
  return v;
423
287
  }
424
288
  static AnyValue make_promise(const JsPromise &promise) noexcept
425
289
  {
426
290
  AnyValue v;
427
- v.storage.type = JsType::Promise;
428
- new (&v.storage.promise) std::shared_ptr<JsPromise>(std::make_shared<JsPromise>(promise));
291
+ v.storage = std::make_shared<JsPromise>(promise);
429
292
  return v;
430
293
  }
431
294
  static AnyValue make_data_descriptor(const AnyValue &value, bool writable, bool enumerable, bool configurable) noexcept
432
295
  {
433
296
  AnyValue v;
434
- v.storage.type = JsType::DataDescriptor;
435
- new (&v.storage.data_desc) std::shared_ptr<DataDescriptor>(std::make_shared<DataDescriptor>(std::make_shared<AnyValue>(value), writable, enumerable, configurable));
297
+ v.storage = std::make_shared<DataDescriptor>(std::make_shared<AnyValue>(value), writable, enumerable, configurable);
436
298
  return v;
437
299
  }
438
- static AnyValue make_accessor_descriptor(const std::optional<std::function<AnyValue(const AnyValue &, const std::vector<AnyValue> &)>> &get,
439
- const std::optional<std::function<AnyValue(const AnyValue &, const std::vector<AnyValue> &)>> &set,
300
+ static AnyValue make_accessor_descriptor(const std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> &get,
301
+ const std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> &set,
440
302
  bool enumerable,
441
303
  bool configurable) noexcept
442
304
  {
443
305
  AnyValue v;
444
- v.storage.type = JsType::AccessorDescriptor;
445
- new (&v.storage.accessor_desc) std::shared_ptr<AccessorDescriptor>(std::make_shared<AccessorDescriptor>(get, set, enumerable, configurable));
306
+ v.storage = std::make_shared<AccessorDescriptor>(get, set, enumerable, configurable);
446
307
  return v;
447
308
  }
448
309
 
449
310
  static AnyValue from_symbol(std::shared_ptr<JsSymbol> sym) noexcept
450
311
  {
451
312
  AnyValue v;
452
- v.storage.type = JsType::Symbol;
453
- new (&v.storage.symbol) std::shared_ptr<JsSymbol>(std::move(sym));
313
+ v.storage = std::move(sym);
454
314
  return v;
455
315
  }
456
316
  static AnyValue from_string(std::shared_ptr<JsString> str) noexcept
457
317
  {
458
318
  AnyValue v;
459
- v.storage.type = JsType::String;
460
- new (&v.storage.str) std::shared_ptr<JsString>(std::move(str));
319
+ v.storage = std::move(str);
461
320
  return v;
462
321
  }
463
322
  static AnyValue from_iterator(JsIterator<AnyValue> &&iterator) noexcept
464
323
  {
465
324
  AnyValue v;
466
- v.storage.type = JsType::Iterator;
467
- new (&v.storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(std::make_shared<JsIterator<AnyValue>>(std::move(iterator)));
325
+ v.storage = std::make_shared<JsIterator<AnyValue>>(std::move(iterator));
468
326
  return v;
469
327
  }
470
328
  static AnyValue from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept
471
329
  {
472
330
  AnyValue v;
473
- v.storage.type = JsType::Iterator;
474
- new (&v.storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(iterator, [](JsIterator<AnyValue> *) {});
331
+ v.storage = std::shared_ptr<JsIterator<AnyValue>>(iterator, [](JsIterator<AnyValue> *) {});
332
+ return v;
333
+ }
334
+ static AnyValue from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept
335
+ {
336
+ AnyValue v;
337
+ v.storage = std::make_shared<JsAsyncIterator<AnyValue>>(std::move(iterator));
475
338
  return v;
476
339
  }
477
340
 
478
341
  // PROPERTY RESOLUTION HELPERS ---------------------------------------
479
342
  static AnyValue resolve_property_for_read(const AnyValue &val, const AnyValue &thisVal, const std::string &propName) noexcept
480
343
  {
481
- switch (val.storage.type)
344
+ switch (val.get_type())
482
345
  {
483
346
  case JsType::DataDescriptor:
484
347
  {
485
- return *(val.storage.data_desc->value);
348
+ return *(val.as_data_descriptor()->value);
486
349
  }
487
350
  case JsType::AccessorDescriptor:
488
351
  {
489
- if (val.storage.accessor_desc->get.has_value())
490
- return val.storage.accessor_desc->get.value()(thisVal, {});
352
+ const auto &accessor = val.as_accessor_descriptor();
353
+ if (accessor->get.has_value())
354
+ return accessor->get.value()(thisVal, std::span<const AnyValue>{});
491
355
  else
492
356
  {
493
357
  static AnyValue undefined = AnyValue{};
@@ -502,13 +366,14 @@ namespace jspp
502
366
  }
503
367
  static AnyValue resolve_property_for_write(AnyValue &val, const AnyValue &thisVal, const AnyValue &new_val, const std::string &propName)
504
368
  {
505
- switch (val.storage.type)
369
+ switch (val.get_type())
506
370
  {
507
371
  case JsType::DataDescriptor:
508
372
  {
509
- if (val.storage.data_desc->writable)
373
+ const auto &data = val.as_data_descriptor();
374
+ if (data->writable)
510
375
  {
511
- *(val.storage.data_desc->value) = new_val;
376
+ *(data->value) = new_val;
512
377
  return new_val;
513
378
  }
514
379
  else
@@ -518,9 +383,11 @@ namespace jspp
518
383
  }
519
384
  case JsType::AccessorDescriptor:
520
385
  {
521
- if (val.storage.accessor_desc->set.has_value())
386
+ const auto &accessor = val.as_accessor_descriptor();
387
+ if (accessor->set.has_value())
522
388
  {
523
- val.storage.accessor_desc->set.value()(thisVal, {new_val});
389
+ const AnyValue args[] = {new_val};
390
+ accessor->set.value()(thisVal, args);
524
391
  return new_val;
525
392
  }
526
393
  else
@@ -537,94 +404,92 @@ namespace jspp
537
404
  }
538
405
 
539
406
  // TYPE CHECKERS AND ACCESSORS ---------------------------------------
540
- JsType get_type() const noexcept { return storage.type; }
541
- bool is_number() const noexcept { return storage.type == JsType::Number; }
542
- bool is_string() const noexcept { return storage.type == JsType::String; }
543
- bool is_object() const noexcept { return storage.type == JsType::Object; }
544
- bool is_array() const noexcept { return storage.type == JsType::Array; }
545
- bool is_function() const noexcept { return storage.type == JsType::Function; }
546
- bool is_iterator() const noexcept { return storage.type == JsType::Iterator; }
547
- bool is_boolean() const noexcept { return storage.type == JsType::Boolean; }
548
- bool is_symbol() const noexcept { return storage.type == JsType::Symbol; }
549
- bool is_promise() const noexcept { return storage.type == JsType::Promise; }
550
- bool is_null() const noexcept { return storage.type == JsType::Null; }
551
- bool is_undefined() const noexcept { return storage.type == JsType::Undefined; }
552
- bool is_uninitialized() const noexcept { return storage.type == JsType::Uninitialized; }
553
- bool is_data_descriptor() const noexcept { return storage.type == JsType::DataDescriptor; }
554
- bool is_accessor_descriptor() const noexcept { return storage.type == JsType::AccessorDescriptor; }
555
- bool is_generator() const noexcept { return storage.type == JsType::Function && storage.function->is_generator; }
407
+ JsType get_type() const noexcept { return static_cast<JsType>(storage.index()); }
408
+ bool is_number() const noexcept { return storage.index() == 4; }
409
+ bool is_string() const noexcept { return storage.index() == 5; }
410
+ bool is_object() const noexcept { return storage.index() == 6; }
411
+ bool is_array() const noexcept { return storage.index() == 7; }
412
+ bool is_function() const noexcept { return storage.index() == 8; }
413
+ bool is_iterator() const noexcept { return storage.index() == 9; }
414
+ bool is_boolean() const noexcept { return storage.index() == 3; }
415
+ bool is_symbol() const noexcept { return storage.index() == 10; }
416
+ bool is_promise() const noexcept { return storage.index() == 11; }
417
+ bool is_null() const noexcept { return storage.index() == 1; }
418
+ bool is_undefined() const noexcept { return storage.index() == 0; }
419
+ bool is_uninitialized() const noexcept { return storage.index() == 2; }
420
+ bool is_data_descriptor() const noexcept { return storage.index() == 12; }
421
+ bool is_accessor_descriptor() const noexcept { return storage.index() == 13; }
422
+ bool is_async_iterator() const noexcept { return storage.index() == 14; }
423
+ bool is_generator() const noexcept { return is_function() && as_function()->is_generator; }
556
424
 
557
425
  // --- TYPE CASTERS
558
426
  double as_double() const noexcept
559
427
  {
560
- assert(is_number());
561
- return storage.number;
428
+ return std::get<double>(storage);
562
429
  }
563
430
  bool as_boolean() const noexcept
564
431
  {
565
- assert(is_boolean());
566
- return storage.boolean;
432
+ return std::get<bool>(storage);
567
433
  }
568
434
  JsString *as_string() const noexcept
569
435
  {
570
- assert(is_string());
571
- return storage.str.get();
436
+ return std::get<std::shared_ptr<JsString>>(storage).get();
572
437
  }
573
438
  JsObject *as_object() const noexcept
574
439
  {
575
- assert(is_object());
576
- return storage.object.get();
440
+ return std::get<std::shared_ptr<JsObject>>(storage).get();
577
441
  }
578
442
  JsArray *as_array() const noexcept
579
443
  {
580
- assert(is_array());
581
- return storage.array.get();
444
+ return std::get<std::shared_ptr<JsArray>>(storage).get();
582
445
  }
583
- JsFunction *as_function(const std::optional<std::string> &expression = std::nullopt) const
446
+ JsFunction *as_function() const noexcept
584
447
  {
585
- if (is_function())
586
- return storage.function.get();
587
- throw Exception::make_exception(expression.value_or(to_std_string()) + " is not a function", "TypeError");
448
+ return std::get<std::shared_ptr<JsFunction>>(storage).get();
588
449
  }
589
450
  JsSymbol *as_symbol() const noexcept
590
451
  {
591
- assert(is_symbol());
592
- return storage.symbol.get();
452
+ return std::get<std::shared_ptr<JsSymbol>>(storage).get();
593
453
  }
594
454
  JsPromise *as_promise() const noexcept
595
455
  {
596
- assert(is_promise());
597
- return storage.promise.get();
456
+ return std::get<std::shared_ptr<JsPromise>>(storage).get();
598
457
  }
599
458
  std::shared_ptr<JsIterator<AnyValue>> as_iterator() const
600
459
  {
601
- assert(is_iterator());
602
- return storage.iterator; // Returns the shared_ptr, incrementing ref count
460
+ return std::get<std::shared_ptr<JsIterator<AnyValue>>>(storage);
461
+ }
462
+ std::shared_ptr<JsAsyncIterator<AnyValue>> as_async_iterator() const
463
+ {
464
+ return std::get<std::shared_ptr<JsAsyncIterator<AnyValue>>>(storage);
603
465
  }
604
466
  DataDescriptor *as_data_descriptor() const noexcept
605
467
  {
606
- assert(is_data_descriptor());
607
- return storage.data_desc.get();
468
+ return std::get<std::shared_ptr<DataDescriptor>>(storage).get();
608
469
  }
609
470
  AccessorDescriptor *as_accessor_descriptor() const noexcept
610
471
  {
611
- assert(is_accessor_descriptor());
612
- return storage.accessor_desc.get();
472
+ return std::get<std::shared_ptr<AccessorDescriptor>>(storage).get();
613
473
  }
614
474
 
615
475
  // --- CO_AWAIT Operator ---
616
476
  auto operator co_await() const;
617
477
 
618
478
  // --- PROPERTY ACCESS OPERATORS
479
+ bool has_property(const std::string &key) const;
619
480
  AnyValue get_own_property(const std::string &key) const;
620
- AnyValue get_own_property(uint32_t idx) const noexcept;
621
- AnyValue get_own_property(const AnyValue &key) const noexcept;
481
+ AnyValue get_own_property(uint32_t idx) const;
482
+ AnyValue get_own_property(const AnyValue &key) const;
622
483
  // for getting values with a specific receiver (used in inheritance chains)
623
484
  AnyValue get_property_with_receiver(const std::string &key, const AnyValue &receiver) const;
624
485
  // for setting values
625
486
  AnyValue set_own_property(const std::string &key, const AnyValue &value) const;
626
487
  AnyValue set_own_property(uint32_t idx, const AnyValue &value) const;
627
488
  AnyValue set_own_property(const AnyValue &key, const AnyValue &value) const;
489
+ // for calling the gotten the property
490
+ AnyValue call_own_property(const std::string &key, std::span<const AnyValue> args) const;
491
+ AnyValue call_own_property(uint32_t idx, std::span<const AnyValue> args) const;
492
+ AnyValue call_own_property(const AnyValue &key, std::span<const AnyValue> args) const;
628
493
 
629
494
  // --- DEFINERS (Object.defineProperty semantics)
630
495
  void define_data_property(const std::string &key, const AnyValue &value);
@@ -636,18 +501,19 @@ namespace jspp
636
501
  void define_setter(const AnyValue &key, const AnyValue &setter);
637
502
 
638
503
  // --- HELPERS
639
- const bool is_truthy() const noexcept;
640
- const bool is_strictly_equal_to_primitive(const AnyValue &other) const noexcept;
641
- const bool is_equal_to_primitive(const AnyValue &other) const noexcept;
642
-
643
- const AnyValue is_strictly_equal_to(const AnyValue &other) const noexcept;
644
- const AnyValue is_equal_to(const AnyValue &other) const noexcept;
645
- const AnyValue not_strictly_equal_to(const AnyValue &other) const noexcept;
646
- const AnyValue not_equal_to(const AnyValue &other) const noexcept;
647
-
648
- const AnyValue construct(const std::vector<AnyValue> &args) const;
504
+ const AnyValue call(const AnyValue &thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const;
505
+ const AnyValue construct(std::span<const AnyValue> args, const std::optional<std::string> &name) const;
649
506
  void set_prototype(const AnyValue &proto);
650
- const std::string to_std_string() const noexcept;
507
+ std::string to_std_string() const;
508
+ };
509
+
510
+ // Awaiter for AnyValue
511
+ struct AnyValueAwaiter
512
+ {
513
+ AnyValue value; // Held by value
514
+ bool await_ready();
515
+ void await_suspend(std::coroutine_handle<> h);
516
+ AnyValue await_resume();
651
517
  };
652
518
 
653
519
  // Inline implementation of operator co_await
@@ -655,4 +521,17 @@ namespace jspp
655
521
  {
656
522
  return AnyValueAwaiter{*this};
657
523
  }
658
- }
524
+
525
+ // Global Constants for Optimization
526
+ namespace Constants
527
+ {
528
+ inline const AnyValue UNINITIALIZED = AnyValue::make_uninitialized();
529
+ inline const AnyValue UNDEFINED = AnyValue::make_undefined();
530
+ inline const AnyValue Null = AnyValue::make_null();
531
+ inline const AnyValue NaN = AnyValue::make_nan();
532
+ inline const AnyValue TRUE = AnyValue::make_boolean(true);
533
+ inline const AnyValue FALSE = AnyValue::make_boolean(false);
534
+ inline const AnyValue ZERO = AnyValue::make_number(0.0);
535
+ inline const AnyValue ONE = AnyValue::make_number(1.0);
536
+ }
537
+ }