@ugo-studio/jspp 0.1.3 → 0.1.4

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 (69) hide show
  1. package/README.md +2 -2
  2. package/dist/analysis/scope.js +16 -4
  3. package/dist/analysis/typeAnalyzer.js +253 -20
  4. package/dist/ast/types.js +6 -0
  5. package/dist/cli.js +1 -2
  6. package/dist/core/codegen/class-handlers.js +127 -0
  7. package/dist/core/codegen/control-flow-handlers.js +464 -0
  8. package/dist/core/codegen/declaration-handlers.js +31 -14
  9. package/dist/core/codegen/expression-handlers.js +429 -117
  10. package/dist/core/codegen/function-handlers.js +91 -15
  11. package/dist/core/codegen/helpers.js +66 -2
  12. package/dist/core/codegen/index.js +17 -6
  13. package/dist/core/codegen/literal-handlers.js +3 -0
  14. package/dist/core/codegen/statement-handlers.js +133 -204
  15. package/dist/core/codegen/visitor.js +29 -3
  16. package/package.json +3 -3
  17. package/src/prelude/any_value.hpp +658 -634
  18. package/src/prelude/any_value_access.hpp +103 -0
  19. package/src/prelude/any_value_defines.hpp +151 -0
  20. package/src/prelude/any_value_helpers.hpp +246 -225
  21. package/src/prelude/exception.hpp +31 -0
  22. package/src/prelude/exception_helpers.hpp +49 -0
  23. package/src/prelude/index.hpp +18 -9
  24. package/src/prelude/library/console.hpp +13 -13
  25. package/src/prelude/library/error.hpp +111 -0
  26. package/src/prelude/library/global.hpp +15 -4
  27. package/src/prelude/library/performance.hpp +2 -2
  28. package/src/prelude/library/promise.hpp +121 -0
  29. package/src/prelude/library/symbol.hpp +3 -4
  30. package/src/prelude/library/timer.hpp +92 -0
  31. package/src/prelude/scheduler.hpp +145 -0
  32. package/src/prelude/types.hpp +10 -1
  33. package/src/prelude/utils/access.hpp +174 -0
  34. package/src/prelude/utils/log_any_value/array.hpp +245 -0
  35. package/src/prelude/utils/log_any_value/config.hpp +32 -0
  36. package/src/prelude/utils/log_any_value/function.hpp +37 -0
  37. package/src/prelude/utils/log_any_value/fwd.hpp +15 -0
  38. package/src/prelude/utils/log_any_value/helpers.hpp +62 -0
  39. package/src/prelude/utils/log_any_value/log_any_value.hpp +94 -0
  40. package/src/prelude/utils/log_any_value/object.hpp +119 -0
  41. package/src/prelude/utils/log_any_value/primitives.hpp +41 -0
  42. package/src/prelude/{operators.hpp → utils/operators.hpp} +29 -10
  43. package/src/prelude/{well_known_symbols.hpp → utils/well_known_symbols.hpp} +0 -1
  44. package/src/prelude/values/array.hpp +3 -2
  45. package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
  46. package/src/prelude/values/function.hpp +76 -51
  47. package/src/prelude/values/helpers/array.hpp +20 -11
  48. package/src/prelude/values/helpers/function.hpp +125 -77
  49. package/src/prelude/values/helpers/iterator.hpp +13 -7
  50. package/src/prelude/values/helpers/object.hpp +36 -6
  51. package/src/prelude/values/helpers/promise.hpp +181 -0
  52. package/src/prelude/values/helpers/string.hpp +3 -3
  53. package/src/prelude/values/helpers/symbol.hpp +2 -2
  54. package/src/prelude/values/iterator.hpp +13 -5
  55. package/src/prelude/values/object.hpp +6 -2
  56. package/src/prelude/values/promise.hpp +73 -0
  57. package/src/prelude/values/prototypes/array.hpp +16 -16
  58. package/src/prelude/values/prototypes/function.hpp +4 -4
  59. package/src/prelude/values/prototypes/iterator.hpp +11 -10
  60. package/src/prelude/values/prototypes/object.hpp +26 -0
  61. package/src/prelude/values/prototypes/promise.hpp +124 -0
  62. package/src/prelude/values/prototypes/string.hpp +26 -26
  63. package/src/prelude/values/prototypes/symbol.hpp +5 -3
  64. package/src/prelude/values/string.hpp +1 -1
  65. package/src/prelude/values/symbol.hpp +1 -1
  66. package/src/prelude/access.hpp +0 -91
  67. package/src/prelude/error.hpp +0 -31
  68. package/src/prelude/error_helpers.hpp +0 -59
  69. package/src/prelude/log_string.hpp +0 -407
