@ugo-studio/jspp 0.1.1 → 0.1.3

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 (41) hide show
  1. package/README.md +3 -1
  2. package/dist/analysis/scope.js +22 -11
  3. package/dist/analysis/typeAnalyzer.js +4 -3
  4. package/dist/cli.js +7 -5
  5. package/dist/core/codegen/expression-handlers.js +10 -6
  6. package/dist/core/codegen/function-handlers.js +27 -6
  7. package/dist/core/codegen/helpers.js +12 -8
  8. package/dist/core/codegen/index.js +3 -1
  9. package/dist/core/codegen/statement-handlers.js +53 -16
  10. package/dist/core/codegen/visitor.js +7 -1
  11. package/package.json +2 -2
  12. package/src/prelude/access.hpp +8 -3
  13. package/src/prelude/any_value.hpp +141 -241
  14. package/src/prelude/any_value_helpers.hpp +225 -0
  15. package/src/prelude/error_helpers.hpp +3 -3
  16. package/src/prelude/index.hpp +17 -3
  17. package/src/prelude/library/console.hpp +7 -7
  18. package/src/prelude/library/performance.hpp +25 -0
  19. package/src/prelude/library/symbol.hpp +60 -3
  20. package/src/prelude/log_string.hpp +10 -6
  21. package/src/prelude/operators.hpp +2 -2
  22. package/src/prelude/types.hpp +24 -6
  23. package/src/prelude/values/array.hpp +2 -0
  24. package/src/prelude/values/function.hpp +33 -1
  25. package/src/prelude/values/{operators → helpers}/array.hpp +14 -7
  26. package/src/prelude/values/helpers/function.hpp +77 -0
  27. package/src/prelude/values/helpers/iterator.hpp +101 -0
  28. package/src/prelude/values/helpers/string.hpp +50 -0
  29. package/src/prelude/values/helpers/symbol.hpp +23 -0
  30. package/src/prelude/values/iterator.hpp +88 -0
  31. package/src/prelude/values/object.hpp +2 -1
  32. package/src/prelude/values/prototypes/array.hpp +18 -11
  33. package/src/prelude/values/prototypes/function.hpp +26 -0
  34. package/src/prelude/values/prototypes/iterator.hpp +57 -0
  35. package/src/prelude/values/prototypes/string.hpp +366 -357
  36. package/src/prelude/values/prototypes/symbol.hpp +39 -0
  37. package/src/prelude/values/string.hpp +25 -0
  38. package/src/prelude/values/symbol.hpp +102 -0
  39. package/src/prelude/well_known_symbols.hpp +7 -3
  40. package/src/prelude/values/operators/function.hpp +0 -34
  41. /package/src/prelude/values/{operators → helpers}/object.hpp +0 -0
@@ -11,18 +11,23 @@
11
11
  #include <memory>
12
12
  #include <utility>
13
13
  #include <string>
14
- #include <unordered_map>
14
+ #include <map>
15
15
  #include <vector>
16
16
  #include <functional>
17
17
  #include <cmath>
18
+ #include <optional>
18
19
 
19
20
  #include "types.hpp"
20
21
  #include "values/non_values.hpp"
21
22
  #include "values/object.hpp"
22
23
  #include "values/array.hpp"
23
24
  #include "values/function.hpp"
25
+ #include "values/iterator.hpp"
26
+ #include "values/symbol.hpp"
27
+ #include "values/string.hpp"
24
28
  #include "error.hpp"
25
29
  #include "descriptors.hpp"
30
+ #include "well_known_symbols.hpp"
26
31
 
27
32
  namespace jspp
28
33
  {
@@ -37,8 +42,10 @@ namespace jspp
37
42
  Object = 6,
38
43
  Array = 7,
39
44
  Function = 8,
40
- DataDescriptor = 9,
41
- AccessorDescriptor = 10,
45
+ Iterator = 9,
46
+ Symbol = 10,
47
+ DataDescriptor = 11,
48
+ AccessorDescriptor = 12,
42
49
  };
