@foxystar/molang 0.1.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.
Files changed (44) hide show
  1. package/README.md +82 -0
  2. package/esm/LRUCache.d.ts +6 -0
  3. package/esm/LRUCache.js +30 -0
  4. package/esm/diagnostics/error.d.ts +12 -0
  5. package/esm/diagnostics/error.js +37 -0
  6. package/esm/diagnostics/suggestions.d.ts +2 -0
  7. package/esm/diagnostics/suggestions.js +35 -0
  8. package/esm/index.d.ts +8 -0
  9. package/esm/index.js +6 -0
  10. package/esm/molang.d.ts +2 -0
  11. package/esm/molang.js +22 -0
  12. package/esm/package.json +3 -0
  13. package/esm/parser/expression.d.ts +87 -0
  14. package/esm/parser/expression.js +19 -0
  15. package/esm/parser/parser.d.ts +20 -0
  16. package/esm/parser/parser.js +490 -0
  17. package/esm/runtime/context.d.ts +19 -0
  18. package/esm/runtime/context.js +51 -0
  19. package/esm/runtime/math.d.ts +32 -0
  20. package/esm/runtime/math.js +89 -0
  21. package/esm/runtime/runtime.d.ts +34 -0
  22. package/esm/runtime/runtime.js +537 -0
  23. package/package.json +39 -0
  24. package/script/LRUCache.d.ts +6 -0
  25. package/script/LRUCache.js +33 -0
  26. package/script/diagnostics/error.d.ts +12 -0
  27. package/script/diagnostics/error.js +42 -0
  28. package/script/diagnostics/suggestions.d.ts +2 -0
  29. package/script/diagnostics/suggestions.js +40 -0
  30. package/script/index.d.ts +8 -0
  31. package/script/index.js +27 -0
  32. package/script/molang.d.ts +2 -0
  33. package/script/molang.js +29 -0
  34. package/script/package.json +3 -0
  35. package/script/parser/expression.d.ts +87 -0
  36. package/script/parser/expression.js +22 -0
  37. package/script/parser/parser.d.ts +20 -0
  38. package/script/parser/parser.js +494 -0
  39. package/script/runtime/context.d.ts +19 -0
  40. package/script/runtime/context.js +57 -0
  41. package/script/runtime/math.d.ts +32 -0
  42. package/script/runtime/math.js +92 -0
  43. package/script/runtime/runtime.d.ts +34 -0
  44. package/script/runtime/runtime.js +567 -0
