novac 2.2.0 → 2.2.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 (122) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/bin/novac +6 -3
  4. package/bin/nvc +0 -0
  5. package/bin/nvml +0 -0
  6. package/demo.nv +0 -0
  7. package/demo_builtins.nv +0 -0
  8. package/demo_http.nv +0 -0
  9. package/examples/bf.nv +5 -13
  10. package/examples/math.nv +2 -2
  11. package/kits/kitffmpeg/kitdef.js +1174 -0
  12. package/kits/libos/kitdef.js +3135 -0
  13. package/kits/libtasker/kitdef.js +125 -0
  14. package/package.json +1 -1
  15. package/scripts/update-bin.js +0 -0
  16. package/src/core/executor.js +7 -4
  17. package/src/core/lexer.js +2 -2
  18. package/src/index.js +0 -0
  19. package/novac/LICENSE +0 -21
  20. package/novac/README.md +0 -1823
  21. package/novac/bin/novac +0 -950
  22. package/novac/bin/nvc +0 -522
  23. package/novac/bin/nvml +0 -542
  24. package/novac/demo.nv +0 -245
  25. package/novac/demo_builtins.nv +0 -209
  26. package/novac/demo_http.nv +0 -62
  27. package/novac/examples/bf.nv +0 -69
  28. package/novac/examples/math.nv +0 -21
  29. package/novac/kits/kitai/kitdef.js +0 -2185
  30. package/novac/kits/kitansi/kitdef.js +0 -1402
  31. package/novac/kits/kitformat/kitdef.js +0 -1485
  32. package/novac/kits/kitgps/kitdef.js +0 -1862
  33. package/novac/kits/kitlibfs/kitdef.js +0 -231
  34. package/novac/kits/kitlibproc/kitdef.js +0 -78
  35. package/novac/kits/kitmatrix/ex.js +0 -19
  36. package/novac/kits/kitmatrix/kitdef.js +0 -960
  37. package/novac/kits/kitmpatch/kitdef.js +0 -906
  38. package/novac/kits/kitnovacweb/README.md +0 -1572
  39. package/novac/kits/kitnovacweb/demo.nv +0 -12
  40. package/novac/kits/kitnovacweb/demo.nvml +0 -71
  41. package/novac/kits/kitnovacweb/index.nova +0 -12
  42. package/novac/kits/kitnovacweb/kitdef.js +0 -692
  43. package/novac/kits/kitnovacweb/nova.kit.json +0 -8
  44. package/novac/kits/kitnovacweb/nvml/executor.js +0 -739
  45. package/novac/kits/kitnovacweb/nvml/index.js +0 -67
  46. package/novac/kits/kitnovacweb/nvml/lexer.js +0 -263
  47. package/novac/kits/kitnovacweb/nvml/parser.js +0 -508
  48. package/novac/kits/kitnovacweb/nvml/renderer.js +0 -924
  49. package/novac/kits/kitparse/kitdef.js +0 -1688
  50. package/novac/kits/kitregex++/kitdef.js +0 -1353
  51. package/novac/kits/kitrequire/kitdef.js +0 -1599
  52. package/novac/kits/kitx11/kitdef.js +0 -1
  53. package/novac/kits/kitx11/kitx11.js +0 -2472
  54. package/novac/kits/kitx11/kitx11_conn.js +0 -948
  55. package/novac/kits/kitx11/kitx11_worker.js +0 -121
  56. package/novac/kits/libtea/tf.js +0 -2691
  57. package/novac/kits/libterm/ex.js +0 -285
  58. package/novac/kits/libterm/kitdef.js +0 -1927
  59. package/novac/node_modules/chalk/license +0 -9
  60. package/novac/node_modules/chalk/package.json +0 -83
  61. package/novac/node_modules/chalk/readme.md +0 -297
  62. package/novac/node_modules/chalk/source/index.d.ts +0 -325
  63. package/novac/node_modules/chalk/source/index.js +0 -225
  64. package/novac/node_modules/chalk/source/utilities.js +0 -33
  65. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +0 -236
  66. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +0 -223
  67. package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +0 -1
  68. package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +0 -34
  69. package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +0 -55
  70. package/novac/node_modules/chalk/source/vendor/supports-color/index.js +0 -190
  71. package/novac/node_modules/commander/LICENSE +0 -22
  72. package/novac/node_modules/commander/Readme.md +0 -1176
  73. package/novac/node_modules/commander/esm.mjs +0 -16
  74. package/novac/node_modules/commander/index.js +0 -24
  75. package/novac/node_modules/commander/lib/argument.js +0 -150
  76. package/novac/node_modules/commander/lib/command.js +0 -2777
  77. package/novac/node_modules/commander/lib/error.js +0 -39
  78. package/novac/node_modules/commander/lib/help.js +0 -747
  79. package/novac/node_modules/commander/lib/option.js +0 -380
  80. package/novac/node_modules/commander/lib/suggestSimilar.js +0 -101
  81. package/novac/node_modules/commander/package-support.json +0 -19
  82. package/novac/node_modules/commander/package.json +0 -82
  83. package/novac/node_modules/commander/typings/esm.d.mts +0 -3
  84. package/novac/node_modules/commander/typings/index.d.ts +0 -1113
  85. package/novac/node_modules/node-addon-api/LICENSE.md +0 -9
  86. package/novac/node_modules/node-addon-api/README.md +0 -95
  87. package/novac/node_modules/node-addon-api/common.gypi +0 -21
  88. package/novac/node_modules/node-addon-api/except.gypi +0 -25
  89. package/novac/node_modules/node-addon-api/index.js +0 -14
  90. package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +0 -186
  91. package/novac/node_modules/node-addon-api/napi-inl.h +0 -7165
  92. package/novac/node_modules/node-addon-api/napi.h +0 -3364
  93. package/novac/node_modules/node-addon-api/node_addon_api.gyp +0 -42
  94. package/novac/node_modules/node-addon-api/node_api.gyp +0 -9
  95. package/novac/node_modules/node-addon-api/noexcept.gypi +0 -26
  96. package/novac/node_modules/node-addon-api/nothing.c +0 -0
  97. package/novac/node_modules/node-addon-api/package-support.json +0 -21
  98. package/novac/node_modules/node-addon-api/package.json +0 -480
  99. package/novac/node_modules/node-addon-api/tools/README.md +0 -73
  100. package/novac/node_modules/node-addon-api/tools/check-napi.js +0 -99
  101. package/novac/node_modules/node-addon-api/tools/clang-format.js +0 -71
  102. package/novac/node_modules/node-addon-api/tools/conversion.js +0 -301
  103. package/novac/node_modules/serialize-javascript/LICENSE +0 -27
  104. package/novac/node_modules/serialize-javascript/README.md +0 -149
  105. package/novac/node_modules/serialize-javascript/index.js +0 -297
  106. package/novac/node_modules/serialize-javascript/package.json +0 -33
  107. package/novac/package.json +0 -27
  108. package/novac/scripts/update-bin.js +0 -24
  109. package/novac/src/core/bstd.js +0 -1035
  110. package/novac/src/core/config.js +0 -155
  111. package/novac/src/core/describe.js +0 -187
  112. package/novac/src/core/emitter.js +0 -499
  113. package/novac/src/core/error.js +0 -86
  114. package/novac/src/core/executor.js +0 -5606
  115. package/novac/src/core/formatter.js +0 -686
  116. package/novac/src/core/lexer.js +0 -1026
  117. package/novac/src/core/nova_builtins.js +0 -717
  118. package/novac/src/core/nova_thread_worker.js +0 -166
  119. package/novac/src/core/parser.js +0 -2181
  120. package/novac/src/core/types.js +0 -112
  121. package/novac/src/index.js +0 -28
  122. package/novac/src/runtime/stdlib.js +0 -244
