@ugo-studio/jspp 0.2.5 → 0.2.7
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 +51 -36
- package/dist/analysis/scope.js +7 -0
- package/dist/analysis/typeAnalyzer.js +96 -43
- package/dist/ast/symbols.js +34 -24
- package/dist/cli/args.js +59 -0
- package/dist/cli/colors.js +9 -0
- package/dist/cli/file-utils.js +20 -0
- package/dist/cli/index.js +160 -0
- package/dist/cli/spinner.js +55 -0
- package/dist/core/codegen/class-handlers.js +8 -8
- package/dist/core/codegen/control-flow-handlers.js +19 -9
- package/dist/core/codegen/declaration-handlers.js +30 -10
- package/dist/core/codegen/expression-handlers.js +649 -161
- package/dist/core/codegen/function-handlers.js +107 -103
- package/dist/core/codegen/helpers.js +61 -14
- package/dist/core/codegen/index.js +13 -9
- package/dist/core/codegen/literal-handlers.js +4 -2
- package/dist/core/codegen/statement-handlers.js +147 -55
- package/dist/core/codegen/visitor.js +22 -2
- package/dist/core/constants.js +16 -0
- package/dist/core/error.js +58 -0
- package/dist/index.js +6 -3
- package/package.json +3 -3
- package/src/prelude/any_value.hpp +89 -59
- package/src/prelude/any_value_access.hpp +1 -1
- package/src/prelude/any_value_helpers.hpp +85 -43
- package/src/prelude/index.hpp +1 -0
- package/src/prelude/library/array.hpp +3 -2
- package/src/prelude/scheduler.hpp +144 -144
- package/src/prelude/types.hpp +8 -8
- package/src/prelude/utils/access.hpp +62 -6
- package/src/prelude/utils/assignment_operators.hpp +14 -14
- package/src/prelude/utils/log_any_value/array.hpp +0 -15
- package/src/prelude/utils/log_any_value/object.hpp +12 -10
- package/src/prelude/utils/log_any_value/primitives.hpp +2 -0
- package/src/prelude/utils/operators.hpp +117 -474
- package/src/prelude/utils/operators_primitive.hpp +337 -0
- package/src/prelude/values/helpers/array.hpp +4 -4
- package/src/prelude/values/helpers/async_iterator.hpp +2 -2
- package/src/prelude/values/helpers/function.hpp +3 -3
- package/src/prelude/values/helpers/iterator.hpp +2 -2
- package/src/prelude/values/helpers/object.hpp +3 -3
- package/src/prelude/values/helpers/promise.hpp +1 -1
- package/src/prelude/values/helpers/string.hpp +1 -1
- package/src/prelude/values/helpers/symbol.hpp +1 -1
- package/src/prelude/values/prototypes/array.hpp +1125 -853
- package/src/prelude/values/prototypes/async_iterator.hpp +32 -14
- package/src/prelude/values/prototypes/function.hpp +30 -18
- package/src/prelude/values/prototypes/iterator.hpp +40 -17
- package/src/prelude/values/prototypes/number.hpp +119 -62
- package/src/prelude/values/prototypes/object.hpp +10 -4
- package/src/prelude/values/prototypes/promise.hpp +167 -109
- package/src/prelude/values/prototypes/string.hpp +407 -231
- package/src/prelude/values/prototypes/symbol.hpp +45 -23
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
#include <deque>
|
|
3
|
-
#include <functional>
|
|
4
|
-
#include <chrono>
|
|
5
|
-
#include <queue>
|
|
6
|
-
#include <unordered_set>
|
|
7
|
-
#include <vector>
|
|
8
|
-
#include <thread>
|
|
9
|
-
#include <iostream>
|
|
10
|
-
|
|
11
|
-
namespace jspp {
|
|
12
|
-
class Scheduler {
|
|
13
|
-
public:
|
|
14
|
-
using Task = std::function<void()>;
|
|
15
|
-
using TimePoint = std::chrono::steady_clock::time_point;
|
|
16
|
-
|
|
17
|
-
struct Timer {
|
|
18
|
-
size_t id;
|
|
19
|
-
TimePoint next_run;
|
|
20
|
-
std::chrono::milliseconds interval; // 0 if not repeating
|
|
21
|
-
Task task;
|
|
22
|
-
|
|
23
|
-
// Min-heap priority queue (smallest time at top)
|
|
24
|
-
bool operator>(const Timer& other) const {
|
|
25
|
-
return next_run > other.next_run;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
static Scheduler& instance() {
|
|
30
|
-
static Scheduler s;
|
|
31
|
-
return s;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
void enqueue(Task task) {
|
|
35
|
-
tasks.push_back(std::move(task));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
size_t set_timeout(Task task, size_t delay_ms) {
|
|
39
|
-
return schedule_timer(std::move(task), delay_ms, false);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
size_t set_interval(Task task, size_t delay_ms) {
|
|
43
|
-
return schedule_timer(std::move(task), delay_ms, true);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
void clear_timer(size_t id) {
|
|
47
|
-
cancelled_timers.insert(id);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
void run() {
|
|
51
|
-
while (true) {
|
|
52
|
-
bool has_work = false;
|
|
53
|
-
|
|
54
|
-
// 1. Process all immediate tasks (microtask/task queue)
|
|
55
|
-
while (!tasks.empty()) {
|
|
56
|
-
Task task = tasks.front();
|
|
57
|
-
tasks.pop_front();
|
|
58
|
-
task();
|
|
59
|
-
has_work = true;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 2. Process timers
|
|
63
|
-
auto now = std::chrono::steady_clock::now();
|
|
64
|
-
while (!timers.empty()) {
|
|
65
|
-
// Peek top
|
|
66
|
-
const auto& top = timers.top();
|
|
67
|
-
|
|
68
|
-
// Cleanup cancelled timers lazily
|
|
69
|
-
if (cancelled_timers.count(top.id)) {
|
|
70
|
-
cancelled_timers.erase(top.id);
|
|
71
|
-
timers.pop();
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (top.next_run <= now) {
|
|
76
|
-
// Timer is ready
|
|
77
|
-
Timer t = top;
|
|
78
|
-
timers.pop();
|
|
79
|
-
|
|
80
|
-
// Execute task
|
|
81
|
-
t.task();
|
|
82
|
-
has_work = true;
|
|
83
|
-
|
|
84
|
-
// Reschedule if interval and not cancelled during execution
|
|
85
|
-
if (t.interval.count() > 0 && cancelled_timers.find(t.id) == cancelled_timers.end()) {
|
|
86
|
-
// Drift-safe(ish) scheduling: run next interval relative to now
|
|
87
|
-
// Note: JS allows drift.
|
|
88
|
-
t.next_run = std::chrono::steady_clock::now() + t.interval;
|
|
89
|
-
timers.push(t);
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
break; // Next timer is in the future
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// 3. Exit or Wait
|
|
97
|
-
if (!has_work) {
|
|
98
|
-
if (tasks.empty() && timers.empty()) {
|
|
99
|
-
break; // No pending work, exit event loop
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!timers.empty()) {
|
|
103
|
-
auto next_time = timers.top().next_run;
|
|
104
|
-
std::this_thread::sleep_until(next_time);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
bool has_tasks() const {
|
|
111
|
-
return !tasks.empty() || !timers.empty();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private:
|
|
115
|
-
std::deque<Task> tasks;
|
|
116
|
-
std::priority_queue<Timer, std::vector<Timer>, std::greater<Timer>> timers;
|
|
117
|
-
std::unordered_set<size_t> cancelled_timers;
|
|
118
|
-
size_t next_timer_id = 1;
|
|
119
|
-
const size_t MAX_TIMER_ID = 2147483647; // 2^31 - 1
|
|
120
|
-
|
|
121
|
-
size_t schedule_timer(Task task, size_t delay_ms, bool repeat) {
|
|
122
|
-
size_t id = next_timer_id++;
|
|
123
|
-
if (next_timer_id > MAX_TIMER_ID) {
|
|
124
|
-
next_timer_id = 1;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// If we wrap around, ensure we don't accidentally treat this new ID as cancelled
|
|
128
|
-
// (in case an old timer with this ID is still lingering in the 'cancelled' set)
|
|
129
|
-
if (cancelled_timers.count(id)) {
|
|
130
|
-
cancelled_timers.erase(id);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
auto now = std::chrono::steady_clock::now();
|
|
134
|
-
|
|
135
|
-
Timer t;
|
|
136
|
-
t.id = id;
|
|
137
|
-
t.next_run = now + std::chrono::milliseconds(delay_ms);
|
|
138
|
-
t.interval = repeat ? std::chrono::milliseconds(delay_ms) : std::chrono::milliseconds(0);
|
|
139
|
-
t.task = std::move(task);
|
|
140
|
-
|
|
141
|
-
timers.push(t);
|
|
142
|
-
return id;
|
|
143
|
-
}
|
|
144
|
-
};
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <deque>
|
|
3
|
+
#include <functional>
|
|
4
|
+
#include <chrono>
|
|
5
|
+
#include <queue>
|
|
6
|
+
#include <unordered_set>
|
|
7
|
+
#include <vector>
|
|
8
|
+
#include <thread>
|
|
9
|
+
#include <iostream>
|
|
10
|
+
|
|
11
|
+
namespace jspp {
|
|
12
|
+
class Scheduler {
|
|
13
|
+
public:
|
|
14
|
+
using Task = std::function<void()>;
|
|
15
|
+
using TimePoint = std::chrono::steady_clock::time_point;
|
|
16
|
+
|
|
17
|
+
struct Timer {
|
|
18
|
+
size_t id;
|
|
19
|
+
TimePoint next_run;
|
|
20
|
+
std::chrono::milliseconds interval; // 0 if not repeating
|
|
21
|
+
Task task;
|
|
22
|
+
|
|
23
|
+
// Min-heap priority queue (smallest time at top)
|
|
24
|
+
bool operator>(const Timer& other) const {
|
|
25
|
+
return next_run > other.next_run;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
static Scheduler& instance() {
|
|
30
|
+
static Scheduler s;
|
|
31
|
+
return s;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void enqueue(Task task) {
|
|
35
|
+
tasks.push_back(std::move(task));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
size_t set_timeout(Task task, size_t delay_ms) {
|
|
39
|
+
return schedule_timer(std::move(task), delay_ms, false);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
size_t set_interval(Task task, size_t delay_ms) {
|
|
43
|
+
return schedule_timer(std::move(task), delay_ms, true);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void clear_timer(size_t id) {
|
|
47
|
+
cancelled_timers.insert(id);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void run() {
|
|
51
|
+
while (true) {
|
|
52
|
+
bool has_work = false;
|
|
53
|
+
|
|
54
|
+
// 1. Process all immediate tasks (microtask/task queue)
|
|
55
|
+
while (!tasks.empty()) {
|
|
56
|
+
Task task = tasks.front();
|
|
57
|
+
tasks.pop_front();
|
|
58
|
+
task();
|
|
59
|
+
has_work = true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 2. Process timers
|
|
63
|
+
auto now = std::chrono::steady_clock::now();
|
|
64
|
+
while (!timers.empty()) {
|
|
65
|
+
// Peek top
|
|
66
|
+
const auto& top = timers.top();
|
|
67
|
+
|
|
68
|
+
// Cleanup cancelled timers lazily
|
|
69
|
+
if (cancelled_timers.count(top.id)) {
|
|
70
|
+
cancelled_timers.erase(top.id);
|
|
71
|
+
timers.pop();
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (top.next_run <= now) {
|
|
76
|
+
// Timer is ready
|
|
77
|
+
Timer t = top;
|
|
78
|
+
timers.pop();
|
|
79
|
+
|
|
80
|
+
// Execute task
|
|
81
|
+
t.task();
|
|
82
|
+
has_work = true;
|
|
83
|
+
|
|
84
|
+
// Reschedule if interval and not cancelled during execution
|
|
85
|
+
if (t.interval.count() > 0 && cancelled_timers.find(t.id) == cancelled_timers.end()) {
|
|
86
|
+
// Drift-safe(ish) scheduling: run next interval relative to now
|
|
87
|
+
// Note: JS allows drift.
|
|
88
|
+
t.next_run = std::chrono::steady_clock::now() + t.interval;
|
|
89
|
+
timers.push(t);
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
break; // Next timer is in the future
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 3. Exit or Wait
|
|
97
|
+
if (!has_work) {
|
|
98
|
+
if (tasks.empty() && timers.empty()) {
|
|
99
|
+
break; // No pending work, exit event loop
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!timers.empty()) {
|
|
103
|
+
auto next_time = timers.top().next_run;
|
|
104
|
+
std::this_thread::sleep_until(next_time);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
bool has_tasks() const {
|
|
111
|
+
return !tasks.empty() || !timers.empty();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private:
|
|
115
|
+
std::deque<Task> tasks;
|
|
116
|
+
std::priority_queue<Timer, std::vector<Timer>, std::greater<Timer>> timers;
|
|
117
|
+
std::unordered_set<size_t> cancelled_timers;
|
|
118
|
+
size_t next_timer_id = 1;
|
|
119
|
+
const size_t MAX_TIMER_ID = 2147483647; // 2^31 - 1
|
|
120
|
+
|
|
121
|
+
size_t schedule_timer(Task task, size_t delay_ms, bool repeat) {
|
|
122
|
+
size_t id = next_timer_id++;
|
|
123
|
+
if (next_timer_id > MAX_TIMER_ID) {
|
|
124
|
+
next_timer_id = 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// If we wrap around, ensure we don't accidentally treat this new ID as cancelled
|
|
128
|
+
// (in case an old timer with this ID is still lingering in the 'cancelled' set)
|
|
129
|
+
if (cancelled_timers.count(id)) {
|
|
130
|
+
cancelled_timers.erase(id);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
auto now = std::chrono::steady_clock::now();
|
|
134
|
+
|
|
135
|
+
Timer t;
|
|
136
|
+
t.id = id;
|
|
137
|
+
t.next_run = now + std::chrono::milliseconds(delay_ms);
|
|
138
|
+
t.interval = repeat ? std::chrono::milliseconds(delay_ms) : std::chrono::milliseconds(0);
|
|
139
|
+
t.task = std::move(task);
|
|
140
|
+
|
|
141
|
+
timers.push(t);
|
|
142
|
+
return id;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
145
|
}
|
package/src/prelude/types.hpp
CHANGED
|
@@ -146,34 +146,34 @@ namespace jspp
|
|
|
146
146
|
// AnyValue prototypes
|
|
147
147
|
namespace ObjectPrototypes
|
|
148
148
|
{
|
|
149
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
149
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
150
150
|
}
|
|
151
151
|
namespace StringPrototypes
|
|
152
152
|
{
|
|
153
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
153
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
154
154
|
}
|
|
155
155
|
namespace NumberPrototypes
|
|
156
156
|
{
|
|
157
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
157
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
158
158
|
}
|
|
159
159
|
namespace ArrayPrototypes
|
|
160
160
|
{
|
|
161
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
161
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
162
162
|
}
|
|
163
163
|
namespace FunctionPrototypes
|
|
164
164
|
{
|
|
165
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
165
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
166
166
|
}
|
|
167
167
|
namespace PromisePrototypes
|
|
168
168
|
{
|
|
169
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
169
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
170
170
|
}
|
|
171
171
|
namespace IteratorPrototypes
|
|
172
172
|
{
|
|
173
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
173
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
174
174
|
}
|
|
175
175
|
namespace SymbolPrototypes
|
|
176
176
|
{
|
|
177
|
-
inline std::optional<AnyValue> get(const std::string &key
|
|
177
|
+
inline std::optional<AnyValue> get(const std::string &key);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
@@ -306,32 +306,88 @@ namespace jspp
|
|
|
306
306
|
return Constants::TRUE;
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
inline AnyValue
|
|
309
|
+
inline AnyValue get_optional_property(const AnyValue &obj, const std::string &key)
|
|
310
310
|
{
|
|
311
311
|
if (obj.is_null() || obj.is_undefined())
|
|
312
312
|
return Constants::UNDEFINED;
|
|
313
313
|
return obj.get_own_property(key);
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
inline AnyValue
|
|
316
|
+
inline AnyValue get_optional_element(const AnyValue &obj, const AnyValue &key)
|
|
317
317
|
{
|
|
318
318
|
if (obj.is_null() || obj.is_undefined())
|
|
319
319
|
return Constants::UNDEFINED;
|
|
320
320
|
return obj.get_own_property(key);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
inline AnyValue
|
|
323
|
+
inline AnyValue get_optional_element(const AnyValue &obj, const double &key)
|
|
324
324
|
{
|
|
325
325
|
if (obj.is_null() || obj.is_undefined())
|
|
326
326
|
return Constants::UNDEFINED;
|
|
327
327
|
return obj.get_own_property(static_cast<uint32_t>(key));
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
inline AnyValue
|
|
330
|
+
inline AnyValue call_optional_property(const AnyValue &obj, const std::string &key, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt)
|
|
331
331
|
{
|
|
332
|
-
if (
|
|
332
|
+
if (obj.is_null() || obj.is_undefined())
|
|
333
333
|
return Constants::UNDEFINED;
|
|
334
|
-
return
|
|
334
|
+
return obj.get_own_property(key).call(obj, args, expr);
|
|
335
|
+
}
|
|
336
|
+
inline AnyValue call_optional_property_with_optional_call(const AnyValue &obj, const std::string &key, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt)
|
|
337
|
+
{
|
|
338
|
+
if (obj.is_null() || obj.is_undefined())
|
|
339
|
+
return Constants::UNDEFINED;
|
|
340
|
+
return obj.get_own_property(key).optional_call(obj, args, expr);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
inline void spread_array(std::vector<AnyValue> &target, const AnyValue &source)
|
|
344
|
+
{
|
|
345
|
+
if (source.is_array())
|
|
346
|
+
{
|
|
347
|
+
auto arr = source.as_array();
|
|
348
|
+
target.reserve(target.size() + arr->length);
|
|
349
|
+
for (uint64_t i = 0; i < arr->length; ++i)
|
|
350
|
+
{
|
|
351
|
+
target.push_back(arr->get_property(static_cast<uint32_t>(i)));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (source.is_string())
|
|
355
|
+
{
|
|
356
|
+
auto s = source.as_string();
|
|
357
|
+
target.reserve(target.size() + s->value.length());
|
|
358
|
+
for (char c : s->value)
|
|
359
|
+
{
|
|
360
|
+
target.push_back(AnyValue::make_string(std::string(1, c)));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else if (source.is_object() || source.is_function() || source.is_iterator())
|
|
364
|
+
{
|
|
365
|
+
auto iter = get_object_value_iterator(source, "spread target");
|
|
366
|
+
auto next_fn = iter.get_own_property("next");
|
|
367
|
+
while (true)
|
|
368
|
+
{
|
|
369
|
+
auto next_res = next_fn.call(iter, {});
|
|
370
|
+
if (is_truthy(next_res.get_own_property("done")))
|
|
371
|
+
break;
|
|
372
|
+
target.push_back(next_res.get_own_property("value"));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else
|
|
376
|
+
{
|
|
377
|
+
throw jspp::Exception::make_exception("Spread syntax requires an iterable object", "TypeError");
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
inline void spread_object(AnyValue &target, const AnyValue &source)
|
|
382
|
+
{
|
|
383
|
+
if (source.is_null() || source.is_undefined())
|
|
384
|
+
return;
|
|
385
|
+
|
|
386
|
+
auto keys = get_object_keys(source);
|
|
387
|
+
for (const auto &key : keys)
|
|
388
|
+
{
|
|
389
|
+
target.set_own_property(key, source.get_property_with_receiver(key, source));
|
|
390
|
+
}
|
|
335
391
|
}
|
|
336
392
|
|
|
337
393
|
}
|
|
@@ -9,56 +9,56 @@ namespace jspp {
|
|
|
9
9
|
// --- FRIEND IMPLEMENTATIONS ---
|
|
10
10
|
|
|
11
11
|
inline AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs) {
|
|
12
|
-
lhs = lhs
|
|
12
|
+
lhs = jspp::add(lhs, rhs);
|
|
13
13
|
return lhs;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
inline AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs) {
|
|
17
|
-
lhs = lhs
|
|
17
|
+
lhs = jspp::sub(lhs, rhs);
|
|
18
18
|
return lhs;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
inline AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs) {
|
|
22
|
-
lhs = lhs
|
|
22
|
+
lhs = jspp::mul(lhs, rhs);
|
|
23
23
|
return lhs;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
inline AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs) {
|
|
27
|
-
lhs = lhs
|
|
27
|
+
lhs = jspp::div(lhs, rhs);
|
|
28
28
|
return lhs;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
inline AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs) {
|
|
32
|
-
lhs = lhs
|
|
32
|
+
lhs = jspp::mod(lhs, rhs);
|
|
33
33
|
return lhs;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
inline AnyValue &operator++(AnyValue &val) {
|
|
37
|
-
val = val
|
|
37
|
+
val = jspp::add(val, 1.0);
|
|
38
38
|
return val;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
inline AnyValue operator++(AnyValue &val, int) {
|
|
42
42
|
AnyValue temp = val;
|
|
43
|
-
val = val
|
|
43
|
+
val = jspp::add(val, 1.0);
|
|
44
44
|
return temp;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
inline AnyValue &operator--(AnyValue &val) {
|
|
48
|
-
val = val
|
|
48
|
+
val = jspp::sub(val, 1.0);
|
|
49
49
|
return val;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
inline AnyValue operator--(AnyValue &val, int) {
|
|
53
53
|
AnyValue temp = val;
|
|
54
|
-
val = val
|
|
54
|
+
val = jspp::sub(val, 1.0);
|
|
55
55
|
return temp;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// --- OVERLOADS FOR PRIMITIVES ---
|
|
59
59
|
|
|
60
60
|
inline AnyValue &operator+=(AnyValue &lhs, const double &rhs) {
|
|
61
|
-
lhs = lhs
|
|
61
|
+
lhs = jspp::add(lhs, rhs);
|
|
62
62
|
return lhs;
|
|
63
63
|
}
|
|
64
64
|
inline AnyValue &operator+=(AnyValue &lhs, const int &rhs) {
|
|
@@ -66,7 +66,7 @@ namespace jspp {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
inline AnyValue &operator-=(AnyValue &lhs, const double &rhs) {
|
|
69
|
-
lhs = lhs
|
|
69
|
+
lhs = jspp::sub(lhs, rhs);
|
|
70
70
|
return lhs;
|
|
71
71
|
}
|
|
72
72
|
inline AnyValue &operator-=(AnyValue &lhs, const int &rhs) {
|
|
@@ -74,7 +74,7 @@ namespace jspp {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
inline AnyValue &operator*=(AnyValue &lhs, const double &rhs) {
|
|
77
|
-
lhs = lhs
|
|
77
|
+
lhs = jspp::mul(lhs, rhs);
|
|
78
78
|
return lhs;
|
|
79
79
|
}
|
|
80
80
|
inline AnyValue &operator*=(AnyValue &lhs, const int &rhs) {
|
|
@@ -82,7 +82,7 @@ namespace jspp {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
inline AnyValue &operator/=(AnyValue &lhs, const double &rhs) {
|
|
85
|
-
lhs = lhs
|
|
85
|
+
lhs = jspp::div(lhs, rhs);
|
|
86
86
|
return lhs;
|
|
87
87
|
}
|
|
88
88
|
inline AnyValue &operator/=(AnyValue &lhs, const int &rhs) {
|
|
@@ -90,7 +90,7 @@ namespace jspp {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
inline AnyValue &operator%=(AnyValue &lhs, const double &rhs) {
|
|
93
|
-
lhs = lhs
|
|
93
|
+
lhs = jspp::mod(lhs, rhs);
|
|
94
94
|
return lhs;
|
|
95
95
|
}
|
|
96
96
|
inline AnyValue &operator%=(AnyValue &lhs, const int &rhs) {
|
|
@@ -20,21 +20,6 @@ namespace jspp
|
|
|
20
20
|
size_t item_count = static_cast<size_t>(arr->length);
|
|
21
21
|
size_t prop_count = arr->props.size();
|
|
22
22
|
|
|
23
|
-
// // If custom toString exists on the object, prefer it
|
|
24
|
-
// auto itToString = arr->props.find("toString");
|
|
25
|
-
// if (depth > 0 && itToString != arr->props.end() && itToString->second.is_function())
|
|
26
|
-
// {
|
|
27
|
-
// try
|
|
28
|
-
// {
|
|
29
|
-
// auto result = itToString->second.as_function()->call(itToString->second, {});
|
|
30
|
-
// return to_log_string(result, visited, depth);
|
|
31
|
-
// }
|
|
32
|
-
// catch (...)
|
|
33
|
-
// {
|
|
34
|
-
// // ignore and fallback to manual formatting
|
|
35
|
-
// }
|
|
36
|
-
// }
|
|
37
|
-
|
|
38
23
|
std::string indent(depth * 2, ' ');
|
|
39
24
|
std::string next_indent((depth + 1) * 2, ' ');
|
|
40
25
|
std::stringstream ss;
|
|
@@ -22,7 +22,7 @@ namespace jspp
|
|
|
22
22
|
|
|
23
23
|
for (size_t i = 0; i < obj->storage.size(); ++i)
|
|
24
24
|
{
|
|
25
|
-
const auto&
|
|
25
|
+
const auto &prop_val = obj->storage[i];
|
|
26
26
|
if (!is_enumerable_property(prop_val))
|
|
27
27
|
{
|
|
28
28
|
prop_count--;
|
|
@@ -69,8 +69,8 @@ namespace jspp
|
|
|
69
69
|
size_t current_prop = 0;
|
|
70
70
|
for (size_t i = 0; i < obj->shape->property_names.size(); ++i)
|
|
71
71
|
{
|
|
72
|
-
const auto&
|
|
73
|
-
const auto&
|
|
72
|
+
const auto &key = obj->shape->property_names[i];
|
|
73
|
+
const auto &prop_val = obj->storage[i];
|
|
74
74
|
|
|
75
75
|
if (!is_enumerable_property(prop_val))
|
|
76
76
|
continue;
|
|
@@ -81,9 +81,10 @@ namespace jspp
|
|
|
81
81
|
}
|
|
82
82
|
else
|
|
83
83
|
{
|
|
84
|
-
ss << "\"" << key << "\"";
|
|
84
|
+
ss << Color::GREEN << "\"" << key << "\"" << Color::RESET;
|
|
85
85
|
}
|
|
86
|
-
ss << ": " <<
|
|
86
|
+
ss << Color::BRIGHT_BLACK << ": " << Color::RESET;
|
|
87
|
+
ss << to_log_string(prop_val, visited, depth + 1);
|
|
87
88
|
if (++current_prop < prop_count)
|
|
88
89
|
ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
|
|
89
90
|
}
|
|
@@ -98,12 +99,12 @@ namespace jspp
|
|
|
98
99
|
size_t props_shown = 0;
|
|
99
100
|
for (size_t i = 0; i < obj->shape->property_names.size(); ++i)
|
|
100
101
|
{
|
|
101
|
-
const auto&
|
|
102
|
-
const auto&
|
|
102
|
+
const auto &key = obj->shape->property_names[i];
|
|
103
|
+
const auto &prop_val = obj->storage[i];
|
|
103
104
|
|
|
104
105
|
if (props_shown >= MAX_OBJECT_PROPS)
|
|
105
106
|
break;
|
|
106
|
-
|
|
107
|
+
|
|
107
108
|
if (!is_enumerable_property(prop_val))
|
|
108
109
|
continue;
|
|
109
110
|
|
|
@@ -117,9 +118,10 @@ namespace jspp
|
|
|
117
118
|
}
|
|
118
119
|
else
|
|
119
120
|
{
|
|
120
|
-
ss << "\"" << key << "\"";
|
|
121
|
+
ss << Color::GREEN << "\"" << key << "\"" << Color::RESET;
|
|
121
122
|
}
|
|
122
|
-
ss << ": " <<
|
|
123
|
+
ss << Color::BRIGHT_BLACK << ": " << Color::RESET;
|
|
124
|
+
ss << to_log_string(prop_val, visited, depth + 1);
|
|
123
125
|
props_shown++;
|
|
124
126
|
}
|
|
125
127
|
if (prop_count > MAX_OBJECT_PROPS)
|
|
@@ -14,8 +14,10 @@ namespace jspp
|
|
|
14
14
|
inline std::optional<std::string> format_primitive(const AnyValue &val, int depth)
|
|
15
15
|
{
|
|
16
16
|
if (val.is_uninitialized())
|
|
17
|
+
{
|
|
17
18
|
// THROW
|
|
18
19
|
Exception::throw_uninitialized_reference("#<Object>");
|
|
20
|
+
}
|
|
19
21
|
if (val.is_undefined())
|
|
20
22
|
return Color::BRIGHT_BLACK + std::string("undefined") + Color::RESET;
|
|
21
23
|
if (val.is_null())
|