43
50
 
44
51
  // Tagged storage with a union for payload
@@ -52,10 +59,12 @@ namespace jspp
52
59
  JsUninitialized uninitialized;
53
60
  bool boolean;
54
61
  double number;
55
- std::unique_ptr<std::string> str;
62
+ std::shared_ptr<JsString> str;
56
63
  std::shared_ptr<JsObject> object;
57
64
  std::shared_ptr<JsArray> array;
58
65
  std::shared_ptr<JsFunction> function;
66
+ std::shared_ptr<JsIterator<AnyValue>> iterator;
67
+ std::shared_ptr<JsSymbol> symbol;
59
68
  std::shared_ptr<DataDescriptor> data_desc;
60
69
  std::shared_ptr<AccessorDescriptor> accessor_desc;
61
70
  };
@@ -74,7 +83,7 @@ namespace jspp
74
83
  switch (storage.type)
75
84
  {
76
85
  case JsType::String:
77
- storage.str.~unique_ptr();
86
+ storage.str.~shared_ptr();
78
87
  break;
79
88
  case JsType::Object:
80
89
  storage.object.~shared_ptr();
@@ -85,6 +94,12 @@ namespace jspp
85
94
  case JsType::Function:
86
95
  storage.function.~shared_ptr();
87
96
  break;
97
+ case JsType::Iterator:
98
+ storage.iterator.~shared_ptr();
99
+ break;
100
+ case JsType::Symbol:
101
+ storage.symbol.~shared_ptr();
102
+ break;
88
103
  case JsType::DataDescriptor:
89
104
  storage.data_desc.~shared_ptr();
90
105
  break;
@@ -124,7 +139,7 @@ namespace jspp
124
139
  storage.number = other.storage.number;
125
140
  break;
126
141
  case JsType::String:
127
- new (&storage.str) std::unique_ptr<std::string>(std::move(other.storage.str));
142
+ new (&storage.str) std::shared_ptr<JsString>(std::move(other.storage.str));
128
143
  break;
129
144
  case JsType::Object:
130
145
  new (&storage.object) std::shared_ptr<JsObject>(std::move(other.storage.object));
@@ -135,6 +150,12 @@ namespace jspp
135
150
  case JsType::Function:
136
151
  new (&storage.function) std::shared_ptr<JsFunction>(std::move(other.storage.function));
137
152
  break;
153
+ case JsType::Iterator:
154
+ new (&storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(std::move(other.storage.iterator));
155
+ break;
156
+ case JsType::Symbol:
157
+ new (&storage.symbol) std::shared_ptr<JsSymbol>(std::move(other.storage.symbol));
158
+ break;
138
159
  case JsType::DataDescriptor:
139
160
  new (&storage.data_desc) std::shared_ptr<DataDescriptor>(std::move(other.storage.data_desc));
140
161
  break;
@@ -165,7 +186,7 @@ namespace jspp
165
186
  storage.number = other.storage.number;
166
187
  break;
167
188
  case JsType::String:
168
- new (&storage.str) std::unique_ptr<std::string>(std::make_unique<std::string>(*other.storage.str));
189
+ new (&storage.str) std::shared_ptr<JsString>(std::make_shared<JsString>(*other.storage.str));
169
190
  break;
170
191
  case JsType::Object:
171
192
  new (&storage.object) std::shared_ptr<JsObject>(other.storage.object); // shallow copy
@@ -176,6 +197,12 @@ namespace jspp
176
197
  case JsType::Function:
177
198
  new (&storage.function) std::shared_ptr<JsFunction>(other.storage.function); // shallow copy
178
199
  break;
200
+ case JsType::Iterator:
201
+ new (&storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(other.storage.iterator); // shallow copy
202
+ break;
203
+ case JsType::Symbol:
204
+ new (&storage.symbol) std::shared_ptr<JsSymbol>(other.storage.symbol); // shallow copy (shared)
205
+ break;
179
206
  case JsType::DataDescriptor:
180
207
  new (&storage.data_desc) std::shared_ptr<DataDescriptor>(other.storage.data_desc); // shallow copy
181
208
  break;
@@ -291,10 +318,10 @@ namespace jspp
291
318
  {
292
319
  AnyValue v;
293
320
  v.storage.type = JsType::String;
294
- new (&v.storage.str) std::unique_ptr<std::string>(std::make_unique<std::string>(raw_s));
321
+ new (&v.storage.str) std::shared_ptr<JsString>(std::make_shared<JsString>(raw_s));
295
322
  return v;
296
323
  }
297
- static AnyValue make_object(const std::unordered_map<std::string, AnyValue> &props) noexcept
324
+ static AnyValue make_object(const std::map<std::string, AnyValue> &props) noexcept
298
325
  {
299
326
  AnyValue v;
300
327
  v.storage.type = JsType::Object;
@@ -308,13 +335,27 @@ namespace jspp
308
335
  new (&v.storage.array) std::shared_ptr<JsArray>(std::make_shared<JsArray>(dense));
309
336
  return v;
310
337
  }
311
- static AnyValue make_function(const std::function<AnyValue(const std::vector<AnyValue> &)> &call, const std::string &name) noexcept
338
+ static AnyValue make_function(const JsFunctionCallable &call, const std::string &name) noexcept
312
339
  {
313
340
  AnyValue v;
314
341
  v.storage.type = JsType::Function;
315
342
  new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, name));
316
343
  return v;
317
344
  }
345
+ static AnyValue make_generator(const JsFunctionCallable &call, const std::string &name) noexcept
346
+ {
347
+ AnyValue v;
348
+ v.storage.type = JsType::Function;
349
+ new (&v.storage.function) std::shared_ptr<JsFunction>(std::make_shared<JsFunction>(call, true, name));
350
+ return v;
351
+ }
352
+ static AnyValue make_symbol(const std::string &description = "") noexcept
353
+ {
354
+ AnyValue v;
355
+ v.storage.type = JsType::Symbol;
356
+ new (&v.storage.symbol) std::shared_ptr<JsSymbol>(std::make_shared<JsSymbol>(description));
357
+ return v;
358
+ }
318
359
  static AnyValue make_data_descriptor(const AnyValue &value, bool writable, bool enumerable, bool configurable) noexcept
319
360
  {
320
361
  AnyValue v;
@@ -333,6 +374,35 @@ namespace jspp
333
374
  return v;
334
375
  }
335
376
 
377
+ static AnyValue from_symbol(std::shared_ptr<JsSymbol> sym) noexcept
378
+ {
379
+ AnyValue v;
380
+ v.storage.type = JsType::Symbol;
381
+ new (&v.storage.symbol) std::shared_ptr<JsSymbol>(std::move(sym));
382
+ return v;
383
+ }
384
+ static AnyValue from_string(std::shared_ptr<JsString> str) noexcept
385
+ {
386
+ AnyValue v;
387
+ v.storage.type = JsType::String;
388
+ new (&v.storage.str) std::shared_ptr<JsString>(std::move(str));
389
+ return v;
390
+ }
391
+ static AnyValue from_iterator(JsIterator<AnyValue> &&iterator) noexcept
392
+ {
393
+ AnyValue v;
394
+ v.storage.type = JsType::Iterator;
395
+ new (&v.storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(std::make_shared<JsIterator<AnyValue>>(std::move(iterator)));
396
+ return v;
397
+ }
398
+ static AnyValue from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept
399
+ {
400
+ AnyValue v;
401
+ v.storage.type = JsType::Iterator;
402
+ new (&v.storage.iterator) std::shared_ptr<JsIterator<AnyValue>>(iterator, [](JsIterator<AnyValue> *) {});
403
+ return v;
404
+ }
405
+
336
406
  // property resolution helpers ---------------------------------------
337
407
  static AnyValue resolve_property_for_read(const AnyValue &val) noexcept
338
408
  {
@@ -393,12 +463,15 @@ namespace jspp
393
463
  bool is_object() const noexcept { return storage.type == JsType::Object; }
394
464
  bool is_array() const noexcept { return storage.type == JsType::Array; }
395
465
  bool is_function() const noexcept { return storage.type == JsType::Function; }
466
+ bool is_iterator() const noexcept { return storage.type == JsType::Iterator; }
396
467
  bool is_boolean() const noexcept { return storage.type == JsType::Boolean; }
468
+ bool is_symbol() const noexcept { return storage.type == JsType::Symbol; }
397
469
  bool is_null() const noexcept { return storage.type == JsType::Null; }
398
470
  bool is_undefined() const noexcept { return storage.type == JsType::Undefined; }
399
471
  bool is_uninitialized() const noexcept { return storage.type == JsType::Uninitialized; }
400
472
  bool is_data_descriptor() const noexcept { return storage.type == JsType::DataDescriptor; }
401
473
  bool is_accessor_descriptor() const noexcept { return storage.type == JsType::AccessorDescriptor; }
474
+ bool is_generator() const noexcept { return storage.type == JsType::Function && storage.function->is_generator; }
402
475
 
403
476
  // --- TYPE CASTERS
404
477
  double as_double() const noexcept
@@ -411,7 +484,7 @@ namespace jspp
411
484
  assert(is_boolean());
412
485
  return storage.boolean;
413
486
  }
414
- std::string *as_string() const noexcept
487
+ JsString *as_string() const noexcept
415
488
  {
416
489
  assert(is_string());
417
490
  return storage.str.get();
@@ -426,11 +499,21 @@ namespace jspp
426
499
  assert(is_array());
427
500
  return storage.array.get();
428
501
  }
429
- JsFunction *as_function(const std::string &expression = "") const
502
+ JsFunction *as_function(const std::optional<std::string> &expression = std::nullopt) const
430
503
  {
431
504
  if (is_function())
432
505
  return storage.function.get();
433
- throw RuntimeError::make_error(expression + " is not a function", "TypeError");
506
+ throw RuntimeError::make_error(expression.value_or(to_std_string()) + " is not a function", "TypeError");
507
+ }
508
+ JsSymbol *as_symbol() const noexcept
509
+ {
510
+ assert(is_symbol());
511
+ return storage.symbol.get();
512
+ }
513
+ std::shared_ptr<JsIterator<AnyValue>> as_iterator() const
514
+ {
515
+ assert(is_iterator());
516
+ return storage.iterator; // Returns the shared_ptr, incrementing ref count
434
517
  }
435
518
  DataDescriptor *as_data_descriptor() const noexcept
436
519
  {
@@ -444,31 +527,22 @@ namespace jspp
444
527
  }
445
528
 
446
529
  // --- PROPERTY ACCESS OPERATORS
447
- AnyValue get_own_property(const std::string &key)
530
+ AnyValue get_own_property(const std::string &key) const
448
531
  {
449
532
  switch (storage.type)
450
533
  {
451
534
  case JsType::Object:
452
- return as_object()->get_property(key);
535
+ return storage.object->get_property(key);
453
536
  case JsType::Array:
454
- return as_array()->get_property(key);
537
+ return storage.array->get_property(key);
455
538
  case JsType::Function:
456
- return as_function()->get_property(key);
539
+ return storage.function->get_property(key);
540
+ case JsType::Iterator:
541
+ return storage.iterator->get_property(key);
542
+ case JsType::Symbol:
543
+ return storage.symbol->get_property(key);
457
544
  case JsType::String:
458
- {
459
- // Check for prototype methods
460
- auto proto_fn = StringPrototypes::get(key, this->storage.str);
461
- if (proto_fn.has_value())
462
- {
463
- return resolve_property_for_read(proto_fn.value());
464
- }
465
- // Handle character access by string index (e.g., "abc"["1"])
466
- if (JsArray::is_array_index(key))
467
- {
468
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
469
- return get_own_property(idx);
470
- }
471
- }
545
+ return storage.str->get_property(key);
472
546
  case JsType::Undefined:
473
547
  throw RuntimeError::make_error("Cannot read properties of undefined (reading '" + key + "')", "TypeError");
474
548
  case JsType::Null:
@@ -477,41 +551,42 @@ namespace jspp
477
551
  return AnyValue::make_undefined();
478
552
  }
479
553
  }
480
- AnyValue get_own_property(uint32_t idx) noexcept
554
+ AnyValue get_own_property(uint32_t idx) const noexcept
481
555
  {
482
556
  switch (storage.type)
483
557
  {
484
558
  case JsType::Array:
485
- return as_array()->get_property(idx);
486
- case JsType::String: // Handle character access by index (e.g., "abc"[1])
487
- {
488
- if (idx < storage.str->length())
489
- {
490
- return AnyValue::make_string(std::string(1, (*storage.str)[idx]));
491
- }
492
- return AnyValue::make_undefined();
493
- }
559
+ return storage.array->get_property(idx);
560
+ case JsType::String:
561
+ return storage.str->get_property(idx);
494
562
  default:
495
563
  return get_own_property(std::to_string(idx));
496
564
  }
497
565
  }
498
- AnyValue get_own_property(const AnyValue &key) noexcept
566
+ AnyValue get_own_property(const AnyValue &key) const noexcept
499
567
  {
500
568
  if (key.storage.type == JsType::Number && storage.type == JsType::Array)
501
569
  return storage.array->get_property(key.storage.number);
570
+ if (key.storage.type == JsType::Number && storage.type == JsType::String)
571
+ return storage.str->get_property(key.storage.number);
572
+
573
+ // If the key is a Symbol, use its internal key string
574
+ if (key.storage.type == JsType::Symbol)
575
+ return get_own_property(key.storage.symbol->key);
576
+
502
577
  return get_own_property(key.to_std_string());
503
578
  }
504
579
  // for setting values
505
- AnyValue set_own_property(const std::string &key, const AnyValue &value)
580
+ AnyValue set_own_property(const std::string &key, const AnyValue &value) const
506
581
  {
507
582
  switch (storage.type)
508
583
  {
509
584
  case JsType::Object:
510
- return as_object()->set_property(key, value);
585
+ return storage.object->set_property(key, value);
511
586
  case JsType::Array:
512
- return as_array()->set_property(key, value);
587
+ return storage.array->set_property(key, value);
513
588
  case JsType::Function:
514
- return as_function()->set_property(key, value);
589
+ return storage.function->set_property(key, value);
515
590
  case JsType::Undefined:
516
591
  throw RuntimeError::make_error("Cannot set properties of undefined (setting '" + key + "')", "TypeError");
517
592
  case JsType::Null:
@@ -520,215 +595,40 @@ namespace jspp
520
595
  return value;
521
596
  }
522
597
  }
523
- AnyValue set_own_property(uint32_t idx, const AnyValue &value)
598
+ AnyValue set_own_property(uint32_t idx, const AnyValue &value) const
524
599
  {
525
600
  if (storage.type == JsType::Array)
526
601
  {
527
- return as_array()->set_property(idx, value);
602
+ return storage.array->set_property(idx, value);
528
603
  }
529
604
  return set_own_property(std::to_string(idx), value);
530
605
  }
531
- AnyValue set_own_property(const AnyValue &key, const AnyValue &value)
606
+ AnyValue set_own_property(const AnyValue &key, const AnyValue &value) const
532
607
  {
533
608
  if (key.storage.type == JsType::Number && storage.type == JsType::Array)
534
609
  {
535
610
  return storage.array->set_property(key.storage.number, value);
536
611
  }
612
+
613
+ // If the key is a Symbol, use its internal key string
614
+ if (key.storage.type == JsType::Symbol)
615
+ return set_own_property(key.storage.symbol->key, value);
616
+
537
617
  return set_own_property(key.to_std_string(), value);
538
618
  }
539
619
 
540
620
  // --- HELPERS
541
- const bool is_truthy() const noexcept
542
- {
543
- switch (storage.type)
544
- {
545
- case JsType::Boolean:
546
- return storage.boolean;
547
- case JsType::Number:
548
- return storage.number != 0.0;
549
- case JsType::String:
550
- return !storage.str->empty();
551
- default:
552
- return true;
553
- }
554
- }
555
- const bool is_strictly_equal_to(const AnyValue &other) const noexcept
556
- {
557
- if (storage.type == other.storage.type)
558
- {
559
- switch (storage.type)
560
- {
561
- case JsType::Boolean:
562
- return storage.boolean == other.storage.boolean;
563
- case JsType::Number:
564
- return storage.number == other.storage.number;
565
- case JsType::String:
566
- return (*storage.str.get() == *other.storage.str.get());
567
- case JsType::Array:
568
- return (storage.array == other.storage.array);
569
- case JsType::Object:
570
- return (storage.object == other.storage.object);
571
- case JsType::Function:
572
- return (storage.function == other.storage.function);
573
- default:
574
- return true;
575
- }
576
- }
577
- return false;
578
- }
579
- const bool is_equal_to(const AnyValue &other) const noexcept
580
- {
581
- // Implements JavaScript's Abstract Equality Comparison Algorithm (==)
582
- // Step 1: If types are the same, use strict equality (===)
583
- if (storage.type == other.storage.type)
584
- {
585
- return is_strictly_equal_to(other);
586
- }
587
- // Steps 2 & 3: null == undefined
588
- if ((is_null() && other.is_undefined()) || (is_undefined() && other.is_null()))
589
- {
590
- return true;
591
- }
592
- // Step 4 & 5: number == string
593
- if (is_number() && other.is_string())
594
- {
595
- double num_this = this->as_double();
596
- double num_other;
597
- try
598
- {
599
- const std::string &s = *other.as_string();
600
- // JS considers empty string or whitespace-only string to be 0
601
- if (s.empty() || std::all_of(s.begin(), s.end(), [](unsigned char c)
602
- { return std::isspace(c); }))
603
- {
604
- num_other = 0.0;
605
- }
606
- else
607
- {
608
- size_t pos;
609
- num_other = std::stod(s, &pos);
610
- // Check if the entire string was consumed, allowing for trailing whitespace
611
- while (pos < s.length() && std::isspace(static_cast<unsigned char>(s[pos])))
612
- {
613
- pos++;
614
- }
615
- if (pos != s.length())
616
- {
617
- num_other = std::numeric_limits<double>::quiet_NaN();
618
- }
619
- }
620
- }
621
- catch (...)
622
- {
623
- num_other = std::numeric_limits<double>::quiet_NaN();
624
- }
625
- return num_this == num_other;
626
- }
627
- if (is_string() && other.is_number())
628
- {
629
- // Delegate to the other operand to avoid code duplication
630
- return other.is_equal_to(*this);
631
- }
632
- // Step 6 & 7: boolean == any
633
- if (is_boolean())
634
- {
635
- // Convert boolean to number and re-compare
636
- return AnyValue::make_number(as_boolean() ? 1.0 : 0.0).is_equal_to(other);
637
- }
638
- if (other.is_boolean())
639
- {
640
- // Convert boolean to number and re-compare
641
- return is_equal_to(AnyValue::make_number(other.as_boolean() ? 1.0 : 0.0));
642
- }
643
- // Step 8 & 9: object == (string or number)
644
- if ((other.is_object() || other.is_array() || other.is_function()) && (is_string() || is_number()))
645
- {
646
- // Delegate to the other operand to avoid code duplication
647
- return other.is_equal_to(*this);
648
- }
649
- if ((is_object() || is_array() || is_function()) && (other.is_string() || other.is_number()))
650
- {
651
- // Convert object to primitive (string) and re-compare.
652
- // This is a simplification of JS's ToPrimitive which would try valueOf() first.
653
- return AnyValue::make_string(to_std_string()).is_equal_to(other);
654
- }
655
- // Step 10: All other cases (e.g., object == null) are false.
656
- return false;
657
- }
658
- const AnyValue is_strictly_equal_to_primitive(const AnyValue &other) const noexcept
659
- {
660
- return AnyValue::make_boolean(is_strictly_equal_to(other));
661
- }
662
- const AnyValue is_equal_to_primitive(const AnyValue &other) const noexcept
663
- {
664
- return AnyValue::make_boolean(is_equal_to(other));
665
- }
666
- const AnyValue not_strictly_equal_to_primitive(const AnyValue &other) const noexcept
667
- {
668
- return AnyValue::make_boolean(!is_strictly_equal_to(other));
669
- }
670
- const AnyValue not_equal_to_primitive(const AnyValue &other) const noexcept
671
- {
672
- return AnyValue::make_boolean(!is_equal_to(other));
673
- }
674
- const std::string to_std_string() const noexcept
675
- {
676
- switch (storage.type)
677
- {
678
- case JsType::Undefined:
679
- return "undefined";
680
- case JsType::Null:
681
- return "null";
682
- case JsType::Boolean:
683
- return storage.boolean ? "true" : "false";
684
- case JsType::String:
685
- return *storage.str.get();
686
- case JsType::Object:
687
- return storage.object->to_std_string();
688
- case JsType::Array:
689
- return storage.array->to_std_string();
690
- case JsType::Function:
691
- return storage.function->to_std_string();
692
- case JsType::DataDescriptor:
693
- return storage.data_desc->value->to_std_string();
694
- case JsType::AccessorDescriptor:
695
- {
696
- if (storage.accessor_desc->get.has_value())
697
- return storage.accessor_desc->get.value()({}).to_std_string();
698
- else
699
- return "undefined";
700
- }
701
- case JsType::Number:
702
- {
703
- if (std::isnan(storage.number))
704
- {
705
- return "NaN";
706
- }
707
- if (std::abs(storage.number) >= 1e21 || (std::abs(storage.number) > 0 && std::abs(storage.number) < 1e-6))
708
- {
709
- std::ostringstream oss;
710
- oss << std::scientific << std::setprecision(4) << storage.number;
711
- return oss.str();
712
- }
713
- else
714
- {
715
- std::ostringstream oss;
716
- oss << std::setprecision(6) << std::fixed << storage.number;
717
- std::string s = oss.str();
718
- s.erase(s.find_last_not_of('0') + 1, std::string::npos);
719
- if (!s.empty() && s.back() == '.')
720
- {
721
- s.pop_back();
722
- }
723
- return s;
724
- }
725
- }
726
- // Uninitialized and default should not be reached under normal circumstances
727
- case JsType::Uninitialized:
728
- return "<uninitialized>";
729
- default:
730
- return "";
731
- }
732
- }
621
+ const bool is_truthy() const noexcept;
622
+
623
+ const bool is_strictly_equal_to(const AnyValue &other) const noexcept;
624
+ const bool is_equal_to(const AnyValue &other) const noexcept;
625
+
626
+ const AnyValue is_strictly_equal_to_primitive(const AnyValue &other) const noexcept;
627
+ const AnyValue is_equal_to_primitive(const AnyValue &other) const noexcept;
628
+
629
+ const AnyValue not_strictly_equal_to_primitive(const AnyValue &other) const noexcept;
630
+ const AnyValue not_equal_to_primitive(const AnyValue &other) const noexcept;
631
+
632
+ const std::string to_std_string() const noexcept;
733
633
  };
734
634
  }