jslike 1.3.1 → 1.4.0
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/bin/jslike.js +1 -1
- package/dist/editor/monaco/index.cjs +239 -0
- package/{src/editor/monaco/index.js → dist/editor/monaco/index.d.cts} +4 -2
- package/dist/editor/monaco/index.d.ts +236 -0
- package/dist/editor/monaco/index.js +214 -0
- package/dist/editor/wang-prism.cjs +109 -0
- package/dist/editor/wang-prism.d.ts +136 -0
- package/dist/editor/wang-prism.js +109 -0
- package/dist/index.cjs +8106 -0
- package/{src/parser.js → dist/index.d.cts} +3276 -41
- package/dist/index.d.ts +9476 -0
- package/dist/index.js +8072 -0
- package/dist/validator/index.cjs +5753 -0
- package/dist/validator/index.d.cts +103 -0
- package/{src/validator/index.js → dist/validator/index.d.ts} +5 -2
- package/dist/validator/index.js +5727 -0
- package/package.json +49 -10
- package/src/ast/nodes.js +0 -236
- package/src/cli/wang-run.js +0 -89
- package/src/cli/wang-validate.js +0 -87
- package/src/errors/enhanced-error.js +0 -124
- package/src/index.js +0 -186
- package/src/interpreter/index.js +0 -201
- package/src/interpreter/interpreter.js +0 -2155
- package/src/metadata/index.js +0 -531
- package/src/resolvers/memory.js +0 -17
- package/src/runtime/builtins.js +0 -517
- package/src/runtime/environment.js +0 -75
- /package/{src/editor/wang-prism.js → dist/editor/wang-prism.d.cts} +0 -0
package/src/runtime/builtins.js
DELETED
|
@@ -1,517 +0,0 @@
|
|
|
1
|
-
// Built-in global objects and functions
|
|
2
|
-
|
|
3
|
-
export function createGlobalEnvironment(env) {
|
|
4
|
-
// Global objects (only those not already defined below)
|
|
5
|
-
env.define('Date', Date);
|
|
6
|
-
|
|
7
|
-
// console object
|
|
8
|
-
env.define('console', {
|
|
9
|
-
log: (...args) => {
|
|
10
|
-
console.log(...args);
|
|
11
|
-
return undefined;
|
|
12
|
-
},
|
|
13
|
-
error: (...args) => {
|
|
14
|
-
console.error(...args);
|
|
15
|
-
return undefined;
|
|
16
|
-
},
|
|
17
|
-
warn: (...args) => {
|
|
18
|
-
console.warn(...args);
|
|
19
|
-
return undefined;
|
|
20
|
-
},
|
|
21
|
-
info: (...args) => {
|
|
22
|
-
console.info(...args);
|
|
23
|
-
return undefined;
|
|
24
|
-
},
|
|
25
|
-
dir: (...args) => {
|
|
26
|
-
console.dir(...args);
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Math object
|
|
32
|
-
env.define('Math', {
|
|
33
|
-
PI: Math.PI,
|
|
34
|
-
E: Math.E,
|
|
35
|
-
abs: Math.abs,
|
|
36
|
-
acos: Math.acos,
|
|
37
|
-
asin: Math.asin,
|
|
38
|
-
atan: Math.atan,
|
|
39
|
-
atan2: Math.atan2,
|
|
40
|
-
ceil: Math.ceil,
|
|
41
|
-
cos: Math.cos,
|
|
42
|
-
exp: Math.exp,
|
|
43
|
-
floor: Math.floor,
|
|
44
|
-
log: Math.log,
|
|
45
|
-
max: Math.max,
|
|
46
|
-
min: Math.min,
|
|
47
|
-
pow: Math.pow,
|
|
48
|
-
random: Math.random,
|
|
49
|
-
round: Math.round,
|
|
50
|
-
sin: Math.sin,
|
|
51
|
-
sqrt: Math.sqrt,
|
|
52
|
-
tan: Math.tan,
|
|
53
|
-
trunc: Math.trunc
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Global values
|
|
57
|
-
env.define('undefined', undefined);
|
|
58
|
-
|
|
59
|
-
// Global functions
|
|
60
|
-
env.define('parseInt', parseInt);
|
|
61
|
-
env.define('parseFloat', parseFloat);
|
|
62
|
-
env.define('isNaN', isNaN);
|
|
63
|
-
env.define('isFinite', isFinite);
|
|
64
|
-
|
|
65
|
-
// Array constructor
|
|
66
|
-
env.define('Array', Array);
|
|
67
|
-
|
|
68
|
-
// Object constructor
|
|
69
|
-
env.define('Object', Object);
|
|
70
|
-
|
|
71
|
-
// String constructor
|
|
72
|
-
env.define('String', String);
|
|
73
|
-
|
|
74
|
-
// Number constructor
|
|
75
|
-
env.define('Number', Number);
|
|
76
|
-
|
|
77
|
-
// Boolean constructor
|
|
78
|
-
env.define('Boolean', Boolean);
|
|
79
|
-
|
|
80
|
-
// Function constructor
|
|
81
|
-
env.define('Function', Function);
|
|
82
|
-
|
|
83
|
-
// RegExp constructor
|
|
84
|
-
env.define('RegExp', RegExp);
|
|
85
|
-
|
|
86
|
-
// Symbol constructor
|
|
87
|
-
env.define('Symbol', Symbol);
|
|
88
|
-
|
|
89
|
-
// Map and Set constructors
|
|
90
|
-
env.define('Map', Map);
|
|
91
|
-
env.define('Set', Set);
|
|
92
|
-
env.define('WeakMap', WeakMap);
|
|
93
|
-
env.define('WeakSet', WeakSet);
|
|
94
|
-
|
|
95
|
-
// JSON object
|
|
96
|
-
env.define('JSON', {
|
|
97
|
-
parse: JSON.parse,
|
|
98
|
-
stringify: JSON.stringify
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// setTimeout, setInterval (basic implementations)
|
|
102
|
-
env.define('setTimeout', setTimeout);
|
|
103
|
-
env.define('setInterval', setInterval);
|
|
104
|
-
env.define('clearTimeout', clearTimeout);
|
|
105
|
-
env.define('clearInterval', clearInterval);
|
|
106
|
-
|
|
107
|
-
// Promise
|
|
108
|
-
env.define('Promise', Promise);
|
|
109
|
-
|
|
110
|
-
// Error constructors
|
|
111
|
-
env.define('Error', Error);
|
|
112
|
-
env.define('TypeError', TypeError);
|
|
113
|
-
env.define('ReferenceError', ReferenceError);
|
|
114
|
-
env.define('SyntaxError', SyntaxError);
|
|
115
|
-
env.define('RangeError', RangeError);
|
|
116
|
-
|
|
117
|
-
// Global console functions (shortcuts for console.log/warn/error)
|
|
118
|
-
env.define('log', (...args) => {
|
|
119
|
-
console.log(...args);
|
|
120
|
-
return undefined;
|
|
121
|
-
});
|
|
122
|
-
env.define('warn', (...args) => {
|
|
123
|
-
console.warn(...args);
|
|
124
|
-
return undefined;
|
|
125
|
-
});
|
|
126
|
-
env.define('error', (...args) => {
|
|
127
|
-
console.error(...args);
|
|
128
|
-
return undefined;
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Wang Standard Library - Array Operations
|
|
132
|
-
env.define('sort_by', (array, keyOrFn) => {
|
|
133
|
-
const arr = [...array];
|
|
134
|
-
if (typeof keyOrFn === 'function') {
|
|
135
|
-
return arr.sort((a, b) => {
|
|
136
|
-
const aVal = keyOrFn(a);
|
|
137
|
-
const bVal = keyOrFn(b);
|
|
138
|
-
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
139
|
-
});
|
|
140
|
-
} else {
|
|
141
|
-
return arr.sort((a, b) => {
|
|
142
|
-
const aVal = a[keyOrFn];
|
|
143
|
-
const bVal = b[keyOrFn];
|
|
144
|
-
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
env.define('reverse', (array) => {
|
|
150
|
-
return [...array].reverse();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
env.define('unique', (array) => {
|
|
154
|
-
return [...new Set(array)];
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
env.define('unique_by', (array, key) => {
|
|
158
|
-
const seen = new Set();
|
|
159
|
-
return array.filter(item => {
|
|
160
|
-
const val = item[key];
|
|
161
|
-
if (seen.has(val)) return false;
|
|
162
|
-
seen.add(val);
|
|
163
|
-
return true;
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
env.define('group_by', (array, key) => {
|
|
168
|
-
return array.reduce((groups, item) => {
|
|
169
|
-
const groupKey = item[key];
|
|
170
|
-
if (!groups[groupKey]) groups[groupKey] = [];
|
|
171
|
-
groups[groupKey].push(item);
|
|
172
|
-
return groups;
|
|
173
|
-
}, {});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
env.define('chunk', (array, size) => {
|
|
177
|
-
const chunks = [];
|
|
178
|
-
for (let i = 0; i < array.length; i += size) {
|
|
179
|
-
chunks.push(array.slice(i, i + size));
|
|
180
|
-
}
|
|
181
|
-
return chunks;
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
env.define('flatten', (array, depth = 1) => {
|
|
185
|
-
return array.flat(depth);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
env.define('first', (array, n) => {
|
|
189
|
-
if (n === undefined) return array[0];
|
|
190
|
-
return array.slice(0, n);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
env.define('last', (array, n) => {
|
|
194
|
-
if (n === undefined) return array[array.length - 1];
|
|
195
|
-
return array.slice(-n);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
env.define('take', (array, n) => {
|
|
199
|
-
return array.slice(0, n);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
env.define('drop', (array, n) => {
|
|
203
|
-
return array.slice(n);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
env.define('zip', (...arrays) => {
|
|
207
|
-
const length = Math.min(...arrays.map(a => a.length));
|
|
208
|
-
return Array.from({ length }, (_, i) => arrays.map(a => a[i]));
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
env.define('partition', (array, predicate) => {
|
|
212
|
-
const truthy = [];
|
|
213
|
-
const falsy = [];
|
|
214
|
-
array.forEach(item => {
|
|
215
|
-
if (predicate(item)) truthy.push(item);
|
|
216
|
-
else falsy.push(item);
|
|
217
|
-
});
|
|
218
|
-
return [truthy, falsy];
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
env.define('filter', (array, predicate) => {
|
|
222
|
-
return array.filter(predicate);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
env.define('map', (array, fn) => {
|
|
226
|
-
return array.map(fn);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
env.define('find', (array, predicate) => {
|
|
230
|
-
return array.find(predicate);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
env.define('find_index', (array, predicate) => {
|
|
234
|
-
return array.findIndex(predicate);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
env.define('every', (array, predicate) => {
|
|
238
|
-
return array.every(predicate);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
env.define('some', (array, predicate) => {
|
|
242
|
-
return array.some(predicate);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
env.define('count', (array, predicate) => {
|
|
246
|
-
if (!predicate) {
|
|
247
|
-
return array.length;
|
|
248
|
-
}
|
|
249
|
-
return array.filter(predicate).length;
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Wang Standard Library - Object Operations
|
|
253
|
-
env.define('keys', (obj) => {
|
|
254
|
-
return Object.keys(obj);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
env.define('values', (obj) => {
|
|
258
|
-
return Object.values(obj);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
env.define('entries', (obj) => {
|
|
262
|
-
return Object.entries(obj);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
env.define('pick', (obj, keys) => {
|
|
266
|
-
const result = {};
|
|
267
|
-
keys.forEach(key => {
|
|
268
|
-
if (key in obj) result[key] = obj[key];
|
|
269
|
-
});
|
|
270
|
-
return result;
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
env.define('omit', (obj, keys) => {
|
|
274
|
-
const result = { ...obj };
|
|
275
|
-
keys.forEach(key => delete result[key]);
|
|
276
|
-
return result;
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
env.define('merge', (...objects) => {
|
|
280
|
-
return Object.assign({}, ...objects);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
env.define('get', (obj, path, defaultValue) => {
|
|
284
|
-
const keys = path.split('.');
|
|
285
|
-
let current = obj;
|
|
286
|
-
for (const key of keys) {
|
|
287
|
-
if (current == null) return defaultValue;
|
|
288
|
-
current = current[key];
|
|
289
|
-
}
|
|
290
|
-
return current !== undefined ? current : defaultValue;
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
env.define('set', (obj, path, value) => {
|
|
294
|
-
const keys = path.split('.');
|
|
295
|
-
const result = JSON.parse(JSON.stringify(obj)); // Deep clone
|
|
296
|
-
let current = result;
|
|
297
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
298
|
-
const key = keys[i];
|
|
299
|
-
if (!(key in current)) current[key] = {};
|
|
300
|
-
current = current[key];
|
|
301
|
-
}
|
|
302
|
-
current[keys[keys.length - 1]] = value;
|
|
303
|
-
return result;
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
env.define('clone', (obj) => {
|
|
307
|
-
return JSON.parse(JSON.stringify(obj));
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
// Wang Standard Library - String Operations
|
|
311
|
-
env.define('split', (str, separator) => {
|
|
312
|
-
return str.split(separator);
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
env.define('join', (array, separator) => {
|
|
316
|
-
return array.join(separator);
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
env.define('trim', (str) => {
|
|
320
|
-
return str.trim();
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
env.define('trim_start', (str) => {
|
|
324
|
-
return str.trimStart();
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
env.define('trim_end', (str) => {
|
|
328
|
-
return str.trimEnd();
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
env.define('upper', (str) => {
|
|
332
|
-
return str.toUpperCase();
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
env.define('toUpperCase', (str) => {
|
|
336
|
-
return str.toUpperCase();
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
env.define('lower', (str) => {
|
|
340
|
-
return str.toLowerCase();
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
env.define('toLowerCase', (str) => {
|
|
344
|
-
return str.toLowerCase();
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
env.define('capitalize', (str) => {
|
|
348
|
-
if (!str) return str;
|
|
349
|
-
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
env.define('starts_with', (str, prefix) => {
|
|
353
|
-
return str.startsWith(prefix);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
env.define('ends_with', (str, suffix) => {
|
|
357
|
-
return str.endsWith(suffix);
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
env.define('includes', (str, substring) => {
|
|
361
|
-
return str.includes(substring);
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
env.define('pad_start', (str, length, char = ' ') => {
|
|
365
|
-
return str.padStart(length, char);
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
env.define('pad_end', (str, length, char = ' ') => {
|
|
369
|
-
return str.padEnd(length, char);
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
env.define('truncate', (str, length) => {
|
|
373
|
-
if (str.length <= length) return str;
|
|
374
|
-
return str.slice(0, length - 3) + '...';
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
env.define('replace_all', (str, search, replace) => {
|
|
378
|
-
return str.replaceAll(search, replace);
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
// Wang Standard Library - Type Checking
|
|
382
|
-
env.define('is_string', (value) => {
|
|
383
|
-
return typeof value === 'string';
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
env.define('is_number', (value) => {
|
|
387
|
-
return typeof value === 'number';
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
env.define('is_boolean', (value) => {
|
|
391
|
-
return typeof value === 'boolean';
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
env.define('is_array', (value) => {
|
|
395
|
-
return Array.isArray(value);
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
env.define('is_object', (value) => {
|
|
399
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
env.define('is_function', (value) => {
|
|
403
|
-
return typeof value === 'function';
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
env.define('is_null', (value) => {
|
|
407
|
-
return value === null;
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
env.define('is_undefined', (value) => {
|
|
411
|
-
return value === undefined;
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
env.define('is_empty', (value) => {
|
|
415
|
-
if (value == null) return true;
|
|
416
|
-
if (typeof value === 'string' || Array.isArray(value)) return value.length === 0;
|
|
417
|
-
if (typeof value === 'object') return Object.keys(value).length === 0;
|
|
418
|
-
return false;
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// Wang Standard Library - Math Operations
|
|
422
|
-
env.define('min', (array) => {
|
|
423
|
-
return Math.min(...array);
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
env.define('max', (array) => {
|
|
427
|
-
return Math.max(...array);
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
env.define('sum', (array) => {
|
|
431
|
-
return array.reduce((a, b) => a + b, 0);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
env.define('avg', (array) => {
|
|
435
|
-
return array.reduce((a, b) => a + b, 0) / array.length;
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
env.define('median', (array) => {
|
|
439
|
-
const sorted = [...array].sort((a, b) => a - b);
|
|
440
|
-
const mid = Math.floor(sorted.length / 2);
|
|
441
|
-
return sorted.length % 2 === 0
|
|
442
|
-
? (sorted[mid - 1] + sorted[mid]) / 2
|
|
443
|
-
: sorted[mid];
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
env.define('round', (num, decimals = 0) => {
|
|
447
|
-
const factor = Math.pow(10, decimals);
|
|
448
|
-
return Math.round(num * factor) / factor;
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
env.define('floor', (num) => {
|
|
452
|
-
return Math.floor(num);
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
env.define('ceil', (num) => {
|
|
456
|
-
return Math.ceil(num);
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
env.define('abs', (num) => {
|
|
460
|
-
return Math.abs(num);
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
env.define('clamp', (num, min, max) => {
|
|
464
|
-
return Math.min(Math.max(num, min), max);
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
env.define('range', (start, end, step) => {
|
|
468
|
-
// Support range(n) -> [0, 1, ..., n-1]
|
|
469
|
-
if (end === undefined) {
|
|
470
|
-
end = start;
|
|
471
|
-
start = 0;
|
|
472
|
-
step = 1;
|
|
473
|
-
}
|
|
474
|
-
if (step === undefined) {
|
|
475
|
-
step = start < end ? 1 : -1;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const result = [];
|
|
479
|
-
if (step > 0) {
|
|
480
|
-
for (let i = start; i < end; i += step) {
|
|
481
|
-
result.push(i);
|
|
482
|
-
}
|
|
483
|
-
} else {
|
|
484
|
-
for (let i = start; i > end; i += step) {
|
|
485
|
-
result.push(i);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
return result;
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
// Wang Standard Library - Utility Functions
|
|
492
|
-
env.define('uuid', () => {
|
|
493
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
494
|
-
const r = Math.random() * 16 | 0;
|
|
495
|
-
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
496
|
-
return v.toString(16);
|
|
497
|
-
});
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
env.define('to_json', (value) => {
|
|
501
|
-
return JSON.stringify(value);
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
env.define('from_json', (str) => {
|
|
505
|
-
return JSON.parse(str);
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
env.define('sleep', async (ms) => {
|
|
509
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
env.define('wait', async (ms) => {
|
|
513
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
return env;
|
|
517
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// Runtime Environment for variable scoping and storage
|
|
2
|
-
|
|
3
|
-
export class Environment {
|
|
4
|
-
constructor(parent = null) {
|
|
5
|
-
this.parent = parent;
|
|
6
|
-
this.vars = new Map();
|
|
7
|
-
this.consts = new Set(); // Track const variables
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
define(name, value, isConst = false) {
|
|
11
|
-
if (this.vars.has(name)) {
|
|
12
|
-
throw new Error(`Variable '${name}' already declared`);
|
|
13
|
-
}
|
|
14
|
-
this.vars.set(name, value);
|
|
15
|
-
if (isConst) {
|
|
16
|
-
this.consts.add(name);
|
|
17
|
-
}
|
|
18
|
-
return value;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get(name) {
|
|
22
|
-
if (this.vars.has(name)) {
|
|
23
|
-
return this.vars.get(name);
|
|
24
|
-
}
|
|
25
|
-
if (this.parent) {
|
|
26
|
-
return this.parent.get(name);
|
|
27
|
-
}
|
|
28
|
-
throw new ReferenceError(`Variable "${name}" is not defined`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
set(name, value) {
|
|
32
|
-
if (this.vars.has(name)) {
|
|
33
|
-
// Check if trying to reassign a const variable
|
|
34
|
-
if (this.consts.has(name)) {
|
|
35
|
-
throw new TypeError(`Cannot reassign const variable '${name}'`);
|
|
36
|
-
}
|
|
37
|
-
this.vars.set(name, value);
|
|
38
|
-
return value;
|
|
39
|
-
}
|
|
40
|
-
if (this.parent) {
|
|
41
|
-
return this.parent.set(name, value);
|
|
42
|
-
}
|
|
43
|
-
throw new ReferenceError(`Variable "${name}" is not defined`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
has(name) {
|
|
47
|
-
return this.vars.has(name) || (this.parent ? this.parent.has(name) : false);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// For let/const block scoping
|
|
51
|
-
extend() {
|
|
52
|
-
return new Environment(this);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Special control flow signals
|
|
57
|
-
export class ReturnValue {
|
|
58
|
-
constructor(value) {
|
|
59
|
-
this.value = value;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export class BreakSignal {
|
|
64
|
-
constructor() {}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export class ContinueSignal {
|
|
68
|
-
constructor() {}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export class ThrowSignal {
|
|
72
|
-
constructor(value) {
|
|
73
|
-
this.value = value;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
File without changes
|