@@ -11,9 +11,9 @@ namespace jspp
11
11
  inline std::optional<AnyValue> get(const std::string &key, JsSymbol *self)
12
12
  {
13
13
  // --- toString() method ---
14
- if (key == "toString" || key == WellKnownSymbols::toString->key)
14
+ if (key == "toString" )
15
15
  {
16
- return AnyValue::make_function([self](const std::vector<AnyValue> &) -> AnyValue
16
+ return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &) -> AnyValue
17
17
  { return AnyValue::make_string(self->to_std_string()); },
18
18
  key);
19
19
  }
@@ -22,10 +22,12 @@ namespace jspp
22
22
  if (key == "description")
23
23
  {
24
24
  return AnyValue::make_accessor_descriptor(
25
- [self](const std::vector<AnyValue> &) -> AnyValue
25
+ [self](const AnyValue &thisVal, const std::vector<AnyValue> &) -> AnyValue
26
26
  {
27
27
  if (self->description.empty())
28
+ {
28
29
  return AnyValue::make_undefined();
30
+ }
29
31
  return AnyValue::make_string(self->description);
30
32
  },
31
33
  std::nullopt,
@@ -19,7 +19,7 @@ namespace jspp
19
19
  std::string to_std_string() const;
20
20
  JsIterator<AnyValue> get_iterator();
21
21
 
22
- AnyValue get_property(const std::string &key);
22
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
23
23
  AnyValue get_property(uint32_t idx);
24
24
  };
25
25
  }
@@ -97,6 +97,6 @@ namespace jspp
97
97
 
98
98
  // --- Methods ---
99
99
  std::string to_std_string() const;
100
- AnyValue get_property(const std::string &key);
100
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
101
101
  };
102
102
  }