@@ -1,906 +0,0 @@
1
- // ============================================
2
- // novac monkey patching + live AST toolkit
3
- // ============================================
4
-
5
- // --------------------------------------------
6
- // utilities
7
- // --------------------------------------------
8
-
9
- function deepClone(obj) {
10
- return structuredClone
11
- ? structuredClone(obj)
12
- : JSON.parse(JSON.stringify(obj));
13
- }
14
-
15
- function deepEqual(a, b) {
16
- if (a === b) return true;
17
-
18
- if (typeof a !== typeof b)
19
- return false;
20
-
21
- if (typeof a !== 'object' || a === null || b === null)
22
- return false;
23
-
24
- let aKeys = Object.keys(a);
25
- let bKeys = Object.keys(b);
26
-
27
- if (aKeys.length !== bKeys.length)
28
- return false;
29
-
30
- for (let key of aKeys) {
31
- if (!deepEqual(a[key], b[key]))
32
- return false;
33
- }
34
-
35
- return true;
36
- }
37
-
38
- function stripMeta(obj) {
39
- if (typeof obj !== 'object' || obj === null)
40
- return obj;
41
-
42
- let out = Array.isArray(obj) ? [] : {};
43
-
44
- for (let key in obj) {
45
- if (
46
- key === 'line' ||
47
- key === 'column' ||
48
- key === 'collumn' ||
49
- key === 'loc'
50
- ) continue;
51
-
52
- out[key] = stripMeta(obj[key]);
53
- }
54
-
55
- return out;
56
- }
57
-
58
- function randomID() {
59
- return Math.random()
60
- .toString(36)
61
- .slice(2);
62
- }
63
-
64
- // ============================================
65
- // AST factory helpers
66
- // ============================================
67
-
68
- class AST {
69
- static node(kind, props = {}) {
70
- return {
71
- kind,
72
- ...props
73
- };
74
- }
75
-
76
- static return(value) {
77
- return {
78
- kind: 'return',
79
- value
80
- };
81
- }
82
-
83
- static log(msg) {
84
- return AST.call('log', [msg]);
85
- }
86
-
87
- static throw(err) {
88
- return {
89
- kind: 'throw',
90
- value: err
91
- };
92
- }
93
-
94
- static raw(ast) {
95
- return ast;
96
- }
97
- }
98
-
99
- // ============================================
100
- // AST walker
101
- // ============================================
102
-
103
- class Walker {
104
- static walk(node, visitor) {
105
- function visit(n, parent = null) {
106
- if (!n || typeof n !== 'object')
107
- return;
108
-
109
- visitor(n, parent);
110
-
111
- for (let key in n) {
112
- visit(n[key], n);
113
- }
114
- }
115
-
116
- visit(node);
117
- }
118
-
119
- static map(node, mapper) {
120
- function transform(n) {
121
- if (!n || typeof n !== 'object')
122
- return n;
123
-
124
- n = mapper(n) || n;
125
-
126
- for (let key in n) {
127
- n[key] = transform(n[key]);
128
- }
129
-
130
- return n;
131
- }
132
-
133
- return transform(node);
134
- }
135
-
136
- static find(node, predicate) {
137
- let matches = [];
138
-
139
- Walker.walk(node, (n) => {
140
- if (predicate(n))
141
- matches.push(n);
142
- });
143
-
144
- return matches;
145
- }
146
- }
147
-
148
- // ============================================
149
- // AST diffing engine
150
- // ============================================
151
-
152
- class ASTDiff {
153
- static compare(a, b) {
154
- return deepEqual(
155
- stripMeta(a),
156
- stripMeta(b)
157
- );
158
- }
159
-
160
- static changed(a, b) {
161
- return !ASTDiff.compare(a, b);
162
- }
163
-
164
- static diff(a, b) {
165
- let diffs = [];
166
-
167
- function scan(x, y, path = '') {
168
- if (!deepEqual(x, y)) {
169
- diffs.push({
170
- path,
171
- old: x,
172
- new: y
173
- });
174
- }
175
-
176
- if (
177
- typeof x === 'object' &&
178
- typeof y === 'object'
179
- ) {
180
- for (let k in x) {
181
- scan(
182
- x[k],
183
- y[k],
184
- path + '.' + k
185
- );
186
- }
187
- }
188
- }
189
-
190
- scan(a, b);
191
-
192
- return diffs;
193
- }
194
- }
195
-
196
- // ============================================
197
- // patch transaction system
198
- // ============================================
199
-
200
- class PatchTransaction {
201
- constructor(patcher) {
202
- this.patcher = patcher;
203
- this.snapshot = deepClone(
204
- patcher.ast
205
- );
206
- }
207
-
208
- rollback() {
209
- this.patcher.ast =
210
- deepClone(this.snapshot);
211
-
212
- this.patcher.fn.body =
213
- this.patcher.ast;
214
-
215
- return this.patcher;
216
- }
217
-
218
- commit() {
219
- return this.patcher.patch();
220
- }
221
- }
222
-
223
- // ============================================
224
- // hook system
225
- // ============================================
226
-
227
- class HookManager {
228
- constructor() {
229
- this.hooks = {};
230
- }
231
-
232
- on(event, fn) {
233
- if (!this.hooks[event])
234
- this.hooks[event] = [];
235
-
236
- this.hooks[event].push(fn);
237
- }
238
-
239
- emit(event, data) {
240
- if (!this.hooks[event])
241
- return;
242
-
243
- this.hooks[event]
244
- .forEach(fn => fn(data));
245
- }
246
-
247
- off(event, fn) {
248
- if (!this.hooks[event])
249
- return;
250
-
251
- this.hooks[event] =
252
- this.hooks[event]
253
- .filter(x => x !== fn);
254
- }
255
- }
256
-
257
- // ============================================
258
- // live function registry
259
- // ============================================
260
-
261
- class LiveRegistry {
262
- constructor() {
263
- this.functions = new Map();
264
- }
265
-
266
- register(name, fn) {
267
- this.functions.set(name, fn);
268
- }
269
-
270
- get(name) {
271
- return this.functions.get(name);
272
- }
273
-
274
- patch(name) {
275
- return new Patcher(
276
- this.get(name)
277
- );
278
- }
279
-
280
- remove(name) {
281
- this.functions.delete(name);
282
- }
283
-
284
- list() {
285
- return [
286
- ...this.functions.keys()
287
- ];
288
- }
289
- }
290
-
291
- // ============================================
292
- // main patcher
293
- // ============================================
294
-
295
- class Patcher {
296
- static hooks = new HookManager();
297
-
298
- constructor(fn) {
299
- this.id = randomID();
300
-
301
- this.fn = fn;
302
-
303
- this.ast = fn.body;
304
-
305
- this.original =
306
- deepClone(fn.body);
307
-
308
- this.history = [];
309
-
310
- Patcher.hooks.emit(
311
- 'patcher:create',
312
- this
313
- );
314
- }
315
-
316
- // ----------------------------------------
317
- // internals
318
- // ----------------------------------------
319
-
320
- _save(op, data) {
321
- this.history.push({
322
- op,
323
- data,
324
- time: Date.now()
325
- });
326
-
327
- Patcher.hooks.emit(
328
- 'patch',
329
- {
330
- patcher: this,
331
- op,
332
- data
333
- }
334
- );
335
- }
336
-
337
- _normalize(ast) {
338
- return ast?.ast ?? ast;
339
- }
340
-
341
- // ----------------------------------------
342
- // transactions
343
- // ----------------------------------------
344
-
345
- transaction() {
346
- return new PatchTransaction(
347
- this
348
- );
349
- }
350
-
351
- // ----------------------------------------
352
- // restore
353
- // ----------------------------------------
354
-
355
- old() {
356
- this.fn.body =
357
- deepClone(this.original);
358
-
359
- this.ast = this.fn.body;
360
-
361
- return this;
362
- }
363
-
364
- rollback(steps = 1) {
365
- while (
366
- steps-- > 0 &&
367
- this.history.length > 0
368
- ) {
369
- let h = this.history.pop();
370
-
371
- switch (h.op) {
372
- case 'insert':
373
- this.ast.splice(
374
- h.data.idx,
375
- 1
376
- );
377
- break;
378
-
379
- case 'remove':
380
- this.ast.splice(
381
- h.data.idx,
382
- 0,
383
- h.data.oldNode
384
- );
385
- break;
386
-
387
- case 'replace':
388
- this.ast[h.data.idx] =
389
- h.data.oldNode;
390
- break;
391
- }
392
- }
393
-
394
- return this;
395
- }
396
-
397
- // ----------------------------------------
398
- // mutations
399
- // ----------------------------------------
400
-
401
- injectBefore(idx, ast) {
402
- this._save('insert', { idx });
403
-
404
- this.ast.splice(
405
- idx,
406
- 0,
407
- this._normalize(ast)
408
- );
409
-
410
- return this;
411
- }
412
-
413
- injectAfter(idx, ast) {
414
- this._save('insert', {
415
- idx: idx + 1
416
- });
417
-
418
- this.ast.splice(
419
- idx + 1,
420
- 0,
421
- this._normalize(ast)
422
- );
423
-
424
- return this;
425
- }
426
-
427
- replace(idx, ast) {
428
- this._save('replace', {
429
- idx,
430
- oldNode: deepClone(
431
- this.ast[idx]
432
- )
433
- });
434
-
435
- this.ast[idx] =
436
- this._normalize(ast);
437
-
438
- return this;
439
- }
440
-
441
- remove(idx) {
442
- this._save('remove', {
443
- idx,
444
- oldNode: deepClone(
445
- this.ast[idx]
446
- )
447
- });
448
-
449
- this.ast.splice(idx, 1);
450
-
451
- return this;
452
- }
453
-
454
- append(ast) {
455
- this.ast.push(
456
- this._normalize(ast)
457
- );
458
-
459
- return this;
460
- }
461
-
462
- // inside the Patcher class
463
-
464
- /**
465
- * Match AST nodes by a predicate function or pattern object.
466
- *
467
- * Usage:
468
- * patcher.match(node => node.kind === "call")
469
- * patcher.match({ kind: "return" })
470
- *
471
- * Returns: array of { idx, node } objects
472
- */
473
- match(pattern) {
474
- const matches = [];
475
-
476
- function isMatch(node, pattern) {
477
- // If pattern is a function
478
- if (typeof pattern === 'function') {
479
- return pattern(node);
480
- }
481
-
482
- // If pattern is an object
483
- if (typeof pattern === 'object' && pattern !== null) {
484
- // Strip metadata for comparison
485
- const cleanNode = stripMeta(node);
486
- const cleanPattern = stripMeta(pattern);
487
-
488
- // Check every property in the pattern
489
- for (let key in cleanPattern) {
490
- if (typeof cleanPattern[key] === 'object' && cleanPattern[key] !== null) {
491
- if (!isMatch(cleanNode[key], cleanPattern[key])) return false;
492
- } else {
493
- if (cleanNode[key] !== cleanPattern[key]) return false;
494
- }
495
- }
496
- return true;
497
- }
498
-
499
- return false;
500
- }
501
-
502
- this.ast.forEach((node, idx) => {
503
- if (isMatch(node, pattern)) {
504
- matches.push({ idx, node });
505
- }
506
- });
507
-
508
- return matches;
509
- }
510
-
511
- prepend(ast) {
512
- this.ast.unshift(
513
- this._normalize(ast)
514
- );
515
-
516
- return this;
517
- }
518
-
519
- clear() {
520
- this.ast.length = 0;
521
- return this;
522
- }
523
-
524
- reverse() {
525
- this.ast.reverse();
526
- return this;
527
- }
528
-
529
- shuffle() {
530
- this.ast.sort(
531
- () => Math.random() - 0.5
532
- );
533
-
534
- return this;
535
- }
536
-
537
- duplicate(idx) {
538
- this.ast.splice(
539
- idx,
540
- 0,
541
- deepClone(this.ast[idx])
542
- );
543
-
544
- return this;
545
- }
546
-
547
- // ----------------------------------------
548
- // querying
549
- // ----------------------------------------
550
-
551
- find(kind) {
552
- let out = [];
553
-
554
- this.ast.forEach((n, i) => {
555
- if (n.kind === kind)
556
- out.push(i);
557
- });
558
-
559
- return out;
560
- }
561
-
562
- where(node) {
563
- let out = [];
564
-
565
- this.ast.forEach((n, i) => {
566
- if (
567
- deepEqual(
568
- stripMeta(n),
569
- stripMeta(node)
570
- )
571
- ) {
572
- out.push(i);
573
- }
574
- });
575
-
576
- return out;
577
- }
578
-
579
- select(predicate) {
580
- let out = [];
581
-
582
- this.ast.forEach((n, i) => {
583
- if (predicate(n, i))
584
- out.push(i);
585
- });
586
-
587
- return out;
588
- }
589
-
590
- // ----------------------------------------
591
- // high level patching
592
- // ----------------------------------------
593
-
594
- before(kind, ast) {
595
- this.find(kind)
596
- .reverse()
597
- .forEach(idx => {
598
- this.injectBefore(
599
- idx,
600
- ast
601
- );
602
- });
603
-
604
- return this;
605
- }
606
-
607
- after(kind, ast) {
608
- this.find(kind)
609
- .reverse()
610
- .forEach(idx => {
611
- this.injectAfter(
612
- idx,
613
- ast
614
- );
615
- });
616
-
617
- return this;
618
- }
619
-
620
- replaceKind(kind, ast) {
621
- this.find(kind)
622
- .reverse()
623
- .forEach(idx => {
624
- this.replace(
625
- idx,
626
- ast
627
- );
628
- });
629
-
630
- return this;
631
- }
632
-
633
- interceptCall(
634
- name,
635
- transformer
636
- ) {
637
- this.select(n =>
638
- n.kind === 'call' &&
639
- n.name === name
640
- )
641
- .reverse()
642
- .forEach(idx => {
643
- this.ast[idx] =
644
- transformer(
645
- this.ast[idx]
646
- );
647
- });
648
-
649
- return this;
650
- }
651
-
652
- renameCall(from, to) {
653
- return this.interceptCall(
654
- from,
655
- call => {
656
- call.name = to;
657
- return call;
658
- }
659
- );
660
- }
661
-
662
- // ----------------------------------------
663
- // instrumentation
664
- // ----------------------------------------
665
-
666
- trace() {
667
- this.ast = this.ast.flatMap(
668
- node => [
669
- AST.log(
670
- `[TRACE] ${node.kind}`
671
- ),
672
- node
673
- ]
674
- );
675
-
676
- return this;
677
- }
678
-
679
- profile() {
680
- this.prepend(
681
- AST.call(
682
- '__profilerStart'
683
- )
684
- );
685
-
686
- this.after(
687
- 'return',
688
- AST.call(
689
- '__profilerEnd'
690
- )
691
- );
692
-
693
- return this;
694
- }
695
-
696
- freeze() {
697
- Object.freeze(this.ast);
698
- return this;
699
- }
700
-
701
- // ----------------------------------------
702
- // compiler transforms
703
- // ----------------------------------------
704
-
705
- constantFold() {
706
- this.walk(node => {
707
- if (
708
- node.kind === 'binary' &&
709
- typeof node.left ===
710
- 'number' &&
711
- typeof node.right ===
712
- 'number'
713
- ) {
714
- switch (node.op) {
715
- case '+':
716
- node.kind =
717
- 'number';
718
-
719
- node.value =
720
- node.left +
721
- node.right;
722
- }
723
- }
724
- });
725
-
726
- return this;
727
- }
728
-
729
- deadCodeElimination() {
730
- let foundReturn = false;
731
-
732
- this.ast = this.ast.filter(
733
- node => {
734
- if (foundReturn)
735
- return false;
736
-
737
- if (
738
- node.kind ===
739
- 'return'
740
- ) {
741
- foundReturn = true;
742
- }
743
-
744
- return true;
745
- }
746
- );
747
-
748
- return this;
749
- }
750
-
751
- inlineCalls(name, body) {
752
- this.select(n =>
753
- n.kind === 'call' &&
754
- n.name === name
755
- )
756
- .reverse()
757
- .forEach(idx => {
758
- this.replace(
759
- idx,
760
- deepClone(body)
761
- );
762
- });
763
-
764
- return this;
765
- }
766
-
767
- // ----------------------------------------
768
- // walking
769
- // ----------------------------------------
770
-
771
- walk(visitor) {
772
- this.ast.forEach(node => {
773
- Walker.walk(
774
- node,
775
- visitor
776
- );
777
- });
778
-
779
- return this;
780
- }
781
-
782
- map(transformer) {
783
- this.ast = this.ast.map(
784
- transformer
785
- );
786
-
787
- return this;
788
- }
789
-
790
- filter(predicate) {
791
- this.ast = this.ast.filter(
792
- predicate
793
- );
794
-
795
- return this;
796
- }
797
-
798
- // ----------------------------------------
799
- // snapshots
800
- // ----------------------------------------
801
-
802
- snapshot() {
803
- return deepClone(this.ast);
804
- }
805
-
806
- compare(snapshot) {
807
- return ASTDiff.diff(
808
- snapshot,
809
- this.ast
810
- );
811
- }
812
-
813
- // ----------------------------------------
814
- // finalize
815
- // ----------------------------------------
816
-
817
- patch() {
818
- this.fn.body = this.ast;
819
-
820
- Patcher.hooks.emit(
821
- 'patcher:commit',
822
- this
823
- );
824
-
825
- return this.fn;
826
- }
827
- }
828
-
829
- // ============================================
830
- // plugin system
831
- // ============================================
832
-
833
- class PluginSystem {
834
- constructor() {
835
- this.plugins = [];
836
- }
837
-
838
- use(plugin) {
839
- this.plugins.push(plugin);
840
-
841
- if (plugin.install)
842
- plugin.install(this);
843
- }
844
-
845
- apply(patcher) {
846
- this.plugins.forEach(p => {
847
- if (p.transform)
848
- p.transform(patcher);
849
- });
850
- }
851
- }
852
-
853
- // ============================================
854
- // built-in plugins
855
- // ============================================
856
-
857
- const DebugPlugin = {
858
- transform(patcher) {
859
- patcher.trace();
860
- }
861
- };
862
-
863
- const SafetyPlugin = {
864
- transform(patcher) {
865
- patcher.before(
866
- 'return',
867
- AST.log(
868
- '[SAFE RETURN]'
869
- )
870
- );
871
- }
872
- };
873
-
874
- // ============================================
875
- // exports
876
- // ============================================
877
-
878
- const registry =
879
- new LiveRegistry();
880
-
881
- const plugins =
882
- new PluginSystem();
883
-
884
- const kitdef = {
885
- patcher: Patcher,
886
- walker: Walker,
887
- ast: AST,
888
- diff: ASTDiff,
889
- registry,
890
- plugins,
891
- hooks: Patcher.hooks,
892
- transaction: PatchTransaction,
893
- debugPlugin: DebugPlugin,
894
- safetyPlugin: SafetyPlugin,
895
-
896
- utils: {
897
- deepClone,
898
- deepEqual,
899
- stripMeta,
900
- randomID
901
- }
902
- };
903
-
904
- module.exports = {
905
- kitdef
906
- };