@graffiticode/parser 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/api/src/config/config.d.ts +3 -0
  2. package/dist/api/src/config/config.js +4 -0
  3. package/dist/api/src/config/config.js.map +1 -0
  4. package/dist/api/src/config/index.d.ts +1 -0
  5. package/dist/api/src/config/index.js +3 -0
  6. package/dist/api/src/config/index.js.map +1 -0
  7. package/dist/api/src/lang/base-url.d.ts +7 -0
  8. package/dist/api/src/lang/base-url.js +24 -0
  9. package/dist/api/src/lang/base-url.js.map +1 -0
  10. package/dist/api/src/lang/compile.d.ts +4 -0
  11. package/dist/api/src/lang/compile.js +6 -0
  12. package/dist/api/src/lang/compile.js.map +1 -0
  13. package/dist/api/src/lang/get-asset.d.ts +4 -0
  14. package/dist/api/src/lang/get-asset.js +9 -0
  15. package/dist/api/src/lang/get-asset.js.map +1 -0
  16. package/dist/api/src/lang/index.d.ts +4 -0
  17. package/dist/api/src/lang/index.js +22 -0
  18. package/dist/api/src/lang/index.js.map +1 -0
  19. package/dist/api/src/lang/ping-lang.d.ts +5 -0
  20. package/dist/api/src/lang/ping-lang.js +31 -0
  21. package/dist/api/src/lang/ping-lang.js.map +1 -0
  22. package/dist/api/src/util.d.ts +23 -0
  23. package/dist/api/src/util.js +187 -0
  24. package/dist/api/src/util.js.map +1 -0
  25. package/dist/parser/src/ast.d.ts +58 -0
  26. package/dist/parser/src/ast.js +683 -0
  27. package/dist/parser/src/ast.js.map +1 -0
  28. package/dist/parser/src/env.d.ts +8 -0
  29. package/dist/parser/src/env.js +38 -0
  30. package/dist/parser/src/env.js.map +1 -0
  31. package/dist/parser/src/fold.d.ts +4 -0
  32. package/dist/parser/src/fold.js +217 -0
  33. package/dist/parser/src/fold.js.map +1 -0
  34. package/dist/parser/src/folder.d.ts +30 -0
  35. package/dist/parser/src/folder.js +231 -0
  36. package/dist/parser/src/folder.js.map +1 -0
  37. package/dist/parser/src/index.d.ts +5 -0
  38. package/dist/parser/src/index.js +6 -0
  39. package/dist/parser/src/index.js.map +1 -0
  40. package/dist/parser/src/parse.d.ts +56 -0
  41. package/dist/parser/src/parse.js +902 -0
  42. package/dist/parser/src/parse.js.map +1 -0
  43. package/dist/parser/src/parser.d.ts +17 -0
  44. package/dist/parser/src/parser.js +89 -0
  45. package/dist/parser/src/parser.js.map +1 -0
  46. package/dist/parser/src/parserForTests.d.ts +3 -0
  47. package/dist/parser/src/parserForTests.js +4 -0
  48. package/dist/parser/src/parserForTests.js.map +1 -0
  49. package/dist/parser/src/stringstream.d.ts +10 -0
  50. package/dist/parser/src/stringstream.js +21 -0
  51. package/dist/parser/src/stringstream.js.map +1 -0
  52. package/dist/parser/src/testing/index.d.ts +2 -0
  53. package/dist/parser/src/testing/index.js +17 -0
  54. package/dist/parser/src/testing/index.js.map +1 -0
  55. package/dist/parser/src/types.d.ts +44 -0
  56. package/dist/parser/src/types.js +2 -0
  57. package/dist/parser/src/types.js.map +1 -0
  58. package/package.json +5 -9
  59. package/src/ast.js +730 -0
  60. package/src/env.js +50 -0
  61. package/src/folder.js +249 -0
  62. package/src/folder.spec.js +42 -0
  63. package/src/parse.js +35 -935
  64. package/src/parse.spec.js +118 -0
  65. package/src/parse.spec.js~ +119 -0
  66. package/src/parse.ts~ +1037 -0
  67. package/src/parser.spec.js +11 -35
  68. package/src/{parser.js~ → parser.ts~} +25 -7
  69. package/src/stringstream.js +22 -0
  70. package/src/fold.js +0 -235
  71. package/src/parser.spec.js~ +0 -175