@@ -1,91 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "well_known_symbols.hpp"
5
- #include "values/function.hpp"
6
- #include "values/symbol.hpp"
7
- #include "error.hpp"
8
- #include "any_value.hpp"
9
- #include <ranges>
10
-
11
- namespace jspp
12
- {
13
- namespace Access
14
- {
15
- // Helper function to check for TDZ and deref variables
16
- inline const AnyValue &deref(const std::shared_ptr<AnyValue> &var, const std::string &name)
17
- {
18
- if ((*var).is_uninitialized()) [[unlikely]]
19
- {
20
- RuntimeError::throw_uninitialized_reference_error(name);
21
- }
22
- return *var;
23
- }
24
- inline AnyValue &deref(std::shared_ptr<AnyValue> &var, const std::string &name)
25
- {
26
- if ((*var).is_uninitialized()) [[unlikely]]
27
- {
28
- RuntimeError::throw_uninitialized_reference_error(name);
29
- }
30
- return *var;
31
- }
32
- inline const AnyValue &deref(const std::unique_ptr<AnyValue> &var, const std::string &name)
33
- {
34
- if ((*var).is_uninitialized()) [[unlikely]]
35
- {
36
- RuntimeError::throw_uninitialized_reference_error(name);
37
- }
38
- return *var;
39
- }
40
- inline AnyValue &deref(std::unique_ptr<AnyValue> &var, const std::string &name)
41
- {
42
- if ((*var).is_uninitialized()) [[unlikely]]
43
- {
44
- RuntimeError::throw_uninitialized_reference_error(name);
45
- }
46
- return *var;
47
- }
48
-
49
- inline std::vector<std::string> get_object_keys(const AnyValue &obj)
50
- {
51
- std::vector<std::string> keys;
52
-
53
- if (obj.is_object())
54
- {
55
- auto ptr = obj.as_object();
56
- for (const auto &pair : ptr->props)
57
- {
58
- if (!JsSymbol::is_internal_key(pair.first))
59
- keys.push_back(pair.first);
60
- }
61
- }
62
- if (obj.is_function())
63
- {
64
- auto ptr = obj.as_function();
65
- for (const auto &pair : ptr->props)
66
- {
67
- if (!JsSymbol::is_internal_key(pair.first))
68
- keys.push_back(pair.first);
69
- }
70
- }
71
- if (obj.is_array())
72
- {
73
- auto len = obj.as_array()->length;
74
- for (auto i = 0; i < len; ++i)
75
- {
76
- keys.push_back(std::to_string(i));
77
- }
78
- }
79
- if (obj.is_string())
80
- {
81
- auto len = obj.as_string()->value.length();
82
- for (auto i = 0; i < len; ++i)
83
- {
84
- keys.push_back(std::to_string(i));
85
- }
86
- }
87
-
88
- return keys;
89
- }
90
- }
91
- }
@@ -1,31 +0,0 @@
1
-
2
- #pragma once
3
-
4
- #include "types.hpp"
5
-
6
- namespace jspp
7
- {
8
- class AnyValue;
9
-
10
- struct RuntimeError : std::exception
11
- {
12
- std::shared_ptr<AnyValue> data;
13
-
14
- explicit RuntimeError(std::shared_ptr<AnyValue> d)
15
- : data(std::move(d)) {}
16
- explicit RuntimeError(const AnyValue &value)
17
- : data(std::make_shared<AnyValue>(value)) {}
18
- explicit RuntimeError(AnyValue &&value)
19
- : data(std::make_shared<AnyValue>(std::move(value))) {}
20
-
21
- const char *what() const noexcept override;
22
- static RuntimeError make_error(const std::string &message, const std::string &name);
23
- static AnyValue error_to_value(const std::exception &ex);
24
-
25
- // --- THROWERS
26
- static AnyValue throw_unresolved_reference_error(const std::string &var_name);
27
- static AnyValue throw_uninitialized_reference_error(const std::string &var_name);
28
- static AnyValue throw_immutable_assignment_error();
29
- static AnyValue throw_invalid_return_statement_error();
30
- };
31
- }
@@ -1,59 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "error.hpp"
5
- #include "any_value.hpp"
6
-
7
- const char *jspp::RuntimeError::what() const noexcept
8
- {
9
- return data->to_std_string().c_str();
10
- }
11
-
12
- jspp::RuntimeError jspp::RuntimeError::make_error(const std::string &message, const std::string &name = "Error")
13
- {
14
- auto errorObj = std::make_shared<AnyValue>(AnyValue::make_object({{"message", AnyValue::make_string(message)}, {"name", AnyValue::make_string(name)}}));
15
- (*errorObj).set_own_property(WellKnownSymbols::toString->key, AnyValue::make_function([errorObj](const std::vector<AnyValue> &) -> AnyValue
16
- {
17
- AnyValue name = (*errorObj).get_own_property("name");
18
- AnyValue message = (*errorObj).get_own_property("message");
19
- std::string str = "";
20
- if (name.is_string())
21
- str = name.to_std_string();
22
- else
23
- str = "Error";
24
- str += ": ";
25
- if (message.is_string())
26
- str += message.to_std_string();
27
- return AnyValue::make_string(str); },
28
- WellKnownSymbols::toString->key));
29
- return RuntimeError(errorObj);
30
- }
31
- jspp::AnyValue jspp::RuntimeError::error_to_value(const std::exception &ex)
32
- {
33
- if (const jspp::RuntimeError *err = dynamic_cast<const jspp::RuntimeError *>(&ex))
34
- {
35
- return (*err->data);
36
- }
37
- else
38
- {
39
- return AnyValue::make_string(ex.what());
40
- }
41
- }
42
-
43
- // --- THROWERS
44
- jspp::AnyValue jspp::RuntimeError::throw_unresolved_reference_error(const std::string &var_name)
45
- {
46
- throw RuntimeError::make_error(var_name + " is not defined", "ReferenceError");
47
- }
48
- jspp::AnyValue jspp::RuntimeError::throw_uninitialized_reference_error(const std::string &var_name)
49
- {
50
- throw RuntimeError::make_error("Cannot access '" + var_name + "' before initialization", "ReferenceError");
51
- }
52
- jspp::AnyValue jspp::RuntimeError::throw_immutable_assignment_error()
53
- {
54
- throw RuntimeError::make_error("Assignment to constant variable.", "TypeError");
55
- }
56
- jspp::AnyValue jspp::RuntimeError::throw_invalid_return_statement_error()
57
- {
58
- throw RuntimeError::make_error("Return statements are only valid inside functions.", "SyntaxError");
59
- }
@@ -1,407 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "well_known_symbols.hpp"
5
- #include "any_value.hpp"
6
- #include <sstream>
7
- #include <unordered_set>
8
- #include <algorithm>
9
-
10
- namespace jspp
11
- {
12
- namespace LogString
13
- {
14
- // --- Configuration for Logging Verbosity ---
15
- const int MAX_DEPTH = 5;
16
- const size_t MAX_STRING_LENGTH = 100;
17
- const size_t MAX_ARRAY_ITEMS = 50;
18
- const size_t MAX_OBJECT_PROPS = 30;
19
- // --- Configuration for Horizontal Layout ---
20
- const size_t HORIZONTAL_ARRAY_MAX_ITEMS = 10;
21
- const size_t HORIZONTAL_OBJECT_MAX_PROPS = 5;
22
-
23
- // ANSI Color Codes for terminal output
24
- namespace Color
25
- {
26
- const std::string RESET = "\033[0m";
27
- const std::string GREEN = "\033[32m";
28
- const std::string YELLOW = "\033[33m";
29
- const std::string BLUE = "\033[94m";
30
- const std::string CYAN = "\033[36m";
31
- const std::string MAGENTA = "\033[35m";
32
- const std::string BRIGHT_BLACK = "\033[90m"; // Grey
33
- }
34
-
35
- // Forward declarations
36
- inline std::string to_log_string(const AnyValue &val);
37
- inline std::string to_log_string(const AnyValue &val, std::unordered_set<const void *> &visited, int depth);
38
- inline bool is_simple_value(const AnyValue &val);
39
-
40
- inline bool is_valid_js_identifier(const std::string &s)
41
- {
42
- if (s.empty())
43
- {
44
- return false;
45
- }
46
- if (!std::isalpha(s[0]) && s[0] != '_' && s[0] != '$')
47
- {
48
- return false;
49
- }
50
- for (size_t i = 1; i < s.length(); ++i)
51
- {
52
- if (!std::isalnum(s[i]) && s[i] != '_' && s[i] != '$')
53
- {
54
- return false;
55
- }
56
- }
57
- return true;
58
- }
59
-
60
- inline bool is_simple_value(const AnyValue &val)
61
- {
62
- return val.is_undefined() || val.is_null() || val.is_uninitialized() ||
63
- val.is_boolean() || val.is_number() || val.is_string();
64
- }
65
-
66
- inline std::string truncate_string(const std::string &str)
67
- {
68
- if (str.length() > MAX_STRING_LENGTH)
69
- {
70
- return str.substr(0, MAX_STRING_LENGTH) + "...";
71
- }
72
- return str;
73
- }
74
-
75
- inline std::string to_log_string(const AnyValue &val)
76
- {
77
- std::unordered_set<const void *> visited;
78
- return to_log_string(val, visited, 0);
79
- }
80
-
81
- inline std::string to_log_string(const AnyValue &val, std::unordered_set<const void *> &visited, int depth)
82
- {
83
- // Primitives and simple wrapped values
84
- if (val.is_uninitialized())
85
- return Color::BRIGHT_BLACK + std::string("<uninitialized>") + Color::RESET;
86
- if (val.is_undefined())
87
- return Color::BRIGHT_BLACK + std::string("undefined") + Color::RESET;
88
- if (val.is_null())
89
- return Color::MAGENTA + std::string("null") + Color::RESET;
90
- if (val.is_boolean())
91
- return Color::YELLOW + std::string(val.as_boolean() ? "true" : "false") + Color::RESET;
92
- if (val.is_number())
93
- return Color::YELLOW + val.to_std_string() + Color::RESET;
94
- if (val.is_symbol())
95
- return Color::BLUE + val.to_std_string() + Color::RESET;
96
- if (val.is_string())
97
- {
98
- const std::string &s = val.as_string()->value;
99
- if (depth == 0)
100
- return truncate_string(s);
101
- return Color::GREEN + std::string("\"") + truncate_string(s) + "\"" + Color::RESET;
102
- }
103
- if (val.is_function())
104
- {
105
- auto fn = val.as_function();
106
- auto type_part = fn->is_generator ? "GeneratorFunction" : "Function";
107
- auto name_part = fn->name.size() > 0 ? ": " + fn->name : "";
108
- return Color::CYAN + "[" + type_part + name_part + "]" + Color::RESET;
109
- }
110
-
111
- // Depth limit
112
- if (depth > MAX_DEPTH)
113
- {
114
- if (val.is_object())
115
- return Color::CYAN + std::string("[Object]") + Color::RESET;
116
- if (val.is_array())
117
- return Color::CYAN + std::string("[Array]") + Color::RESET;
118
- }
119
-
120
- // Circular reference detection
121
- const void *ptr_address = nullptr;
122
- if (val.is_object())
123
- ptr_address = val.as_object();
124
- else if (val.is_array())
125
- ptr_address = val.as_array();
126
-
127
- if (ptr_address)
128
- {
129
- if (visited.count(ptr_address))
130
- return Color::CYAN + std::string("[Circular]") + Color::RESET;
131
- visited.insert(ptr_address);
132
- }
133
-
134
- std::string indent(depth * 2, ' ');
135
- std::string next_indent((depth + 1) * 2, ' ');
136
- std::stringstream ss;
137
-
138
- // Objects
139
- if (val.is_object())
140
- {
141
- auto obj = val.as_object();
142
-
143
- // If custom toString exists on the object, prefer it
144
- auto itToString = obj->props.find(jspp::WellKnownSymbols::toString->key);
145
- if (itToString != obj->props.end() && itToString->second.is_function())
146
- {
147
- try
148
- {
149
- auto result = itToString->second.as_function()->call({});
150
- return to_log_string(result, visited, depth);
151
- }
152
- catch (...)
153
- {
154
- // ignore and fallback to manual formatting
155
- }
156
- }
157
-
158
- size_t prop_count = obj->props.size();
159
-
160
- bool use_horizontal_layout = prop_count > 0 && prop_count <= HORIZONTAL_OBJECT_MAX_PROPS;
161
- if (use_horizontal_layout)
162
- {
163
- for (const auto &pair : obj->props)
164
- {
165
- if (!is_simple_value(pair.second))
166
- {
167
- use_horizontal_layout = false;
168
- break;
169
- }
170
- }
171
- }
172
-
173
- if (use_horizontal_layout)
174
- {
175
- ss << "{ ";
176
- size_t current_prop = 0;
177
- for (const auto &pair : obj->props)
178
- {
179
- if (is_valid_js_identifier(pair.first))
180
- {
181
- ss << pair.first;
182
- }
183
- else
184
- {
185
- ss << "\"" << pair.first << "\"";
186
- }
187
- ss << ": " << to_log_string(pair.second, visited, depth + 1);
188
- if (++current_prop < prop_count)
189
- ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
190
- }
191
- ss << " }";
192
- }
193
- else
194
- {
195
- ss << "{";
196
- if (prop_count > 0)
197
- {
198
- ss << "\n";
199
- size_t props_shown = 0;
200
- for (const auto &pair : obj->props)
201
- {
202
- if (props_shown >= MAX_OBJECT_PROPS)
203
- break;
204
- if (props_shown > 0)
205
- ss << ",\n";
206
-
207
- ss << next_indent;
208
- if (is_valid_js_identifier(pair.first))
209
- {
210
- ss << pair.first;
211
- }
212
- else
213
- {
214
- ss << "\"" << pair.first << "\"";
215
- }
216
- ss << ": " << to_log_string(pair.second, visited, depth + 1);
217
- props_shown++;
218
- }
219
- if (prop_count > MAX_OBJECT_PROPS)
220
- ss << ",\n"
221
- << next_indent << Color::BRIGHT_BLACK << "... " << (prop_count - MAX_OBJECT_PROPS) << " more properties" << Color::RESET;
222
- ss << "\n"
223
- << indent;
224
- }
225
- ss << "}";
226
- }
227
- return ss.str();
228
- }
229
-
230
- // Arrays
231
- if (val.is_array())
232
- {
233
- auto arr = val.as_array();
234
- size_t item_count = static_cast<size_t>(arr->length);
235
-
236
- // If custom toString exists on the object, prefer it
237
- auto itToString = arr->props.find(jspp::WellKnownSymbols::toString->key);
238
- if (depth > 0 && itToString != arr->props.end() && itToString->second.is_function())
239
- {
240
- try
241
- {
242
- auto result = itToString->second.as_function()->call({});
243
- return to_log_string(result, visited, depth);
244
- }
245
- catch (...)
246
- {
247
- // ignore and fallback to manual formatting
248
- }
249
- }
250
-
251
- std::string indent(depth * 2, ' ');
252
- std::string next_indent((depth + 1) * 2, ' ');
253
- std::stringstream ss;
254
-
255
- // Horizontal layout for small and simple arrays
256
- bool use_horizontal_layout = item_count <= HORIZONTAL_ARRAY_MAX_ITEMS;
257
- if (use_horizontal_layout)
258
- {
259
- for (size_t i = 0; i < item_count; ++i)
260
- {
261
- std::optional<AnyValue> itemVal;
262
- if (i < arr->dense.size())
263
- {
264
- itemVal = arr->dense[i];
265
- }
266
- else
267
- {
268
- auto it = arr->sparse.find(static_cast<uint32_t>(i));
269
- if (it != arr->sparse.end())
270
- {
271
- itemVal = it->second;
272
- }
273
- }
274
- if (itemVal.has_value() && !is_simple_value(itemVal.value()))
275
- {
276
- use_horizontal_layout = false;
277
- break;
278
- }
279
- }
280
- }
281
-
282
- if (use_horizontal_layout)
283
- {
284
- ss << "[ ";
285
- size_t empty_count = 0;
286
- bool needs_comma = false;
287
-
288
- for (size_t i = 0; i < item_count; ++i)
289
- {
290
- std::optional<AnyValue> itemVal;
291
- if (i < arr->dense.size())
292
- {
293
- itemVal = arr->dense[i];
294
- }
295
- else
296
- {
297
- auto it = arr->sparse.find(static_cast<uint32_t>(i));
298
- if (it != arr->sparse.end())
299
- {
300
- itemVal = it->second;
301
- }
302
- }
303
-
304
- if (itemVal.has_value())
305
- {
306
- if (empty_count > 0)
307
- {
308
- if (needs_comma)
309
- ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
310
- ss << Color::BRIGHT_BLACK << empty_count << " x empty item" << (empty_count > 1 ? "s" : "") << Color::RESET;
311
- needs_comma = true;
312
- empty_count = 0;
313
- }
314
- if (needs_comma)
315
- ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
316
- ss << to_log_string(itemVal.value(), visited, depth + 1);
317
- needs_comma = true;
318
- }
319
- else
320
- {
321
- empty_count++;
322
- }
323
- }
324
-
325
- if (empty_count > 0)
326
- {
327
- if (needs_comma)
328
- ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
329
- ss << Color::BRIGHT_BLACK << empty_count << " x empty item" << (empty_count > 1 ? "s" : "") << Color::RESET;
330
- }
331
-
332
- ss << " ]";
333
- return ss.str();
334
- }
335
-
336
- // Bun-like multi-line layout
337
- ss << "[\n";
338
-
339
- const size_t items_to_show = std::min(item_count, MAX_ARRAY_ITEMS);
340
- size_t empty_count = 0;
341
- bool first_item_printed = false;
342
-
343
- for (size_t i = 0; i < items_to_show; ++i)
344
- {
345
- std::optional<AnyValue> itemVal;
346
- if (i < arr->dense.size())
347
- {
348
- itemVal = arr->dense[i];
349
- }
350
- else
351
- {
352
- auto it = arr->sparse.find(static_cast<uint32_t>(i));
353
- if (it != arr->sparse.end())
354
- {
355
- itemVal = it->second;
356
- }
357
- }
358
-
359
- if (itemVal.has_value())
360
- {
361
- if (empty_count > 0)
362
- {
363
- if (first_item_printed)
364
- ss << Color::BRIGHT_BLACK << ",\n"
365
- << Color::RESET;
366
- ss << next_indent << Color::BRIGHT_BLACK << empty_count << " x empty item" << (empty_count > 1 ? "s" : "") << Color::RESET;
367
- first_item_printed = true;
368
- empty_count = 0;
369
- }
370
- if (first_item_printed)
371
- ss << Color::BRIGHT_BLACK << ",\n"
372
- << Color::RESET;
373
- ss << next_indent << to_log_string(itemVal.value(), visited, depth + 1);
374
- first_item_printed = true;
375
- }
376
- else
377
- {
378
- empty_count++;
379
- }
380
- }
381
-
382
- if (empty_count > 0)
383
- {
384
- if (first_item_printed)
385
- ss << Color::BRIGHT_BLACK << ",\n"
386
- << Color::RESET;
387
- ss << next_indent << Color::BRIGHT_BLACK << empty_count << " x empty item" << (empty_count > 1 ? "s" : "") << Color::RESET;
388
- first_item_printed = true;
389
- }
390
-
391
- if (item_count > items_to_show)
392
- {
393
- if (first_item_printed)
394
- ss << Color::BRIGHT_BLACK << ",\n"
395
- << Color::RESET;
396
- ss << next_indent << Color::BRIGHT_BLACK << "... " << (item_count - items_to_show) << " more items" << Color::RESET;
397
- }
398
- ss << "\n";
399
- ss << indent << "]";
400
- return ss.str();
401
- }
402
-
403
- // Fallback
404
- return val.to_std_string();
405
- }
406
- }
407
- }