@@ -0,0 +1,34 @@
1
+ import { Expr, Program } from "../parser/expression.js";
2
+ import { MolangContext } from "./context.js";
3
+ export interface MolangOptions {
4
+ strict?: boolean;
5
+ }
6
+ export declare class ReturnSignal {
7
+ value: unknown;
8
+ constructor(value: unknown);
9
+ }
10
+ export declare class BreakSignal {
11
+ }
12
+ export declare class ContinueSignal {
13
+ }
14
+ export declare class MolangRuntime {
15
+ private context;
16
+ private source;
17
+ private options;
18
+ private rootContext;
19
+ private loopDepth;
20
+ constructor(context: MolangContext, source: string, options?: MolangOptions, rootContext?: MolangContext);
21
+ private static NAMESPACE_ALIASES;
22
+ private safe;
23
+ evaluateProgram(program: Program): unknown;
24
+ private evaluateStatement;
25
+ private assign;
26
+ private findAssignmentRoot;
27
+ evaluate(expr: Expr): any;
28
+ private toNumber;
29
+ private toBoolean;
30
+ private applyOperator;
31
+ static normalizePath(path: string): string[];
32
+ private suggestPath;
33
+ private resolvePath;
34
+ }
@@ -0,0 +1,537 @@
1
+ import { MolangRuntimeError } from "../diagnostics/error.js";
2
+ import * as Suggestions from "../diagnostics/suggestions.js";
3
+ import { DEFAULT_CONTEXT, isNamespace } from "./context.js";
4
+ export class ReturnSignal {
5
+ constructor(value) {
6
+ Object.defineProperty(this, "value", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: value
11
+ });
12
+ }
13
+ ;
14
+ }
15
+ export class BreakSignal {
16
+ }
17
+ ;
18
+ export class ContinueSignal {
19
+ }
20
+ ;
21
+ export class MolangRuntime {
22
+ constructor(context = DEFAULT_CONTEXT, source, options = {}, rootContext = context) {
23
+ Object.defineProperty(this, "context", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: context
28
+ });
29
+ Object.defineProperty(this, "source", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: source
34
+ });
35
+ Object.defineProperty(this, "options", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: options
40
+ });
41
+ Object.defineProperty(this, "rootContext", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: rootContext
46
+ });
47
+ Object.defineProperty(this, "loopDepth", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: 0
52
+ });
53
+ }
54
+ safe(fn) {
55
+ try {
56
+ return fn();
57
+ }
58
+ catch (e) {
59
+ if (this.options.strict) {
60
+ throw e;
61
+ }
62
+ return 0;
63
+ }
64
+ }
65
+ evaluateProgram(program) {
66
+ try {
67
+ let result = undefined;
68
+ for (const stmt of program.body) {
69
+ result = this.evaluateStatement(stmt);
70
+ }
71
+ return result;
72
+ }
73
+ catch (e) {
74
+ if (e instanceof ReturnSignal) {
75
+ return e.value;
76
+ }
77
+ throw e;
78
+ }
79
+ }
80
+ evaluateStatement(stmt) {
81
+ switch (stmt.type) {
82
+ case "ExprStatement": {
83
+ return this.evaluate(stmt.expr);
84
+ }
85
+ case "AssignStatement": {
86
+ if (stmt.target.type === "ArrowExpression") {
87
+ throw new MolangRuntimeError("Cannot assign through '->'", stmt.target, this.source);
88
+ }
89
+ const value = this.evaluate(stmt.value);
90
+ this.assign(stmt.target, value, stmt);
91
+ return value;
92
+ }
93
+ case "BreakStatement": {
94
+ if (this.loopDepth === 0) {
95
+ throw new MolangRuntimeError("break used outside of loop", stmt, this.source);
96
+ }
97
+ throw new BreakSignal();
98
+ }
99
+ case "ContinueStatement": {
100
+ if (this.loopDepth === 0) {
101
+ throw new MolangRuntimeError("continue used outside of loop", stmt, this.source);
102
+ }
103
+ throw new ContinueSignal();
104
+ }
105
+ case "ReturnStatement": {
106
+ const value = stmt.value
107
+ ? this.evaluate(stmt.value)
108
+ : undefined;
109
+ throw new ReturnSignal(value);
110
+ }
111
+ case "ConditionalStatement": {
112
+ const condition = this.evaluate(stmt.condition);
113
+ if (this.toBoolean(condition)) {
114
+ return this.evaluateStatement(stmt.then);
115
+ }
116
+ if (stmt.else) {
117
+ return this.evaluateStatement(stmt.else);
118
+ }
119
+ return undefined;
120
+ }
121
+ case "LoopStatement": {
122
+ const result = this.toNumber(this.evaluate(stmt.count));
123
+ const count = Math.min(1024, Math.max(0, result | 0));
124
+ this.loopDepth++;
125
+ for (let i = 0; i < count; i++) {
126
+ try {
127
+ this.evaluateStatement(stmt.body);
128
+ }
129
+ catch (e) {
130
+ if (e instanceof BreakSignal) {
131
+ break;
132
+ }
133
+ if (e instanceof ContinueSignal) {
134
+ continue;
135
+ }
136
+ throw e;
137
+ }
138
+ }
139
+ this.loopDepth--;
140
+ return 0;
141
+ }
142
+ case "ForEachStatement": {
143
+ const value = this.evaluate(stmt.iterable);
144
+ if (!Array.isArray(value)) {
145
+ return 0;
146
+ }
147
+ const max = Math.min(1024, value.length);
148
+ for (let i = 0; i < max; i++) {
149
+ try {
150
+ const iterationContext = Object.create(this.context);
151
+ iterationContext.this = value[i];
152
+ const nested = new MolangRuntime(iterationContext, this.source, this.options, this.rootContext);
153
+ // ALWAYS assign iterator
154
+ nested.assign(stmt.iterator, value[i], stmt);
155
+ nested.evaluateStatement(stmt.body);
156
+ }
157
+ catch (e) {
158
+ if (e instanceof BreakSignal) {
159
+ break;
160
+ }
161
+ if (e instanceof ContinueSignal) {
162
+ continue;
163
+ }
164
+ throw e;
165
+ }
166
+ }
167
+ return 0;
168
+ }
169
+ case "BlockStatement": {
170
+ let result = undefined;
171
+ for (const s of stmt.body) {
172
+ result = this.evaluateStatement(s);
173
+ }
174
+ return result;
175
+ }
176
+ default: {
177
+ throw new Error("Unknown statement type");
178
+ }
179
+ }
180
+ }
181
+ assign(target, value, _stmt) {
182
+ // Index assignment: arr[idx] = value
183
+ if (target.type === "IndexExpression") {
184
+ // Ensure the base identifier is assignable
185
+ const root = this.findAssignmentRoot(target.array);
186
+ if (root !== "variable" && root !== "temp") {
187
+ throw new MolangRuntimeError(`Cannot assign to namespace '${root}'`, target, this.source);
188
+ }
189
+ const container = this.evaluate(target.array);
190
+ const index = this.evaluate(target.index);
191
+ if (!isNamespace(container)) {
192
+ throw new MolangRuntimeError("Cannot assign to property of null or undefined", target, this.source);
193
+ }
194
+ container[index] = value;
195
+ return;
196
+ }
197
+ if (target.type !== "Identifier") {
198
+ throw new MolangRuntimeError("Invalid assignment target", target, this.source);
199
+ }
200
+ const parts = MolangRuntime.normalizePath(target.name);
201
+ if (parts.length < 2) {
202
+ throw new MolangRuntimeError("Assignments must target a namespace like v.x or variable.x", target, this.source);
203
+ }
204
+ // Enforce allowed namespaces (very important for safety)
205
+ const root = parts[0];
206
+ if (root !== "variable" && root !== "temp") {
207
+ throw new MolangRuntimeError(`Cannot assign to namespace '${root}'`, target, this.source);
208
+ }
209
+ let current = this.context;
210
+ for (let i = 0; i < parts.length - 1; i++) {
211
+ const part = parts[i];
212
+ if (!isNamespace(current)) {
213
+ throw new MolangRuntimeError(`Unknown identifier '${parts.join(".")}'`, target, this.source);
214
+ }
215
+ if (!(part in current)) {
216
+ if (this.options.strict) {
217
+ let message = `Cannot assign to '${parts.join(".")}' because '${parts.slice(0, i + 1).join(".")}' does not exist`;
218
+ const suggestion = this.suggestPath(parts, i, current);
219
+ if (suggestion) {
220
+ message += `. Did you mean '${suggestion}'?`;
221
+ }
222
+ throw new MolangRuntimeError(message, target, this.source);
223
+ }
224
+ current[part] = {};
225
+ }
226
+ current = current[part];
227
+ }
228
+ const last = parts[parts.length - 1];
229
+ if (!isNamespace(current)) {
230
+ throw new MolangRuntimeError(`Cannot assign to '${parts.join(".")}'`, target, this.source);
231
+ }
232
+ current[last] = value;
233
+ }
234
+ findAssignmentRoot(expr) {
235
+ if (expr.type === "Identifier") {
236
+ return MolangRuntime.normalizePath(expr.name)[0] ?? null;
237
+ }
238
+ if (expr.type === "IndexExpression") {
239
+ return this.findAssignmentRoot(expr.array);
240
+ }
241
+ return null;
242
+ }
243
+ evaluate(expr) {
244
+ switch (expr.type) {
245
+ case "Literal": {
246
+ return expr.value;
247
+ }
248
+ case "Identifier": {
249
+ try {
250
+ return this.resolvePath(expr.path, expr);
251
+ }
252
+ catch {
253
+ return undefined;
254
+ }
255
+ }
256
+ case "BinaryExpression": {
257
+ return this.safe(() => {
258
+ const left = this.evaluate(expr.left);
259
+ const right = this.evaluate(expr.right);
260
+ return this.applyOperator(expr.operator, left, right, expr);
261
+ });
262
+ }
263
+ case "CallExpression": {
264
+ try {
265
+ if (expr.callee.type !== "Identifier") {
266
+ throw new MolangRuntimeError("Invalid function call target", expr.callee, this.source);
267
+ }
268
+ const name = expr.callee.name;
269
+ const func = this.evaluate(expr.callee);
270
+ if (func === undefined) {
271
+ const parts = MolangRuntime.normalizePath(name);
272
+ // resolve parent safely
273
+ let parent = this.context;
274
+ for (let i = 0; i < parts.length - 1; i++) {
275
+ const p = parts[i];
276
+ if (!isNamespace(parent) || !(p in parent)) {
277
+ break;
278
+ }
279
+ parent = parent[p];
280
+ }
281
+ let message = `Cannot call '${name}' because it is undefined`;
282
+ if (isNamespace(parent)) {
283
+ const suggestion = this.suggestPath(parts, parts.length - 1, parent);
284
+ if (suggestion) {
285
+ message += `. Did you mean '${suggestion}'?`;
286
+ }
287
+ }
288
+ throw new MolangRuntimeError(message, expr.callee, this.source);
289
+ }
290
+ if (typeof func !== "function") {
291
+ const type = func === null ? "null" : typeof func;
292
+ let message = `Cannot call '${name}' because it is of type '${type}', not a function`;
293
+ const parts = MolangRuntime.normalizePath(name);
294
+ const parent = this.context;
295
+ const suggestion = this.suggestPath(parts, parts.length - 1, parent);
296
+ if (suggestion) {
297
+ message += `. Did you mean '${suggestion}'?`;
298
+ }
299
+ throw new MolangRuntimeError(message, expr.callee, this.source);
300
+ }
301
+ const args = expr.arguments.map(a => this.evaluate(a));
302
+ if (args.length < func.length) {
303
+ throw new MolangRuntimeError(`Function '${name}' expects at least ${func.length} arguments, but got ${args.length}`, expr, this.source);
304
+ }
305
+ return func(...args);
306
+ }
307
+ catch (error) {
308
+ if (error instanceof MolangRuntimeError) {
309
+ throw error;
310
+ }
311
+ throw new MolangRuntimeError(error instanceof Error ? error.message : String(error), expr.callee, this.source);
312
+ }
313
+ }
314
+ case "UnaryExpression": {
315
+ const v = this.evaluate(expr.expression);
316
+ switch (expr.operator) {
317
+ case "-": {
318
+ return -v;
319
+ }
320
+ case "!": {
321
+ return this.toNumber(v) === 0 ? 1 : 0;
322
+ }
323
+ default: {
324
+ throw new MolangRuntimeError(`Unknown unary operator ${expr.operator}`, expr, this.source);
325
+ }
326
+ }
327
+ }
328
+ case "ArrayLiteral": {
329
+ return expr.elements.map(e => this.evaluate(e));
330
+ }
331
+ case "IndexExpression": {
332
+ const container = this.evaluate(expr.array);
333
+ const idx = this.evaluate(expr.index);
334
+ if (!isNamespace(container)) {
335
+ throw new MolangRuntimeError("Cannot index non-object value", expr, this.source);
336
+ }
337
+ return (container)[idx];
338
+ /*if (typeof container !== "object" || container === null || !Array.isArray(container)) {
339
+ throw new MolangRuntimeError("Cannot index non-array value", expr, this.source);
340
+ }
341
+
342
+ if (typeof idx !== "number" || !Number.isInteger(idx)) {
343
+ throw new MolangRuntimeError("Array index must be an integer", expr, this.source);
344
+ }
345
+
346
+ if (Array.isArray(container) && (idx < 0 || idx >= container.length)) {
347
+ throw new MolangRuntimeError("Array index out of bounds", expr, this.source);
348
+ }
349
+
350
+ return container[idx];*/
351
+ }
352
+ case "ArrowExpression": {
353
+ if (expr.left.type === "ArrowExpression") {
354
+ throw new MolangRuntimeError("Chained '->' not supported", expr, this.source);
355
+ }
356
+ let target = this.evaluate(expr.left);
357
+ if (typeof target === "function") {
358
+ if (target.length !== 0) {
359
+ throw new MolangRuntimeError("Arrow target function must take no arguments", expr.left, this.source);
360
+ }
361
+ try {
362
+ target = target();
363
+ }
364
+ catch (error) {
365
+ if (error instanceof MolangRuntimeError) {
366
+ throw error;
367
+ }
368
+ throw new MolangRuntimeError(`Error calling arrow target: ${error instanceof Error ? error.message : String(error)}`, expr.left, this.source);
369
+ }
370
+ }
371
+ if (typeof target !== "object" || target === null) {
372
+ throw new MolangRuntimeError("Left side of '->' must be an object/context", expr.left, this.source);
373
+ }
374
+ if (!("context" in target) || !("query" in target)) {
375
+ throw new MolangRuntimeError("Arrow target is not a valid entity context", expr.left, this.source);
376
+ }
377
+ // Create a new runtime with swapped context
378
+ const nestedRuntime = new MolangRuntime(target, this.source, this.options, this.rootContext);
379
+ return nestedRuntime.evaluate(expr.right);
380
+ }
381
+ case "ConditionalExpression": {
382
+ const condition = this.evaluate(expr.condition);
383
+ if (this.toBoolean(condition)) {
384
+ return this.evaluate(expr.then);
385
+ }
386
+ // A ? B : C
387
+ if (expr.else) {
388
+ return this.evaluate(expr.else);
389
+ }
390
+ // A ? B → returns 0 if false
391
+ return 0;
392
+ }
393
+ default: {
394
+ throw new Error(`Unknown expression type: ${expr.type}`);
395
+ }
396
+ }
397
+ }
398
+ toNumber(value) {
399
+ if (typeof value === "number") {
400
+ return value;
401
+ }
402
+ else if (typeof value === "boolean") {
403
+ return value ? 1 : 0;
404
+ }
405
+ return Number(value) || 0;
406
+ }
407
+ toBoolean(v) {
408
+ return this.options.strict
409
+ ? Boolean(v)
410
+ : this.toNumber(v) !== 0;
411
+ }
412
+ applyOperator(operator, left, right, expr) {
413
+ switch (operator) {
414
+ case "&":
415
+ case "|":
416
+ case "^":
417
+ case "<<":
418
+ case ">>":
419
+ case ">>>": {
420
+ if (!Number.isInteger(left) || !Number.isInteger(right)) {
421
+ throw new MolangRuntimeError("Bitwise operators require numbers", expr, this.source);
422
+ }
423
+ const l = this.toNumber(left) | 0;
424
+ const r = this.toNumber(right) | 0;
425
+ switch (operator) {
426
+ case "&": return l & r;
427
+ case "|": return l | r;
428
+ case "^": return l ^ r;
429
+ case "<<": return l << r;
430
+ case ">>": return l >> r;
431
+ case ">>>": return l >>> r;
432
+ }
433
+ return 0;
434
+ }
435
+ case "+":
436
+ case "-":
437
+ case "*":
438
+ case "/": {
439
+ const l = this.toNumber(left);
440
+ const r = this.toNumber(right);
441
+ switch (operator) {
442
+ case "+": return l + r;
443
+ case "-": return l - r;
444
+ case "*": return l * r;
445
+ case "/": return l / r;
446
+ }
447
+ return 0;
448
+ }
449
+ case "==": return left == right;
450
+ case "!=": return left != right;
451
+ case "<":
452
+ case ">":
453
+ case "<=":
454
+ case ">=": {
455
+ if ((typeof left === "number" && typeof right === "number") && this.options.strict === true) {
456
+ throw new MolangRuntimeError("Expected numbers for comparison", expr, this.source);
457
+ }
458
+ const l = this.toNumber(left);
459
+ const r = this.toNumber(right);
460
+ switch (operator) {
461
+ case "<": return l < r;
462
+ case ">": return l > r;
463
+ case "<=": return l <= r;
464
+ case ">=": return l >= r;
465
+ }
466
+ return 0;
467
+ }
468
+ case "??": {
469
+ return (left !== undefined && left !== null) ? left : right;
470
+ }
471
+ case "&&":
472
+ case "||": {
473
+ if (typeof left !== "boolean" || typeof right !== "boolean") {
474
+ throw new MolangRuntimeError("Expected booleans", expr, this.source);
475
+ }
476
+ return operator === "&&"
477
+ ? (left && right)
478
+ : (left || right);
479
+ }
480
+ default: {
481
+ throw new MolangRuntimeError(`Unknown operator '${operator}'`, expr, this.source);
482
+ }
483
+ }
484
+ }
485
+ // Paths
486
+ static normalizePath(path) {
487
+ const parts = path.split(".");
488
+ // Apply alias only to the root namespace
489
+ const root = parts[0];
490
+ const alias = MolangRuntime.NAMESPACE_ALIASES[root];
491
+ if (alias) {
492
+ parts[0] = alias;
493
+ }
494
+ return parts;
495
+ }
496
+ suggestPath(parts, index, current) {
497
+ const keys = Object.keys(current);
498
+ const suggestion = Suggestions.findBestMatch(parts[index], keys);
499
+ if (!suggestion)
500
+ return;
501
+ const fixed = [...parts];
502
+ fixed[index] = suggestion;
503
+ return fixed.join(".");
504
+ }
505
+ resolvePath(value, expr) {
506
+ const parts = typeof value === "string" ? MolangRuntime.normalizePath(value) : value;
507
+ let current = this.context;
508
+ for (let i = 0; i < parts.length; i++) {
509
+ const part = parts[i];
510
+ if (!isNamespace(current)) {
511
+ throw new MolangRuntimeError(`Unknown identifier '${parts.join(".")}'`, expr, this.source);
512
+ }
513
+ if (!(part in current)) {
514
+ let message = `Unknown identifier '${parts.join(".")}'`;
515
+ // Suggestion logic
516
+ const suggestion = this.suggestPath(parts, i, current);
517
+ if (suggestion) {
518
+ message += `. Did you mean '${suggestion}'?`;
519
+ }
520
+ throw new MolangRuntimeError(message, expr, this.source);
521
+ }
522
+ current = current[part];
523
+ }
524
+ return current;
525
+ }
526
+ }
527
+ Object.defineProperty(MolangRuntime, "NAMESPACE_ALIASES", {
528
+ enumerable: true,
529
+ configurable: true,
530
+ writable: true,
531
+ value: {
532
+ v: "variable",
533
+ t: "temp",
534
+ q: "query",
535
+ c: "context",
536
+ }
537
+ });
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@foxystar/molang",
3
+ "version": "0.1.0",
4
+ "description": "A fast, extensible, and safe implementation of the Molang expression language.",
5
+ "author": {
6
+ "name": "FoxyStar Studios",
7
+ "url": "https://github.com/FoxyStar-Studios"
8
+ },
9
+ "homepage": "https://www.npmjs.com/package/@foxystar/molang",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/FoxyStar-Studios/scripting-libraries.git",
13
+ "directory": "packages/molang"
14
+ },
15
+ "license": "MIT",
16
+ "bugs": {
17
+ "url": "https://github.com/FoxyStar-Studios/scripting-libraries/issues"
18
+ },
19
+ "main": "./script/index.js",
20
+ "module": "./esm/index.js",
21
+ "exports": {
22
+ ".": {
23
+ "import": "./esm/index.js",
24
+ "require": "./script/index.js"
25
+ }
26
+ },
27
+ "$schema": "https://json.schemastore.org/package.json",
28
+ "type": "module",
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@foxystar/math": "^0.1.3"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.9.0"
37
+ },
38
+ "_generatedBy": "dnt@0.40.0"
39
+ }
@@ -0,0 +1,6 @@
1
+ export default class LRUCache<K, V> extends Map<K, V> {
2
+ private maxSize;
3
+ constructor(maxSize: number);
4
+ get(key: K): V | undefined;
5
+ set(key: K, value: V): this;
6
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class LRUCache extends Map {
4
+ constructor(maxSize) {
5
+ super();
6
+ Object.defineProperty(this, "maxSize", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: maxSize
11
+ });
12
+ }
13
+ get(key) {
14
+ const value = super.get(key);
15
+ if (value !== undefined) {
16
+ super.delete(key);
17
+ super.set(key, value);
18
+ }
19
+ return value;
20
+ }
21
+ set(key, value) {
22
+ if (this.has(key)) {
23
+ super.delete(key);
24
+ }
25
+ super.set(key, value);
26
+ if (this.size > this.maxSize) {
27
+ const firstKey = this.keys().next().value;
28
+ super.delete(firstKey);
29
+ }
30
+ return this;
31
+ }
32
+ }
33
+ exports.default = LRUCache;
@@ -0,0 +1,12 @@
1
+ import { ExprBase } from "../parser/expression.js";
2
+ declare class MolangError extends Error {
3
+ constructor(message: string, start: number, end: number, source: string);
4
+ private static formatError;
5
+ }
6
+ export declare class MolangParseError extends MolangError {
7
+ constructor(message: string, position: number, source: string);
8
+ }
9
+ export declare class MolangRuntimeError extends MolangError {
10
+ constructor(message: string, expr: ExprBase, source: string);
11
+ }
12
+ export {};