@@ -0,0 +1,902 @@
1
+ // Copyright 2021, ARTCOMPILER INC
2
+ /*
3
+ Error handling
4
+ -- every range points to a node
5
+ -- multiple ranges can point to the same node
6
+ -- errors are associated with ranges
7
+ -- errors are determined by nodes in context
8
+
9
+ -- parser returns an ast which might compile to a list of errors of the form
10
+ {from, to, message, severity}
11
+ -- compiler checkers report these errors in the err callback arg
12
+ */
13
+ import assert from "assert";
14
+ import { folder } from "./fold.js";
15
+ // Global declarations for CodeMirror and window
16
+ let CodeMirror;
17
+ if (typeof CodeMirror === "undefined") {
18
+ CodeMirror = {
19
+ Pos: function () {
20
+ return {};
21
+ }
22
+ };
23
+ }
24
+ let window;
25
+ if (typeof window === "undefined") {
26
+ window = {
27
+ gcexports: {
28
+ coords: {},
29
+ errors: []
30
+ },
31
+ isSynthetic: true
32
+ };
33
+ }
34
+ // ast module
35
+ export const Ast = (function () {
36
+ const ASSERT = true;
37
+ const assert = function (val, str) {
38
+ if (!ASSERT) {
39
+ return;
40
+ }
41
+ if (str === undefined) {
42
+ str = "failed!";
43
+ }
44
+ if (!val) {
45
+ throw new Error(str);
46
+ }
47
+ };
48
+ class AstClass {
49
+ }
50
+ const astClass = new AstClass();
51
+ // Assign prototype methods to astClass
52
+ function push(ctx, node) {
53
+ let nid;
54
+ if (typeof node === "number") { // if already interned
55
+ nid = node;
56
+ }
57
+ else {
58
+ nid = intern(ctx, node);
59
+ }
60
+ ctx.state.nodeStack.push(nid);
61
+ }
62
+ function topNode(ctx) {
63
+ const nodeStack = ctx.state.nodeStack;
64
+ return nodeStack[nodeStack.length - 1];
65
+ }
66
+ function pop(ctx) {
67
+ const nodeStack = ctx.state.nodeStack;
68
+ return nodeStack.pop();
69
+ }
70
+ function peek(ctx, n) {
71
+ if (n === undefined) {
72
+ n = 0;
73
+ }
74
+ const nodeStack = ctx.state.nodeStack;
75
+ return nodeStack[nodeStack.length - 1 - n];
76
+ }
77
+ function intern(ctx, n) {
78
+ if (!n) {
79
+ return 0;
80
+ }
81
+ const nodeMap = ctx.state.nodeMap;
82
+ const nodePool = ctx.state.nodePool;
83
+ const tag = n.tag;
84
+ let elts = "";
85
+ const count = n.elts.length;
86
+ for (let i = 0; i < count; i++) {
87
+ if (typeof n.elts[i] === "object") {
88
+ n.elts[i] = intern(ctx, n.elts[i]);
89
+ }
90
+ elts += n.elts[i];
91
+ }
92
+ const key = tag + count + elts;
93
+ let nid = nodeMap[key];
94
+ if (nid === undefined) {
95
+ nodePool.push({ tag, elts: n.elts });
96
+ nid = nodePool.length - 1;
97
+ nodeMap[key] = nid;
98
+ if (n.coord) {
99
+ ctx.state.coords[nid] = n.coord;
100
+ }
101
+ }
102
+ return nid;
103
+ }
104
+ function node(ctx, nid) {
105
+ const n = ctx.state.nodePool[nid];
106
+ if (!nid) {
107
+ return null;
108
+ }
109
+ else if (!n) {
110
+ return {};
111
+ }
112
+ const elts = [];
113
+ switch (n.tag) {
114
+ case "NULL":
115
+ break;
116
+ case "NUM":
117
+ case "STR":
118
+ case "IDENT":
119
+ case "BOOL":
120
+ elts[0] = n.elts[0];
121
+ break;
122
+ default:
123
+ for (let i = 0; i < n.elts.length; i++) {
124
+ elts[i] = node(ctx, n.elts[i]);
125
+ }
126
+ break;
127
+ }
128
+ return {
129
+ tag: n.tag,
130
+ elts,
131
+ coord: getCoord(ctx)
132
+ };
133
+ }
134
+ function dumpAll(ctx) {
135
+ const nodePool = ctx.state.nodePool;
136
+ let s = "\n{";
137
+ for (let i = 1; i < nodePool.length; i++) {
138
+ const n = nodePool[i];
139
+ s = s + "\n " + i + ": " + dump(n) + ",";
140
+ }
141
+ s += "\n root: " + (nodePool.length - 1);
142
+ s += "\n}\n";
143
+ return s;
144
+ }
145
+ function poolToJSON(ctx) {
146
+ const nodePool = ctx.state.nodePool;
147
+ const obj = {};
148
+ for (let i = 1; i < nodePool.length; i++) {
149
+ const n = nodePool[i];
150
+ obj[i] = nodeToJSON(n);
151
+ }
152
+ obj.root = (nodePool.length - 1);
153
+ return obj;
154
+ }
155
+ function nodeToJSON(n) {
156
+ let obj;
157
+ if (typeof n === "object") {
158
+ switch (n.tag) {
159
+ case "num":
160
+ obj = n.elts[0];
161
+ break;
162
+ case "str":
163
+ obj = n.elts[0];
164
+ break;
165
+ default:
166
+ obj = {};
167
+ obj.tag = n.tag;
168
+ obj.elts = [];
169
+ for (let i = 0; i < n.elts.length; i++) {
170
+ obj.elts[i] = nodeToJSON(n.elts[i]);
171
+ }
172
+ break;
173
+ }
174
+ }
175
+ else if (typeof n === "string") {
176
+ obj = n;
177
+ }
178
+ else {
179
+ obj = n;
180
+ }
181
+ return obj;
182
+ }
183
+ function dump(n) {
184
+ let s = "";
185
+ if (typeof n === "object") {
186
+ switch (n.tag) {
187
+ case "num":
188
+ s = n.elts[0];
189
+ break;
190
+ case "str":
191
+ s = "\"" + n.elts[0] + "\"";
192
+ break;
193
+ default:
194
+ if (!n.elts) {
195
+ s += "<invalid>";
196
+ }
197
+ else {
198
+ s = "{ tag: \"" + n.tag + "\", elts: [ ";
199
+ for (let i = 0; i < n.elts.length; i++) {
200
+ if (i > 0) {
201
+ s += " , ";
202
+ }
203
+ s += dump(n.elts[i]);
204
+ }
205
+ s += " ] }";
206
+ }
207
+ break;
208
+ }
209
+ }
210
+ else if (typeof n === "string") {
211
+ s = "\"" + n + "\"";
212
+ }
213
+ else {
214
+ s = String(n);
215
+ }
216
+ return s;
217
+ }
218
+ function fold(ctx, fn, args) {
219
+ // Local defs:
220
+ // -- put bindings in env
221
+ // Three cases:
222
+ // -- full application, all args are available at parse time
223
+ // -- partial application, only some args are available at parse time
224
+ // -- late application, args are available at compile time (not parse time)
225
+ // apply <[x y]: add x y> data..
226
+ // x: val 0 data
227
+ // y: val 1 data
228
+ env.enterEnv(ctx, fn.name);
229
+ if (fn.env) {
230
+ const lexicon = fn.env.lexicon;
231
+ const pattern = Ast.node(ctx, fn.env.pattern);
232
+ let outerEnv = null;
233
+ // let isListPattern;
234
+ // setup inner environment record (lexicon)
235
+ if (pattern && pattern.elts &&
236
+ pattern.elts.length === 1 &&
237
+ pattern.elts[0].tag === "LIST") {
238
+ // For now we only support one pattern per param list.
239
+ // isListPattern = true;
240
+ }
241
+ for (const id in lexicon) {
242
+ // For each parameter, get its definition assign the value of the argument
243
+ // used on the current function application.
244
+ if (!id)
245
+ continue;
246
+ const word = JSON.parse(JSON.stringify(lexicon[id])); // poor man's copy.
247
+ const index = args.length - word.offset - 1;
248
+ // TODO we currently ignore list patterns
249
+ // if (isListPattern) {
250
+ // // <[x y]: ...> foo..
251
+ // word.nid = Ast.intern(ctx, {
252
+ // tag: "VAL",
253
+ // elts: [{
254
+ // tag: "NUM",
255
+ // elts: [
256
+ // String(word.offset),
257
+ // ]}, {
258
+ // tag: "ARG",
259
+ // elts: [{
260
+ // tag: "NUM",
261
+ // elts: ["0"]
262
+ // }]
263
+ // }]
264
+ // });
265
+ // } else
266
+ if (index >= 0 && index < args.length) {
267
+ word.nid = args[index];
268
+ }
269
+ if (index < 0) {
270
+ // We've got an unbound variable or a variable with a default value,
271
+ // so add it to the new variable list.
272
+ // <x:x> => <x:x>
273
+ // (<x y: add x y> 10) => <y: add 10 y>
274
+ // (<y: let x = 10.. add x y>) => <y: add 10 y>
275
+ if (!outerEnv) {
276
+ outerEnv = {};
277
+ }
278
+ outerEnv[id] = word;
279
+ }
280
+ env.addWord(ctx, id, word);
281
+ }
282
+ folder.fold(ctx, fn.nid);
283
+ if (outerEnv) {
284
+ lambda(ctx, {
285
+ lexicon: outerEnv,
286
+ pattern // FIXME need to trim pattern if some args where applied.
287
+ }, pop(ctx));
288
+ }
289
+ }
290
+ env.exitEnv(ctx);
291
+ }
292
+ function applyLate(ctx, count) {
293
+ // Ast.applyLate
294
+ const elts = [];
295
+ for (let i = count; i > 0; i--) {
296
+ elts.push(pop(ctx));
297
+ }
298
+ push(ctx, {
299
+ tag: "APPLY",
300
+ elts
301
+ });
302
+ }
303
+ function apply(ctx, fnId, argc) {
304
+ // Construct function and apply available arguments.
305
+ const fn = node(ctx, fnId);
306
+ // if (fn.tag !== "LAMBDA") {
307
+ // // Construct an APPLY node for compiling later.
308
+ // return {
309
+ // tag: "APPLY",
310
+ // elts: [
311
+ // fnId,
312
+ // ]
313
+ // };
314
+ // }
315
+ // Construct a lexicon
316
+ const lexicon = {};
317
+ let paramc = 0;
318
+ fn.elts[0].elts.forEach(function (n, i) {
319
+ const name = n.elts[0];
320
+ const nid = Ast.intern(ctx, fn.elts[3].elts[i]);
321
+ lexicon[name] = {
322
+ cls: "val",
323
+ name,
324
+ offset: i,
325
+ nid
326
+ };
327
+ if (!nid) {
328
+ // Parameters don't have nids.
329
+ // assert that there are parameters after a binding without a nid.
330
+ paramc++;
331
+ }
332
+ });
333
+ const def = {
334
+ name: "lambda",
335
+ nid: Ast.intern(ctx, fn.elts[1]),
336
+ env: {
337
+ lexicon,
338
+ pattern: Ast.intern(ctx, fn.elts[2])
339
+ }
340
+ };
341
+ const elts = [];
342
+ // While there are args on the stack, pop them.
343
+ while (argc-- > 0 && paramc-- > 0) {
344
+ const elt = pop(ctx);
345
+ elts.unshift(elt); // Get the order right.
346
+ }
347
+ fold(ctx, def, elts);
348
+ }
349
+ // Node constructors
350
+ function error(ctx, str, coord) {
351
+ console.log("error()", "str=" + str, "coord=" + JSON.stringify(coord));
352
+ const from = coord?.from !== undefined ? coord.from : -1;
353
+ const to = coord?.to !== undefined ? coord.to : -1;
354
+ number(ctx, to);
355
+ number(ctx, from);
356
+ string(ctx, str, coord);
357
+ push(ctx, {
358
+ tag: "ERROR",
359
+ elts: [
360
+ pop(ctx),
361
+ pop(ctx),
362
+ pop(ctx),
363
+ ],
364
+ coord
365
+ });
366
+ }
367
+ function bool(ctx, val) {
368
+ let b;
369
+ if (val) {
370
+ b = true;
371
+ }
372
+ else {
373
+ b = false;
374
+ }
375
+ push(ctx, {
376
+ tag: "BOOL",
377
+ elts: [b]
378
+ });
379
+ }
380
+ function nul(ctx) {
381
+ push(ctx, {
382
+ tag: "NULL",
383
+ elts: []
384
+ });
385
+ }
386
+ function number(ctx, num, coord) {
387
+ assert(typeof num === "string" || typeof num === "number");
388
+ push(ctx, {
389
+ tag: "NUM",
390
+ elts: [String(num)],
391
+ coord
392
+ });
393
+ }
394
+ function string(ctx, str, coord) {
395
+ push(ctx, {
396
+ tag: "STR",
397
+ elts: [str],
398
+ coord
399
+ });
400
+ }
401
+ function name(ctx, name, coord) {
402
+ push(ctx, {
403
+ tag: "IDENT",
404
+ elts: [name],
405
+ coord
406
+ });
407
+ }
408
+ function expr(ctx, argc) {
409
+ // Ast.expr -- construct a expr node for the compiler.
410
+ const elts = [];
411
+ const pos = getPos(ctx);
412
+ console.trace("expr()", "argc=" + argc, "nodeStack=" + JSON.stringify(ctx.state.nodeStack, null, 2));
413
+ assertErr(ctx, argc <= ctx.state.nodeStack.length - 1, `Too few arguments. Expected ${argc} got ${ctx.state.nodeStack.length - 1}.`, {
414
+ from: pos - 1, to: pos
415
+ });
416
+ while (argc--) {
417
+ const elt = pop(ctx);
418
+ elts.push(elt);
419
+ }
420
+ const nameId = pop(ctx);
421
+ console.log("expr()", "nameId=" + nameId);
422
+ assertErr(ctx, nameId, "Ill formed node.");
423
+ const e = node(ctx, nameId).elts;
424
+ assertErr(ctx, e && e.length > 0, "Ill formed node.");
425
+ const nodeName = e[0];
426
+ push(ctx, {
427
+ tag: nodeName,
428
+ elts,
429
+ coord: getCoord(ctx)
430
+ });
431
+ }
432
+ function parenExpr(ctx, coord) {
433
+ // Ast.parenExpr
434
+ const elts = [];
435
+ const elt = pop(ctx);
436
+ elts.push(elt);
437
+ push(ctx, {
438
+ tag: "PAREN",
439
+ elts,
440
+ coord
441
+ });
442
+ }
443
+ function list(ctx, count, coord, reverse) {
444
+ // Ast.list
445
+ const elts = [];
446
+ for (let i = count; i > 0; i--) {
447
+ const elt = pop(ctx);
448
+ if (elt !== undefined) {
449
+ elts.push(elt);
450
+ }
451
+ }
452
+ push(ctx, {
453
+ tag: "LIST",
454
+ elts: reverse ? elts : elts.reverse(),
455
+ coord
456
+ });
457
+ }
458
+ function binaryExpr(ctx, name) {
459
+ const elts = [];
460
+ // args are in the order produced by the parser
461
+ elts.push(pop(ctx));
462
+ elts.push(pop(ctx));
463
+ push(ctx, {
464
+ tag: name,
465
+ elts: elts.reverse()
466
+ });
467
+ }
468
+ function unaryExpr(ctx, name) {
469
+ const elts = [];
470
+ elts.push(pop(ctx));
471
+ push(ctx, {
472
+ tag: name,
473
+ elts
474
+ });
475
+ }
476
+ function prefixExpr(ctx, name) {
477
+ const elts = [];
478
+ elts.push(pop(ctx));
479
+ push(ctx, {
480
+ tag: name,
481
+ elts
482
+ });
483
+ }
484
+ function neg(ctx) {
485
+ const v1 = +node(ctx, pop(ctx)).elts[0];
486
+ number(ctx, -1 * v1);
487
+ }
488
+ function add(ctx, coord) {
489
+ const n2 = node(ctx, pop(ctx));
490
+ const n1 = node(ctx, pop(ctx));
491
+ const v2 = n2.elts[0];
492
+ const v1 = n1.elts[0];
493
+ if (n1.tag !== "NUM" || n2.tag !== "NUM") {
494
+ push(ctx, {
495
+ tag: "ADD",
496
+ elts: [n1, n2],
497
+ coord
498
+ });
499
+ }
500
+ else {
501
+ number(ctx, +v1 + +v2);
502
+ }
503
+ }
504
+ function sub(ctx) {
505
+ const n2 = node(ctx, pop(ctx));
506
+ const n1 = node(ctx, pop(ctx));
507
+ const v2 = n2.elts[0];
508
+ const v1 = n1.elts[0];
509
+ if (n1.tag !== "NUM" || n2.tag !== "NUM") {
510
+ push(ctx, { tag: "SUB", elts: [n1, n2] });
511
+ }
512
+ else {
513
+ number(ctx, +v1 - +v2);
514
+ }
515
+ }
516
+ // function mul(ctx: ParserContext): void {
517
+ // let n2 = node(ctx, pop(ctx));
518
+ // let n1 = node(ctx, pop(ctx));
519
+ // const v2 = n2.elts[0];
520
+ // const v1 = n1.elts[0];
521
+ // if (n1.tag === undefined) {
522
+ // n1 = n1.elts[0];
523
+ // }
524
+ // if (n2.tag === undefined) {
525
+ // n2 = n2.elts[0];
526
+ // }
527
+ // if (n1.tag !== "NUM" || n2.tag !== "NUM") {
528
+ // push(ctx, { tag: "MUL", elts: [n2, n1] });
529
+ // } else {
530
+ // number(ctx, +v1 * +v2);
531
+ // }
532
+ // }
533
+ function div(ctx) {
534
+ const n2 = node(ctx, pop(ctx));
535
+ const n1 = node(ctx, pop(ctx));
536
+ const v2 = n2.elts[0];
537
+ const v1 = n1.elts[0];
538
+ if (n1.tag !== "NUM" || n2.tag !== "NUM") {
539
+ push(ctx, { tag: "DIV", elts: [n1, n2] });
540
+ }
541
+ else {
542
+ number(ctx, +v1 / +v2);
543
+ }
544
+ }
545
+ function mod(ctx) {
546
+ const n2 = node(ctx, pop(ctx));
547
+ const n1 = node(ctx, pop(ctx));
548
+ const v1 = n1.elts[0];
549
+ const v2 = n2.elts[0];
550
+ if (n1.tag !== "NUM" || n2.tag !== "NUM") {
551
+ push(ctx, { tag: "MOD", elts: [n1, n2] });
552
+ }
553
+ else {
554
+ number(ctx, +v1 % +v2);
555
+ }
556
+ }
557
+ function pow(ctx) {
558
+ const n2 = node(ctx, pop(ctx));
559
+ const n1 = node(ctx, pop(ctx));
560
+ const v2 = n2.elts[0];
561
+ const v1 = n1.elts[0];
562
+ if (n1.tag !== "NUM" || n2.tag !== "NUM") {
563
+ push(ctx, { tag: "POW", elts: [n1, n2] });
564
+ }
565
+ else {
566
+ number(ctx, Math.pow(+v1, +v2));
567
+ }
568
+ }
569
+ function concat(ctx) {
570
+ const n1 = node(ctx, pop(ctx));
571
+ push(ctx, {
572
+ tag: "CONCAT",
573
+ elts: [n1]
574
+ });
575
+ }
576
+ function eq(ctx) {
577
+ const v2 = node(ctx, pop(ctx)).elts[0];
578
+ const v1 = node(ctx, pop(ctx)).elts[0];
579
+ bool(ctx, v1 === v2);
580
+ }
581
+ function ne(ctx) {
582
+ const v2 = +node(ctx, pop(ctx)).elts[0];
583
+ const v1 = +node(ctx, pop(ctx)).elts[0];
584
+ bool(ctx, v1 !== v2);
585
+ }
586
+ function lt(ctx) {
587
+ const v2 = +node(ctx, pop(ctx)).elts[0];
588
+ const v1 = +node(ctx, pop(ctx)).elts[0];
589
+ bool(ctx, v1 < v2);
590
+ }
591
+ function gt(ctx) {
592
+ const v2 = +node(ctx, pop(ctx)).elts[0];
593
+ const v1 = +node(ctx, pop(ctx)).elts[0];
594
+ bool(ctx, v1 > v2);
595
+ }
596
+ function le(ctx) {
597
+ const v2 = +node(ctx, pop(ctx)).elts[0];
598
+ const v1 = +node(ctx, pop(ctx)).elts[0];
599
+ bool(ctx, v1 <= v2);
600
+ }
601
+ function ge(ctx) {
602
+ const v2 = +node(ctx, pop(ctx)).elts[0];
603
+ const v1 = +node(ctx, pop(ctx)).elts[0];
604
+ bool(ctx, v1 >= v2);
605
+ }
606
+ function ifExpr(ctx) {
607
+ const elts = [];
608
+ elts.push(pop(ctx)); // if
609
+ elts.push(pop(ctx)); // then
610
+ elts.push(pop(ctx)); // else
611
+ push(ctx, { tag: "IF", elts: elts.reverse() });
612
+ }
613
+ function caseExpr(ctx, n) {
614
+ const elts = [];
615
+ elts.push(pop(ctx)); // val
616
+ for (let i = n; i > 0; i--) {
617
+ elts.push(pop(ctx)); // of
618
+ }
619
+ push(ctx, { tag: "CASE", elts: elts.reverse() });
620
+ }
621
+ function ofClause(ctx) {
622
+ const elts = [];
623
+ elts.push(pop(ctx));
624
+ elts.push(pop(ctx));
625
+ push(ctx, { tag: "OF", elts: elts.reverse() });
626
+ }
627
+ function record(ctx) {
628
+ // Ast.record
629
+ const count = ctx.state.exprc;
630
+ const elts = [];
631
+ for (let i = count; i > 0; i--) {
632
+ const elt = pop(ctx);
633
+ if (elt !== undefined) {
634
+ elts.push(elt);
635
+ }
636
+ }
637
+ push(ctx, {
638
+ tag: "RECORD",
639
+ elts
640
+ });
641
+ }
642
+ function binding(ctx) {
643
+ // Ast.binding
644
+ const elts = [];
645
+ elts.push(pop(ctx));
646
+ elts.push(pop(ctx));
647
+ push(ctx, {
648
+ tag: "BINDING",
649
+ elts: elts.reverse()
650
+ });
651
+ }
652
+ function lambda(ctx, env, nid) {
653
+ // Ast.lambda
654
+ const names = [];
655
+ const nids = [];
656
+ for (const id in env.lexicon) {
657
+ const word = env.lexicon[id];
658
+ names.push({
659
+ tag: "IDENT",
660
+ elts: [word.name],
661
+ coord: getCoord(ctx)
662
+ });
663
+ nids.push(word.nid || 0);
664
+ }
665
+ const pattern = env.pattern;
666
+ push(ctx, {
667
+ tag: "LAMBDA",
668
+ elts: [{
669
+ tag: "LIST",
670
+ elts: names
671
+ }, nid, {
672
+ tag: "LIST",
673
+ elts: pattern
674
+ }, {
675
+ tag: "LIST",
676
+ elts: nids
677
+ }]
678
+ });
679
+ }
680
+ function exprs(ctx, count, inReverse) {
681
+ // Ast.exprs
682
+ let elts = [];
683
+ assert(ctx.state.nodeStack.length >= count);
684
+ if (inReverse) {
685
+ for (let i = count; i > 0; i--) {
686
+ const elt = pop(ctx);
687
+ elts.push(elt); // Reverse order.
688
+ }
689
+ }
690
+ else {
691
+ for (let i = count; i > 0; i--) {
692
+ const elt = pop(ctx);
693
+ elts.push(elt); // Reverse order.
694
+ }
695
+ elts = elts.reverse();
696
+ }
697
+ push(ctx, {
698
+ tag: "EXPRS",
699
+ elts
700
+ });
701
+ }
702
+ function letDef(ctx) {
703
+ // Clean up stack and produce initializer.
704
+ pop(ctx); // body
705
+ pop(ctx); // name
706
+ for (let i = 0; i < ctx.state.paramc; i++) {
707
+ pop(ctx); // params
708
+ }
709
+ ctx.state.exprc--; // don't count as expr.
710
+ }
711
+ function program(ctx) {
712
+ const elts = [];
713
+ elts.push(pop(ctx));
714
+ push(ctx, {
715
+ tag: "PROG",
716
+ elts
717
+ });
718
+ }
719
+ // Assign all the methods to astClass
720
+ astClass.intern = intern;
721
+ astClass.node = node;
722
+ astClass.dump = dump;
723
+ astClass.dumpAll = dumpAll;
724
+ astClass.poolToJSON = poolToJSON;
725
+ astClass.number = number;
726
+ astClass.string = string;
727
+ astClass.name = name;
728
+ astClass.apply = apply;
729
+ astClass.fold = fold;
730
+ astClass.expr = expr;
731
+ astClass.binaryExpr = binaryExpr;
732
+ astClass.unaryExpr = unaryExpr;
733
+ astClass.parenExpr = parenExpr;
734
+ astClass.prefixExpr = prefixExpr;
735
+ astClass.lambda = lambda;
736
+ astClass.applyLate = applyLate;
737
+ astClass.letDef = letDef;
738
+ astClass.ifExpr = ifExpr;
739
+ astClass.caseExpr = caseExpr;
740
+ astClass.ofClause = ofClause;
741
+ astClass.record = record;
742
+ astClass.binding = binding;
743
+ astClass.exprs = exprs;
744
+ astClass.program = program;
745
+ astClass.pop = pop;
746
+ astClass.topNode = topNode;
747
+ astClass.peek = peek;
748
+ astClass.push = push;
749
+ astClass.mod = mod;
750
+ astClass.add = add;
751
+ astClass.sub = sub;
752
+ astClass.div = div;
753
+ astClass.pow = pow;
754
+ astClass.concat = concat;
755
+ astClass.eq = eq;
756
+ astClass.ne = ne;
757
+ astClass.lt = lt;
758
+ astClass.gt = gt;
759
+ astClass.le = le;
760
+ astClass.ge = ge;
761
+ astClass.neg = neg;
762
+ astClass.list = list;
763
+ astClass.bool = bool;
764
+ astClass.nul = nul;
765
+ astClass.error = error;
766
+ return astClass;
767
+ })();
768
+ // The following code for StreamString was copied from CodeMirror.
769
+ class StringStream {
770
+ constructor(string, tabSize) {
771
+ this.pos = this.start = 0;
772
+ this.string = string;
773
+ this.tabSize = tabSize || 8;
774
+ }
775
+ eol() {
776
+ return this.pos >= this.string.length;
777
+ }
778
+ sol() {
779
+ return this.pos === 0;
780
+ }
781
+ peek() {
782
+ return this.string.charAt(this.pos) || undefined;
783
+ }
784
+ next() {
785
+ if (this.pos < this.string.length) {
786
+ return this.string.charAt(this.pos++);
787
+ }
788
+ return undefined;
789
+ }
790
+ eat(match) {
791
+ const ch = this.string.charAt(this.pos);
792
+ let ok;
793
+ if (typeof match === "string") {
794
+ ok = ch === match;
795
+ }
796
+ else {
797
+ ok = ch && (match instanceof RegExp ? match.test(ch) : match(ch));
798
+ }
799
+ if (ok) {
800
+ ++this.pos;
801
+ return ch;
802
+ }
803
+ return undefined;
804
+ }
805
+ eatWhile(match) {
806
+ const start = this.pos;
807
+ while (this.eat(match) !== undefined) { }
808
+ return this.pos > start;
809
+ }
810
+ eatSpace() {
811
+ const start = this.pos;
812
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos)))
813
+ ++this.pos;
814
+ return this.pos > start;
815
+ }
816
+ skipToEnd() {
817
+ this.pos = this.string.length;
818
+ }
819
+ skipTo(ch) {
820
+ const found = this.string.indexOf(ch, this.pos);
821
+ if (found > -1) {
822
+ this.pos = found;
823
+ return true;
824
+ }
825
+ return undefined;
826
+ }
827
+ backUp(n) {
828
+ this.pos -= n;
829
+ }
830
+ match(pattern, consume, caseInsensitive) {
831
+ assert(false, "Should not get here");
832
+ if (typeof pattern === "string") {
833
+ const cased = function (str) {
834
+ return caseInsensitive ? str.toLowerCase() : str;
835
+ };
836
+ if (cased(this.string).indexOf(cased(pattern), this.pos) === this.pos) {
837
+ if (consume !== false)
838
+ this.pos += pattern.length;
839
+ return true;
840
+ }
841
+ }
842
+ else {
843
+ const match = this.string.slice(this.pos).match(pattern);
844
+ if (match && match.index > 0)
845
+ return null;
846
+ if (match && consume !== false)
847
+ this.pos += match[0].length;
848
+ return match;
849
+ }
850
+ return false;
851
+ }
852
+ current() {
853
+ return this.string.slice(this.start, this.pos);
854
+ }
855
+ }
856
+ // env module
857
+ export const env = (function () {
858
+ return {
859
+ findWord,
860
+ addWord,
861
+ enterEnv,
862
+ exitEnv,
863
+ addPattern
864
+ };
865
+ // private functions
866
+ function findWord(ctx, lexeme) {
867
+ const env = ctx.state.env;
868
+ for (let i = env.length - 1; i >= 0; i--) {
869
+ const word = env[i].lexicon[lexeme];
870
+ if (word) {
871
+ return word;
872
+ }
873
+ }
874
+ return null;
875
+ }
876
+ function addWord(ctx, lexeme, entry) {
877
+ window.gcexports.topEnv(ctx).lexicon[lexeme] = entry;
878
+ return null;
879
+ }
880
+ function addPattern(ctx, pattern) {
881
+ window.gcexports.topEnv(ctx).pattern.push(pattern);
882
+ }
883
+ function enterEnv(ctx, name) {
884
+ // recursion guard
885
+ if (ctx.state.env.length > 380) {
886
+ console.trace("enterEnv()", "name=" + name);
887
+ // return; // just stop recursing
888
+ throw new Error("runaway recursion");
889
+ }
890
+ window.gcexports.topEnv(ctx).paramc = ctx.state.paramc;
891
+ ctx.state.env.push({
892
+ name,
893
+ lexicon: {},
894
+ pattern: []
895
+ });
896
+ }
897
+ function exitEnv(ctx) {
898
+ ctx.state.env.pop();
899
+ ctx.state.paramc = window.gcexports.topEnv(ctx).paramc;
900
+ }
901
+ })();
902
+ //# sourceMappingURL=parse.js.map