@graffiticode/basis 1.3.0 → 1.5.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@graffiticode/basis",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.5.0",
5
5
  "description": "The basis library for creating Graffiticode languages",
6
6
  "main": "index.js",
7
7
  "scripts": {
package/src/compiler.js CHANGED
@@ -25,20 +25,25 @@ class Visitor {
25
25
  this.root = code.root;
26
26
  }
27
27
  visit(nid, options, resume) {
28
- assert(nid);
29
- let node;
30
- if (typeof nid === "object") {
31
- node = nid;
32
- } else {
33
- node = this.nodePool[nid];
34
- }
35
- assert(node && node.tag && node.elts, "2000: Visitor.visit() tag=" + node.tag + " elts= " + JSON.stringify(node.elts));
36
- assert(this[node.tag], "2000: Visitor function not defined for: " + node.tag);
37
- assert(typeof resume === "function", message(1003));
38
- if (!options.SYNC && ASYNC) {
39
- setTimeout(() => this[node.tag](node, options, resume), 0);
40
- } else {
41
- this[node.tag](node, options, resume);
28
+ try {
29
+ assert(nid);
30
+ let node;
31
+ if (typeof nid === "object") {
32
+ node = nid;
33
+ } else {
34
+ node = this.nodePool[nid];
35
+ }
36
+ assert(node && node.tag && node.elts, "2000: Visitor.visit() tag=" + node.tag + " elts= " + JSON.stringify(node.elts));
37
+ assert(this[node.tag], "2000: Visitor function not defined for: " + node.tag);
38
+ assert(typeof resume === "function", message(1003));
39
+ if (!options.SYNC && ASYNC) {
40
+ // This is used to keep from blowing the call stack.
41
+ setTimeout(() => this[node.tag](node, options, resume), 0);
42
+ } else {
43
+ this[node.tag](node, options, resume);
44
+ }
45
+ } catch (x) {
46
+ resume(error(x.stack));
42
47
  }
43
48
  }
44
49
  node(nid) {
@@ -137,6 +142,14 @@ export class Checker extends Visitor {
137
142
  const val = node;
138
143
  resume(err, val);
139
144
  }
145
+ JSON(node, options, resume) {
146
+ this.visit(node.elts[0], options, (e0, v0) => {
147
+ assert(v0.tag === "STR", JSON.stringify(v0, null, 2));
148
+ const err = [];
149
+ const val = node;
150
+ resume(err, val);
151
+ });
152
+ }
140
153
  CONCAT(node, options, resume) {
141
154
  this.visit(node.elts[0], options, (e0, v0) => {
142
155
  const err = [];
@@ -484,6 +497,13 @@ export class Transformer extends Visitor {
484
497
  const val = node.elts[0];
485
498
  resume(err, val);
486
499
  }
500
+ JSON(node, options, resume) {
501
+ this.visit(node.elts[0], options, (e0, v0) => {
502
+ const err = [];
503
+ const val = JSON.parse(v0);
504
+ resume(err, val);
505
+ });
506
+ }
487
507
  CONCAT(node, options, resume) {
488
508
  this.visit(node.elts[0], options, (e0, v0) => {
489
509
  const err = [];
package/src/#compiler.js# DELETED
@@ -1,739 +0,0 @@
1
- /* Copyright (c) 2021, ARTCOMPILER INC */
2
- import {assert, message, messages, reserveCodeRange} from "./share.js";
3
- reserveCodeRange(1000, 1999, "compile");
4
- messages[1001] = "Node ID %1 not found in pool.";
5
- messages[1002] = "Invalid tag in node with Node ID %1.";
6
- messages[1003] = "No async callback provided.";
7
- messages[1004] = "No visitor method defined for '%1'.";
8
-
9
- function error(msg, arg) {
10
- return msg + arg;
11
- }
12
-
13
- function newNode(tag, elts) {
14
- return {
15
- tag: tag,
16
- elts: elts,
17
- };
18
- }
19
-
20
- const ASYNC = true;
21
-
22
- class Visitor {
23
- constructor(code) {
24
- this.nodePool = code;
25
- this.root = code.root;
26
- }
27
- visit(nid, options, resume) {
28
- assert(nid);
29
- let node;
30
- if (typeof nid === "object") {
31
- node = nid;
32
- } else {
33
- node = this.nodePool[nid];
34
- }
35
- assert(node && node.tag && node.elts, "2000: Visitor.visit() tag=" + node.tag + " elts= " + JSON.stringify(node.elts));
36
- assert(this[node.tag], "2000: Visitor function not defined for: " + node.tag);
37
- assert(typeof resume === "function", message(1003));
38
- if (!options.SYNC && ASYNC) {
39
- setTimeout(() => this[node.tag](node, options, resume), 0);
40
- } else {
41
- this[node.tag](node, options, resume);
42
- }
43
- }
44
- node(nid) {
45
- var n = this.nodePool[nid];
46
- if (!nid) {
47
- return null;
48
- } else if (!n) {
49
- return {};
50
- }
51
- var elts = [];
52
- switch (n.tag) {
53
- case "NULL":
54
- break;
55
- case "NUM":
56
- case "STR":
57
- case "IDENT":
58
- case "BOOL":
59
- elts[0] = n.elts[0];
60
- break;
61
- default:
62
- for (var i=0; i < n.elts.length; i++) {
63
- elts[i] = this.node(n.elts[i]);
64
- }
65
- break;
66
- }
67
- return {
68
- tag: n.tag,
69
- elts: elts,
70
- };
71
- }
72
- }
73
-
74
- export class Checker extends Visitor {
75
- constructor(nodePool) {
76
- super(nodePool);
77
- }
78
- check(options, resume) {
79
- const nid = this.root;
80
- this.visit(nid, options, (err, data) => {
81
- resume(err, data);
82
- });
83
- }
84
- PROG(node, options, resume) {
85
- this.visit(node.elts[0], options, (e0, v0) => {
86
- const err = [];
87
- const val = node;
88
- resume(err, val);
89
- });
90
- }
91
- EXPRS(node, options, resume) {
92
- let err = [];
93
- let val = [];
94
- for (let elt of node.elts) {
95
- this.visit(elt, options, (e0, v0) => {
96
- err = err.concat(e0);
97
- val = val.concat(v0);
98
- if (val.length === node.elts.length) {
99
- resume(err, val);
100
- }
101
- });
102
- }
103
- if (node.elts.length === 0) {
104
- resume(err, val);
105
- }
106
- }
107
- NUM(node, options, resume) {
108
- const err = [];
109
- const val = node;
110
- resume(err, val);
111
- }
112
- LAMBDA(node, options, resume) {
113
- const err = [];
114
- const val = node;
115
- this.visit(node.elts[0], options, (e0, v0) => {
116
- resume(err, val);
117
- });
118
- }
119
- LIST(node, options, resume) {
120
- const err = [];
121
- const val = node;
122
- if (node.elts.length === 0) {
123
- resume(err, val);
124
- } else {
125
- this.visit(node.elts[0], options, (e0, v0) => {
126
- resume(err, val);
127
- });
128
- }
129
- }
130
- IDENT(node, options, resume) {
131
- const err = [];
132
- const val = node;
133
- resume(err, val);
134
- }
135
- STR(node, options, resume) {
136
- const err = [];
137
- const val = node;
138
- resume(err, val);
139
- }
140
- CONCAT(node, options, resume) {
141
- this.visit(node.elts[0], options, (e0, v0) => {
142
- const err = [];
143
- const val = node;
144
- resume(err, val);
145
- });
146
- }
147
- ADD(node, options, resume) {
148
- this.visit(node.elts[0], options, (err1, val1) => {
149
- this.visit(node.elts[1], options, (err2, val2) => {
150
- if (isNaN(+val1)) {
151
- err1 = err1.concat(error("Argument must be a number.", node.elts[0]));
152
- }
153
- if (isNaN(+val2)) {
154
- err2 = err2.concat(error("Argument must be a number.", node.elts[1]));
155
- }
156
- const err = [].concat(err1).concat(err2);
157
- const val = node;
158
- resume(err, val);
159
- });
160
- });
161
- }
162
- BOOL(node, options, resume) {
163
- const err = [];
164
- const val = node;
165
- resume(err, val);
166
- }
167
- NULL(node, options, resume) {
168
- const err = [];
169
- const val = node;
170
- resume(err, val);
171
- }
172
- RECORD(node, options, resume) {
173
- const err = [];
174
- const val = node;
175
- resume(err, val);
176
- }
177
- BINDING(node, options, resume) {
178
- const err = [];
179
- const val = node;
180
- resume(err, val);
181
- }
182
- MUL(node, options, resume) {
183
- this.visit(node.elts[0], options, (err1, val1) => {
184
- this.visit(node.elts[1], options, (err2, val2) => {
185
- if (isNaN(+val1)) {
186
- err1 = err1.concat(error("Argument must be a number.", node.elts[0]));
187
- }
188
- if (isNaN(+val2)) {
189
- err2 = err2.concat(error("Argument must be a number.", node.elts[1]));
190
- }
191
- const err = [].concat(err1).concat(err2);
192
- const val = node;
193
- resume(err, val);
194
- });
195
- });
196
- }
197
- POW(node, options, resume) {
198
- this.visit(node.elts[0], options, (err1, val1) => {
199
- this.visit(node.elts[1], options, (err2, val2) => {
200
- if (isNaN(+val1)) {
201
- err1 = err1.concat(error("Argument must be a number.", node.elts[0]));
202
- }
203
- if (isNaN(+val2)) {
204
- err2 = err2.concat(error("Argument must be a number.", node.elts[1]));
205
- }
206
- const err = [].concat(err1).concat(err2);
207
- const val = node;
208
- resume(err, val);
209
- });
210
- });
211
- }
212
- VAL(node, options, resume) {
213
- const err = [];
214
- const val = node;
215
- resume(err, val);
216
- }
217
- KEY(node, options, resume) {
218
- const err = [];
219
- const val = node;
220
- resume(err, val);
221
- }
222
- LEN(node, options, resume) {
223
- const err = [];
224
- const val = node;
225
- resume(err, val);
226
- }
227
- ARG(node, options, resume) {
228
- const err = [];
229
- const val = node;
230
- resume(err, val);
231
- }
232
- DATA(node, options, resume) {
233
- const err = [];
234
- const val = node;
235
- resume(err, val);
236
- }
237
- PAREN(node, options, resume) {
238
- const err = [];
239
- const val = node;
240
- resume(err, val);
241
- }
242
- APPLY(node, options, resume) {
243
- const err = [];
244
- const val = node;
245
- resume(err, val);
246
- }
247
- MAP(node, options, resume) {
248
- const err = [];
249
- const val = node;
250
- resume(err, val);
251
- }
252
- STYLE(node, options, resume) {
253
- const err = [];
254
- const val = node;
255
- resume(err, val);
256
- }
257
- CASE(node, options, resume) {
258
- const err = [];
259
- const val = node;
260
- resume(err, val);
261
- }
262
- OF(node, options, resume) {
263
- const err = [];
264
- const val = node;
265
- resume(err, val);
266
- }
267
- }
268
-
269
- function enterEnv(ctx, name, paramc) {
270
- if (!ctx.env) {
271
- ctx.env = [];
272
- }
273
- // recursion guard
274
- if (ctx.env.length > 380) {
275
- //return; // just stop recursing
276
- throw new Error("runaway recursion");
277
- }
278
- ctx.env.push({
279
- name: name,
280
- paramc: paramc,
281
- lexicon: {},
282
- pattern: [],
283
- });
284
- }
285
- function exitEnv(ctx) {
286
- ctx.env.pop();
287
- }
288
- function findWord(ctx, lexeme) {
289
- let env = ctx.env;
290
- if (!env) {
291
- return null;
292
- }
293
- for (var i = env.length-1; i >= 0; i--) {
294
- var word = env[i].lexicon[lexeme];
295
- if (word) {
296
- return word;
297
- }
298
- }
299
- return null;
300
- }
301
- function addWord(ctx, lexeme, entry) {
302
- topEnv(ctx).lexicon[lexeme] = entry;
303
- return null;
304
- }
305
- function topEnv(ctx) {
306
- return ctx.env[ctx.env.length-1]
307
- }
308
- export class Transformer extends Visitor {
309
- constructor(nodePool) {
310
- super(nodePool);
311
- this.patternNodePool = ['unused'];
312
- this.patternNodeMap = {};
313
- }
314
- transform(options, resume) {
315
- const nid = this.root;
316
- this.visit(nid, options, (err, data) => {
317
- resume(err, data);
318
- });
319
- }
320
- internPattern(n) {
321
- if (!n) {
322
- return 0;
323
- }
324
- const nodeMap = this.patternNodeMap;
325
- const nodePool = this.patternNodePool;
326
- const tag = n.tag;
327
- const elts_nids = [];
328
- const count = n.elts.length;
329
- let elts = "";
330
- for (let i = 0; i < count; i++) {
331
- if (typeof n.elts[i] === "object") {
332
- n.elts[i] = this.internPattern(n.elts[i]);
333
- }
334
- elts += n.elts[i];
335
- }
336
- const key = tag+count+elts;
337
- let nid = nodeMap[key];
338
- if (nid === void 0) {
339
- nodePool.push({tag: tag, elts: n.elts});
340
- nid = nodePool.length - 1;
341
- nodeMap[key] = nid;
342
- if (n.coord) {
343
- ctx.state.coords[nid] = n.coord;
344
- }
345
- }
346
- return nid;
347
- }
348
- match(options, patterns, node) {
349
- if (patterns.size === 0 || node === undefined) {
350
- return false;
351
- }
352
- let matches = patterns.filter((pattern) => {
353
- if (pattern.tag === undefined || node.tag === undefined) {
354
- return false;
355
- }
356
- const patternNid = this.internPattern(pattern);
357
- if (patternNid === this.internPattern(node) ||
358
- patternNid === this.internPattern(newNode('IDENT', ['_']))) {
359
- return true;
360
- }
361
- if (pattern.tag === node.tag) {
362
- if (pattern.elts.length === node.elts.length) {
363
- // Same number of args, so see if each matches.
364
- return pattern.elts.every((arg, i) => {
365
- if (pattern.tag === 'VAR') {
366
- if (arg === node.elts[i]) {
367
- return true;
368
- }
369
- return false;
370
- }
371
- let result = this.match(options, [arg], node.elts[i]);
372
- return result.length === 1;
373
- });
374
- } else if (pattern.elts.length < node.elts.length) {
375
- // Different number of args, then see if there is a wildcard match.
376
- let nargs = node.elts.slice(1);
377
- if (pattern.elts.length === 2) {
378
- // Binary node pattern
379
- let result = (
380
- this.match(options, [pattern.elts[0]], node.elts[0]).length > 0 &&
381
- this.match(options, [pattern.elts[1]], newNode(node.tag, nargs)).length > 0
382
- // Match rest of the node against the second pattern argument.
383
- );
384
- return result;
385
- }
386
- }
387
- }
388
- return false;
389
- });
390
- // if (true || matches.length > 0) {
391
- // console.log("match() node: " + JSON.stringify(node, null, 2));
392
- // console.log("match() matches: " + JSON.stringify(matches, null, 2));
393
- // }
394
- return matches;
395
- }
396
-
397
-
398
- PROG(node, options, resume) {
399
- if (!options) {
400
- options = {};
401
- }
402
- this.visit(node.elts[0], options, (e0, v0) => {
403
- const err = e0;
404
- const val = v0.pop(); // Return the value of the last expression.
405
- resume(err, val);
406
- });
407
- }
408
- EXPRS(node, options, resume) {
409
- let err = [];
410
- let val = [];
411
- for (let elt of node.elts) {
412
- this.visit(elt, options, (e0, v0) => {
413
- err = err.concat(e0);
414
- val.push(v0);
415
- if (val.length === node.elts.length) {
416
- resume(err, val);
417
- }
418
- });
419
- }
420
- if (node.elts.length === 0) {
421
- val.push("");
422
- resume(err, val);
423
- }
424
- }
425
- NUM(node, options, resume) {
426
- const err = [];
427
- const val = +node.elts[0];
428
- resume(err, val);
429
- }
430
- LAMBDA(node, options, resume) {
431
- // Return a function value.
432
- this.visit(node.elts[0], options, (err0, params) => {
433
- let args = [].concat(options.args);
434
- enterEnv(options, "lambda", params.length);
435
- params.forEach((param, i) => {
436
- // let inits = this.nodePool[node.elts[3]].elts;
437
- if (args[i]) {
438
- // Got an arg so use it.
439
- addWord(options, param, {
440
- name: param,
441
- val: args[i],
442
- });
443
- // } else {
444
- // // Don't got an arg so use the init.
445
- // this.visit(inits[i], options, (err, val) => {
446
- // addWord(options, param, {
447
- // name: param,
448
- // val: val,
449
- // });
450
- // });
451
- }
452
- });
453
- this.visit(node.elts[1], options, (err, val) => {
454
- exitEnv(options);
455
- resume([].concat(err0).concat(err).concat(err), val)
456
- });
457
- });
458
- }
459
- LIST(node, options, resume) {
460
- let err = [];
461
- let val = [];
462
- if (node.elts.length === 0) {
463
- resume(err, val);
464
- } else {
465
- for (let elt of node.elts) {
466
- this.visit(elt, options, (e0, v0) => {
467
- err = err.concat(e0);
468
- val.push(v0);
469
- if (val.length === node.elts.length) {
470
- resume(err, val);
471
- }
472
- });
473
- }
474
- }
475
- }
476
- IDENT(node, options, resume) {
477
- let word = findWord(options, node.elts[0]);
478
- const err = [];
479
- const val = word && word.val || node.elts[0];
480
- resume(err, val);
481
- }
482
- STR(node, options, resume) {
483
- const err = [];
484
- const val = node.elts[0];
485
- resume(err, val);
486
- }
487
- CONCAT(node, options, resume) {
488
- this.visit(node.elts[0], options, (e0, v0) => {
489
- const err = [];
490
- const val = ([].concat(v0)).join('');
491
- resume(err, val);
492
- });
493
- }
494
- ADD(node, options, resume) {
495
- this.visit(node.elts[0], options, (e0, v0) => {
496
- this.visit(node.elts[1], options, (e1, v1) => {
497
- const err = [].concat(e0).concat(e1);
498
- const val = +v0 + +v1;
499
- resume(err, val);
500
- });
501
- });
502
- }
503
- BOOL(node, options, resume) {
504
- const err = [];
505
- const val = node;
506
- resume(err, val);
507
- }
508
- NULL(node, options, resume) {
509
- const err = [];
510
- const val = null;
511
- resume(err, val);
512
- }
513
- BINDING(node, options, resume) {
514
- const err = [];
515
- const val = node;
516
- this.visit(node.elts[0], options, (err1, val1) => {
517
- this.visit(node.elts[1], options, (err2, val2) => {
518
- resume([].concat(err1).concat(err2), {key: val1, val: val2});
519
- });
520
- });
521
- }
522
- RECORD(node, options, resume) {
523
- let err = [];
524
- let val = {};
525
- let len = 0;
526
- if (node.elts.length === 0) {
527
- resume(err, val);
528
- } else {
529
- for (let elt of node.elts.reverse()) {
530
- // For historical reasons, the bindings are reversed in the AST.
531
- this.visit(elt, options, (e0, v0) => {
532
- err = err.concat(e0);
533
- val[v0.key] = v0.val;
534
- if (++len === node.elts.length) {
535
- resume(err, val);
536
- }
537
- });
538
- }
539
- }
540
- }
541
- MUL(node, options, resume) {
542
- this.visit(node.elts[0], options, (err1, val1) => {
543
- this.visit(node.elts[1], options, (err2, val2) => {
544
- if (isNaN(+val1)) {
545
- err1 = err1.concat(error("Argument must be a number.", node.elts[0]));
546
- }
547
- if (isNaN(+val2)) {
548
- err2 = err2.concat(error("Argument must be a number.", node.elts[1]));
549
- }
550
- const err = [].concat(err1).concat(err2);
551
- const val = +val1 * +val2;
552
- resume(err, val);
553
- });
554
- });
555
- }
556
- POW(node, options, resume) {
557
- this.visit(node.elts[0], options, (err1, val1) => {
558
- this.visit(node.elts[1], options, (err2, val2) => {
559
- if (isNaN(+val1)) {
560
- err1 = err1.concat(error("Argument must be a number.", node.elts[0]));
561
- }
562
- if (isNaN(+val2)) {
563
- err2 = err2.concat(error("Argument must be a number.", node.elts[1]));
564
- }
565
- const err = [].concat(err1).concat(err2);
566
- const val = node;
567
- resume(err, val);
568
- });
569
- });
570
- }
571
- VAL(node, options, resume) {
572
- this.visit(node.elts[0], options, (e0, v0) => {
573
- this.visit(node.elts[1], options, (e1, v1) => {
574
- const err = [].concat(e0).concat(e1);
575
- const val = v1[v0];
576
- resume(err, val);
577
- });
578
- });
579
- }
580
- KEY(node, options, resume) {
581
- const err = [];
582
- const val = node;
583
- resume(err, val);
584
- }
585
- LEN(node, options, resume) {
586
- const err = [];
587
- const val = node;
588
- resume(err, val);
589
- }
590
- ARG(node, options, resume) {
591
- const err = [];
592
- const val = node;
593
- resume(err, val);
594
- }
595
- DATA(node, options, resume) {
596
- if (options.data && Object.keys(options.data).length !== 0) {
597
- // Got external data, so use it.
598
- const err = [];
599
- const val = options.data;
600
- resume(err, val);
601
- } else {
602
- // Otherwise, use the default data.
603
- this.visit(node.elts[0], options, (e0, v0) => {
604
- const err = e0;
605
- const val = v0;
606
- resume(err, val);
607
- });
608
- }
609
- }
610
- PAREN(node, options, resume) {
611
- this.visit(node.elts[0], options, (e0, v0) => {
612
- const err = [].concat(e0);
613
- const val = v0;
614
- resume(err, val);
615
- });
616
- }
617
- APPLY(node, options, resume) {
618
- // Apply a function to arguments.
619
- this.visit(node.elts[1], options, (e1, v1) => {
620
- options.args = v1;
621
- this.visit(node.elts[0], options, (e0, v0) => {
622
- //exitEnv(options);
623
- const err = [].concat(e1).concat(e0);
624
- const val = v0;
625
- resume(err, val);
626
- });
627
- });
628
- }
629
- MAP(node, options, resume) {
630
- this.visit(node.elts[1], options, (e1, v1) => {
631
- let err = [];
632
- let val = [];
633
- v1.forEach(args => {
634
- options.args = args;
635
- options = JSON.parse(JSON.stringify(options)); // Copy option arg support async.
636
- this.visit(node.elts[0], options, (e0, v0) => {
637
- val.push(v0);
638
- err = err.concat(e0);
639
- if (val.length === v1.length) {
640
- resume(err, val);
641
- }
642
- });
643
- });
644
- });
645
- }
646
- STYLE(node, options, resume) {
647
- const err = [];
648
- const val = node;
649
- resume(err, val);
650
- }
651
- CASE(node, options, resume) {
652
- // FIXME this isn't ASYNC compatible
653
- options.SYNC = true;
654
- this.visit(node.elts[0], options, (err, e0) => {
655
- const e0Node = this.node(node.elts[0]);
656
- const expr = (e0Node.tag === 'NUM' || e0Node.tag === 'NUM') && e0Node || {tag: 'STR', elts: [`${e0}`]};
657
- let foundMatch = false;
658
- const patterns = [];
659
- for (var i = 1; i < node.elts.length; i++) {
660
- this.visit(node.elts[i], options, (err, val) => {
661
- if (this.match(options, [this.node(node.elts[i]).elts[0]], expr).length) {
662
- this.visit(val.exprElt, options, resume);
663
- foundMatch = true;
664
- }
665
- });
666
- if (foundMatch) {
667
- return;
668
- }
669
- }
670
- if (!foundMatch) {
671
- resume([], {})
672
- }
673
- });
674
- options.SYNC = false;
675
- }
676
- OF(node, options, resume) {
677
- this.visit(node.elts[0], options, (err0, pattern) => {
678
- resume([].concat(err0), {
679
- pattern: pattern,
680
- exprElt: node.elts[1],
681
- });
682
- });
683
- }
684
- }
685
-
686
- export class Renderer {
687
- constructor(data) {
688
- this.data = data;
689
- }
690
- render(options, resume) {
691
- // Do some rendering here.
692
- const err = [];
693
- const val = this.data;
694
- resume(err, val);
695
- }
696
- }
697
-
698
- export class Compiler {
699
- constructor(config) {
700
- this.langID = config.langID;
701
- this.version = config.version;
702
- this.Checker = config.Checker || Checker;
703
- this.Transformer = config.Transformer || Transformer;
704
- this.Renderer = config.Renderer || Renderer;
705
- }
706
- compile(code, data, config, resume) {
707
- // Compiler takes an AST in the form of a node pool (code) and transforms it
708
- // into an object to be rendered on the client by the viewer for this
709
- // language.
710
- try {
711
- let options = {
712
- data: data,
713
- config: config,
714
- result: '',
715
- };
716
- const checker = new this.Checker(code);
717
- checker.check(options, (err, val) => {
718
- const transformer = new this.Transformer(code);
719
- transformer.transform(options, (err, val) => {
720
- if (err && err.length) {
721
- resume(err, val);
722
- } else {
723
- const renderer = new this.Renderer(val);
724
- renderer.render(options, (err, val) => {
725
- resume(err, val);
726
- });
727
- }
728
- });
729
- });
730
- } catch (x) {
731
- console.log("ERROR with code");
732
- console.log(x.stack);
733
- resume([{
734
- statusCode: 500,
735
- error: "Compiler error"
736
- }]);
737
- }
738
- }
739
- }