@ugo-studio/jspp 0.1.3 → 0.1.5
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.
- package/README.md +2 -2
- package/dist/analysis/scope.js +33 -4
- package/dist/analysis/typeAnalyzer.js +260 -21
- package/dist/ast/symbols.js +29 -0
- package/dist/cli-utils/args.js +57 -0
- package/dist/cli-utils/colors.js +9 -0
- package/dist/cli-utils/file-utils.js +20 -0
- package/dist/cli-utils/spinner.js +55 -0
- package/dist/cli.js +105 -31
- package/dist/core/codegen/class-handlers.js +131 -0
- package/dist/core/codegen/control-flow-handlers.js +474 -0
- package/dist/core/codegen/declaration-handlers.js +36 -15
- package/dist/core/codegen/expression-handlers.js +579 -125
- package/dist/core/codegen/function-handlers.js +222 -37
- package/dist/core/codegen/helpers.js +158 -4
- package/dist/core/codegen/index.js +20 -8
- package/dist/core/codegen/literal-handlers.js +18 -6
- package/dist/core/codegen/statement-handlers.js +171 -228
- package/dist/core/codegen/visitor.js +31 -3
- package/package.json +3 -3
- package/src/prelude/any_value.hpp +510 -633
- package/src/prelude/any_value_access.hpp +151 -0
- package/src/prelude/any_value_defines.hpp +190 -0
- package/src/prelude/any_value_helpers.hpp +139 -225
- package/src/prelude/exception.hpp +32 -0
- package/src/prelude/exception_helpers.hpp +49 -0
- package/src/prelude/index.hpp +25 -9
- package/src/prelude/library/array.hpp +190 -0
- package/src/prelude/library/console.hpp +14 -13
- package/src/prelude/library/error.hpp +113 -0
- package/src/prelude/library/function.hpp +10 -0
- package/src/prelude/library/global.hpp +35 -4
- package/src/prelude/library/math.hpp +308 -0
- package/src/prelude/library/object.hpp +288 -0
- package/src/prelude/library/performance.hpp +2 -2
- package/src/prelude/library/process.hpp +39 -0
- package/src/prelude/library/promise.hpp +131 -0
- package/src/prelude/library/symbol.hpp +46 -59
- package/src/prelude/library/timer.hpp +92 -0
- package/src/prelude/scheduler.hpp +145 -0
- package/src/prelude/types.hpp +58 -1
- package/src/prelude/utils/access.hpp +345 -0
- package/src/prelude/utils/assignment_operators.hpp +99 -0
- package/src/prelude/utils/log_any_value/array.hpp +245 -0
- package/src/prelude/utils/log_any_value/config.hpp +32 -0
- package/src/prelude/utils/log_any_value/function.hpp +39 -0
- package/src/prelude/utils/log_any_value/fwd.hpp +15 -0
- package/src/prelude/utils/log_any_value/helpers.hpp +62 -0
- package/src/prelude/utils/log_any_value/log_any_value.hpp +94 -0
- package/src/prelude/utils/log_any_value/object.hpp +136 -0
- package/src/prelude/utils/log_any_value/primitives.hpp +43 -0
- package/src/prelude/utils/operators.hpp +751 -0
- package/src/prelude/utils/well_known_symbols.hpp +25 -0
- package/src/prelude/values/array.hpp +10 -7
- package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
- package/src/prelude/values/function.hpp +85 -51
- package/src/prelude/values/helpers/array.hpp +80 -35
- package/src/prelude/values/helpers/function.hpp +110 -77
- package/src/prelude/values/helpers/iterator.hpp +16 -10
- package/src/prelude/values/helpers/object.hpp +85 -10
- package/src/prelude/values/helpers/promise.hpp +181 -0
- package/src/prelude/values/helpers/string.hpp +3 -3
- package/src/prelude/values/helpers/symbol.hpp +2 -2
- package/src/prelude/values/iterator.hpp +14 -6
- package/src/prelude/values/object.hpp +14 -3
- package/src/prelude/values/promise.hpp +73 -0
- package/src/prelude/values/prototypes/array.hpp +855 -16
- package/src/prelude/values/prototypes/function.hpp +4 -4
- package/src/prelude/values/prototypes/iterator.hpp +11 -10
- package/src/prelude/values/prototypes/number.hpp +153 -0
- package/src/prelude/values/prototypes/object.hpp +26 -0
- package/src/prelude/values/prototypes/promise.hpp +134 -0
- package/src/prelude/values/prototypes/string.hpp +29 -29
- package/src/prelude/values/prototypes/symbol.hpp +22 -3
- package/src/prelude/values/shape.hpp +52 -0
- package/src/prelude/values/string.hpp +1 -1
- package/src/prelude/values/symbol.hpp +1 -1
- package/src/prelude/access.hpp +0 -91
- package/src/prelude/error.hpp +0 -31
- package/src/prelude/error_helpers.hpp +0 -59
- package/src/prelude/log_string.hpp +0 -407
- package/src/prelude/operators.hpp +0 -256
- package/src/prelude/well_known_symbols.hpp +0 -14
|
@@ -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
|
-
}
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "types.hpp"
|
|
4
|
-
#include "any_value.hpp"
|
|
5
|
-
#include <cstdint> // For int32_t
|
|
6
|
-
#include <cmath> // For fmod, isnan, isinf, floor, abs, pow
|
|
7
|
-
|
|
8
|
-
namespace jspp
|
|
9
|
-
{
|
|
10
|
-
// Private namespace for helper functions that implement JS type conversions.
|
|
11
|
-
namespace Operators_Private
|
|
12
|
-
{
|
|
13
|
-
// Implements the ToNumber abstract operation from ECMA-262.
|
|
14
|
-
inline double ToNumber(const AnyValue &val)
|
|
15
|
-
{
|
|
16
|
-
if (val.is_number())
|
|
17
|
-
return val.as_double();
|
|
18
|
-
if (val.is_null())
|
|
19
|
-
return 0.0;
|
|
20
|
-
if (val.is_undefined() || val.is_uninitialized())
|
|
21
|
-
return std::numeric_limits<double>::quiet_NaN();
|
|
22
|
-
if (val.is_boolean())
|
|
23
|
-
return val.as_boolean() ? 1.0 : 0.0;
|
|
24
|
-
if (val.is_string())
|
|
25
|
-
{
|
|
26
|
-
const std::string &s = val.as_string()->value;
|
|
27
|
-
// JS considers empty or whitespace-only strings as 0.
|
|
28
|
-
if (s.empty() || std::all_of(s.begin(), s.end(), isspace))
|
|
29
|
-
return 0.0;
|
|
30
|
-
try
|
|
31
|
-
{
|
|
32
|
-
size_t pos;
|
|
33
|
-
double num = std::stod(s, &pos);
|
|
34
|
-
// Ensure the entire string was parsed, allowing for trailing whitespace.
|
|
35
|
-
while (pos < s.length() && std::isspace(s[pos]))
|
|
36
|
-
pos++;
|
|
37
|
-
if (pos != s.length())
|
|
38
|
-
return std::numeric_limits<double>::quiet_NaN();
|
|
39
|
-
return num;
|
|
40
|
-
}
|
|
41
|
-
catch (...)
|
|
42
|
-
{
|
|
43
|
-
return std::numeric_limits<double>::quiet_NaN();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// In a full engine, objects would be converted via valueOf/toString.
|
|
47
|
-
// Here we simplify and return NaN.
|
|
48
|
-
return std::numeric_limits<double>::quiet_NaN();
|
|
49
|
-
}
|
|
50
|
-
// Implements the ToInt32 abstract operation from ECMA-262.
|
|
51
|
-
inline int32_t ToInt32(const AnyValue &val)
|
|
52
|
-
{
|
|
53
|
-
double num = ToNumber(val);
|
|
54
|
-
|
|
55
|
-
if (std::isnan(num) || std::isinf(num) || num == 0)
|
|
56
|
-
return 0;
|
|
57
|
-
|
|
58
|
-
double posInt = std::signbit(num) ? -std::floor(std::abs(num)) : std::floor(std::abs(num));
|
|
59
|
-
double int32bit = fmod(posInt, 4294967296.0); // 2^32
|
|
60
|
-
|
|
61
|
-
if (int32bit >= 2147483648.0) // 2^31
|
|
62
|
-
return static_cast<int32_t>(int32bit - 4294967296.0);
|
|
63
|
-
else
|
|
64
|
-
return static_cast<int32_t>(int32bit);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// --- BASIC ARITHEMETIC
|
|
69
|
-
inline AnyValue operator+(const AnyValue &lhs, const AnyValue &rhs)
|
|
70
|
-
{
|
|
71
|
-
// Special case for addition: string concatenation has priority
|
|
72
|
-
if (lhs.is_string() || rhs.is_string())
|
|
73
|
-
return AnyValue::make_string(lhs.to_std_string() + rhs.to_std_string());
|
|
74
|
-
if (lhs.is_number() && rhs.is_number())
|
|
75
|
-
return AnyValue::make_number(lhs.as_double() + rhs.as_double());
|
|
76
|
-
// Fallback to numeric conversion
|
|
77
|
-
return AnyValue::make_number(Operators_Private::ToNumber(lhs) + Operators_Private::ToNumber(rhs));
|
|
78
|
-
}
|
|
79
|
-
inline AnyValue operator-(const AnyValue &lhs, const AnyValue &rhs)
|
|
80
|
-
{
|
|
81
|
-
return AnyValue::make_number(Operators_Private::ToNumber(lhs) - Operators_Private::ToNumber(rhs));
|
|
82
|
-
}
|
|
83
|
-
inline AnyValue operator*(const AnyValue &lhs, const AnyValue &rhs)
|
|
84
|
-
{
|
|
85
|
-
return AnyValue::make_number(Operators_Private::ToNumber(lhs) * Operators_Private::ToNumber(rhs));
|
|
86
|
-
}
|
|
87
|
-
inline AnyValue operator/(const AnyValue &lhs, const AnyValue &rhs)
|
|
88
|
-
{
|
|
89
|
-
return AnyValue::make_number(Operators_Private::ToNumber(lhs) / Operators_Private::ToNumber(rhs));
|
|
90
|
-
}
|
|
91
|
-
inline AnyValue operator%(const AnyValue &lhs, const AnyValue &rhs)
|
|
92
|
-
{
|
|
93
|
-
return AnyValue::make_number(std::fmod(Operators_Private::ToNumber(lhs), Operators_Private::ToNumber(rhs)));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// --- UNARY OPERATORS
|
|
97
|
-
inline AnyValue operator-(const AnyValue &val)
|
|
98
|
-
{
|
|
99
|
-
return AnyValue::make_number(-Operators_Private::ToNumber(val));
|
|
100
|
-
}
|
|
101
|
-
inline AnyValue operator~(const AnyValue &val)
|
|
102
|
-
{
|
|
103
|
-
return AnyValue::make_number(~Operators_Private::ToInt32(val));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// --- EXPONENTIATION
|
|
107
|
-
inline AnyValue pow(const AnyValue &lhs, const AnyValue &rhs)
|
|
108
|
-
{
|
|
109
|
-
double base = Operators_Private::ToNumber(lhs);
|
|
110
|
-
double exp = Operators_Private::ToNumber(rhs);
|
|
111
|
-
return AnyValue::make_number(std::pow(base, exp));
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// --- COMPARISON OPERATORS
|
|
115
|
-
inline AnyValue operator<(const AnyValue &lhs, const AnyValue &rhs)
|
|
116
|
-
{
|
|
117
|
-
// Simplified Abstract Relational Comparison
|
|
118
|
-
if (lhs.is_string() && rhs.is_string())
|
|
119
|
-
return AnyValue::make_boolean(lhs.as_string()->value < rhs.as_string()->value);
|
|
120
|
-
|
|
121
|
-
double l = Operators_Private::ToNumber(lhs);
|
|
122
|
-
double r = Operators_Private::ToNumber(rhs);
|
|
123
|
-
|
|
124
|
-
if (std::isnan(l) || std::isnan(r))
|
|
125
|
-
return AnyValue::make_boolean(false); // Comparison with NaN is false
|
|
126
|
-
|
|
127
|
-
return AnyValue::make_boolean(l < r);
|
|
128
|
-
}
|
|
129
|
-
inline AnyValue operator>(const AnyValue &lhs, const AnyValue &rhs)
|
|
130
|
-
{
|
|
131
|
-
return rhs < lhs;
|
|
132
|
-
}
|
|
133
|
-
inline AnyValue operator<=(const AnyValue &lhs, const AnyValue &rhs)
|
|
134
|
-
{
|
|
135
|
-
// a <= b is equivalent to !(b < a)
|
|
136
|
-
AnyValue result = rhs < lhs;
|
|
137
|
-
return AnyValue::make_boolean(!result.as_boolean());
|
|
138
|
-
}
|
|
139
|
-
inline AnyValue operator>=(const AnyValue &lhs, const AnyValue &rhs)
|
|
140
|
-
{
|
|
141
|
-
// a >= b is equivalent to !(a < b)
|
|
142
|
-
AnyValue result = lhs < rhs;
|
|
143
|
-
return AnyValue::make_boolean(!result.as_boolean());
|
|
144
|
-
}
|
|
145
|
-
inline AnyValue operator==(const AnyValue &lhs, const AnyValue &rhs)
|
|
146
|
-
{
|
|
147
|
-
return AnyValue::make_boolean(lhs.is_equal_to(rhs));
|
|
148
|
-
}
|
|
149
|
-
inline AnyValue operator!=(const AnyValue &lhs, const AnyValue &rhs)
|
|
150
|
-
{
|
|
151
|
-
return AnyValue::make_boolean(!lhs.is_equal_to(rhs));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// --- BITWISE OPERATORS
|
|
155
|
-
inline AnyValue operator^(const AnyValue &lhs, const AnyValue &rhs)
|
|
156
|
-
{
|
|
157
|
-
return AnyValue::make_number(Operators_Private::ToInt32(lhs) ^ Operators_Private::ToInt32(rhs));
|
|
158
|
-
}
|
|
159
|
-
inline AnyValue operator&(const AnyValue &lhs, const AnyValue &rhs)
|
|
160
|
-
{
|
|
161
|
-
return AnyValue::make_number(Operators_Private::ToInt32(lhs) & Operators_Private::ToInt32(rhs));
|
|
162
|
-
}
|
|
163
|
-
inline AnyValue operator|(const AnyValue &lhs, const AnyValue &rhs)
|
|
164
|
-
{
|
|
165
|
-
return AnyValue::make_number(Operators_Private::ToInt32(lhs) | Operators_Private::ToInt32(rhs));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// --- SHIFT OPERATORS
|
|
169
|
-
inline AnyValue operator<<(const AnyValue &lhs, const AnyValue &rhs)
|
|
170
|
-
{
|
|
171
|
-
// The right operand is treated as an unsigned 32-bit integer, and only the lower 5 bits are used.
|
|
172
|
-
return AnyValue::make_number(Operators_Private::ToInt32(lhs) << (Operators_Private::ToInt32(rhs) & 0x1F));
|
|
173
|
-
}
|
|
174
|
-
inline AnyValue operator>>(const AnyValue &lhs, const AnyValue &rhs)
|
|
175
|
-
{
|
|
176
|
-
return AnyValue::make_number(Operators_Private::ToInt32(lhs) >> (Operators_Private::ToInt32(rhs) & 0x1F));
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// --- INCREMENT / DECREMENT
|
|
180
|
-
inline AnyValue &operator++(AnyValue &val) // pre-increment
|
|
181
|
-
{
|
|
182
|
-
double num = Operators_Private::ToNumber(val);
|
|
183
|
-
val = AnyValue::make_number(num + 1.0);
|
|
184
|
-
return val;
|
|
185
|
-
}
|
|
186
|
-
inline AnyValue operator++(AnyValue &val, int) // post-increment
|
|
187
|
-
{
|
|
188
|
-
AnyValue old = AnyValue::make_number(Operators_Private::ToNumber(val));
|
|
189
|
-
++val;
|
|
190
|
-
return old;
|
|
191
|
-
}
|
|
192
|
-
inline AnyValue &operator--(AnyValue &val) // pre-decrement
|
|
193
|
-
{
|
|
194
|
-
double num = Operators_Private::ToNumber(val);
|
|
195
|
-
val = AnyValue::make_number(num - 1.0);
|
|
196
|
-
return val;
|
|
197
|
-
}
|
|
198
|
-
inline AnyValue operator--(AnyValue &val, int) // post-decrement
|
|
199
|
-
{
|
|
200
|
-
AnyValue old = AnyValue::make_number(Operators_Private::ToNumber(val));
|
|
201
|
-
--val;
|
|
202
|
-
return old;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// --- COMPOUND ASSIGNMENT
|
|
206
|
-
inline AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs)
|
|
207
|
-
{
|
|
208
|
-
lhs = lhs + rhs;
|
|
209
|
-
return lhs;
|
|
210
|
-
}
|
|
211
|
-
inline AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs)
|
|
212
|
-
{
|
|
213
|
-
lhs = lhs - rhs;
|
|
214
|
-
return lhs;
|
|
215
|
-
}
|
|
216
|
-
inline AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs)
|
|
217
|
-
{
|
|
218
|
-
lhs = lhs * rhs;
|
|
219
|
-
return lhs;
|
|
220
|
-
}
|
|
221
|
-
inline AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs)
|
|
222
|
-
{
|
|
223
|
-
lhs = lhs / rhs;
|
|
224
|
-
return lhs;
|
|
225
|
-
}
|
|
226
|
-
inline AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs)
|
|
227
|
-
{
|
|
228
|
-
lhs = lhs % rhs;
|
|
229
|
-
return lhs;
|
|
230
|
-
}
|
|
231
|
-
inline AnyValue &operator^=(AnyValue &lhs, const AnyValue &rhs)
|
|
232
|
-
{
|
|
233
|
-
lhs = lhs ^ rhs;
|
|
234
|
-
return lhs;
|
|
235
|
-
}
|
|
236
|
-
inline AnyValue &operator&=(AnyValue &lhs, const AnyValue &rhs)
|
|
237
|
-
{
|
|
238
|
-
lhs = lhs & rhs;
|
|
239
|
-
return lhs;
|
|
240
|
-
}
|
|
241
|
-
inline AnyValue &operator|=(AnyValue &lhs, const AnyValue &rhs)
|
|
242
|
-
{
|
|
243
|
-
lhs = lhs | rhs;
|
|
244
|
-
return lhs;
|
|
245
|
-
}
|
|
246
|
-
inline AnyValue &operator<<=(AnyValue &lhs, const AnyValue &rhs)
|
|
247
|
-
{
|
|
248
|
-
lhs = lhs << rhs;
|
|
249
|
-
return lhs;
|
|
250
|
-
}
|
|
251
|
-
inline AnyValue &operator>>=(AnyValue &lhs, const AnyValue &rhs)
|
|
252
|
-
{
|
|
253
|
-
lhs = lhs >> rhs;
|
|
254
|
-
return lhs;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "values/symbol.hpp"
|
|
4
|
-
#include <memory>
|
|
5
|
-
|
|
6
|
-
namespace jspp
|
|
7
|
-
{
|
|
8
|
-
namespace WellKnownSymbols
|
|
9
|
-
{
|
|
10
|
-
// We use a specific prefix "@@" for well-known symbols to distinguish them from user symbols
|
|
11
|
-
inline std::shared_ptr<JsSymbol> iterator = std::make_shared<JsSymbol>("Symbol.iterator", "@@iterator");
|
|
12
|
-
inline std::shared_ptr<JsSymbol> toString = std::make_shared<JsSymbol>("Symbol.toString", "@@toString");
|
|
13
|
-
}
|
|
14
|
-
}
|