@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
@@ -1,357 +1,366 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "any_value.hpp"
5
- #include "operators.hpp"
6
- #include <optional>
7
- #include <string>
8
- #include <vector>
9
- #include <algorithm>
10
- #include <cctype>
11
-
12
- namespace jspp
13
- {
14
- namespace StringPrototypes
15
- {
16
- // This function retrieves a prototype method for a given string instance.
17
- // It captures the string instance to act as the 'this' context for the method.
18
- inline std::optional<AnyValue> get(const std::string &key, const std::unique_ptr<std::string> &self)
19
- {
20
- // --- toString() & valueOf() ---
21
- if (key == "toString" || key == "valueOf")
22
- {
23
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
24
- { return AnyValue::make_string(*self); },
25
- key);
26
- }
27
-
28
- // --- length property ---
29
- if (key == "length")
30
- {
31
- return AnyValue::make_accessor_descriptor([&self](const std::vector<AnyValue>) -> AnyValue
32
- { return AnyValue::make_number(self->length()); },
33
- [&self](const std::vector<AnyValue>) -> AnyValue
34
- { return AnyValue::make_undefined(); },
35
- false,
36
- false);
37
- }
38
-
39
- // --- charAt(pos) ---
40
- if (key == "charAt")
41
- {
42
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
43
- {
44
- double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
45
- int index = static_cast<int>(pos);
46
- if (index < 0 || index >= self->length()) {
47
- return AnyValue::make_string("");
48
- }
49
- return AnyValue::make_string(std::string(1, (*self)[index])); },
50
- key);
51
- }
52
-
53
- // --- concat(str1, str2, ...) ---
54
- if (key == "concat")
55
- {
56
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
57
- {
58
- std::string result = *self;
59
- for (const auto& arg : args)
60
- {
61
- result += arg.to_std_string();
62
- }
63
- return AnyValue::make_string(result); },
64
- key);
65
- }
66
-
67
- // --- endsWith(searchString, endPosition) ---
68
- if (key == "endsWith")
69
- {
70
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
71
- {
72
- if(args.empty()) return AnyValue::make_boolean(false);
73
- std::string search = args[0].to_std_string();
74
- size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->length();
75
-
76
- if (end_pos > self->length()) end_pos = self->length();
77
- if (search.length() > end_pos) return AnyValue::make_boolean(false);
78
-
79
- return AnyValue::make_boolean(self->substr(end_pos - search.length(), search.length()) == search); },
80
- key);
81
- }
82
-
83
- // --- includes(searchString, position) ---
84
- if (key == "includes")
85
- {
86
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
87
- {
88
- if(args.empty()) return AnyValue::make_boolean(false);
89
- std::string search = args[0].to_std_string();
90
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
91
-
92
- return AnyValue::make_boolean(self->find(search, pos) != std::string::npos); },
93
- key);
94
- }
95
-
96
- // --- indexOf(searchString, position) ---
97
- if (key == "indexOf")
98
- {
99
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
100
- {
101
- if (args.empty()) return AnyValue::make_number(-1);
102
- std::string search = args[0].to_std_string();
103
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
104
- size_t result = self->find(search, pos);
105
- return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
106
- key);
107
- }
108
-
109
- // --- lastIndexOf(searchString, position) ---
110
- if (key == "lastIndexOf")
111
- {
112
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
113
- {
114
- if (args.empty()) return AnyValue::make_number(-1);
115
- std::string search = args[0].to_std_string();
116
- size_t pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : std::string::npos;
117
- size_t result = self->rfind(search, pos);
118
- return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
119
- key);
120
- }
121
-
122
- // --- padEnd(targetLength, padString) ---
123
- if (key == "padEnd")
124
- {
125
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
126
- {
127
- size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
128
- if (self->length() >= target_length) return AnyValue::make_string(*self);
129
- std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
130
- std::string result = *self;
131
- while (result.length() < target_length)
132
- {
133
- result += pad_string;
134
- }
135
- return AnyValue::make_string(result.substr(0, target_length)); },
136
- key);
137
- }
138
-
139
- // --- padStart(targetLength, padString) ---
140
- if (key == "padStart")
141
- {
142
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
143
- {
144
- size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
145
- if (self->length() >= target_length) return AnyValue::make_string(*self);
146
- std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
147
- std::string padding;
148
- while (padding.length() < target_length - self->length())
149
- {
150
- padding += pad_string;
151
- }
152
- return AnyValue::make_string(padding.substr(0, target_length - self->length()) + *self); },
153
- key);
154
- }
155
-
156
- // --- repeat(count) ---
157
- if (key == "repeat")
158
- {
159
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
160
- {
161
- double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
162
- if (count < 0) {
163
- // In a real implementation, this should throw a RangeError.
164
- return AnyValue::make_string("");
165
- }
166
- std::string result = "";
167
- for (int i = 0; i < count; ++i)
168
- {
169
- result += *self;
170
- }
171
- return AnyValue::make_string(result); },
172
- key);
173
- }
174
-
175
- // --- replace(substr, newSubstr) ---
176
- if (key == "replace")
177
- {
178
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
179
- {
180
- if (args.size() < 2) return AnyValue::make_string(*self);
181
- std::string search = args[0].to_std_string();
182
- std::string replacement = args[1].to_std_string();
183
- std::string result = *self;
184
- size_t pos = result.find(search);
185
- if (pos != std::string::npos)
186
- {
187
- result.replace(pos, search.length(), replacement);
188
- }
189
- return AnyValue::make_string(result); },
190
- key);
191
- }
192
-
193
- // --- replaceAll(substr, newSubstr) ---
194
- if (key == "replaceAll")
195
- {
196
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
197
- {
198
- if (args.size() < 2) return AnyValue::make_string(*self);
199
- std::string search = args[0].to_std_string();
200
- if (search.empty()) return AnyValue::make_string(*self);
201
- std::string replacement = args[1].to_std_string();
202
- std::string result = *self;
203
- size_t pos = result.find(search);
204
- while (pos != std::string::npos)
205
- {
206
- result.replace(pos, search.length(), replacement);
207
- pos = result.find(search, pos + replacement.length());
208
- }
209
- return AnyValue::make_string(result); },
210
- key);
211
- }
212
-
213
- // --- slice(beginIndex, endIndex) ---
214
- if (key == "slice")
215
- {
216
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
217
- {
218
- int len = self->length();
219
- int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
220
- int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
221
-
222
- if (start < 0) start += len;
223
- if (end < 0) end += len;
224
-
225
- start = std::max(0, std::min(len, start));
226
- end = std::max(0, std::min(len, end));
227
-
228
- if (start >= end) return AnyValue::make_string("");
229
- return AnyValue::make_string(self->substr(start, end - start)); },
230
- key);
231
- }
232
-
233
- // --- split(separator) ---
234
- if (key == "split")
235
- {
236
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
237
- {
238
- std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
239
- std::vector<std::optional<AnyValue>> result_vec;
240
-
241
- if (separator.empty()) {
242
- for (char c : (*self)) {
243
- result_vec.push_back(AnyValue::make_string(std::string(1, c)));
244
- }
245
- } else {
246
- std::string temp = (*self);
247
- size_t pos = 0;
248
- while ((pos = temp.find(separator)) != std::string::npos) {
249
- result_vec.push_back(AnyValue::make_string(temp.substr(0, pos)));
250
- temp.erase(0, pos + separator.length());
251
- }
252
- result_vec.push_back(AnyValue::make_string(temp));
253
- }
254
- return AnyValue::make_array(result_vec); },
255
- key);
256
- }
257
-
258
- // --- startsWith(searchString, position) ---
259
- if (key == "startsWith")
260
- {
261
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
262
- {
263
- if(args.empty()) return AnyValue::make_boolean(false);
264
- std::string search = args[0].to_std_string();
265
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
266
- if (pos > self->length()) pos = self->length();
267
-
268
- return AnyValue::make_boolean(self->rfind(search, pos) == pos); },
269
- key);
270
- }
271
-
272
- // --- substring(indexStart, indexEnd) ---
273
- if (key == "substring")
274
- {
275
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
276
- {
277
- int len = self->length();
278
- int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
279
- int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
280
-
281
- start = std::max(0, start);
282
- end = std::max(0, end);
283
-
284
- if (start > end) std::swap(start, end);
285
-
286
- start = std::min(len, start);
287
- end = std::min(len, end);
288
-
289
- return AnyValue::make_string(self->substr(start, end - start)); },
290
- key);
291
- }
292
-
293
- // --- toLowerCase() ---
294
- if (key == "toLowerCase")
295
- {
296
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
297
- {
298
- std::string result = *self;
299
- std::transform(result.begin(), result.end(), result.begin(),
300
- [](unsigned char c){ return std::tolower(c); });
301
- return AnyValue::make_string(result); },
302
- key);
303
- }
304
-
305
- // --- toUpperCase() ---
306
- if (key == "toUpperCase")
307
- {
308
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
309
- {
310
- std::string result = *self;
311
- std::transform(result.begin(), result.end(), result.begin(),
312
- [](unsigned char c){ return std::toupper(c); });
313
- return AnyValue::make_string(result); },
314
- key);
315
- }
316
-
317
- // --- trim() ---
318
- if (key == "trim")
319
- {
320
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
321
- {
322
- const char* whitespace = " \t\n\r\f\v";
323
- std::string result = *self;
324
- result.erase(0, result.find_first_not_of(whitespace));
325
- result.erase(result.find_last_not_of(whitespace) + 1);
326
- return AnyValue::make_string(result); },
327
- key);
328
- }
329
-
330
- // --- trimEnd() ---
331
- if (key == "trimEnd")
332
- {
333
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
334
- {
335
- const char* whitespace = " \t\n\r\f\v";
336
- std::string result = *self;
337
- result.erase(result.find_last_not_of(whitespace) + 1);
338
- return AnyValue::make_string(result); },
339
- key);
340
- }
341
-
342
- // --- trimStart() ---
343
- if (key == "trimStart")
344
- {
345
- return AnyValue::make_function([&self](const std::vector<AnyValue> &args) -> AnyValue
346
- {
347
- const char* whitespace = " \t\n\r\f\v";
348
- std::string result = *self;
349
- result.erase(0, result.find_first_not_of(whitespace));
350
- return AnyValue::make_string(result); },
351
- key);
352
- }
353
-
354
- return std::nullopt;
355
- }
356
- }
357
- }
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "values/string.hpp" // Make sure this is included
5
+ #include "any_value.hpp"
6
+ #include "operators.hpp"
7
+ #include <optional>
8
+ #include <string>
9
+ #include <vector>
10
+ #include <algorithm>
11
+ #include <cctype>
12
+
13
+ namespace jspp
14
+ {
15
+ namespace StringPrototypes
16
+ {
17
+ // This function retrieves a prototype method for a given string instance.
18
+ // It captures the string instance to act as the 'this' context for the method.
19
+ inline std::optional<AnyValue> get(const std::string &key, JsString *self)
20
+ {
21
+ // --- toString() & valueOf() ---
22
+ if (key == "toString" || key == WellKnownSymbols::toString->key || key == "valueOf")
23
+ {
24
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
25
+ { return AnyValue::make_string(self->value); },
26
+ key);
27
+ }
28
+
29
+ // --- [Symbol.iterator]() method ---
30
+ if (key == WellKnownSymbols::iterator->key)
31
+ {
32
+ return AnyValue::make_generator([self](const std::vector<AnyValue> &_) -> AnyValue
33
+ { return AnyValue::from_iterator(self->get_iterator()); },
34
+ key);
35
+ }
36
+
37
+ // --- length property ---
38
+ if (key == "length")
39
+ {
40
+ return AnyValue::make_accessor_descriptor([self](const std::vector<AnyValue>) -> AnyValue
41
+ { return AnyValue::make_number(self->value.length()); },
42
+ [self](const std::vector<AnyValue>) -> AnyValue
43
+ { return AnyValue::make_undefined(); },
44
+ false,
45
+ false);
46
+ }
47
+
48
+ // --- charAt(pos) ---
49
+ if (key == "charAt")
50
+ {
51
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
52
+ {
53
+ double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
54
+ int index = static_cast<int>(pos);
55
+ if (index < 0 || index >= self->value.length()) {
56
+ return AnyValue::make_string("");
57
+ }
58
+ return AnyValue::make_string(std::string(1, self->value[index])); },
59
+ key);
60
+ }
61
+
62
+ // --- concat(str1, str2, ...) ---
63
+ if (key == "concat")
64
+ {
65
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
66
+ {
67
+ std::string result = self->value;
68
+ for (const auto& arg : args)
69
+ {
70
+ result += arg.to_std_string();
71
+ }
72
+ return AnyValue::make_string(result); },
73
+ key);
74
+ }
75
+
76
+ // --- endsWith(searchString, endPosition) ---
77
+ if (key == "endsWith")
78
+ {
79
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
80
+ {
81
+ if(args.empty()) return AnyValue::make_boolean(false);
82
+ std::string search = args[0].to_std_string();
83
+ size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->value.length();
84
+
85
+ if (end_pos > self->value.length()) end_pos = self->value.length();
86
+ if (search.length() > end_pos) return AnyValue::make_boolean(false);
87
+
88
+ return AnyValue::make_boolean(self->value.substr(end_pos - search.length(), search.length()) == search); },
89
+ key);
90
+ }
91
+
92
+ // --- includes(searchString, position) ---
93
+ if (key == "includes")
94
+ {
95
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
96
+ {
97
+ if(args.empty()) return AnyValue::make_boolean(false);
98
+ std::string search = args[0].to_std_string();
99
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
100
+
101
+ return AnyValue::make_boolean(self->value.find(search, pos) != std::string::npos); },
102
+ key);
103
+ }
104
+
105
+ // --- indexOf(searchString, position) ---
106
+ if (key == "indexOf")
107
+ {
108
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
109
+ {
110
+ if (args.empty()) return AnyValue::make_number(-1);
111
+ std::string search = args[0].to_std_string();
112
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
113
+ size_t result = self->value.find(search, pos);
114
+ return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
115
+ key);
116
+ }
117
+
118
+ // --- lastIndexOf(searchString, position) ---
119
+ if (key == "lastIndexOf")
120
+ {
121
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
122
+ {
123
+ if (args.empty()) return AnyValue::make_number(-1);
124
+ std::string search = args[0].to_std_string();
125
+ size_t pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : std::string::npos;
126
+ size_t result = self->value.rfind(search, pos);
127
+ return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
128
+ key);
129
+ }
130
+
131
+ // --- padEnd(targetLength, padString) ---
132
+ if (key == "padEnd")
133
+ {
134
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
135
+ {
136
+ size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
137
+ if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
138
+ std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
139
+ std::string result = self->value;
140
+ while (result.length() < target_length)
141
+ {
142
+ result += pad_string;
143
+ }
144
+ return AnyValue::make_string(result.substr(0, target_length)); },
145
+ key);
146
+ }
147
+
148
+ // --- padStart(targetLength, padString) ---
149
+ if (key == "padStart")
150
+ {
151
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
152
+ {
153
+ size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
154
+ if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
155
+ std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
156
+ std::string padding;
157
+ while (padding.length() < target_length - self->value.length())
158
+ {
159
+ padding += pad_string;
160
+ }
161
+ return AnyValue::make_string(padding.substr(0, target_length - self->value.length()) + self->value); },
162
+ key);
163
+ }
164
+
165
+ // --- repeat(count) ---
166
+ if (key == "repeat")
167
+ {
168
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
169
+ {
170
+ double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
171
+ if (count < 0) {
172
+ // In a real implementation, this should throw a RangeError.
173
+ return AnyValue::make_string("");
174
+ }
175
+ std::string result = "";
176
+ for (int i = 0; i < count; ++i)
177
+ {
178
+ result += self->value;
179
+ }
180
+ return AnyValue::make_string(result); },
181
+ key);
182
+ }
183
+
184
+ // --- replace(substr, newSubstr) ---
185
+ if (key == "replace")
186
+ {
187
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
188
+ {
189
+ if (args.size() < 2) return AnyValue::make_string(self->value);
190
+ std::string search = args[0].to_std_string();
191
+ std::string replacement = args[1].to_std_string();
192
+ std::string result = self->value;
193
+ size_t pos = result.find(search);
194
+ if (pos != std::string::npos)
195
+ {
196
+ result.replace(pos, search.length(), replacement);
197
+ }
198
+ return AnyValue::make_string(result); },
199
+ key);
200
+ }
201
+
202
+ // --- replaceAll(substr, newSubstr) ---
203
+ if (key == "replaceAll")
204
+ {
205
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
206
+ {
207
+ if (args.size() < 2) return AnyValue::make_string(self->value);
208
+ std::string search = args[0].to_std_string();
209
+ if (search.empty()) return AnyValue::make_string(self->value);
210
+ std::string replacement = args[1].to_std_string();
211
+ std::string result = self->value;
212
+ size_t pos = result.find(search);
213
+ while (pos != std::string::npos)
214
+ {
215
+ result.replace(pos, search.length(), replacement);
216
+ pos = result.find(search, pos + replacement.length());
217
+ }
218
+ return AnyValue::make_string(result); },
219
+ key);
220
+ }
221
+
222
+ // --- slice(beginIndex, endIndex) ---
223
+ if (key == "slice")
224
+ {
225
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
226
+ {
227
+ int len = self->value.length();
228
+ int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
229
+ int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
230
+
231
+ if (start < 0) start += len;
232
+ if (end < 0) end += len;
233
+
234
+ start = std::max(0, std::min(len, start));
235
+ end = std::max(0, std::min(len, end));
236
+
237
+ if (start >= end) return AnyValue::make_string("");
238
+ return AnyValue::make_string(self->value.substr(start, end - start)); },
239
+ key);
240
+ }
241
+
242
+ // --- split(separator) ---
243
+ if (key == "split")
244
+ {
245
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
246
+ {
247
+ std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
248
+ std::vector<std::optional<AnyValue>> result_vec;
249
+
250
+ if (separator.empty()) {
251
+ for (char c : (self->value)) {
252
+ result_vec.push_back(AnyValue::make_string(std::string(1, c)));
253
+ }
254
+ } else {
255
+ std::string temp = (self->value);
256
+ size_t pos = 0;
257
+ while ((pos = temp.find(separator)) != std::string::npos) {
258
+ result_vec.push_back(AnyValue::make_string(temp.substr(0, pos)));
259
+ temp.erase(0, pos + separator.length());
260
+ }
261
+ result_vec.push_back(AnyValue::make_string(temp));
262
+ }
263
+ return AnyValue::make_array(result_vec); },
264
+ key);
265
+ }
266
+
267
+ // --- startsWith(searchString, position) ---
268
+ if (key == "startsWith")
269
+ {
270
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
271
+ {
272
+ if(args.empty()) return AnyValue::make_boolean(false);
273
+ std::string search = args[0].to_std_string();
274
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
275
+ if (pos > self->value.length()) pos = self->value.length();
276
+
277
+ return AnyValue::make_boolean(self->value.rfind(search, pos) == pos); },
278
+ key);
279
+ }
280
+
281
+ // --- substring(indexStart, indexEnd) ---
282
+ if (key == "substring")
283
+ {
284
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
285
+ {
286
+ int len = self->value.length();
287
+ int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
288
+ int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
289
+
290
+ start = std::max(0, start);
291
+ end = std::max(0, end);
292
+
293
+ if (start > end) std::swap(start, end);
294
+
295
+ start = std::min(len, start);
296
+ end = std::min(len, end);
297
+
298
+ return AnyValue::make_string(self->value.substr(start, end - start)); },
299
+ key);
300
+ }
301
+
302
+ // --- toLowerCase() ---
303
+ if (key == "toLowerCase")
304
+ {
305
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
306
+ {
307
+ std::string result = self->value;
308
+ std::transform(result.begin(), result.end(), result.begin(),
309
+ [](unsigned char c){ return std::tolower(c); });
310
+ return AnyValue::make_string(result); },
311
+ key);
312
+ }
313
+
314
+ // --- toUpperCase() ---
315
+ if (key == "toUpperCase")
316
+ {
317
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
318
+ {
319
+ std::string result = self->value;
320
+ std::transform(result.begin(), result.end(), result.begin(),
321
+ [](unsigned char c){ return std::toupper(c); });
322
+ return AnyValue::make_string(result); },
323
+ key);
324
+ }
325
+
326
+ // --- trim() ---
327
+ if (key == "trim")
328
+ {
329
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
330
+ {
331
+ const char* whitespace = " \t\n\r\f\v";
332
+ std::string result = self->value;
333
+ result.erase(0, result.find_first_not_of(whitespace));
334
+ result.erase(result.find_last_not_of(whitespace) + 1);
335
+ return AnyValue::make_string(result); },
336
+ key);
337
+ }
338
+
339
+ // --- trimEnd() ---
340
+ if (key == "trimEnd")
341
+ {
342
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
343
+ {
344
+ const char* whitespace = " \t\n\r\f\v";
345
+ std::string result = self->value;
346
+ result.erase(result.find_last_not_of(whitespace) + 1);
347
+ return AnyValue::make_string(result); },
348
+ key);
349
+ }
350
+
351
+ // --- trimStart() ---
352
+ if (key == "trimStart")
353
+ {
354
+ return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
355
+ {
356
+ const char* whitespace = " \t\n\r\f\v";
357
+ std::string result = self->value;
358
+ result.erase(0, result.find_first_not_of(whitespace));
359
+ return AnyValue::make_string(result); },
360
+ key);
361
+ }
362
+
363
+ return std::nullopt;
364
+ }
365
+ }
366
+ }