kei-lisp 2.0.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/dist/cli.cjs ADDED
@@ -0,0 +1,3051 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // node_modules/.pnpm/tsup@8.5.1_postcss@8.5.14_typescript@5.9.3_yaml@2.8.4/node_modules/tsup/assets/cjs_shims.js
27
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
28
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
29
+
30
+ // package.json
31
+ var package_default = {
32
+ name: "kei-lisp",
33
+ version: "2.0.0",
34
+ description: "A Lisp interpreter implemented in TypeScript",
35
+ author: "Keisuke Ikeda",
36
+ license: "MIT",
37
+ type: "module",
38
+ sideEffects: false,
39
+ keywords: [
40
+ "lisp",
41
+ "interpreter",
42
+ "typescript",
43
+ "repl",
44
+ "functional-programming",
45
+ "cli"
46
+ ],
47
+ homepage: "https://github.com/ike-keichan/kei-lisp#readme",
48
+ bugs: {
49
+ url: "https://github.com/ike-keichan/kei-lisp/issues"
50
+ },
51
+ repository: {
52
+ type: "git",
53
+ url: "git+https://github.com/ike-keichan/kei-lisp.git"
54
+ },
55
+ main: "./dist/index.js",
56
+ exports: {
57
+ ".": {
58
+ import: {
59
+ types: "./dist/index.d.ts",
60
+ default: "./dist/index.js"
61
+ },
62
+ require: {
63
+ types: "./dist/index.d.cts",
64
+ default: "./dist/index.cjs"
65
+ }
66
+ }
67
+ },
68
+ types: "./dist/index.d.ts",
69
+ bin: {
70
+ "kei-lisp": "./dist/cli.cjs"
71
+ },
72
+ files: [
73
+ "dist/"
74
+ ],
75
+ scripts: {
76
+ prepare: "pnpm build",
77
+ prepublishOnly: "pnpm check && pnpm test",
78
+ build: "tsup",
79
+ start: "node dist/cli.cjs",
80
+ test: "vitest run",
81
+ "test:watch": "vitest",
82
+ doc: "typedoc",
83
+ check: "run-s check:*",
84
+ "check:format": 'prettier "./src/**/*.ts" "./examples/**/*.ts" --check',
85
+ "check:format-config": 'prettier "./*.{js,mjs,json,md}" "./docs/**/*.md" "./.github/**/*.yml" "./configs/**/*.mjs" --check',
86
+ "check:lint": 'eslint "./src/**/*.ts" "./examples/**/*.ts"',
87
+ "check:lint-config": 'eslint ./*.{js,mjs} "./configs/**/*.mjs"',
88
+ "check:spell": 'cspell "./src/**/*.ts" "./examples/**/*.ts"',
89
+ "check:spell-config": 'cspell "./*.{js,mjs,json,md}" "./docs/**/*.md" "./.github/**/*.yml" "./configs/**/*.mjs"',
90
+ fix: "run-s fix:*",
91
+ "fix:format": 'prettier "./src/**/*.ts" "./examples/**/*.ts" --write',
92
+ "fix:format-config": 'prettier "./*.{js,mjs,json,md}" "./docs/**/*.md" "./.github/**/*.yml" "./configs/**/*.mjs" --write',
93
+ "fix:lint": 'eslint "./src/**/*.ts" "./examples/**/*.ts" --fix',
94
+ "fix:lint-config": 'eslint ./*.{js,mjs} "./configs/**/*.mjs" --fix'
95
+ },
96
+ devDependencies: {
97
+ "@eslint/js": "^10.0.1",
98
+ "@types/node": "^25.6.0",
99
+ "@vitest/eslint-plugin": "^1.6.16",
100
+ cspell: "^9.8.0",
101
+ eslint: "^10.3.0",
102
+ "eslint-config-prettier": "^10.1.8",
103
+ "eslint-import-resolver-typescript": "^4.4.4",
104
+ "eslint-plugin-import-x": "^4.16.2",
105
+ "eslint-plugin-n": "^17.24.0",
106
+ "eslint-plugin-security": "^4.0.0",
107
+ "eslint-plugin-sonarjs": "^4.0.3",
108
+ "eslint-plugin-unicorn": "^63.0.0",
109
+ "eslint-plugin-unused-imports": "^4.4.1",
110
+ globals: "^16.5.0",
111
+ "npm-run-all": "^4.1.5",
112
+ prettier: "^3.8.3",
113
+ tsup: "^8.5.1",
114
+ typedoc: "^0.28.19",
115
+ typescript: "^5.9.3",
116
+ "typescript-eslint": "^8.59.2",
117
+ vitest: "^4.1.5"
118
+ },
119
+ engines: {
120
+ node: ">=24.0.0"
121
+ },
122
+ packageManager: "pnpm@10.33.3"
123
+ };
124
+
125
+ // src/LispInterpreter/index.ts
126
+ var import_node_module = require("module");
127
+
128
+ // src/runtime/Table/index.ts
129
+ var Table = class _Table extends Map {
130
+ source;
131
+ root;
132
+ /**
133
+ * Constructor.
134
+ * @param aTable the environment in which this environment was created
135
+ */
136
+ constructor(aTable = null) {
137
+ super();
138
+ this.source = aTable;
139
+ this.root = aTable == null ? true : false;
140
+ }
141
+ /**
142
+ * Clones this Table and returns the clone.
143
+ */
144
+ clone() {
145
+ const aTable = new _Table(this);
146
+ for (const key of this.keys()) {
147
+ const value = Cons.cloneValue(this.get(key));
148
+ if (value == null) {
149
+ throw new Error("RuntimeException!");
150
+ }
151
+ aTable.set(key, value);
152
+ }
153
+ return aTable;
154
+ }
155
+ /**
156
+ * Returns whether anything is bound to the given property (key).
157
+ */
158
+ has(aSymbol) {
159
+ if (super.has(aSymbol)) {
160
+ return true;
161
+ }
162
+ if (this.isRoot()) {
163
+ return false;
164
+ }
165
+ return this.source.has(aSymbol);
166
+ }
167
+ /**
168
+ * Returns whether this instance equals the given object.
169
+ */
170
+ equals(anObject) {
171
+ return Map.prototype.equals(anObject);
172
+ }
173
+ /**
174
+ * Returns the value bound to the given interpreted symbol.
175
+ */
176
+ get(aSymbol) {
177
+ if (super.has(aSymbol)) {
178
+ return super.get(aSymbol);
179
+ }
180
+ if (this.isRoot()) {
181
+ return null;
182
+ }
183
+ return this.source.get(aSymbol);
184
+ }
185
+ /**
186
+ * Returns whether this instance is the root of the environment chain.
187
+ */
188
+ isRoot() {
189
+ return this.root;
190
+ }
191
+ /**
192
+ * Reassigns the symbol bound in the innermost scope (equivalent to Common Lisp's setq).
193
+ * If a binding exists in the current scope, update it and return; otherwise recurse into the parent scope.
194
+ */
195
+ setIfExist(aSymbol, anObject) {
196
+ if (super.has(aSymbol)) {
197
+ this.set(aSymbol, anObject);
198
+ return anObject;
199
+ }
200
+ if (this.isRoot()) {
201
+ return null;
202
+ }
203
+ return this.source.setIfExist(aSymbol, anObject);
204
+ }
205
+ /**
206
+ * Sets whether this instance is the root of its environment chain.
207
+ */
208
+ setRoot(aBoolean) {
209
+ this.root = aBoolean;
210
+ return null;
211
+ }
212
+ /**
213
+ * Sets the parent environment.
214
+ */
215
+ setSource(aTable) {
216
+ this.source = aTable;
217
+ return null;
218
+ }
219
+ /**
220
+ * Returns a formatted string representation of this instance.
221
+ */
222
+ toString() {
223
+ return "#<Environment>";
224
+ }
225
+ };
226
+
227
+ // src/value/InterpretedSymbol/index.ts
228
+ var InterpretedSymbol = class _InterpretedSymbol {
229
+ /**
230
+ * Table that stores InterpretedSymbol instances (lazily initialized to avoid a circular dependency).
231
+ */
232
+ static #intern = null;
233
+ static get table() {
234
+ this.#intern ??= new Table();
235
+ return this.#intern;
236
+ }
237
+ name;
238
+ /**
239
+ * Constructor.
240
+ * @param name printed name
241
+ */
242
+ constructor(name = "null") {
243
+ this.name = name;
244
+ }
245
+ /**
246
+ * Compares this interpreted symbol with the given one by printed name.
247
+ * @param aSymbol the symbol to compare against
248
+ * @return the difference in string length
249
+ */
250
+ compareTo(aSymbol) {
251
+ const left = this.name.codePointAt(0) ?? 0;
252
+ const right = aSymbol.name.codePointAt(0) ?? 0;
253
+ let aNumber = left < right ? aSymbol.name.length - left : left - aSymbol.name.length;
254
+ aNumber = left === right ? 0 : aNumber;
255
+ return aNumber;
256
+ }
257
+ /**
258
+ * Returns whether this symbol equals the given object.
259
+ */
260
+ equals(anObject) {
261
+ return this === anObject;
262
+ }
263
+ /**
264
+ * Returns the same interpreted symbol for a given printed name.
265
+ * @param aString printed name
266
+ */
267
+ static of(aString) {
268
+ let aSymbol = this.table.get(aString);
269
+ if (aSymbol == null) {
270
+ aSymbol = new _InterpretedSymbol(aString);
271
+ this.table.set(aString, aSymbol);
272
+ }
273
+ return aSymbol;
274
+ }
275
+ /**
276
+ * Returns the string representation of this symbol.
277
+ */
278
+ toString() {
279
+ return this.name;
280
+ }
281
+ };
282
+
283
+ // src/value/Loop/index.ts
284
+ var Loop = class {
285
+ aCons;
286
+ length;
287
+ index;
288
+ /**
289
+ * Constructor.
290
+ * @param aCons the Cons to iterate over
291
+ */
292
+ constructor(aCons) {
293
+ this.aCons = aCons;
294
+ this.length = aCons.length();
295
+ this.index = 1;
296
+ }
297
+ /**
298
+ * Returns this instance.
299
+ */
300
+ iterator() {
301
+ return this;
302
+ }
303
+ /**
304
+ * Returns whether a next element exists.
305
+ */
306
+ hasNext() {
307
+ return this.index <= this.length;
308
+ }
309
+ /**
310
+ * Returns the next element.
311
+ */
312
+ next() {
313
+ const anObject = this.aCons.nth(this.index);
314
+ this.remove();
315
+ return anObject;
316
+ }
317
+ /**
318
+ * Implementation of the iterable protocol.
319
+ * Enables iteration with for...of and similar constructs.
320
+ */
321
+ [Symbol.iterator]() {
322
+ return {
323
+ next: () => {
324
+ if (this.index <= this.length) {
325
+ const nextValue = this.aCons.nth(this.index);
326
+ this.remove();
327
+ return { value: nextValue, done: false };
328
+ }
329
+ return { done: true };
330
+ }
331
+ };
332
+ }
333
+ /**
334
+ * Implementation of the async iterable protocol.
335
+ * Enables iteration with for await...of and similar constructs.
336
+ */
337
+ [Symbol.asyncIterator]() {
338
+ return {
339
+ next: () => {
340
+ if (this.index <= this.length) {
341
+ const nextValue = this.aCons.nth(this.index);
342
+ this.remove();
343
+ return Promise.resolve({ value: nextValue, done: false });
344
+ }
345
+ return Promise.resolve({ done: true });
346
+ }
347
+ };
348
+ }
349
+ /**
350
+ * Advances to the next element.
351
+ */
352
+ remove() {
353
+ this.index++;
354
+ return null;
355
+ }
356
+ };
357
+
358
+ // src/parser/IntStream/index.ts
359
+ var IntStream = class {
360
+ /**
361
+ * Builds and returns an array of consecutive integers from start to afterEnd (exclusive).
362
+ */
363
+ static range(start, afterEnd) {
364
+ const end = afterEnd - 1;
365
+ return this.rangeClosed(start, end);
366
+ }
367
+ /**
368
+ * Builds and returns an array of consecutive integers from start to end (inclusive).
369
+ */
370
+ static rangeClosed(start, end) {
371
+ const range = end - start + 1;
372
+ return Array.from({ length: range }, () => start++);
373
+ }
374
+ };
375
+
376
+ // src/parser/NextState/index.ts
377
+ var NextState = class {
378
+ automaton = null;
379
+ nextState;
380
+ method;
381
+ methodName;
382
+ /**
383
+ * Constructor.
384
+ */
385
+ constructor(aNumber, aString) {
386
+ this.nextState = aNumber;
387
+ this.method = null;
388
+ this.methodName = aString;
389
+ }
390
+ /**
391
+ * Invokes the method corresponding to the input character and returns the resulting token number.
392
+ */
393
+ next(anAutomaton) {
394
+ this.automaton = anAutomaton;
395
+ if (this.methodName == null) {
396
+ return Number(this.nextState);
397
+ }
398
+ if (this.method == null) {
399
+ try {
400
+ this.method = this.automaton[this.methodName];
401
+ } catch {
402
+ throw new Error("Not Found Method: " + this.methodName);
403
+ }
404
+ }
405
+ let aNumber = -1;
406
+ try {
407
+ if (this.nextState != null) {
408
+ aNumber = this.nextState;
409
+ }
410
+ const anObject = this.automaton[this.methodName]();
411
+ if (anObject != null) {
412
+ aNumber = Number(anObject);
413
+ }
414
+ } catch {
415
+ throw new Error("Not Invoke Method: " + this.methodName);
416
+ }
417
+ return aNumber;
418
+ }
419
+ };
420
+
421
+ // src/parser/Parser/index.ts
422
+ var PEEKCOUNT = 10;
423
+ var SYNTAX_ERROR = "Syntax Error!";
424
+ var Parser = class _Parser {
425
+ stream;
426
+ token;
427
+ tokenString;
428
+ states;
429
+ state;
430
+ nexts;
431
+ /**
432
+ * Constructor.
433
+ * @param aString the string to parse
434
+ */
435
+ constructor(aString) {
436
+ this.stream = aString[Symbol.iterator]();
437
+ this.token = null;
438
+ this.tokenString = "";
439
+ this.states = /* @__PURE__ */ new Map();
440
+ this.state = 0;
441
+ this.nexts = Array.from({ length: PEEKCOUNT + 1 }, () => null);
442
+ this.initializeStateTransitionTable();
443
+ let count = 0;
444
+ while (count++ < PEEKCOUNT) {
445
+ this.nextChar();
446
+ }
447
+ }
448
+ /**
449
+ * Returns whether this is the last element.
450
+ */
451
+ atEnd() {
452
+ return this.peekChar() == null;
453
+ }
454
+ /**
455
+ * Concatenates the current character into the token string.
456
+ */
457
+ concatCharacter() {
458
+ this.tokenString = this.tokenString.concat(String(this.nexts[0]));
459
+ return null;
460
+ }
461
+ /**
462
+ * Parses a single character of the input string.
463
+ */
464
+ input(aCharacter = this.nextChar()) {
465
+ const inputs = this.states.get(this.state);
466
+ const codePoint = aCharacter.codePointAt(0) ?? 0;
467
+ const aNumber = inputs.has(String(codePoint)) ? inputs.get(String(codePoint)).next(this) : inputs.get(String(128)).next(this);
468
+ if (aNumber < 0) {
469
+ throw new Error(SYNTAX_ERROR);
470
+ }
471
+ this.state = aNumber;
472
+ return this.token;
473
+ }
474
+ /**
475
+ * Returns the next character to be parsed from the input string.
476
+ */
477
+ nextChar() {
478
+ let aCharacter = null;
479
+ try {
480
+ const aNumber = this.stream.next().value?.codePointAt(0) ?? -1;
481
+ if (aNumber >= 0) {
482
+ aCharacter = String.fromCodePoint(aNumber);
483
+ }
484
+ } catch {
485
+ throw new Error("Read Error!");
486
+ }
487
+ let count = 0;
488
+ while (count < PEEKCOUNT) {
489
+ this.nexts[count] = this.nexts[count + 1];
490
+ count++;
491
+ }
492
+ this.nexts[count] = aCharacter;
493
+ return this.nexts[0];
494
+ }
495
+ /**
496
+ * Determines and returns the next token.
497
+ */
498
+ nextToken() {
499
+ this.token = null;
500
+ let token = null;
501
+ while (!this.atEnd()) {
502
+ if (this.state === 0 && token != null) {
503
+ break;
504
+ }
505
+ token = this.input();
506
+ }
507
+ if (this.atEnd() && this.state !== 0) {
508
+ throw new Error(SYNTAX_ERROR);
509
+ }
510
+ this.tokenString = "";
511
+ return token;
512
+ }
513
+ /**
514
+ * Instantiates and returns a NextState.
515
+ */
516
+ nextState(aNumber, aString) {
517
+ return new NextState(aNumber, aString);
518
+ }
519
+ /**
520
+ * Parses the given string and returns the result.
521
+ */
522
+ static parse(aString) {
523
+ return new _Parser(aString).nextToken();
524
+ }
525
+ /**
526
+ * Returns the next character if one exists.
527
+ */
528
+ peekChar(aNumber = 1) {
529
+ if (aNumber > this.nexts.length) {
530
+ throw new Error("Read Error!");
531
+ }
532
+ return this.nexts[aNumber];
533
+ }
534
+ /**
535
+ * Concatenates characters; invoked from NextState.
536
+ */
537
+ concat() {
538
+ this.concatCharacter();
539
+ return null;
540
+ }
541
+ /**
542
+ * Concatenates the current character after translating common escape sequences
543
+ * (`\n`, `\t`, `\r`, `\\`, `\"`) into their actual characters. Invoked from NextState
544
+ * inside a string literal after a backslash. Unknown escapes pass through as the
545
+ * literal character (e.g. `\x` becomes `x`).
546
+ */
547
+ escapeConcat() {
548
+ const c = String(this.nexts[0]);
549
+ const map = {
550
+ n: "\n",
551
+ t: " ",
552
+ r: "\r",
553
+ "\\": "\\",
554
+ '"': '"'
555
+ };
556
+ this.tokenString = this.tokenString.concat(map[c] ?? c);
557
+ return null;
558
+ }
559
+ /**
560
+ * Returns the token number for a Number-type (double-precision floating point: pseudo-Double); invoked from NextState.
561
+ */
562
+ doubleToken() {
563
+ this.concat();
564
+ if (this.rightParen()) {
565
+ this.tokenToDouble();
566
+ return 0;
567
+ }
568
+ return 3;
569
+ }
570
+ /**
571
+ * Returns the token number for a Number-type (double-precision floating point: pseudo-Double); invoked from NextState.
572
+ */
573
+ doubleTokenAUX() {
574
+ this.concat();
575
+ if (this.rightParen()) {
576
+ this.tokenToDouble();
577
+ return 0;
578
+ }
579
+ return 5;
580
+ }
581
+ /**
582
+ * Returns the token number for a Number-type (integer: pseudo-Integer); invoked from NextState.
583
+ */
584
+ integerToken() {
585
+ this.concat();
586
+ if (this.rightParen()) {
587
+ this.tokenToInteger();
588
+ return 0;
589
+ }
590
+ return 2;
591
+ }
592
+ /**
593
+ * Converts the token into a list (Cons) and returns the token number for a list (Cons); invoked from NextState.
594
+ */
595
+ parseList() {
596
+ this.skippingSpaces();
597
+ if (this.rightParen()) {
598
+ this.nextChar();
599
+ this.token = Cons.nil;
600
+ } else {
601
+ this.token = this.parseListAUX();
602
+ }
603
+ return 0;
604
+ }
605
+ /**
606
+ * Helper that converts the token into a list (Cons); invoked from NextState.
607
+ */
608
+ parseListAUX() {
609
+ this.skippingSpaces();
610
+ if (this.peekChar() === ";") {
611
+ while (this.peekChar() !== "\n" && this.peekChar() != null) {
612
+ this.nextChar();
613
+ }
614
+ this.nextChar();
615
+ this.skippingSpaces();
616
+ }
617
+ if (this.rightParen()) {
618
+ this.nextChar();
619
+ return Cons.nil;
620
+ } else if (this.peekChar() === ".") {
621
+ this.nextChar();
622
+ this.state = 0;
623
+ const cdr = this.nextToken();
624
+ this.skippingSpaces();
625
+ if (!this.rightParen()) {
626
+ throw new Error(SYNTAX_ERROR);
627
+ }
628
+ this.nextChar();
629
+ return cdr;
630
+ } else {
631
+ this.state = 0;
632
+ return new Cons(this.nextToken(), this.parseListAUX());
633
+ }
634
+ }
635
+ /**
636
+ * Recognizes a quote, wraps the token into a list (Cons), and returns the token number; invoked from NextState.
637
+ */
638
+ quote() {
639
+ const anObject = new Cons(this.nextToken(), Cons.nil);
640
+ this.token = new Cons(InterpretedSymbol.of("quote"), anObject);
641
+ return 0;
642
+ }
643
+ /**
644
+ * Returns the token number for a quote or for a 0-origin String-type (pseudo-Character); invoked from NextState.
645
+ */
646
+ quoteOrChar() {
647
+ let aNumber = this.peekChar() === "\\" ? 3 : 2;
648
+ aNumber = this.peekChar(aNumber) === "'" ? 11 : this.quote();
649
+ return aNumber;
650
+ }
651
+ /**
652
+ * Detects a right parenthesis (')', ']', '}') and returns the result; invoked from NextState.
653
+ */
654
+ rightParen() {
655
+ return this.peekChar() === ")" || this.peekChar() === "]" || this.peekChar() === "}";
656
+ }
657
+ /**
658
+ * Returns the token number for a sign symbol ('+', '-'); invoked from NextState.
659
+ */
660
+ sign() {
661
+ this.concat();
662
+ if (this.rightParen()) {
663
+ this.tokenToSymbol();
664
+ return 0;
665
+ }
666
+ return 7;
667
+ }
668
+ /**
669
+ * Skips whitespace; invoked from NextState.
670
+ */
671
+ skippingSpaces() {
672
+ while (this.nexts[1] === String.fromCodePoint(9) || this.nexts[1] === String.fromCodePoint(10) || this.nexts[1] === String.fromCodePoint(11) || this.nexts[1] === String.fromCodePoint(12) || this.nexts[1] === String.fromCodePoint(13) || this.nexts[1] === String.fromCodePoint(32)) {
673
+ this.nextChar();
674
+ }
675
+ return null;
676
+ }
677
+ /**
678
+ * Returns the token number for an InterpretedSymbol; invoked from NextState.
679
+ */
680
+ symbolToken() {
681
+ this.concat();
682
+ if (this.rightParen()) {
683
+ this.tokenToSymbol();
684
+ return 0;
685
+ }
686
+ return 8;
687
+ }
688
+ /**
689
+ * Converts the token into a 0-origin String-type (pseudo-Character); invoked from NextState.
690
+ */
691
+ tokenToCharacter() {
692
+ this.token = this.tokenString.charAt(0);
693
+ return null;
694
+ }
695
+ /**
696
+ * Converts the token into a Number-type (double-precision floating point: pseudo-Double); invoked from NextState.
697
+ */
698
+ tokenToDouble() {
699
+ this.token = Number(this.tokenString);
700
+ return null;
701
+ }
702
+ /**
703
+ * Converts the token into a Number-type (double-precision floating point: pseudo-Double); invoked from NextState.
704
+ */
705
+ tokenToDoubleAUX() {
706
+ this.concat();
707
+ this.token = Number(this.tokenString);
708
+ return null;
709
+ }
710
+ /**
711
+ * Converts the token into a Number-type (integer: pseudo-Integer); invoked from NextState.
712
+ */
713
+ tokenToInteger() {
714
+ const aCharacter = this.tokenString[0];
715
+ if (aCharacter === "+") {
716
+ this.tokenString = this.tokenString.slice(1);
717
+ }
718
+ this.token = Number(this.tokenString);
719
+ return null;
720
+ }
721
+ /**
722
+ * Converts the token into a String-type; invoked from NextState.
723
+ */
724
+ tokenToString() {
725
+ this.token = this.tokenString;
726
+ return null;
727
+ }
728
+ /**
729
+ * Converts the token into an InterpretedSymbol; invoked from NextState.
730
+ */
731
+ tokenToSymbol() {
732
+ this.token = InterpretedSymbol.of(this.tokenString);
733
+ if (this.token === InterpretedSymbol.of("nil")) {
734
+ this.token = Cons.nil;
735
+ }
736
+ return null;
737
+ }
738
+ /**
739
+ * Builds the lookup table that maps character codes to their corresponding methods (tokens).
740
+ */
741
+ initializeStateTransitionTable() {
742
+ let aTable = /* @__PURE__ */ new Map();
743
+ for (const index of IntStream.rangeClosed(0, 8))
744
+ aTable.set(String(index), this.nextState(-1, null));
745
+ for (const index of IntStream.rangeClosed(9, 13))
746
+ aTable.set(String(index), this.nextState(0, null));
747
+ for (const index of IntStream.rangeClosed(14, 31))
748
+ aTable.set(String(index), this.nextState(-1, null));
749
+ aTable.set(String(32), this.nextState(0, null));
750
+ aTable.set(String(33), this.nextState(8, "symbolToken"));
751
+ aTable.set(String(34), this.nextState(9, null));
752
+ aTable.set(String(35), this.nextState(8, "symbolToken"));
753
+ aTable.set(String(36), this.nextState(8, "symbolToken"));
754
+ aTable.set(String(37), this.nextState(8, "symbolToken"));
755
+ aTable.set(String(38), this.nextState(8, "symbolToken"));
756
+ aTable.set(String(39), this.nextState(-1, "quoteOrChar"));
757
+ aTable.set(String(40), this.nextState(-1, "parseList"));
758
+ aTable.set(String(41), this.nextState(-1, null));
759
+ aTable.set(String(42), this.nextState(8, "symbolToken"));
760
+ aTable.set(String(43), this.nextState(7, "sign"));
761
+ aTable.set(String(44), this.nextState(8, "symbolToken"));
762
+ aTable.set(String(45), this.nextState(7, "sign"));
763
+ aTable.set(String(46), this.nextState(-1, null));
764
+ aTable.set(String(47), this.nextState(8, "symbolToken"));
765
+ for (const index of IntStream.rangeClosed(48, 57))
766
+ aTable.set(String(index), this.nextState(2, "integerToken"));
767
+ for (const index of IntStream.rangeClosed(58, 90))
768
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
769
+ aTable.set(String(59), this.nextState(1, null));
770
+ aTable.set(String(91), this.nextState(-1, "parseList"));
771
+ aTable.set(String(92), this.nextState(-1, null));
772
+ aTable.set(String(93), this.nextState(-1, null));
773
+ aTable.set(String(94), this.nextState(8, "symbolToken"));
774
+ aTable.set(String(95), this.nextState(8, "symbolToken"));
775
+ aTable.set(String(96), this.nextState(0, "quote"));
776
+ for (const index of IntStream.rangeClosed(97, 122))
777
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
778
+ aTable.set(String(123), this.nextState(-1, "parseList"));
779
+ aTable.set(String(124), this.nextState(8, "symbolToken"));
780
+ aTable.set(String(125), this.nextState(-1, null));
781
+ aTable.set(String(126), this.nextState(8, "symbolToken"));
782
+ aTable.set(String(127), this.nextState(-1, null));
783
+ aTable.set(String(128), this.nextState(-1, null));
784
+ this.states.set(0, aTable);
785
+ aTable = /* @__PURE__ */ new Map();
786
+ for (const index of IntStream.rangeClosed(0, 8))
787
+ aTable.set(String(index), this.nextState(-1, null));
788
+ aTable.set(String(10), this.nextState(0, null));
789
+ aTable.set(String(13), this.nextState(0, null));
790
+ for (const index of IntStream.rangeClosed(14, 31))
791
+ aTable.set(String(index), this.nextState(-1, null));
792
+ aTable.set(String(127), this.nextState(-1, null));
793
+ aTable.set(String(128), this.nextState(1, null));
794
+ this.states.set(1, aTable);
795
+ aTable = /* @__PURE__ */ new Map();
796
+ for (const index of IntStream.rangeClosed(9, 13))
797
+ aTable.set(String(index), this.nextState(0, "tokenToInteger"));
798
+ aTable.set(String(32), this.nextState(0, "tokenToInteger"));
799
+ aTable.set(String(46), this.nextState(3, "doubleToken"));
800
+ for (const index of IntStream.rangeClosed(48, 57))
801
+ aTable.set(String(index), this.nextState(2, "integerToken"));
802
+ aTable.set(String(69), this.nextState(4, "concat"));
803
+ aTable.set(String(101), this.nextState(4, "concat"));
804
+ aTable.set(String(128), this.nextState(-1, null));
805
+ this.states.set(2, aTable);
806
+ aTable = /* @__PURE__ */ new Map();
807
+ for (const index of IntStream.rangeClosed(9, 13))
808
+ aTable.set(String(index), this.nextState(0, "tokenToDouble"));
809
+ aTable.set(String(32), this.nextState(0, "tokenToDouble"));
810
+ for (const index of IntStream.rangeClosed(48, 57))
811
+ aTable.set(String(index), this.nextState(3, "doubleToken"));
812
+ aTable.set(String(68), this.nextState(0, "tokenToDoubleAUX"));
813
+ aTable.set(String(69), this.nextState(4, "concat"));
814
+ aTable.set(String(100), this.nextState(0, "tokenToDoubleAUX"));
815
+ aTable.set(String(101), this.nextState(4, "concat"));
816
+ aTable.set(String(128), this.nextState(-1, null));
817
+ this.states.set(3, aTable);
818
+ aTable = /* @__PURE__ */ new Map();
819
+ aTable.set(String(43), this.nextState(6, "concat"));
820
+ aTable.set(String(45), this.nextState(6, "concat"));
821
+ for (const index of IntStream.rangeClosed(48, 57))
822
+ aTable.set(String(index), this.nextState(5, "doubleTokenAUX"));
823
+ aTable.set(String(128), this.nextState(-1, null));
824
+ this.states.set(4, aTable);
825
+ aTable = /* @__PURE__ */ new Map();
826
+ for (const index of IntStream.rangeClosed(9, 13))
827
+ aTable.set(String(index), this.nextState(0, "tokenToDouble"));
828
+ aTable.set(String(32), this.nextState(0, "tokenToDouble"));
829
+ for (const index of IntStream.rangeClosed(48, 57))
830
+ aTable.set(String(index), this.nextState(5, "doubleTokenAUX"));
831
+ aTable.set(String(128), this.nextState(-1, null));
832
+ this.states.set(5, aTable);
833
+ aTable = /* @__PURE__ */ new Map();
834
+ for (const index of IntStream.rangeClosed(48, 57))
835
+ aTable.set(String(index), this.nextState(5, "doubleTokenAUX"));
836
+ aTable.set(String(128), this.nextState(-1, null));
837
+ this.states.set(6, aTable);
838
+ aTable = /* @__PURE__ */ new Map();
839
+ for (const index of IntStream.rangeClosed(9, 13))
840
+ aTable.set(String(index), this.nextState(0, "tokenToSymbol"));
841
+ aTable.set(String(32), this.nextState(0, "tokenToSymbol"));
842
+ aTable.set(String(33), this.nextState(8, "symbolToken"));
843
+ for (const index of IntStream.rangeClosed(35, 38))
844
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
845
+ for (const index of IntStream.rangeClosed(42, 45))
846
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
847
+ aTable.set(String(47), this.nextState(8, "symbolToken"));
848
+ for (const index of IntStream.rangeClosed(48, 57))
849
+ aTable.set(String(index), this.nextState(2, "integerToken"));
850
+ for (const index of IntStream.rangeClosed(58, 90))
851
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
852
+ aTable.set(String(94), this.nextState(8, "symbolToken"));
853
+ aTable.set(String(95), this.nextState(8, "symbolToken"));
854
+ for (const index of IntStream.rangeClosed(97, 122))
855
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
856
+ aTable.set(String(124), this.nextState(8, "symbolToken"));
857
+ aTable.set(String(126), this.nextState(8, "symbolToken"));
858
+ aTable.set(String(128), this.nextState(-1, null));
859
+ this.states.set(7, aTable);
860
+ aTable = /* @__PURE__ */ new Map();
861
+ for (const index of IntStream.rangeClosed(9, 13))
862
+ aTable.set(String(index), this.nextState(0, "tokenToSymbol"));
863
+ aTable.set(String(32), this.nextState(0, "tokenToSymbol"));
864
+ aTable.set(String(33), this.nextState(8, "symbolToken"));
865
+ for (const index of IntStream.rangeClosed(35, 38))
866
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
867
+ for (const index of IntStream.rangeClosed(42, 45))
868
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
869
+ aTable.set(String(47), this.nextState(8, "symbolToken"));
870
+ for (const index of IntStream.rangeClosed(48, 57))
871
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
872
+ for (const index of IntStream.rangeClosed(58, 90))
873
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
874
+ aTable.set(String(94), this.nextState(8, "symbolToken"));
875
+ aTable.set(String(95), this.nextState(8, "symbolToken"));
876
+ for (const index of IntStream.rangeClosed(97, 122))
877
+ aTable.set(String(index), this.nextState(8, "symbolToken"));
878
+ aTable.set(String(124), this.nextState(8, "symbolToken"));
879
+ aTable.set(String(126), this.nextState(8, "symbolToken"));
880
+ aTable.set(String(128), this.nextState(-1, null));
881
+ this.states.set(8, aTable);
882
+ aTable = /* @__PURE__ */ new Map();
883
+ for (const index of IntStream.rangeClosed(0, 31))
884
+ aTable.set(String(index), this.nextState(-1, null));
885
+ aTable.set(String(34), this.nextState(0, "tokenToString"));
886
+ aTable.set(String(92), this.nextState(10, null));
887
+ aTable.set(String(127), this.nextState(-1, null));
888
+ aTable.set(String(128), this.nextState(9, "concat"));
889
+ this.states.set(9, aTable);
890
+ aTable = /* @__PURE__ */ new Map();
891
+ for (const index of IntStream.rangeClosed(0, 31))
892
+ aTable.set(String(index), this.nextState(-1, null));
893
+ aTable.set(String(127), this.nextState(-1, null));
894
+ aTable.set(String(128), this.nextState(9, "escapeConcat"));
895
+ this.states.set(10, aTable);
896
+ aTable = /* @__PURE__ */ new Map();
897
+ for (const index of IntStream.rangeClosed(32, 38))
898
+ aTable.set(String(index), this.nextState(12, "concat"));
899
+ for (const index of IntStream.rangeClosed(40, 91))
900
+ aTable.set(String(index), this.nextState(12, "concat"));
901
+ aTable.set(String(92), this.nextState(13, null));
902
+ for (const index of IntStream.rangeClosed(93, 126))
903
+ aTable.set(String(index), this.nextState(12, "concat"));
904
+ aTable.set(String(128), this.nextState(-1, null));
905
+ this.states.set(11, aTable);
906
+ aTable = /* @__PURE__ */ new Map();
907
+ aTable.set(String(39), this.nextState(0, "tokenToCharacter"));
908
+ aTable.set(String(128), this.nextState(-1, null));
909
+ this.states.set(12, aTable);
910
+ aTable = /* @__PURE__ */ new Map();
911
+ for (const index of IntStream.rangeClosed(32, 38))
912
+ aTable.set(String(index), this.nextState(12, "concat"));
913
+ for (const index of IntStream.rangeClosed(40, 126))
914
+ aTable.set(String(index), this.nextState(12, "concat"));
915
+ aTable.set(String(128), this.nextState(-1, null));
916
+ this.states.set(13, aTable);
917
+ return null;
918
+ }
919
+ };
920
+
921
+ // src/value/Cons/index.ts
922
+ var Cons = class _Cons {
923
+ static nil = new _Cons();
924
+ car;
925
+ cdr;
926
+ /**
927
+ * Constructor.
928
+ * @constructor
929
+ * @param car the car; defaults to nil when no argument is given.
930
+ * @param cdr the cdr; defaults to nil when no argument is given.
931
+ */
932
+ constructor(car = _Cons.nil, cdr = _Cons.nil) {
933
+ this.car = car;
934
+ this.cdr = cdr;
935
+ }
936
+ /**
937
+ * Appends the given element to the end of this Cons.
938
+ * @param anObject the object to append
939
+ * @return the Cons with the element appended
940
+ */
941
+ add(anObject) {
942
+ const aCons = new _Cons(anObject, _Cons.nil);
943
+ return this.nconc(aCons);
944
+ }
945
+ /**
946
+ * Clones this Cons and returns the clone.
947
+ * @return the cloned Cons
948
+ */
949
+ clone() {
950
+ return new _Cons(_Cons.cloneValue(this.car), _Cons.cloneValue(this.cdr));
951
+ }
952
+ /**
953
+ * Clones the given value (a Cons element) and returns the clone.
954
+ * @param value a Cons element
955
+ * @return the cloned element
956
+ */
957
+ static cloneValue(value) {
958
+ if (_Cons.isCons(value)) {
959
+ return value.clone();
960
+ }
961
+ if (_Cons.isNil(value)) {
962
+ return _Cons.nil;
963
+ }
964
+ if (_Cons.isNumber(value)) {
965
+ return value;
966
+ }
967
+ if (_Cons.isString(value)) {
968
+ return value;
969
+ }
970
+ if (_Cons.isSymbol(value)) {
971
+ return value;
972
+ }
973
+ if (_Cons.isTable(value)) {
974
+ return value;
975
+ }
976
+ return value;
977
+ }
978
+ /**
979
+ * Returns whether this Cons equals the given object.
980
+ * @param anObject the object to compare against
981
+ * @return a boolean
982
+ */
983
+ equals(anObject) {
984
+ if (_Cons.isCons(anObject)) {
985
+ return this.equalsAUX(this, anObject);
986
+ }
987
+ return false;
988
+ }
989
+ /**
990
+ * Returns whether both arguments are Cons cells and are equal.
991
+ * @param left the object to compare
992
+ * @param right the object to compare
993
+ * @return a boolean
994
+ */
995
+ equalsAUX(left, right) {
996
+ if (left === right) {
997
+ return true;
998
+ }
999
+ if (!(_Cons.isCons(left) && _Cons.isCons(right))) {
1000
+ return false;
1001
+ }
1002
+ if (this.equalsAUX(left.car, right.car)) {
1003
+ return this.equalsAUX(left.cdr, right.cdr);
1004
+ }
1005
+ return false;
1006
+ }
1007
+ /**
1008
+ * Returns whether the given argument is an Atom.
1009
+ */
1010
+ static isAtom(anObject) {
1011
+ return _Cons.isNotCons(anObject);
1012
+ }
1013
+ /**
1014
+ * Returns whether the given argument is a Cons.
1015
+ */
1016
+ static isCons(anObject) {
1017
+ return anObject !== _Cons.nil && anObject instanceof _Cons;
1018
+ }
1019
+ /**
1020
+ * Returns whether the given argument is a List.
1021
+ */
1022
+ static isList(anObject) {
1023
+ return _Cons.isNil(anObject) || _Cons.isCons(anObject);
1024
+ }
1025
+ /**
1026
+ * Returns whether the given argument is Nil.
1027
+ */
1028
+ static isNil(anObject) {
1029
+ return anObject === _Cons.nil;
1030
+ }
1031
+ /**
1032
+ * Returns whether the given argument is not a Cons.
1033
+ */
1034
+ static isNotCons(anObject) {
1035
+ return !_Cons.isCons(anObject);
1036
+ }
1037
+ /**
1038
+ * Returns whether the given argument is not a List.
1039
+ */
1040
+ static isNotList(anObject) {
1041
+ return !_Cons.isList(anObject);
1042
+ }
1043
+ /**
1044
+ * Returns whether the given argument is not Nil.
1045
+ */
1046
+ static isNotNil(anObject) {
1047
+ return !_Cons.isNil(anObject);
1048
+ }
1049
+ /**
1050
+ * Returns whether the given argument is not an interpreted symbol.
1051
+ */
1052
+ static isNotSymbol(anObject) {
1053
+ return !_Cons.isSymbol(anObject);
1054
+ }
1055
+ /**
1056
+ * Returns whether the given argument is a number.
1057
+ */
1058
+ static isNumber(anObject) {
1059
+ return typeof anObject === "number";
1060
+ }
1061
+ /**
1062
+ * Returns whether the given argument is a string.
1063
+ */
1064
+ static isString(anObject) {
1065
+ return typeof anObject === "string";
1066
+ }
1067
+ /**
1068
+ * Returns whether the given argument is an interpreted symbol.
1069
+ */
1070
+ static isSymbol(anObject) {
1071
+ return anObject instanceof InterpretedSymbol;
1072
+ }
1073
+ /**
1074
+ * Returns whether the given argument is an environment.
1075
+ */
1076
+ static isTable(anObject) {
1077
+ return anObject instanceof Table;
1078
+ }
1079
+ /**
1080
+ * Returns the last cell of this Cons.
1081
+ * @return this Cons's last cell
1082
+ */
1083
+ last() {
1084
+ let theCons = new _Cons(_Cons.nil, this);
1085
+ let aCons = this;
1086
+ while (_Cons.isCons(aCons)) {
1087
+ if (!_Cons.isCons(aCons.cdr)) {
1088
+ break;
1089
+ }
1090
+ theCons = theCons.cdr;
1091
+ aCons = aCons.cdr;
1092
+ }
1093
+ return aCons;
1094
+ }
1095
+ /**
1096
+ * Returns an iterator over this Cons.
1097
+ * @return an iterator over this Cons
1098
+ */
1099
+ loop() {
1100
+ return new Loop(this);
1101
+ }
1102
+ /**
1103
+ * Returns the length (depth) of this Cons.
1104
+ * @return the length (depth) of this Cons
1105
+ */
1106
+ length() {
1107
+ let count = 0;
1108
+ let aCons = this;
1109
+ while (_Cons.isCons(aCons)) {
1110
+ count++;
1111
+ aCons = aCons.cdr;
1112
+ }
1113
+ return count;
1114
+ }
1115
+ /**
1116
+ * Concatenates the given Cons and returns this Cons.
1117
+ * @param aCons the Cons to concatenate
1118
+ * @return this Cons
1119
+ */
1120
+ nconc(aCons) {
1121
+ this.last().setCdr(aCons);
1122
+ return this;
1123
+ }
1124
+ /**
1125
+ * Returns the nth element of this Cons.
1126
+ * @param aNumber the index to retrieve
1127
+ * @return the element at the given index
1128
+ */
1129
+ nth(aNumber) {
1130
+ if (aNumber <= 0) {
1131
+ return _Cons.nil;
1132
+ }
1133
+ let count = 1;
1134
+ let aCons = this;
1135
+ while (_Cons.isCons(aCons)) {
1136
+ if (count >= aNumber) {
1137
+ return aCons.car;
1138
+ }
1139
+ count++;
1140
+ aCons = aCons.cdr;
1141
+ }
1142
+ return _Cons.nil;
1143
+ }
1144
+ /**
1145
+ * Lexes the given string into a Cons and returns it.
1146
+ * @param aString the string to lex
1147
+ */
1148
+ static parse(aString) {
1149
+ return Parser.parse(aString);
1150
+ }
1151
+ /**
1152
+ * Sets the car.
1153
+ */
1154
+ setCar(anObject) {
1155
+ this.car = anObject;
1156
+ return null;
1157
+ }
1158
+ /**
1159
+ * Sets the cdr.
1160
+ */
1161
+ setCdr(anObject) {
1162
+ this.cdr = anObject;
1163
+ return null;
1164
+ }
1165
+ /**
1166
+ * Sets both the car and the cdr.
1167
+ */
1168
+ setCons(car, cdr) {
1169
+ this.car = car;
1170
+ this.cdr = cdr;
1171
+ return this;
1172
+ }
1173
+ /**
1174
+ * Returns a formatted string representation of this Cons.
1175
+ */
1176
+ toString() {
1177
+ let aString = "";
1178
+ if (_Cons.isNil(this)) {
1179
+ aString += _Cons.toString(_Cons.nil);
1180
+ } else {
1181
+ aString += "(" + _Cons.toString(this.car);
1182
+ if (_Cons.isNil(this.cdr)) {
1183
+ aString += ")";
1184
+ } else if (this.cdr instanceof _Cons) {
1185
+ let aCons = this.cdr;
1186
+ while (_Cons.isCons(aCons)) {
1187
+ const head = aCons.car;
1188
+ if (!(head instanceof Table)) {
1189
+ aString += " " + _Cons.toString(head);
1190
+ }
1191
+ aCons = aCons.cdr;
1192
+ }
1193
+ aString += _Cons.isNil(aCons) ? ")" : " . " + _Cons.toString(aCons) + ")";
1194
+ } else {
1195
+ aString += " . " + _Cons.toString(this.cdr) + ")";
1196
+ }
1197
+ }
1198
+ return aString;
1199
+ }
1200
+ /**
1201
+ * Returns a formatted string representation of the given object.
1202
+ * @param anObject the object to format
1203
+ */
1204
+ static toString(anObject) {
1205
+ return _Cons.isNil(anObject) ? "nil" : anObject.toString();
1206
+ }
1207
+ };
1208
+
1209
+ // src/runtime/Evaluator/index.ts
1210
+ var import_node_v8 = __toESM(require("v8"), 1);
1211
+ var import_node_vm = __toESM(require("vm"), 1);
1212
+
1213
+ // src/constants/index.ts
1214
+ var cannotApply = (fn, value) => `Can not apply "${fn}" to "${String(value)}"`;
1215
+ var notSymbol = (value) => `"${String(value)}" is not symbol`;
1216
+ var noBinding = (symbol) => `I could find no variable binding for ${String(symbol)}`;
1217
+ var noProcedure = (procedure) => `I could find no procedure description for ${String(procedure)}`;
1218
+ var argumentNotSymbol = (position) => `arguments ${String(position)} is not symbol.`;
1219
+ var SIZES_DO_NOT_MATCH = "sizes do not match.";
1220
+ var SIZE_DO_NOT_MATCH = "size do not match.";
1221
+
1222
+ // src/runtime/Applier/index.ts
1223
+ var SELECT_PRINT_FUNCTION_NOT_DEFINED = "selectPrintFunction is not defined";
1224
+ var Applier = class _Applier {
1225
+ static buildInFunctions = _Applier.setup();
1226
+ static #generateNumber = 0;
1227
+ environment;
1228
+ streamManager;
1229
+ depth;
1230
+ constructor(aTable, aStreamManager, aNumber) {
1231
+ this.environment = new Table(aTable);
1232
+ this.streamManager = aStreamManager;
1233
+ this.depth = aNumber;
1234
+ }
1235
+ abs(args2) {
1236
+ if (Cons.isNumber(args2.car)) {
1237
+ return Math.abs(args2.car);
1238
+ }
1239
+ console.error(cannotApply("abs", args2.car));
1240
+ return Cons.nil;
1241
+ }
1242
+ add(args2) {
1243
+ if (Cons.isNumber(args2.car)) {
1244
+ return this.add_Number(args2.car, args2.cdr);
1245
+ }
1246
+ console.error(cannotApply("add", args2.car));
1247
+ return Cons.nil;
1248
+ }
1249
+ add_Number(init, args2) {
1250
+ let result = init;
1251
+ let aCons = args2;
1252
+ while (Cons.isNotNil(aCons)) {
1253
+ const each = aCons.car;
1254
+ if (Cons.isNumber(each)) {
1255
+ result = result + each;
1256
+ } else {
1257
+ console.error(cannotApply("add", each));
1258
+ return Cons.nil;
1259
+ }
1260
+ aCons = aCons.cdr;
1261
+ }
1262
+ return result;
1263
+ }
1264
+ static apply(procedure, args2, environment, aStreamManager, depth) {
1265
+ return new _Applier(environment, aStreamManager, depth).apply(procedure, args2);
1266
+ }
1267
+ apply(procedure, args2) {
1268
+ if (Cons.isSymbol(procedure)) {
1269
+ return this.selectProcedure(procedure, args2);
1270
+ }
1271
+ return this.entrustEvaluator(procedure, args2);
1272
+ }
1273
+ assoc(args2) {
1274
+ const target = args2.car;
1275
+ if (Cons.isNotCons(args2.nth(2))) {
1276
+ return Cons.nil;
1277
+ }
1278
+ const aCons = args2.nth(2);
1279
+ for (const each of aCons.loop()) {
1280
+ if (Cons.isNotCons(each)) {
1281
+ console.error(cannotApply("assoc", each));
1282
+ }
1283
+ const eachCons = each;
1284
+ const key = eachCons.car;
1285
+ if (this.equal_(new Cons(target, new Cons(key, Cons.nil))) === InterpretedSymbol.of("t")) {
1286
+ return eachCons;
1287
+ }
1288
+ }
1289
+ return Cons.nil;
1290
+ }
1291
+ atom_(args2) {
1292
+ if (Cons.isAtom(args2.car)) {
1293
+ return InterpretedSymbol.of("t");
1294
+ }
1295
+ return Cons.nil;
1296
+ }
1297
+ binding(parameter, args2) {
1298
+ if (Cons.isNil(parameter)) {
1299
+ return null;
1300
+ }
1301
+ let aCons = parameter;
1302
+ let theCons = args2;
1303
+ while (Cons.isNotNil(aCons)) {
1304
+ try {
1305
+ this.environment.set(aCons.car, theCons.car);
1306
+ } catch {
1307
+ console.error(SIZES_DO_NOT_MATCH);
1308
+ return null;
1309
+ }
1310
+ if (Cons.isNotCons(aCons.cdr)) {
1311
+ break;
1312
+ }
1313
+ aCons = aCons.cdr;
1314
+ theCons = theCons.cdr;
1315
+ }
1316
+ if (Cons.isNotList(aCons.cdr) && Cons.isNotNil(aCons.cdr)) {
1317
+ try {
1318
+ this.environment.set(aCons.cdr, theCons.cdr);
1319
+ } catch {
1320
+ console.error(SIZES_DO_NOT_MATCH);
1321
+ return null;
1322
+ }
1323
+ } else if (Cons.isNotNil(aCons.cdr)) {
1324
+ throw new ReferenceError("aList is not defined");
1325
+ }
1326
+ return null;
1327
+ }
1328
+ buildInFunction(procedure, args2) {
1329
+ if (this.isSpy(procedure)) {
1330
+ this.spyPrint(this.streamManager.spyStream(procedure), new Cons(procedure, args2).toString());
1331
+ this.setDepth(this.depth + 1);
1332
+ }
1333
+ const methodName = _Applier.buildInFunctions.get(procedure);
1334
+ const target = this;
1335
+ const fn = target[methodName];
1336
+ if (typeof fn !== "function") {
1337
+ throw new TypeError(`${this.constructor.name} does not have a method named "${methodName}"`);
1338
+ }
1339
+ const answer = fn.apply(target, [args2]);
1340
+ if (this.isSpy(procedure)) {
1341
+ this.setDepth(this.depth - 1);
1342
+ this.spyPrint(
1343
+ this.streamManager.spyStream(procedure),
1344
+ String(answer) + " <== " + new Cons(procedure, args2).toString()
1345
+ );
1346
+ }
1347
+ return answer;
1348
+ }
1349
+ car(args2) {
1350
+ return args2.car.car;
1351
+ }
1352
+ cdr(args2) {
1353
+ return args2.car.cdr;
1354
+ }
1355
+ character_(args2) {
1356
+ if (Cons.isString(args2.car) && args2.car.length === 1) {
1357
+ return InterpretedSymbol.of("t");
1358
+ }
1359
+ return Cons.nil;
1360
+ }
1361
+ cons(args2) {
1362
+ return new Cons(args2.car, args2.nth(2));
1363
+ }
1364
+ cons_(args2) {
1365
+ if (Cons.isCons(args2.car)) {
1366
+ return InterpretedSymbol.of("t");
1367
+ }
1368
+ return Cons.nil;
1369
+ }
1370
+ copy(args2) {
1371
+ return Cons.cloneValue(args2.car);
1372
+ }
1373
+ cos(args2) {
1374
+ if (Cons.isNumber(args2.car)) {
1375
+ return Math.cos(args2.car);
1376
+ }
1377
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
1378
+ }
1379
+ divide(args2) {
1380
+ if (Cons.isNumber(args2.car)) {
1381
+ return this.divide_Number(args2.car, args2.cdr);
1382
+ }
1383
+ console.error(cannotApply("divide", args2.car));
1384
+ return Cons.nil;
1385
+ }
1386
+ divide_Number(init, args2) {
1387
+ let result = init;
1388
+ let aCons = args2;
1389
+ while (Cons.isNotNil(aCons)) {
1390
+ const each = aCons.car;
1391
+ if (Cons.isNumber(each)) {
1392
+ result = result / each;
1393
+ } else {
1394
+ console.error(cannotApply("divide", each));
1395
+ return Cons.nil;
1396
+ }
1397
+ aCons = aCons.cdr;
1398
+ }
1399
+ return result;
1400
+ }
1401
+ entrustEvaluator(procedure, args2) {
1402
+ let anObject = Cons.nil;
1403
+ let aCons = procedure.cdr;
1404
+ this.binding(aCons.car, args2);
1405
+ aCons = aCons.cdr;
1406
+ for (const each of aCons.loop()) {
1407
+ if (each instanceof Table) {
1408
+ break;
1409
+ }
1410
+ anObject = Evaluator.eval(each, this.environment, this.streamManager, this.depth);
1411
+ }
1412
+ return anObject;
1413
+ }
1414
+ // NOTE: Implements Common Lisp's eq as JS strict identity (===). Symbols are eq because
1415
+ // InterpretedSymbol.of interns by name; numbers / strings are eq because JS primitive
1416
+ // equality is by value; Cons / Table / other objects are eq only when they are the same
1417
+ // reference. Edge cases: NaN is never eq to itself (matches IEEE 754 and most CL
1418
+ // implementations); +0 and -0 are eq (CL leaves this implementation-defined).
1419
+ eq_(args2) {
1420
+ const first = args2.car;
1421
+ const second = args2.nth(2);
1422
+ if (first === second) {
1423
+ return InterpretedSymbol.of("t");
1424
+ }
1425
+ return Cons.nil;
1426
+ }
1427
+ equal_(args2) {
1428
+ const first = args2.car;
1429
+ const second = args2.nth(2);
1430
+ if (this.eq_(args2) === InterpretedSymbol.of("t")) {
1431
+ return InterpretedSymbol.of("t");
1432
+ }
1433
+ if (Cons.isCons(first) && Cons.isCons(second)) {
1434
+ if (first.equals(second)) {
1435
+ return InterpretedSymbol.of("t");
1436
+ }
1437
+ if (second.equals(first)) {
1438
+ return InterpretedSymbol.of("t");
1439
+ }
1440
+ }
1441
+ return Cons.nil;
1442
+ }
1443
+ exp(args2) {
1444
+ if (Cons.isNumber(args2.car)) {
1445
+ return Math.exp(args2.car);
1446
+ }
1447
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
1448
+ }
1449
+ format(args2) {
1450
+ if (!Cons.isString(args2.car)) {
1451
+ console.error(cannotApply("format", args2.car));
1452
+ }
1453
+ const aCons = args2.cdr;
1454
+ const format = this.format_AUX(String(args2.car), aCons);
1455
+ process.stdout.write(String(format));
1456
+ return Cons.nil;
1457
+ }
1458
+ format_AUX(format, aCons) {
1459
+ let theCons = aCons;
1460
+ let index = 0;
1461
+ let state = 0;
1462
+ let buffer = "";
1463
+ let token = "";
1464
+ while (index < format.length) {
1465
+ const aCharacter = format[index];
1466
+ switch (state) {
1467
+ case 0: {
1468
+ if (aCharacter === "~") {
1469
+ state = 1;
1470
+ } else {
1471
+ buffer += aCharacter;
1472
+ }
1473
+ break;
1474
+ }
1475
+ case 1: {
1476
+ switch (aCharacter) {
1477
+ case "0":
1478
+ case "1":
1479
+ case "2":
1480
+ case "3":
1481
+ case "4":
1482
+ case "5":
1483
+ case "6":
1484
+ case "7":
1485
+ case "8":
1486
+ case "9": {
1487
+ token += aCharacter;
1488
+ state = 2;
1489
+ break;
1490
+ }
1491
+ case "a": {
1492
+ buffer += theCons.car.toString();
1493
+ theCons = theCons.cdr;
1494
+ state = 0;
1495
+ break;
1496
+ }
1497
+ case "%": {
1498
+ buffer += "\n";
1499
+ state = 0;
1500
+ break;
1501
+ }
1502
+ case "-": {
1503
+ state = 3;
1504
+ break;
1505
+ }
1506
+ default: {
1507
+ buffer += "~";
1508
+ buffer += aCharacter;
1509
+ state = 0;
1510
+ }
1511
+ }
1512
+ break;
1513
+ }
1514
+ case 2: {
1515
+ switch (aCharacter) {
1516
+ case "0":
1517
+ case "1":
1518
+ case "2":
1519
+ case "3":
1520
+ case "4":
1521
+ case "5":
1522
+ case "6":
1523
+ case "7":
1524
+ case "8":
1525
+ case "9": {
1526
+ token += aCharacter;
1527
+ state = 2;
1528
+ break;
1529
+ }
1530
+ case "a": {
1531
+ const size = Number(token);
1532
+ token = "";
1533
+ if (Cons.isNil(theCons)) {
1534
+ console.error(SIZE_DO_NOT_MATCH);
1535
+ return void 0;
1536
+ }
1537
+ let value = theCons.car.toString();
1538
+ theCons = theCons.cdr;
1539
+ while (value.length < size) {
1540
+ value += " ";
1541
+ }
1542
+ buffer += value;
1543
+ state = 0;
1544
+ break;
1545
+ }
1546
+ default: {
1547
+ buffer += "~";
1548
+ buffer += token + aCharacter;
1549
+ token = "";
1550
+ state = 0;
1551
+ }
1552
+ }
1553
+ break;
1554
+ }
1555
+ case 3: {
1556
+ switch (aCharacter) {
1557
+ case "0":
1558
+ case "1":
1559
+ case "2":
1560
+ case "3":
1561
+ case "4":
1562
+ case "5":
1563
+ case "6":
1564
+ case "7":
1565
+ case "8":
1566
+ case "9": {
1567
+ token += aCharacter;
1568
+ state = 3;
1569
+ break;
1570
+ }
1571
+ case "a": {
1572
+ const size = Number(token);
1573
+ token = "";
1574
+ if (Cons.isNil(theCons)) {
1575
+ console.error(SIZE_DO_NOT_MATCH);
1576
+ return void 0;
1577
+ }
1578
+ const value = theCons.car.toString();
1579
+ theCons = theCons.cdr;
1580
+ let spaces = "";
1581
+ while (value.length + spaces.length < size) {
1582
+ spaces += " ";
1583
+ }
1584
+ buffer += spaces + value;
1585
+ state = 0;
1586
+ break;
1587
+ }
1588
+ default: {
1589
+ buffer += "~";
1590
+ buffer += "-";
1591
+ buffer += token + aCharacter;
1592
+ token = "";
1593
+ state = 0;
1594
+ }
1595
+ }
1596
+ break;
1597
+ }
1598
+ default: {
1599
+ console.error("Error!");
1600
+ }
1601
+ }
1602
+ index++;
1603
+ }
1604
+ if (Cons.isNotNil(theCons)) {
1605
+ console.error(SIZE_DO_NOT_MATCH);
1606
+ return void 0;
1607
+ }
1608
+ return buffer;
1609
+ }
1610
+ // NOTE: Common Lisp's floatp is a type-tag predicate (integer vs float), but JS has only one
1611
+ // numeric type (double). The original chose to interpret floatp as a range check
1612
+ // "is this number representable in IEEE 32-bit (single-precision) float?" rather than a
1613
+ // type-tag check. Following the original semantics. Revisit if numeric types are split
1614
+ // in a future revision.
1615
+ float_(args2) {
1616
+ if (Cons.isNumber(args2.car) && -34e37 <= args2.car && args2.car <= 34e37) {
1617
+ return InterpretedSymbol.of("t");
1618
+ }
1619
+ return Cons.nil;
1620
+ }
1621
+ gensym() {
1622
+ const aSymbol = InterpretedSymbol.of("id" + String(_Applier.#generateNumber));
1623
+ _Applier.incrementGenerateNumber();
1624
+ return aSymbol;
1625
+ }
1626
+ getStream(anObject) {
1627
+ if (typeof anObject === "string") {
1628
+ return process.out;
1629
+ }
1630
+ return this.streamManager.getStream();
1631
+ }
1632
+ greaterThan(args2) {
1633
+ if (Cons.isNumber(args2.car)) {
1634
+ return this.greaterThan_Number(args2.car, args2.cdr);
1635
+ }
1636
+ console.error(cannotApply(">", args2.car));
1637
+ return Cons.nil;
1638
+ }
1639
+ greaterThan_Number(init, args2) {
1640
+ let leftValue = init;
1641
+ let aCons = args2;
1642
+ let aBoolean;
1643
+ while (Cons.isNotNil(aCons)) {
1644
+ const rightValue = aCons.car;
1645
+ if (Cons.isNumber(rightValue)) {
1646
+ aBoolean = leftValue > rightValue;
1647
+ } else {
1648
+ console.error(cannotApply(">", rightValue));
1649
+ return Cons.nil;
1650
+ }
1651
+ if (!aBoolean) {
1652
+ return Cons.nil;
1653
+ }
1654
+ leftValue = rightValue;
1655
+ aCons = aCons.cdr;
1656
+ }
1657
+ return InterpretedSymbol.of("t");
1658
+ }
1659
+ greaterThanOrEqual(args2) {
1660
+ if (Cons.isNumber(args2.car)) {
1661
+ return this.greaterThanOrEqual_Number(args2.car, args2.cdr);
1662
+ }
1663
+ console.error(cannotApply(">=", args2.car));
1664
+ return Cons.nil;
1665
+ }
1666
+ greaterThanOrEqual_Number(init, args2) {
1667
+ let leftValue = init;
1668
+ let aCons = args2;
1669
+ let aBoolean;
1670
+ while (Cons.isNotNil(aCons)) {
1671
+ const rightValue = aCons.car;
1672
+ if (Cons.isNumber(rightValue)) {
1673
+ aBoolean = leftValue >= rightValue;
1674
+ } else {
1675
+ console.error(cannotApply(">=", rightValue));
1676
+ return Cons.nil;
1677
+ }
1678
+ if (!aBoolean) {
1679
+ return Cons.nil;
1680
+ }
1681
+ leftValue = rightValue;
1682
+ aCons = aCons.cdr;
1683
+ }
1684
+ return InterpretedSymbol.of("t");
1685
+ }
1686
+ static incrementGenerateNumber() {
1687
+ _Applier.#generateNumber++;
1688
+ return null;
1689
+ }
1690
+ indent() {
1691
+ let index = 0;
1692
+ let aString = "";
1693
+ while (index++ < this.depth) {
1694
+ aString += "| ";
1695
+ }
1696
+ return aString;
1697
+ }
1698
+ integer_(args2) {
1699
+ if (Cons.isNumber(args2.car) && Number.isInteger(args2.car)) {
1700
+ return InterpretedSymbol.of("t");
1701
+ }
1702
+ return Cons.nil;
1703
+ }
1704
+ isSpy(aSymbol) {
1705
+ return this.streamManager.isSpy(aSymbol);
1706
+ }
1707
+ last(args2) {
1708
+ if (Cons.isNotCons(args2)) {
1709
+ return Cons.nil;
1710
+ }
1711
+ const aCons = args2.car;
1712
+ return aCons.last();
1713
+ }
1714
+ lessThan(args2) {
1715
+ if (Cons.isNumber(args2.car)) {
1716
+ return this.lessThan_Number(args2.car, args2.cdr);
1717
+ }
1718
+ console.error(cannotApply("<", args2.car));
1719
+ return Cons.nil;
1720
+ }
1721
+ lessThan_Number(init, args2) {
1722
+ let leftValue = init;
1723
+ let aCons = args2;
1724
+ let aBoolean;
1725
+ while (Cons.isNotNil(aCons)) {
1726
+ const rightValue = aCons.car;
1727
+ if (Cons.isNumber(rightValue)) {
1728
+ aBoolean = leftValue < rightValue;
1729
+ } else {
1730
+ console.error(cannotApply("<", rightValue));
1731
+ return Cons.nil;
1732
+ }
1733
+ if (!aBoolean) {
1734
+ return Cons.nil;
1735
+ }
1736
+ leftValue = rightValue;
1737
+ aCons = aCons.cdr;
1738
+ }
1739
+ return InterpretedSymbol.of("t");
1740
+ }
1741
+ lessThanOrEqual(args2) {
1742
+ if (Cons.isNumber(args2.car)) {
1743
+ return this.lessThanOrEqual_Number(args2.car, args2.cdr);
1744
+ }
1745
+ console.error(cannotApply("<=", args2.car));
1746
+ return Cons.nil;
1747
+ }
1748
+ lessThanOrEqual_Number(init, args2) {
1749
+ let leftValue = init;
1750
+ let aCons = args2;
1751
+ let aBoolean;
1752
+ while (Cons.isNotNil(aCons)) {
1753
+ const rightValue = aCons.car;
1754
+ if (Cons.isNumber(rightValue)) {
1755
+ aBoolean = leftValue <= rightValue;
1756
+ } else {
1757
+ console.error(cannotApply("<=", rightValue));
1758
+ return Cons.nil;
1759
+ }
1760
+ if (!aBoolean) {
1761
+ return Cons.nil;
1762
+ }
1763
+ leftValue = rightValue;
1764
+ aCons = aCons.cdr;
1765
+ }
1766
+ return InterpretedSymbol.of("t");
1767
+ }
1768
+ list(args2) {
1769
+ if (Cons.isNil(args2)) {
1770
+ return Cons.nil;
1771
+ }
1772
+ return new Cons(args2.car, this.list(args2.cdr));
1773
+ }
1774
+ list_(args2) {
1775
+ if (Cons.isList(args2.car)) {
1776
+ return InterpretedSymbol.of("t");
1777
+ }
1778
+ return Cons.nil;
1779
+ }
1780
+ mapcar(args2) {
1781
+ const aCons = new Cons(Cons.nil, Cons.nil);
1782
+ const procedure = args2.car;
1783
+ const parameters = args2.nth(2);
1784
+ const options = args2.cdr.cdr;
1785
+ let theCons = aCons;
1786
+ let index = 1;
1787
+ for (const each of parameters.loop()) {
1788
+ const argumentsCons = new Cons(Cons.nil, Cons.nil);
1789
+ let temporaryCons = argumentsCons;
1790
+ if (Cons.isNotNil(each)) {
1791
+ for (const arg of options.loop()) {
1792
+ if (Cons.isNotCons(arg)) {
1793
+ throw new ReferenceError("consol is not defined");
1794
+ }
1795
+ temporaryCons.setCdr(new Cons(arg.nth(index), Cons.nil));
1796
+ temporaryCons = temporaryCons.cdr;
1797
+ }
1798
+ }
1799
+ argumentsCons.setCar(each);
1800
+ const anObject = _Applier.apply(
1801
+ procedure,
1802
+ argumentsCons,
1803
+ this.environment,
1804
+ this.streamManager,
1805
+ this.depth
1806
+ );
1807
+ theCons.setCdr(new Cons(anObject, Cons.nil));
1808
+ theCons = theCons.cdr;
1809
+ index++;
1810
+ }
1811
+ return aCons.cdr;
1812
+ }
1813
+ member(args2) {
1814
+ let aSymbol = InterpretedSymbol.of("equal?");
1815
+ if (Cons.isNotNil(args2.nth(3))) {
1816
+ aSymbol = args2.nth(3);
1817
+ }
1818
+ if (Cons.isNotCons(args2.nth(2))) {
1819
+ return Cons.nil;
1820
+ }
1821
+ let aCons = args2.nth(2);
1822
+ while (Cons.isCons(aCons)) {
1823
+ let anObject = null;
1824
+ if (aSymbol === InterpretedSymbol.of("eq?")) {
1825
+ anObject = this.eq_(new Cons(args2.car, new Cons(aCons.car, Cons.nil)));
1826
+ }
1827
+ if (aSymbol === InterpretedSymbol.of("equal?")) {
1828
+ anObject = this.equal_(new Cons(args2.car, new Cons(aCons.car, Cons.nil)));
1829
+ }
1830
+ if (anObject == null) {
1831
+ console.error(cannotApply("member", aSymbol));
1832
+ }
1833
+ if (anObject === InterpretedSymbol.of("t")) {
1834
+ return aCons;
1835
+ }
1836
+ aCons = aCons.cdr;
1837
+ }
1838
+ return Cons.nil;
1839
+ }
1840
+ memq(args2) {
1841
+ if (this.member(args2) === Cons.nil) {
1842
+ return Cons.nil;
1843
+ }
1844
+ return InterpretedSymbol.of("t");
1845
+ }
1846
+ mod(args2) {
1847
+ if (Cons.isNumber(args2.car)) {
1848
+ return this.mod_Number(args2.car, args2.cdr);
1849
+ }
1850
+ console.error(cannotApply("mod", args2.car));
1851
+ return Cons.nil;
1852
+ }
1853
+ mod_Number(init, args2) {
1854
+ let result = init;
1855
+ let aCons = args2;
1856
+ while (Cons.isNotNil(aCons)) {
1857
+ const each = aCons.car;
1858
+ if (Cons.isNumber(each)) {
1859
+ result = result % each;
1860
+ } else {
1861
+ console.error(cannotApply("mod", each));
1862
+ return Cons.nil;
1863
+ }
1864
+ aCons = aCons.cdr;
1865
+ }
1866
+ return result;
1867
+ }
1868
+ multiply(args2) {
1869
+ if (Cons.isNumber(args2.car)) {
1870
+ return this.multiply_Number(args2.car, args2.cdr);
1871
+ }
1872
+ console.error(cannotApply("multiply", args2.car));
1873
+ return Cons.nil;
1874
+ }
1875
+ multiply_Number(init, args2) {
1876
+ let result = init;
1877
+ let aCons = args2;
1878
+ while (Cons.isNotNil(aCons)) {
1879
+ const each = aCons.car;
1880
+ if (Cons.isNumber(each)) {
1881
+ result = result * each;
1882
+ } else {
1883
+ console.error(cannotApply("multiply", each));
1884
+ return Cons.nil;
1885
+ }
1886
+ aCons = aCons.cdr;
1887
+ }
1888
+ return result;
1889
+ }
1890
+ napier() {
1891
+ return Math.E;
1892
+ }
1893
+ neq(args2) {
1894
+ if (this.eq_(args2) === InterpretedSymbol.of("t")) {
1895
+ return Cons.nil;
1896
+ }
1897
+ return InterpretedSymbol.of("t");
1898
+ }
1899
+ nequal(args2) {
1900
+ if (this.equal_(args2) === InterpretedSymbol.of("t")) {
1901
+ return Cons.nil;
1902
+ }
1903
+ return InterpretedSymbol.of("t");
1904
+ }
1905
+ nth(args2) {
1906
+ if (!Number.isInteger(args2.car)) {
1907
+ return Cons.nil;
1908
+ }
1909
+ const index = args2.car;
1910
+ const aCons = args2.nth(2);
1911
+ return aCons.nth(index);
1912
+ }
1913
+ null_(args2) {
1914
+ if (Cons.isNil(args2.car)) {
1915
+ return InterpretedSymbol.of("t");
1916
+ }
1917
+ return Cons.nil;
1918
+ }
1919
+ // NOTE: Lisp's numberp and doublep are originally distinct predicates, but because JS has only
1920
+ // one numeric type (double), we share a single implementation. In Applier.setup() both
1921
+ // Lisp function names numberp / doublep map to this method. Split into separate methods if
1922
+ // a future revision introduces additional numeric types such as BigInt.
1923
+ number_(args2) {
1924
+ if (Cons.isNumber(args2.car)) {
1925
+ return InterpretedSymbol.of("t");
1926
+ }
1927
+ return Cons.nil;
1928
+ }
1929
+ pi() {
1930
+ return Math.PI;
1931
+ }
1932
+ random() {
1933
+ return Math.random();
1934
+ }
1935
+ round(args2) {
1936
+ if (Cons.isNumber(args2.car)) {
1937
+ return Math.round(args2.car);
1938
+ }
1939
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
1940
+ }
1941
+ selectProcedure(procedure, args2) {
1942
+ if (_Applier.buildInFunctions.has(procedure)) {
1943
+ return this.buildInFunction(procedure, args2);
1944
+ }
1945
+ if (this.environment.has(procedure)) {
1946
+ return this.userFunction(procedure, args2);
1947
+ }
1948
+ console.error(noProcedure(procedure));
1949
+ return Cons.nil;
1950
+ }
1951
+ setDepth(aNumber) {
1952
+ this.depth = aNumber;
1953
+ return null;
1954
+ }
1955
+ static setup() {
1956
+ try {
1957
+ const entries = [
1958
+ ["abs", "abs"],
1959
+ ["add", "add"],
1960
+ ["assoc", "assoc"],
1961
+ ["atom", "atom_"],
1962
+ ["car", "car"],
1963
+ ["cdr", "cdr"],
1964
+ ["characterp", "character_"],
1965
+ ["cons", "cons"],
1966
+ ["consp", "cons_"],
1967
+ ["copy", "copy"],
1968
+ ["cos", "cos"],
1969
+ ["floatp", "float_"],
1970
+ ["divide", "divide"],
1971
+ ["doublep", "number_"],
1972
+ ["eq", "eq_"],
1973
+ ["equal", "equal_"],
1974
+ ["exp", "exp"],
1975
+ ["format", "format"],
1976
+ ["gensym", "gensym"],
1977
+ ["integerp", "integer_"],
1978
+ ["last", "last"],
1979
+ ["list", "list"],
1980
+ ["listp", "list_"],
1981
+ ["mapcar", "mapcar"],
1982
+ ["member", "member"],
1983
+ ["memq", "memq"],
1984
+ ["mod", "mod"],
1985
+ ["multiply", "multiply"],
1986
+ ["napier", "napier"],
1987
+ ["neq", "neq"],
1988
+ ["nequal", "nequal"],
1989
+ ["nth", "nth"],
1990
+ ["null", "null_"],
1991
+ ["numberp", "number_"],
1992
+ ["pi", "pi"],
1993
+ ["random", "random"],
1994
+ ["round", "round"],
1995
+ ["sin", "sin"],
1996
+ ["sqrt", "sqrt"],
1997
+ ["subtract", "subtract"],
1998
+ ["stringp", "string_"],
1999
+ ["symbolp", "symbol_"],
2000
+ ["tan", "tan"],
2001
+ ["+", "add"],
2002
+ ["-", "subtract"],
2003
+ ["*", "multiply"],
2004
+ ["/", "divide"],
2005
+ ["//", "mod"],
2006
+ ["==", "eq_"],
2007
+ ["=", "equal_"],
2008
+ ["~~", "neq"],
2009
+ ["~=", "nequal"],
2010
+ ["<", "lessThan"],
2011
+ ["<=", "lessThanOrEqual"],
2012
+ [">", "greaterThan"],
2013
+ [">=", "greaterThanOrEqual"]
2014
+ ];
2015
+ return new Map(entries.map(([key, value]) => [InterpretedSymbol.of(key), value]));
2016
+ } catch {
2017
+ throw new Error("NullPointerException (Applier, initialize)");
2018
+ }
2019
+ }
2020
+ sin(args2) {
2021
+ if (Cons.isNumber(args2.car)) {
2022
+ return Math.sin(args2.car);
2023
+ }
2024
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
2025
+ }
2026
+ // NOTE: Lisp's trace/spy writes the call line to a designated output stream. The original
2027
+ // implementation logged the stream object itself rather than writing to it (a bug that
2028
+ // went unnoticed because trace/spy is rarely exercised). We now write the indented line
2029
+ // to the given WritableStream, falling back to stdout when the argument is a string
2030
+ // descriptor (stored by `(spy fn "label")`) or null.
2031
+ spyPrint(aStream, line) {
2032
+ const target = aStream != null && typeof aStream === "object" && "write" in aStream ? aStream : process.stdout;
2033
+ target.write(this.indent() + line + "\n");
2034
+ return null;
2035
+ }
2036
+ sqrt(args2) {
2037
+ if (Cons.isNumber(args2.car)) {
2038
+ return Math.sqrt(args2.car);
2039
+ }
2040
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
2041
+ }
2042
+ string_(args2) {
2043
+ if (Cons.isString(args2.car)) {
2044
+ return InterpretedSymbol.of("t");
2045
+ }
2046
+ return Cons.nil;
2047
+ }
2048
+ subtract(args2) {
2049
+ if (Cons.isNumber(args2.car)) {
2050
+ return this.subtract_Number(args2.car, args2.cdr);
2051
+ }
2052
+ console.error(cannotApply("subtract", args2.car));
2053
+ return Cons.nil;
2054
+ }
2055
+ subtract_Number(init, args2) {
2056
+ let result = init;
2057
+ let aCons = args2;
2058
+ while (Cons.isNotNil(aCons)) {
2059
+ const each = aCons.car;
2060
+ if (Cons.isNumber(each)) {
2061
+ result = result - each;
2062
+ } else {
2063
+ console.error(cannotApply("subtract", each));
2064
+ return Cons.nil;
2065
+ }
2066
+ aCons = aCons.cdr;
2067
+ }
2068
+ return result;
2069
+ }
2070
+ symbol_(args2) {
2071
+ if (Cons.isSymbol(args2.car)) {
2072
+ return InterpretedSymbol.of("t");
2073
+ }
2074
+ return Cons.nil;
2075
+ }
2076
+ tan(args2) {
2077
+ if (Cons.isNumber(args2.car)) {
2078
+ return Math.tan(args2.car);
2079
+ }
2080
+ throw new ReferenceError(SELECT_PRINT_FUNCTION_NOT_DEFINED);
2081
+ }
2082
+ userFunction(procedure, args2) {
2083
+ if (this.isSpy(procedure)) {
2084
+ this.spyPrint(this.streamManager.spyStream(procedure), new Cons(procedure, args2).toString());
2085
+ this.setDepth(this.depth + 1);
2086
+ }
2087
+ const lambda = this.environment.get(procedure);
2088
+ const theEnvironment = lambda.last().car;
2089
+ const answer = _Applier.apply(lambda, args2, theEnvironment, this.streamManager, this.depth);
2090
+ if (this.isSpy(procedure)) {
2091
+ this.setDepth(this.depth - 1);
2092
+ this.spyPrint(
2093
+ this.streamManager.spyStream(procedure),
2094
+ String(answer) + " <== " + new Cons(procedure, args2).toString()
2095
+ );
2096
+ }
2097
+ return answer;
2098
+ }
2099
+ };
2100
+
2101
+ // src/runtime/ExitError/index.ts
2102
+ var ExitError = class extends Error {
2103
+ /**
2104
+ * Constructor.
2105
+ * @constructor
2106
+ */
2107
+ constructor() {
2108
+ super("Exit");
2109
+ this.name = "ExitError";
2110
+ }
2111
+ };
2112
+
2113
+ // src/runtime/StreamManager/index.ts
2114
+ var StreamManager = class {
2115
+ isTrace = false;
2116
+ streamTable;
2117
+ spyTable;
2118
+ traceStream;
2119
+ constructor() {
2120
+ this.streamTable = /* @__PURE__ */ new Map();
2121
+ this.spyTable = /* @__PURE__ */ new Map();
2122
+ this.traceStream = null;
2123
+ this.initialize();
2124
+ }
2125
+ getStream() {
2126
+ let aPrintStream = null;
2127
+ if (this.isTrace) {
2128
+ return this.traceStream();
2129
+ }
2130
+ const filePath = process.env["HOME"];
2131
+ if (this.streamTable.has(filePath)) {
2132
+ aPrintStream = this.streamTable.get(filePath) ?? null;
2133
+ }
2134
+ return aPrintStream;
2135
+ }
2136
+ /**
2137
+ * Initializes the instance variables.
2138
+ */
2139
+ initialize() {
2140
+ this.streamTable.set("default", process.stdout);
2141
+ this.streamTable.set("stdout", process.stdout);
2142
+ this.streamTable.set("stderr", process.stderr);
2143
+ return null;
2144
+ }
2145
+ isSpy(aSymbol) {
2146
+ if (this.isTrace) {
2147
+ return true;
2148
+ }
2149
+ if (aSymbol != null && this.spyTable_().has(aSymbol)) {
2150
+ return true;
2151
+ }
2152
+ return false;
2153
+ }
2154
+ noSpy(aSymbol) {
2155
+ if (this.spyTable_().has(aSymbol)) {
2156
+ this.spyTable_().delete(aSymbol);
2157
+ }
2158
+ return null;
2159
+ }
2160
+ noTrace() {
2161
+ this.setIsTrace(false);
2162
+ this.spyTable.clear();
2163
+ return null;
2164
+ }
2165
+ setIsTrace(aBoolean) {
2166
+ this.isTrace = aBoolean;
2167
+ return null;
2168
+ }
2169
+ setTraceStream(aStream) {
2170
+ this.traceStream = aStream;
2171
+ return null;
2172
+ }
2173
+ spy(aSymbol, aString) {
2174
+ const aPrintStream = this.getStream();
2175
+ if (aPrintStream != null) {
2176
+ this.spyTable_().set(aSymbol, aString);
2177
+ }
2178
+ return null;
2179
+ }
2180
+ spyStream(aSymbol) {
2181
+ if (this.isTrace) {
2182
+ return this.traceStream;
2183
+ }
2184
+ if (aSymbol != null && this.spyTable_().has(aSymbol)) {
2185
+ return this.spyTable_().get(aSymbol);
2186
+ }
2187
+ throw new Error("Stream is not found.");
2188
+ }
2189
+ spyTable_() {
2190
+ const aTable = /* @__PURE__ */ new Map();
2191
+ for (const [key, value] of this.spyTable) {
2192
+ aTable.set(key, value);
2193
+ }
2194
+ return aTable;
2195
+ }
2196
+ trace() {
2197
+ this.noTrace();
2198
+ const aPrintStream = this.getStream();
2199
+ this.setTraceStream(aPrintStream);
2200
+ this.setIsTrace(true);
2201
+ return null;
2202
+ }
2203
+ };
2204
+
2205
+ // src/runtime/Evaluator/index.ts
2206
+ var cachedGc = null;
2207
+ var triggerGc = () => {
2208
+ if (cachedGc == null) {
2209
+ import_node_v8.default.setFlagsFromString("--expose_gc");
2210
+ cachedGc = import_node_vm.default.runInNewContext("gc");
2211
+ }
2212
+ cachedGc();
2213
+ };
2214
+ var Evaluator = class _Evaluator {
2215
+ static buildInFunctions = _Evaluator.setup();
2216
+ environment;
2217
+ streamManager;
2218
+ depth;
2219
+ constructor(aTable, aStreamManager, aNumber) {
2220
+ this.environment = aTable;
2221
+ this.streamManager = aStreamManager;
2222
+ this.depth = aNumber;
2223
+ }
2224
+ and(aCons) {
2225
+ for (const each of aCons.loop()) {
2226
+ const anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2227
+ if (Cons.isNil(anObject)) {
2228
+ return Cons.nil;
2229
+ }
2230
+ }
2231
+ return InterpretedSymbol.of("t");
2232
+ }
2233
+ apply_lisp(aCons) {
2234
+ const procedure = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2235
+ const args2 = _Evaluator.eval(aCons.nth(2), this.environment, this.streamManager, this.depth);
2236
+ let aTable = this.environment;
2237
+ if (procedure instanceof Cons && procedure.last().car instanceof Table) {
2238
+ aTable = procedure.last().car;
2239
+ }
2240
+ return Applier.apply(procedure, args2, aTable, this.streamManager, this.depth);
2241
+ }
2242
+ bind(aCons) {
2243
+ if (Cons.isNotSymbol(aCons.car)) {
2244
+ console.error(cannotApply("bind", aCons.car));
2245
+ return Cons.nil;
2246
+ }
2247
+ const aSymbol = aCons.car;
2248
+ if (!this.environment.has(aSymbol)) {
2249
+ return Cons.nil;
2250
+ }
2251
+ return this.bindAUX(aSymbol);
2252
+ }
2253
+ bindAUX(aSymbol) {
2254
+ let aTable = this.environment;
2255
+ let anObject = aTable.get(aSymbol);
2256
+ let count = 1;
2257
+ while (aTable != null) {
2258
+ if (!aTable.has(aSymbol)) {
2259
+ break;
2260
+ }
2261
+ const theObject = aTable.get(aSymbol);
2262
+ if (theObject != anObject) {
2263
+ count++;
2264
+ anObject = theObject;
2265
+ }
2266
+ aTable = aTable.source;
2267
+ }
2268
+ return count;
2269
+ }
2270
+ binding(parameters, aTable) {
2271
+ for (const each of parameters.loop()) {
2272
+ const theCons = each;
2273
+ let key = null;
2274
+ if (Cons.isSymbol(theCons.car)) {
2275
+ key = theCons.car;
2276
+ } else {
2277
+ console.error(notSymbol(theCons.car));
2278
+ }
2279
+ const value = _Evaluator.eval(theCons.nth(2), aTable, this.streamManager, this.depth);
2280
+ aTable.set(key, value);
2281
+ }
2282
+ return null;
2283
+ }
2284
+ bindingParallel(parameters, aTable) {
2285
+ const theTable = /* @__PURE__ */ new Map();
2286
+ for (const each of parameters.loop()) {
2287
+ const theCons = each;
2288
+ let key = null;
2289
+ if (Cons.isSymbol(theCons.car)) {
2290
+ key = theCons.car;
2291
+ } else {
2292
+ console.error(notSymbol(theCons.car));
2293
+ }
2294
+ const value = _Evaluator.eval(theCons.nth(2), aTable, this.streamManager, this.depth);
2295
+ theTable.set(key, value);
2296
+ }
2297
+ for (const [key, value] of theTable) {
2298
+ aTable.set(key, value);
2299
+ }
2300
+ return null;
2301
+ }
2302
+ cond(aCons) {
2303
+ if (Cons.isNil(aCons)) {
2304
+ return Cons.nil;
2305
+ }
2306
+ const consCell = aCons;
2307
+ const clause = consCell.car;
2308
+ let anObject = _Evaluator.eval(
2309
+ clause.car,
2310
+ this.environment,
2311
+ this.streamManager,
2312
+ this.depth
2313
+ );
2314
+ if (Cons.isNil(anObject)) {
2315
+ return this.cond(consCell.cdr);
2316
+ }
2317
+ const consequent = clause.cdr;
2318
+ for (const each of consequent.loop()) {
2319
+ anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2320
+ }
2321
+ return anObject;
2322
+ }
2323
+ defun(aCons) {
2324
+ const variable = aCons.car;
2325
+ let lambda = aCons.cdr;
2326
+ lambda = aCons.length() === 2 ? lambda.car : new Cons(InterpretedSymbol.of("lambda"), lambda);
2327
+ lambda = _Evaluator.eval(lambda, new Table(this.environment), this.streamManager, this.depth);
2328
+ this.environment.set(variable, lambda);
2329
+ return variable;
2330
+ }
2331
+ do_(aCons) {
2332
+ const parameters = aCons.car;
2333
+ const bool = aCons.nth(2);
2334
+ const expressions = aCons.cdr.cdr;
2335
+ this.bindingParallel(parameters, this.environment);
2336
+ if (Cons.isNil(bool)) {
2337
+ bool.setCar(Cons.nil);
2338
+ }
2339
+ while (Cons.isNil(_Evaluator.eval(bool.car, this.environment, this.streamManager, this.depth))) {
2340
+ const theTable = /* @__PURE__ */ new Map();
2341
+ for (const each of expressions.loop()) {
2342
+ _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2343
+ }
2344
+ for (const each of parameters.loop()) {
2345
+ const theCons = each;
2346
+ if (Cons.isNotSymbol(theCons.car)) {
2347
+ console.error(notSymbol(theCons.car));
2348
+ }
2349
+ const key = theCons.car;
2350
+ if (Cons.isNotNil(theCons.nth(3))) {
2351
+ const value = _Evaluator.eval(
2352
+ theCons.nth(3),
2353
+ this.environment,
2354
+ this.streamManager,
2355
+ this.depth
2356
+ );
2357
+ theTable.set(key, value);
2358
+ }
2359
+ }
2360
+ for (const [key, value] of theTable) {
2361
+ this.environment.set(key, value);
2362
+ }
2363
+ }
2364
+ return _Evaluator.eval(bool.nth(2), this.environment, this.streamManager, this.depth);
2365
+ }
2366
+ doList(aCons) {
2367
+ const parameter = aCons.car;
2368
+ const theCons = aCons.cdr;
2369
+ const args2 = _Evaluator.eval(
2370
+ parameter.nth(2),
2371
+ this.environment,
2372
+ this.streamManager,
2373
+ this.depth
2374
+ );
2375
+ for (const element of args2.loop()) {
2376
+ this.environment.set(parameter.car, element);
2377
+ for (const each of theCons.loop()) {
2378
+ _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2379
+ }
2380
+ }
2381
+ return _Evaluator.eval(parameter.nth(3), this.environment, this.streamManager, this.depth);
2382
+ }
2383
+ doStar(aCons) {
2384
+ const parameters = aCons.car;
2385
+ const bool = aCons.nth(2);
2386
+ const expressions = aCons.cdr.cdr;
2387
+ this.binding(parameters, this.environment);
2388
+ if (Cons.isNil(bool)) {
2389
+ bool.setCar(Cons.nil);
2390
+ }
2391
+ while (Cons.isNil(_Evaluator.eval(bool.car, this.environment, this.streamManager, this.depth))) {
2392
+ for (const each of expressions.loop()) {
2393
+ _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2394
+ }
2395
+ for (const each of parameters.loop()) {
2396
+ const theCons = each;
2397
+ if (Cons.isNotSymbol(theCons.car)) {
2398
+ console.error(notSymbol(theCons.car));
2399
+ }
2400
+ const key = theCons.car;
2401
+ if (Cons.isNotNil(theCons.nth(3))) {
2402
+ const value = _Evaluator.eval(
2403
+ theCons.nth(3),
2404
+ this.environment,
2405
+ this.streamManager,
2406
+ this.depth
2407
+ );
2408
+ this.environment.set(key, value);
2409
+ }
2410
+ }
2411
+ }
2412
+ return _Evaluator.eval(bool.nth(2), this.environment, this.streamManager, this.depth);
2413
+ }
2414
+ entrustApplier(form) {
2415
+ const aCons = form.cdr;
2416
+ let args2 = new Cons(Cons.nil, Cons.nil);
2417
+ const procedure = form.car;
2418
+ let aSymbol = null;
2419
+ if (Cons.isSymbol(procedure)) {
2420
+ aSymbol = procedure;
2421
+ }
2422
+ if (this.isSpy(aSymbol)) {
2423
+ this.spyPrint(this.streamManager.spyStream(aSymbol), form.toString());
2424
+ this.setDepth(this.depth + 1);
2425
+ }
2426
+ for (const each of aCons.loop()) {
2427
+ if (each instanceof Table) {
2428
+ break;
2429
+ }
2430
+ args2.add(_Evaluator.eval(each, this.environment, this.streamManager, this.depth));
2431
+ }
2432
+ if (this.isSpy(aSymbol)) {
2433
+ this.setDepth(this.depth - 1);
2434
+ }
2435
+ args2 = args2.cdr;
2436
+ return Applier.apply(procedure, args2, this.environment, this.streamManager, this.depth);
2437
+ }
2438
+ static eval(form, environment, aStreamManager = new StreamManager(), depth = 1) {
2439
+ return new _Evaluator(environment, aStreamManager, depth).eval(form);
2440
+ }
2441
+ eval(form) {
2442
+ if (Cons.isSymbol(form)) {
2443
+ return this.evaluateSymbol(form);
2444
+ }
2445
+ if (Cons.isNil(form) || Cons.isNotList(form)) {
2446
+ return form;
2447
+ }
2448
+ const formCons = form;
2449
+ if (Cons.isSymbol(formCons.car) && _Evaluator.buildInFunctions.has(formCons.car)) {
2450
+ return this.specialForm(formCons);
2451
+ }
2452
+ return this.entrustApplier(formCons);
2453
+ }
2454
+ eval_lisp(aCons) {
2455
+ return _Evaluator.eval(
2456
+ _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth),
2457
+ this.environment,
2458
+ this.streamManager,
2459
+ this.depth
2460
+ );
2461
+ }
2462
+ evaluateSymbol(aSymbol) {
2463
+ let answer = Cons.nil;
2464
+ if (this.environment.has(aSymbol)) {
2465
+ if (this.isSpy(aSymbol)) {
2466
+ this.spyPrint(this.streamManager.spyStream(aSymbol), aSymbol.toString());
2467
+ this.setDepth(this.depth + 1);
2468
+ }
2469
+ answer = this.environment.get(aSymbol);
2470
+ if (answer instanceof Cons && answer.cdr instanceof Table) {
2471
+ answer = answer.car;
2472
+ }
2473
+ if (this.isSpy(aSymbol)) {
2474
+ this.setDepth(this.depth - 1);
2475
+ this.spyPrint(
2476
+ this.streamManager.spyStream(aSymbol),
2477
+ String(answer) + " <== " + String(aSymbol)
2478
+ );
2479
+ }
2480
+ } else {
2481
+ console.error(noBinding(aSymbol));
2482
+ }
2483
+ return answer;
2484
+ }
2485
+ exit() {
2486
+ console.log("Bye!");
2487
+ throw new ExitError();
2488
+ }
2489
+ gc() {
2490
+ triggerGc();
2491
+ return InterpretedSymbol.of("t");
2492
+ }
2493
+ if_(aCons) {
2494
+ const bool = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2495
+ const anObject = Cons.isNil(bool) ? aCons.nth(3) : aCons.nth(2);
2496
+ return _Evaluator.eval(anObject, this.environment, this.streamManager, this.depth);
2497
+ }
2498
+ indent() {
2499
+ let index = 0;
2500
+ let aString = "";
2501
+ while (index++ < this.depth) {
2502
+ aString += "| ";
2503
+ }
2504
+ return aString;
2505
+ }
2506
+ isSpy(aSymbol) {
2507
+ if (aSymbol == null) {
2508
+ return false;
2509
+ }
2510
+ return this.streamManager.isSpy(aSymbol);
2511
+ }
2512
+ lambda(args2) {
2513
+ const aCons = Cons.cloneValue(args2);
2514
+ const theCons = aCons.cdr;
2515
+ theCons.setCdr(new Cons(this.environment, Cons.nil));
2516
+ return new Cons(InterpretedSymbol.of("lambda"), aCons);
2517
+ }
2518
+ let(aCons) {
2519
+ const aTable = new Table(this.environment);
2520
+ const parameters = aCons.car;
2521
+ const forms = aCons.cdr;
2522
+ let anObject = Cons.nil;
2523
+ this.bindingParallel(parameters, aTable);
2524
+ for (const each of forms.loop()) {
2525
+ anObject = _Evaluator.eval(each, aTable, this.streamManager, this.depth);
2526
+ }
2527
+ return anObject;
2528
+ }
2529
+ letStar(aCons) {
2530
+ const aTable = new Table(this.environment);
2531
+ const parameters = aCons.car;
2532
+ const forms = aCons.cdr;
2533
+ let anObject = Cons.nil;
2534
+ this.binding(parameters, aTable);
2535
+ for (const each of forms.loop()) {
2536
+ anObject = _Evaluator.eval(each, aTable, this.streamManager, this.depth);
2537
+ }
2538
+ return anObject;
2539
+ }
2540
+ not(aCons) {
2541
+ if (Cons.isNil(_Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth))) {
2542
+ return InterpretedSymbol.of("t");
2543
+ }
2544
+ return Cons.nil;
2545
+ }
2546
+ notrace() {
2547
+ this.streamManager.noTrace();
2548
+ return InterpretedSymbol.of("t");
2549
+ }
2550
+ or(aCons) {
2551
+ for (const each of aCons.loop()) {
2552
+ const anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2553
+ if (Cons.isNotNil(anObject)) {
2554
+ return InterpretedSymbol.of("t");
2555
+ }
2556
+ }
2557
+ return Cons.nil;
2558
+ }
2559
+ pop_(aCons) {
2560
+ if (Cons.isNotSymbol(aCons.car)) {
2561
+ console.error(argumentNotSymbol(1));
2562
+ }
2563
+ const aSymbol = aCons.car;
2564
+ const anObject = _Evaluator.eval(aSymbol, this.environment, this.streamManager, this.depth);
2565
+ if (Cons.isNotCons(anObject)) {
2566
+ return Cons.nil;
2567
+ }
2568
+ const consObject = anObject;
2569
+ this.environment.setIfExist(aSymbol, consObject.cdr);
2570
+ return consObject.car;
2571
+ }
2572
+ progn(aCons) {
2573
+ let anObject = Cons.nil;
2574
+ for (const each of aCons.loop()) {
2575
+ anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2576
+ }
2577
+ return anObject;
2578
+ }
2579
+ princ(aCons) {
2580
+ const anObject = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2581
+ process.stdout.write(String(anObject));
2582
+ return anObject;
2583
+ }
2584
+ print(aCons) {
2585
+ const anObject = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2586
+ process.stdout.write(String(anObject) + "\n");
2587
+ return anObject;
2588
+ }
2589
+ push_(aCons) {
2590
+ let anObject = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2591
+ if (Cons.isNotSymbol(aCons.nth(2))) {
2592
+ console.error(argumentNotSymbol(2));
2593
+ }
2594
+ const aSymbol = aCons.nth(2);
2595
+ anObject = new Cons(
2596
+ anObject,
2597
+ _Evaluator.eval(aSymbol, this.environment, this.streamManager, this.depth)
2598
+ );
2599
+ this.environment.setIfExist(aSymbol, anObject);
2600
+ return anObject;
2601
+ }
2602
+ quote(aCons) {
2603
+ return aCons.car;
2604
+ }
2605
+ rplaca(args2) {
2606
+ let anObject = _Evaluator.eval(args2.car, this.environment, this.streamManager, this.depth);
2607
+ if (Cons.isNotCons(anObject)) {
2608
+ console.error(cannotApply("set-car!", anObject));
2609
+ return Cons.nil;
2610
+ }
2611
+ const aCons = anObject;
2612
+ anObject = _Evaluator.eval(args2.nth(2), this.environment, this.streamManager, this.depth);
2613
+ aCons.setCar(anObject);
2614
+ return _Evaluator.eval(args2.car, this.environment, this.streamManager, this.depth);
2615
+ }
2616
+ rplacd(args2) {
2617
+ let anObject = _Evaluator.eval(args2.car, this.environment, this.streamManager, this.depth);
2618
+ if (Cons.isNotCons(anObject)) {
2619
+ console.error(cannotApply("set-cdr!", anObject));
2620
+ return Cons.nil;
2621
+ }
2622
+ const aCons = anObject;
2623
+ anObject = _Evaluator.eval(args2.nth(2), this.environment, this.streamManager, this.depth);
2624
+ aCons.setCdr(anObject);
2625
+ return _Evaluator.eval(args2.car, this.environment, this.streamManager, this.depth);
2626
+ }
2627
+ setq(args2) {
2628
+ let anObject = Cons.nil;
2629
+ const anIterator = args2.loop();
2630
+ const index = -1;
2631
+ while (anIterator.hasNext()) {
2632
+ let key = null;
2633
+ if (Cons.isSymbol(args2.nth(index + 2))) {
2634
+ key = anIterator.next();
2635
+ } else {
2636
+ console.error(notSymbol(args2.car));
2637
+ }
2638
+ if (!anIterator.hasNext()) {
2639
+ console.error(SIZES_DO_NOT_MATCH);
2640
+ }
2641
+ anObject = _Evaluator.eval(
2642
+ anIterator.next(),
2643
+ this.environment,
2644
+ this.streamManager,
2645
+ this.depth
2646
+ );
2647
+ this.environment.set(key, anObject);
2648
+ }
2649
+ return anObject;
2650
+ }
2651
+ set_allq(args2) {
2652
+ let anObject = Cons.nil;
2653
+ const anIterator = args2.loop();
2654
+ const index = -1;
2655
+ while (anIterator.hasNext()) {
2656
+ let key = null;
2657
+ if (Cons.isSymbol(args2.nth(index + 2))) {
2658
+ key = anIterator.next();
2659
+ } else {
2660
+ console.error(notSymbol(args2.car));
2661
+ }
2662
+ anObject = _Evaluator.eval(
2663
+ anIterator.next(),
2664
+ this.environment,
2665
+ this.streamManager,
2666
+ this.depth
2667
+ );
2668
+ this.environment.setIfExist(key, anObject);
2669
+ }
2670
+ return anObject;
2671
+ }
2672
+ setDepth(aNumber) {
2673
+ this.depth = aNumber;
2674
+ return null;
2675
+ }
2676
+ static setup() {
2677
+ try {
2678
+ const entries = [
2679
+ ["and", "and"],
2680
+ ["apply", "apply_lisp"],
2681
+ ["bind", "bind"],
2682
+ ["cond", "cond"],
2683
+ ["defun", "defun"],
2684
+ ["do", "do_"],
2685
+ ["dolist", "doList"],
2686
+ ["do*", "doStar"],
2687
+ ["eval", "eval_lisp"],
2688
+ ["exit", "exit"],
2689
+ ["gc", "gc"],
2690
+ ["if", "if_"],
2691
+ ["lambda", "lambda"],
2692
+ ["let", "let"],
2693
+ ["let*", "letStar"],
2694
+ ["not", "not"],
2695
+ ["notrace", "notrace"],
2696
+ ["or", "or"],
2697
+ ["pop", "pop_"],
2698
+ ["progn", "progn"],
2699
+ ["princ", "princ"],
2700
+ ["print", "print"],
2701
+ ["push", "push_"],
2702
+ ["quote", "quote"],
2703
+ ["rplaca", "rplaca"],
2704
+ ["rplacd", "rplacd"],
2705
+ ["setq", "setq"],
2706
+ ["set-allq", "set_allq"],
2707
+ ["terpri", "terpri"],
2708
+ ["time", "time"],
2709
+ ["trace", "trace"],
2710
+ ["unless", "unless"],
2711
+ ["when", "when"]
2712
+ ];
2713
+ return new Map(entries.map(([key, value]) => [InterpretedSymbol.of(key), value]));
2714
+ } catch {
2715
+ throw new Error("NullPointerException (Evaluator, initialize)");
2716
+ }
2717
+ }
2718
+ specialForm(form) {
2719
+ const aSymbol = form.car;
2720
+ if (this.isSpy(aSymbol)) {
2721
+ this.spyPrint(this.streamManager.spyStream(aSymbol), form.toString());
2722
+ this.setDepth(this.depth + 1);
2723
+ }
2724
+ const aCons = form.cdr;
2725
+ const methodName = _Evaluator.buildInFunctions.get(aSymbol);
2726
+ const target = this;
2727
+ const fn = target[methodName];
2728
+ if (typeof fn !== "function") {
2729
+ throw new TypeError(`${this.constructor.name} does not have a method named "${methodName}"`);
2730
+ }
2731
+ const answer = fn.apply(target, [aCons]);
2732
+ if (this.isSpy(aSymbol)) {
2733
+ this.setDepth(this.depth - 1);
2734
+ this.spyPrint(
2735
+ this.streamManager.spyStream(aSymbol),
2736
+ String(answer) + " <== " + String(aSymbol)
2737
+ );
2738
+ }
2739
+ return answer;
2740
+ }
2741
+ // NOTE: Lisp's trace/spy writes the call line to a designated output stream. The original
2742
+ // implementation logged the stream object itself rather than writing to it (a bug that
2743
+ // went unnoticed because trace/spy is rarely exercised). We now write the indented line
2744
+ // to the given WritableStream, falling back to stdout when the argument is a string
2745
+ // descriptor (stored by `(spy fn "label")`) or null.
2746
+ spyPrint(aStream, line) {
2747
+ const target = aStream != null && typeof aStream === "object" && "write" in aStream ? aStream : process.stdout;
2748
+ target.write(this.indent() + line + "\n");
2749
+ return null;
2750
+ }
2751
+ terpri() {
2752
+ process.stdout.write("\n");
2753
+ return InterpretedSymbol.of("t");
2754
+ }
2755
+ time(aCons) {
2756
+ const start = process.hrtime();
2757
+ _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2758
+ const end = process.hrtime(start);
2759
+ return end[1] / 1e6;
2760
+ }
2761
+ trace() {
2762
+ this.streamManager.trace();
2763
+ return InterpretedSymbol.of("t");
2764
+ }
2765
+ unless(aCons) {
2766
+ let anObject = Cons.nil;
2767
+ const theCons = aCons.cdr;
2768
+ const flag = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2769
+ if (Cons.isNotNil(flag)) {
2770
+ return Cons.nil;
2771
+ }
2772
+ for (const each of theCons.loop()) {
2773
+ anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2774
+ }
2775
+ return anObject;
2776
+ }
2777
+ when(aCons) {
2778
+ let anObject = Cons.nil;
2779
+ const theCons = aCons.cdr;
2780
+ const flag = _Evaluator.eval(aCons.car, this.environment, this.streamManager, this.depth);
2781
+ if (Cons.isNil(flag)) {
2782
+ return Cons.nil;
2783
+ }
2784
+ for (const each of theCons.loop()) {
2785
+ anObject = _Evaluator.eval(each, this.environment, this.streamManager, this.depth);
2786
+ }
2787
+ return anObject;
2788
+ }
2789
+ };
2790
+
2791
+ // src/LispInterpreter/index.ts
2792
+ var require2 = (0, import_node_module.createRequire)(importMetaUrl);
2793
+ var LispInterpreter = class {
2794
+ root;
2795
+ streamManager;
2796
+ rl;
2797
+ constructor() {
2798
+ this.root = this.initializeTable();
2799
+ this.streamManager = new StreamManager();
2800
+ const readline = require2("node:readline");
2801
+ this.rl = readline.createInterface({
2802
+ input: process.stdin,
2803
+ output: process.stdout,
2804
+ prompt: ">> "
2805
+ });
2806
+ }
2807
+ /**
2808
+ * Starts the interpreter.
2809
+ */
2810
+ run() {
2811
+ let aCons = new Cons();
2812
+ let aString = "";
2813
+ let leftParentheses = 0;
2814
+ let exitedViaLisp = false;
2815
+ this.rl.prompt();
2816
+ this.rl.on("line", (line) => {
2817
+ line += " ";
2818
+ for (const aCharacter of line) {
2819
+ if (aCharacter === "(") {
2820
+ leftParentheses++;
2821
+ }
2822
+ if (aCharacter === ")") {
2823
+ leftParentheses--;
2824
+ }
2825
+ aString += aCharacter;
2826
+ }
2827
+ if (leftParentheses <= 0) {
2828
+ aCons = this.parse(aString);
2829
+ try {
2830
+ for (const each of aCons.loop()) {
2831
+ process.stdout.write(this.eval(each).toString() + "\n");
2832
+ }
2833
+ } catch (error) {
2834
+ if (error instanceof ExitError) {
2835
+ exitedViaLisp = true;
2836
+ this.rl.close();
2837
+ return;
2838
+ }
2839
+ console.error("*** can not eval " + aCons.toString() + " ***");
2840
+ process.stdout.write(Cons.nil.toString() + "\n");
2841
+ }
2842
+ leftParentheses = 0;
2843
+ aString = "";
2844
+ this.rl.prompt();
2845
+ }
2846
+ }).on("close", () => {
2847
+ if (!exitedViaLisp) {
2848
+ console.log("\nBye!");
2849
+ }
2850
+ });
2851
+ return null;
2852
+ }
2853
+ /**
2854
+ * Evaluates the given list and returns the evaluation result.
2855
+ */
2856
+ eval(aCons) {
2857
+ try {
2858
+ return Evaluator.eval(aCons, this.root, this.streamManager);
2859
+ } catch (error) {
2860
+ if (error instanceof ExitError) throw error;
2861
+ console.error("*** can not eval " + aCons.toString() + " ***");
2862
+ return Cons.nil;
2863
+ }
2864
+ }
2865
+ /**
2866
+ * Parses the source string, evaluates every expression it contains, and returns the results as an array.
2867
+ */
2868
+ evalAll(source) {
2869
+ const ast = this.parse(source);
2870
+ const results = [];
2871
+ if (Cons.isCons(ast)) {
2872
+ for (const expr of ast.loop()) {
2873
+ results.push(this.eval(expr));
2874
+ }
2875
+ }
2876
+ return results;
2877
+ }
2878
+ /**
2879
+ * Parses and evaluates the source string and returns the value of the last expression.
2880
+ */
2881
+ evalString(source) {
2882
+ const results = this.evalAll(source);
2883
+ return results.length === 0 ? Cons.nil : results.at(-1) ?? Cons.nil;
2884
+ }
2885
+ /**
2886
+ * Parses the given string into a list and returns it.
2887
+ */
2888
+ parse(aString) {
2889
+ try {
2890
+ return Cons.parse("(" + aString + "\n);");
2891
+ } catch {
2892
+ console.error("*** can not parse " + aString.replaceAll("\n", "") + " ***");
2893
+ return Cons.nil;
2894
+ }
2895
+ }
2896
+ /**
2897
+ * Sets the given environment as the root of the environment chain.
2898
+ */
2899
+ setRoot(environment) {
2900
+ if (environment instanceof Table) {
2901
+ environment.setRoot(true);
2902
+ this.root = environment;
2903
+ }
2904
+ return null;
2905
+ }
2906
+ /**
2907
+ * Initializes the environment table.
2908
+ */
2909
+ initializeTable() {
2910
+ const aList = [];
2911
+ const aTable = new Table();
2912
+ aTable.setRoot(true);
2913
+ aList.push(
2914
+ "abs",
2915
+ "add",
2916
+ "and",
2917
+ "apply",
2918
+ "assoc",
2919
+ "atom",
2920
+ "bind",
2921
+ "car",
2922
+ "cdr",
2923
+ "characterp",
2924
+ "cond",
2925
+ "cons",
2926
+ "consp",
2927
+ "copy",
2928
+ "cos",
2929
+ "floatp",
2930
+ "defun",
2931
+ "divide",
2932
+ "do",
2933
+ "do*",
2934
+ "dolist",
2935
+ "doublep",
2936
+ "eq",
2937
+ "equal",
2938
+ "exit",
2939
+ "exp",
2940
+ "gc",
2941
+ "gensym",
2942
+ "if",
2943
+ "integerp",
2944
+ "lambda",
2945
+ "let",
2946
+ "let*",
2947
+ "last",
2948
+ "list",
2949
+ "listp",
2950
+ "mapcar",
2951
+ "member",
2952
+ "memq",
2953
+ "mod",
2954
+ "multiply",
2955
+ "napier",
2956
+ "neq",
2957
+ "nequal",
2958
+ "not",
2959
+ "notrace",
2960
+ "nth",
2961
+ "null",
2962
+ "numberp",
2963
+ "or",
2964
+ "pi",
2965
+ "pop",
2966
+ "progn",
2967
+ "printc",
2968
+ "print",
2969
+ "push",
2970
+ "quote",
2971
+ "random",
2972
+ "reload",
2973
+ "round",
2974
+ "rplaca",
2975
+ "rplacd",
2976
+ "setq",
2977
+ "set-allq",
2978
+ "sin",
2979
+ "sqrt",
2980
+ "subtract",
2981
+ "stringp",
2982
+ "symbolp",
2983
+ "tan",
2984
+ "terpri",
2985
+ "time",
2986
+ "trace",
2987
+ "unless",
2988
+ "when",
2989
+ "+",
2990
+ "-",
2991
+ "*",
2992
+ "/",
2993
+ "//",
2994
+ "=",
2995
+ "==",
2996
+ "~=",
2997
+ "~~",
2998
+ "<",
2999
+ "<=",
3000
+ ">",
3001
+ ">="
3002
+ );
3003
+ for (const each of aList) {
3004
+ const aSymbol = InterpretedSymbol.of(each);
3005
+ aTable.set(aSymbol, aSymbol);
3006
+ }
3007
+ let aString;
3008
+ let aCons;
3009
+ aString = "(lambda (list1 list2) (cond ((null (listp list1)) nil) ((null (listp list2)) nil) ((null list1) list2) (t (cons (car list1) (append (cdr list1) list2)))))";
3010
+ aCons = Cons.parse(aString);
3011
+ aCons.last().setCdr(new Cons(aTable, Cons.nil));
3012
+ aTable.set(InterpretedSymbol.of("append"), aCons);
3013
+ aString = "(lambda (l n) (cond ((<= (length l) n) nil) (t (cons (car l) (butlast (cdr l) n)))))";
3014
+ aCons = Cons.parse(aString);
3015
+ aCons.last().setCdr(new Cons(aTable, Cons.nil));
3016
+ aTable.set(InterpretedSymbol.of("butlast"), aCons);
3017
+ aString = "(lambda (l) (cond ((null (listp l)) nil) ((null l) 0) (t (+ 1 (length (cdr l))))))";
3018
+ aCons = Cons.parse(aString);
3019
+ aCons.last().setCdr(new Cons(aTable, Cons.nil));
3020
+ aTable.set(InterpretedSymbol.of("length"), aCons);
3021
+ aString = "(lambda (n l) (cond ((> n (length l)) nil) ((= 0 n) l) (t (nthcdr (- n 1) (cdr l)))))";
3022
+ aCons = Cons.parse(aString);
3023
+ aCons.last().setCdr(new Cons(aTable, Cons.nil));
3024
+ aTable.set(InterpretedSymbol.of("nthcdr"), aCons);
3025
+ aString = "(lambda (l) (cond ((null (listp l)) l) ((null l) '()) (t (append (reverse (cdr l)) (list (car l))))))";
3026
+ aCons = Cons.parse(aString);
3027
+ aCons.last().setCdr(new Cons(aTable, Cons.nil));
3028
+ aTable.set(InterpretedSymbol.of("reverse"), aCons);
3029
+ aTable.set(InterpretedSymbol.of("t"), InterpretedSymbol.of("t"));
3030
+ return aTable;
3031
+ }
3032
+ };
3033
+
3034
+ // src/cli.ts
3035
+ var HELP_MESSAGE = `Usage: kei-lisp [options]
3036
+
3037
+ Options:
3038
+ -v, --version Show version number
3039
+ -h, --help Show help`;
3040
+ var args = process.argv.slice(2);
3041
+ if (args.includes("--version") || args.includes("-v")) {
3042
+ console.log(`kei-lisp v${package_default.version}`);
3043
+ } else if (args.includes("--help") || args.includes("-h")) {
3044
+ console.log(HELP_MESSAGE);
3045
+ } else if (args.length > 0) {
3046
+ console.error(`kei-lisp: unknown argument: ${args[0]}`);
3047
+ console.error(HELP_MESSAGE);
3048
+ process.exitCode = 1;
3049
+ } else {
3050
+ new LispInterpreter().run();
3051
+ }