novac 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1574 -597
  3. package/bin/novac +468 -171
  4. package/bin/nvc +522 -0
  5. package/bin/nvml +78 -17
  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 +69 -0
  10. package/examples/math.nv +21 -0
  11. package/kits/birdAPI/kitdef.js +954 -0
  12. package/kits/kitRNG/kitdef.js +740 -0
  13. package/kits/kitSSH/kitdef.js +1272 -0
  14. package/kits/kitadb/kitdef.js +606 -0
  15. package/kits/kitai/kitdef.js +2185 -0
  16. package/kits/kitansi/kitdef.js +1402 -0
  17. package/kits/kitcanvas/kitdef.js +914 -0
  18. package/kits/kitclippy/kitdef.js +925 -0
  19. package/kits/kitformat/kitdef.js +1485 -0
  20. package/kits/kitgps/kitdef.js +1862 -0
  21. package/kits/kitlibproc/kitdef.js +3 -2
  22. package/kits/kitmatrix/ex.js +19 -0
  23. package/kits/kitmatrix/kitdef.js +960 -0
  24. package/kits/kitmorse/kitdef.js +229 -0
  25. package/kits/kitmpatch/kitdef.js +906 -0
  26. package/kits/kitnet/kitdef.js +1401 -0
  27. package/kits/kitnovacweb/README.md +1416 -143
  28. package/kits/kitnovacweb/kitdef.js +92 -2
  29. package/kits/kitnovacweb/nvml/executor.js +578 -176
  30. package/kits/kitnovacweb/nvml/index.js +2 -2
  31. package/kits/kitnovacweb/nvml/lexer.js +72 -69
  32. package/kits/kitnovacweb/nvml/parser.js +328 -159
  33. package/kits/kitnovacweb/nvml/renderer.js +770 -270
  34. package/kits/kitparse/kitdef.js +1688 -0
  35. package/kits/kitproto/kitdef.js +613 -0
  36. package/kits/kitqr/kitdef.js +637 -0
  37. package/kits/kitregex++/kitdef.js +1353 -0
  38. package/kits/kitrequire/kitdef.js +1599 -0
  39. package/kits/kitx11/kitdef.js +1 -0
  40. package/kits/kitx11/kitx11.js +2472 -0
  41. package/kits/kitx11/kitx11_conn.js +948 -0
  42. package/kits/kitx11/kitx11_worker.js +121 -0
  43. package/kits/libtea/kitdef.js +2691 -0
  44. package/kits/libterm/ex.js +285 -0
  45. package/kits/libterm/kitdef.js +1927 -0
  46. package/novac/LICENSE +21 -0
  47. package/novac/README.md +1823 -0
  48. package/novac/bin/novac +950 -0
  49. package/novac/bin/nvc +522 -0
  50. package/novac/bin/nvml +542 -0
  51. package/novac/demo.nv +245 -0
  52. package/novac/demo_builtins.nv +209 -0
  53. package/novac/demo_http.nv +62 -0
  54. package/novac/examples/bf.nv +69 -0
  55. package/novac/examples/math.nv +21 -0
  56. package/novac/kits/kitai/kitdef.js +2185 -0
  57. package/novac/kits/kitansi/kitdef.js +1402 -0
  58. package/novac/kits/kitformat/kitdef.js +1485 -0
  59. package/novac/kits/kitgps/kitdef.js +1862 -0
  60. package/novac/kits/kitlibfs/kitdef.js +231 -0
  61. package/{examples/example-project/nova_modules → novac/kits}/kitlibproc/kitdef.js +3 -2
  62. package/novac/kits/kitmatrix/ex.js +19 -0
  63. package/novac/kits/kitmatrix/kitdef.js +960 -0
  64. package/novac/kits/kitmpatch/kitdef.js +906 -0
  65. package/novac/kits/kitnovacweb/README.md +1572 -0
  66. package/novac/kits/kitnovacweb/demo.nv +12 -0
  67. package/novac/kits/kitnovacweb/demo.nvml +71 -0
  68. package/novac/kits/kitnovacweb/index.nova +12 -0
  69. package/novac/kits/kitnovacweb/kitdef.js +692 -0
  70. package/novac/kits/kitnovacweb/nova.kit.json +8 -0
  71. package/novac/kits/kitnovacweb/nvml/executor.js +739 -0
  72. package/novac/kits/kitnovacweb/nvml/index.js +67 -0
  73. package/novac/kits/kitnovacweb/nvml/lexer.js +263 -0
  74. package/novac/kits/kitnovacweb/nvml/parser.js +508 -0
  75. package/novac/kits/kitnovacweb/nvml/renderer.js +924 -0
  76. package/novac/kits/kitparse/kitdef.js +1688 -0
  77. package/novac/kits/kitregex++/kitdef.js +1353 -0
  78. package/novac/kits/kitrequire/kitdef.js +1599 -0
  79. package/novac/kits/kitx11/kitdef.js +1 -0
  80. package/novac/kits/kitx11/kitx11.js +2472 -0
  81. package/novac/kits/kitx11/kitx11_conn.js +948 -0
  82. package/novac/kits/kitx11/kitx11_worker.js +121 -0
  83. package/novac/kits/libtea/tf.js +2691 -0
  84. package/novac/kits/libterm/ex.js +285 -0
  85. package/novac/kits/libterm/kitdef.js +1927 -0
  86. package/novac/node_modules/chalk/license +9 -0
  87. package/novac/node_modules/chalk/package.json +83 -0
  88. package/novac/node_modules/chalk/readme.md +297 -0
  89. package/novac/node_modules/chalk/source/index.d.ts +325 -0
  90. package/novac/node_modules/chalk/source/index.js +225 -0
  91. package/novac/node_modules/chalk/source/utilities.js +33 -0
  92. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
  93. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
  94. package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
  95. package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
  96. package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
  97. package/novac/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
  98. package/novac/node_modules/commander/LICENSE +22 -0
  99. package/novac/node_modules/commander/Readme.md +1176 -0
  100. package/novac/node_modules/commander/esm.mjs +16 -0
  101. package/novac/node_modules/commander/index.js +24 -0
  102. package/novac/node_modules/commander/lib/argument.js +150 -0
  103. package/novac/node_modules/commander/lib/command.js +2777 -0
  104. package/novac/node_modules/commander/lib/error.js +39 -0
  105. package/novac/node_modules/commander/lib/help.js +747 -0
  106. package/novac/node_modules/commander/lib/option.js +380 -0
  107. package/novac/node_modules/commander/lib/suggestSimilar.js +101 -0
  108. package/novac/node_modules/commander/package-support.json +19 -0
  109. package/novac/node_modules/commander/package.json +82 -0
  110. package/novac/node_modules/commander/typings/esm.d.mts +3 -0
  111. package/novac/node_modules/commander/typings/index.d.ts +1113 -0
  112. package/novac/node_modules/node-addon-api/LICENSE.md +9 -0
  113. package/novac/node_modules/node-addon-api/README.md +95 -0
  114. package/novac/node_modules/node-addon-api/common.gypi +21 -0
  115. package/novac/node_modules/node-addon-api/except.gypi +25 -0
  116. package/novac/node_modules/node-addon-api/index.js +14 -0
  117. package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
  118. package/novac/node_modules/node-addon-api/napi-inl.h +7165 -0
  119. package/novac/node_modules/node-addon-api/napi.h +3364 -0
  120. package/novac/node_modules/node-addon-api/node_addon_api.gyp +42 -0
  121. package/novac/node_modules/node-addon-api/node_api.gyp +9 -0
  122. package/novac/node_modules/node-addon-api/noexcept.gypi +26 -0
  123. package/novac/node_modules/node-addon-api/package-support.json +21 -0
  124. package/novac/node_modules/node-addon-api/package.json +480 -0
  125. package/novac/node_modules/node-addon-api/tools/README.md +73 -0
  126. package/novac/node_modules/node-addon-api/tools/check-napi.js +99 -0
  127. package/novac/node_modules/node-addon-api/tools/clang-format.js +71 -0
  128. package/novac/node_modules/node-addon-api/tools/conversion.js +301 -0
  129. package/novac/node_modules/serialize-javascript/LICENSE +27 -0
  130. package/novac/node_modules/serialize-javascript/README.md +149 -0
  131. package/novac/node_modules/serialize-javascript/index.js +297 -0
  132. package/novac/node_modules/serialize-javascript/package.json +33 -0
  133. package/novac/package.json +27 -0
  134. package/novac/scripts/update-bin.js +24 -0
  135. package/novac/src/core/bstd.js +1035 -0
  136. package/novac/src/core/config.js +155 -0
  137. package/novac/src/core/describe.js +187 -0
  138. package/novac/src/core/emitter.js +499 -0
  139. package/novac/src/core/error.js +86 -0
  140. package/novac/src/core/executor.js +5606 -0
  141. package/novac/src/core/formatter.js +686 -0
  142. package/novac/src/core/lexer.js +1026 -0
  143. package/novac/src/core/nova_builtins.js +717 -0
  144. package/novac/src/core/nova_thread_worker.js +166 -0
  145. package/novac/src/core/parser.js +2181 -0
  146. package/novac/src/core/types.js +112 -0
  147. package/novac/src/index.js +28 -0
  148. package/novac/src/runtime/stdlib.js +244 -0
  149. package/package.json +6 -3
  150. package/scripts/update-bin.js +0 -0
  151. package/src/core/bstd.js +838 -362
  152. package/src/core/executor.js +2578 -170
  153. package/src/core/lexer.js +502 -54
  154. package/src/core/nova_builtins.js +21 -3
  155. package/src/core/parser.js +413 -72
  156. package/src/core/types.js +30 -2
  157. package/src/index.js +0 -0
  158. package/examples/example-project/README.md +0 -3
  159. package/examples/example-project/src/main.nova +0 -3
  160. package/src/core/environment.js +0 -0
  161. /package/{examples/example-project/bin/example-project.nv → novac/node_modules/node-addon-api/nothing.c} +0 -0
@@ -0,0 +1,717 @@
1
+ /**
2
+ * Nova Built-in Class Objects
3
+ * ════════════════════════════
4
+ * Every statement in Nova has an equivalent OOP form.
5
+ * All registries are unified under the `nova` global object.
6
+ *
7
+ * Built-in constructable objects:
8
+ * ForLoop, WhileLoop, UntilLoop, RepeatLoop, EachLoop,
9
+ * IfBlock, MatchBlock, SwitchBlock,
10
+ * TryCatch, Pipeline, FuncDef, EventBus,
11
+ * Timer, Counter, Stack, Queue, LinkedList,
12
+ * State, Struct, Enum, Range, Signal,
13
+ * Lazy, Memo, Observable, Validator,
14
+ * DataStream, Transformer, Router
15
+ */
16
+
17
+ const { NovaArray, NovaObject, NovaRange, NovaStruct, NovaEnum, NovaBool, NovaNull } = require('./types');
18
+
19
+ /** Unwrap NovaObject/NovaStruct to plain JS object for option spreading */
20
+ function unwrapOpts(opts) {
21
+ if (!opts) return {};
22
+ if (opts instanceof NovaObject) return opts.inner;
23
+ if (opts instanceof NovaStruct) return opts.inner;
24
+ if (typeof opts === 'object') return opts;
25
+ return {};
26
+ }
27
+
28
+ // ═══════════════════════════════════════════════════════════
29
+ // Unified Registry — all Nova registries in one place
30
+ // ═══════════════════════════════════════════════════════════
31
+ function makeUnifiedRegistry(executor) {
32
+ const self = executor;
33
+
34
+ const registry = new NovaObject({});
35
+
36
+ // Live proxy that always reflects current state
37
+ const handler = {
38
+ get(target, prop) {
39
+ switch (prop) {
40
+ case 'macros': return new NovaObject(Object.fromEntries(self.macros));
41
+ case 'blocks': return new NovaObject(Object.fromEntries(self.blocks));
42
+ case 'snippets': return new NovaObject(Object.fromEntries(self.snippets));
43
+ case 'gears': return new NovaObject(Object.fromEntries(self.gears));
44
+ case 'sessions': return new NovaObject(Object.fromEntries(self.sessions));
45
+ case 'resus': return new NovaObject(Object.fromEntries(self.resus));
46
+ case 'keyfuncs': return new NovaObject(Object.fromEntries(self.keyfuncs));
47
+ case 'backups': return new NovaObject(Object.fromEntries(self.backups));
48
+ case 'options': return new NovaObject({ ...self.options });
49
+ case 'descriptions':return new NovaArray([...self.descriptions]);
50
+ case 'types': return makeTypeRegistryView(self.types);
51
+ case 'events': return makeEventBusView(self.eventBus);
52
+ case 'scope': return self.globalScope;
53
+ case 'version': return '2.0';
54
+ // Kit metadata — { kitName: { meta, docs, provides, ... } }
55
+ case 'kitMeta': return new NovaObject(self._kitMeta || {});
56
+ // Custom dynamic variables registered by kits — { name: fn }
57
+ case 'dvars': return new NovaObject(Object.fromEntries(self._customDvars || new Map()));
58
+
59
+ // Registry mutation methods
60
+ case 'setMacro': return (name, val) => { self.macros.set(String(name), String(val)); self.globalScope.set(String(name), String(val)); };
61
+ case 'getMacro': return (name) => self.macros.get(String(name)) ?? null;
62
+ case 'hasMacro': return (name) => self.macros.has(String(name));
63
+
64
+ // Register a custom dynamic variable at runtime:
65
+ // nova.registerDvar('__myvar__', (scope, exe) => someValue)
66
+ case 'registerDvar': return (name, fn) => {
67
+ if (!self._customDvars) self._customDvars = new Map();
68
+ self._customDvars.set(String(name), fn);
69
+ };
70
+ case 'unregisterDvar': return (name) => {
71
+ if (self._customDvars) self._customDvars.delete(String(name));
72
+ };
73
+
74
+ case 'setBlock': return (name, fn) => { self.blocks.set(String(name), { body: [], _native: fn }); };
75
+ case 'runBlock': return (name) => {
76
+ const b = self.blocks.get(String(name));
77
+ if (!b) throw new Error('Block not found: ' + name);
78
+ if (b._native) return b._native();
79
+ return self.runLoop(b.body, b.scope || self.globalScope);
80
+ };
81
+
82
+ case 'runSnippet': return (name, ...args) => {
83
+ const s = self.snippets.get(String(name));
84
+ if (!s) throw new Error('Snippet not found: ' + name);
85
+ if (s._native) return s._native(...args);
86
+ return self.runLoop(s.body, s.scope || self.globalScope);
87
+ };
88
+
89
+ case 'emit': return (event, val) => {
90
+ const handlers = self.eventBus.get(String(event)) || [];
91
+ for (const h of handlers) {
92
+ if (h._native && typeof h._native === 'function') {
93
+ try { h._native(val); } catch (_) {}
94
+ } else {
95
+ const hs = new (require('./executor').Scope)('function', self.globalScope, self.globalScope);
96
+ if (h.param) hs.set(h.param, val);
97
+ self.runLoop(h.body, hs);
98
+ }
99
+ }
100
+ };
101
+ case 'on': return (event, fn) => {
102
+ const name = String(event);
103
+ if (!self.eventBus.has(name)) self.eventBus.set(name, []);
104
+ self.eventBus.get(name).push({ param: '_v', body: [], _native: fn });
105
+ };
106
+
107
+ case 'eval': return (code) => {
108
+ const { Parser } = require('./parser');
109
+ const ast = new Parser(String(code)).parse();
110
+ return self.run(ast);
111
+ };
112
+
113
+ case 'inspect': return (name) => {
114
+ // Return everything about a name across all registries
115
+ return new NovaObject({
116
+ inScope: self.globalScope.get(String(name)) != null,
117
+ isMacro: self.macros.has(String(name)),
118
+ isBlock: self.blocks.has(String(name)),
119
+ isSnippet: self.snippets.has(String(name)),
120
+ isGear: self.gears.has(String(name)),
121
+ isSession: self.sessions.has(String(name)),
122
+ isResu: self.resus.has(String(name)),
123
+ value: self.globalScope.get(String(name)),
124
+ });
125
+ };
126
+
127
+ case 'clearAll': return () => {
128
+ self.macros.clear(); self.blocks.clear(); self.snippets.clear();
129
+ self.gears.clear(); self.sessions.clear(); self.descriptions.length = 0;
130
+ };
131
+
132
+ default:
133
+ // Try each registry in order
134
+ if (self.macros.has(prop)) return self.macros.get(prop);
135
+ if (self.blocks.has(prop)) return { run: () => self.runLoop(self.blocks.get(prop).body, self.blocks.get(prop).scope || self.globalScope) };
136
+ if (self.snippets.has(prop)) return self.snippets.get(prop);
137
+ if (self.gears.has(prop)) return self.gears.get(prop);
138
+ if (self.sessions.has(prop)) return self.sessions.get(prop);
139
+ if (self.resus.has(prop)) return self.resus.get(prop);
140
+ return target[prop] ?? null;
141
+ }
142
+ },
143
+ set(target, prop, value) {
144
+ // Write-through to appropriate registry
145
+ self.macros.set(String(prop), value);
146
+ self.globalScope.set(String(prop), value);
147
+ return true;
148
+ }
149
+ };
150
+
151
+ return new Proxy({}, handler);
152
+ }
153
+
154
+ function makeTypeRegistryView(types) {
155
+ return new NovaObject({
156
+ structs: new NovaArray([...types.structs.keys()]),
157
+ interfaces: new NovaArray([...types.interfaces.keys()]),
158
+ enums: new NovaArray([...types.enums.keys()]),
159
+ traits: new NovaArray([...types.traits.keys()]),
160
+ check: (val, typeName) => types.check(val, { kind: 'named_type', name: String(typeName) }),
161
+ list: () => new NovaArray([
162
+ ...types.structs.keys(), ...types.interfaces.keys(),
163
+ ...types.enums.keys(), ...types.traits.keys()
164
+ ]),
165
+ });
166
+ }
167
+
168
+ function makeEventBusView(bus) {
169
+ return new NovaObject({
170
+ events: () => new NovaArray([...bus.keys()]),
171
+ count: (ev) => (bus.get(String(ev)) || []).length,
172
+ has: (ev) => bus.has(String(ev)),
173
+ clear: (ev) => bus.delete(String(ev)),
174
+ clearAll: () => bus.clear(),
175
+ });
176
+ }
177
+
178
+ // ═══════════════════════════════════════════════════════════
179
+ // Built-in Class Objects — OOP alternatives to statement syntax
180
+ // ═══════════════════════════════════════════════════════════
181
+
182
+ /** ForLoop — OOP wrapper around for-loop logic */
183
+ class NovaForLoop {
184
+ constructor(opts = {}) {
185
+ opts = unwrapOpts(opts);
186
+ this._from = opts.from ?? 0;
187
+ this._to = opts.to ?? 0;
188
+ this._step = opts.step ?? 1;
189
+ this._body = opts.body ?? null;
190
+ this._var = opts.var ?? 'i';
191
+ this._result = null;
192
+ }
193
+ from(n) { this._from = n; return this; }
194
+ to(n) { this._to = n; return this; }
195
+ step(n) { this._step = n; return this; }
196
+ do(fn) { this._body = fn; return this; }
197
+ each(fn) { this._body = fn; return this; }
198
+ map(fn) { this._body = fn; return this; } // alias for do/each when collecting
199
+ // pipe() — convert to Pipeline for further transformation
200
+ pipe() { return new NovaPipeline(this.toArray().inner); }
201
+ // toStream() — convert to DataStream
202
+ toStream() { return new NovaDataStream(this.toArray().inner); }
203
+ collect() {
204
+ const out = [];
205
+ for (let i = this._from; this._step > 0 ? i <= this._to : i >= this._to; i += this._step) {
206
+ out.push(this._body ? this._body(i) : i);
207
+ }
208
+ this._result = new NovaArray(out);
209
+ return this._result;
210
+ }
211
+ // For chained .map(...).collect() on a ForLoop:
212
+ // NovaForLoop supports being used as a Pipeline head
213
+ filter(fn) { return new NovaPipeline(this.toArray().inner).filter(fn); }
214
+ run() {
215
+ const fn = this._body;
216
+ for (let i = this._from; this._step > 0 ? i <= this._to : i >= this._to; i += this._step) {
217
+ if (fn) { try { fn(i); } catch(e) { if (e && '__break' in e) break; if (e && '__continue' in e) continue; throw e; } }
218
+ }
219
+ return this;
220
+ }
221
+ toRange() { return new NovaRange(this._from, this._to, this._step); }
222
+ toArray() {
223
+ const out = [];
224
+ for (let i = this._from; this._step > 0 ? i <= this._to : i >= this._to; i += this._step) out.push(i);
225
+ return new NovaArray(out);
226
+ }
227
+ toString() { return `ForLoop(${this._from}..${this._to} step ${this._step})`; }
228
+ }
229
+
230
+ /** WhileLoop */
231
+ class NovaWhileLoop {
232
+ constructor(opts = {}) {
233
+ opts = unwrapOpts(opts);
234
+ this._cond = opts.cond ?? (() => false);
235
+ this._body = opts.body ?? null;
236
+ this._max = opts.max ?? Infinity;
237
+ }
238
+ cond(fn) { this._cond = fn; return this; }
239
+ do(fn) { this._body = fn; return this; }
240
+ maxIter(n) { this._max = n; return this; }
241
+ run() {
242
+ let count = 0;
243
+ while (this._cond() && count++ < this._max) {
244
+ if (this._body) { try { this._body(count - 1); } catch(e) { if (e && '__break' in e) break; throw e; } }
245
+ }
246
+ return this;
247
+ }
248
+ toString() { return 'WhileLoop'; }
249
+ }
250
+
251
+ /** IfBlock */
252
+ class NovaIfBlock {
253
+ constructor(opts = {}) {
254
+ opts = unwrapOpts(opts);
255
+ this._cond = opts.cond ?? false;
256
+ this._then = opts.then ?? null;
257
+ this._else = opts.else ?? null;
258
+ this._elseIfs = [];
259
+ }
260
+ cond(v) { this._cond = v; return this; }
261
+ then(fn) { this._then = fn; return this; }
262
+ else(fn) { this._else = fn; return this; }
263
+ elseIf(c, fn) { this._elseIfs.push({ cond: c, fn }); return this; }
264
+ run() {
265
+ const c = typeof this._cond === 'function' ? this._cond() : this._cond;
266
+ if (c) { if (this._then) return this._then(); return true; }
267
+ for (const branch of this._elseIfs) {
268
+ const bc = typeof branch.cond === 'function' ? branch.cond() : branch.cond;
269
+ if (bc) { if (branch.fn) return branch.fn(); return true; }
270
+ }
271
+ if (this._else) return this._else();
272
+ return false;
273
+ }
274
+ toString() { return 'IfBlock'; }
275
+ }
276
+
277
+ /** TryCatch */
278
+ class NovaTryCatch {
279
+ constructor(opts = {}) {
280
+ opts = unwrapOpts(opts);
281
+ this._try = opts.try ?? null;
282
+ this._catch = opts.catch ?? null;
283
+ this._finally = opts.finally ?? null;
284
+ this._error = null;
285
+ this._result = undefined;
286
+ }
287
+ try(fn) { this._try = fn; return this; }
288
+ catch(fn) { this._catch = fn; return this; }
289
+ finally(fn) { this._finally = fn; return this; }
290
+ run() {
291
+ try {
292
+ if (this._try) this._result = this._try();
293
+ } catch(e) {
294
+ // Unwrap Nova exceptions to their payload value
295
+ const payload = (e && e.payload !== undefined) ? e.payload : e;
296
+ this._error = payload;
297
+ if (this._catch) this._result = this._catch(payload);
298
+ } finally {
299
+ if (this._finally) this._finally();
300
+ }
301
+ return this._result;
302
+ }
303
+ get error() { return this._error; }
304
+ toString() { return 'TryCatch'; }
305
+ }
306
+
307
+ /** Pipeline — functional composition chain */
308
+ class NovaPipeline {
309
+ constructor(initial) {
310
+ this._val = initial;
311
+ this._fns = [];
312
+ this._name = null;
313
+ }
314
+ pipe(fn) { this._fns.push({ fn, type: 'map' }); return this; }
315
+ filter(fn) { this._fns.push({ fn, type: 'filter' }); return this; }
316
+ tap(fn) { this._fns.push({ fn, type: 'tap' }); return this; }
317
+ map(fn) { return this.pipe(fn); }
318
+ flatMap(fn) { this._fns.push({ fn, type: 'flatMap'}); return this; }
319
+ reduce(fn, init) {
320
+ if (arguments.length === 0) { this._fns.push({ fn: null, type: 'reduce', init: undefined }); return this; }
321
+ if (typeof init !== 'undefined') {
322
+ // immediate reduce — collect then reduce
323
+ return this.collect().inner.reduce(fn, init);
324
+ }
325
+ this._fns.push({ fn, type: 'reduce', init }); return this;
326
+ }
327
+ take(n) { this._fns.push({ n, type: 'take' }); return this; }
328
+ skip(n) { this._fns.push({ n, type: 'skip' }); return this; }
329
+ named(n) { this._name = n; return this; }
330
+ run(input) {
331
+ let val = input !== undefined ? input : this._val;
332
+ for (const step of this._fns) {
333
+ const arr = val instanceof NovaArray ? val.inner : (Array.isArray(val) ? val : null);
334
+ switch(step.type) {
335
+ case 'map': val = arr ? new NovaArray(arr.map(step.fn)) : step.fn(val); break;
336
+ case 'filter': val = arr ? new NovaArray(arr.filter(step.fn)) : (step.fn(val) ? val : null); break;
337
+ case 'tap': step.fn(val); break;
338
+ case 'flatMap': val = arr ? new NovaArray(arr.flatMap(v => { const r = step.fn(v); return r instanceof NovaArray ? r.inner : [r]; })) : step.fn(val); break;
339
+ case 'reduce': val = arr ? arr.reduce(step.fn, step.init) : step.fn(step.init, val); break;
340
+ case 'take': val = arr ? new NovaArray(arr.slice(0, step.n)) : val; break;
341
+ case 'skip': val = arr ? new NovaArray(arr.slice(step.n)) : val; break;
342
+ }
343
+ }
344
+ return val;
345
+ }
346
+ collect(input) { return this.run(input); }
347
+ toString() { return 'Pipeline[' + (this._name || this._fns.length + ' steps') + ']'; }
348
+ }
349
+
350
+ /** FuncDef — define and call functions dynamically */
351
+ class NovaFuncDef {
352
+ constructor(opts = {}) {
353
+ opts = unwrapOpts(opts);
354
+ this._args = opts.args ?? [];
355
+ this._body = opts.body ?? null;
356
+ this._name = opts.name ?? 'anonymous';
357
+ this._executor = null;
358
+ }
359
+ args(...a) { this._args = a.flat(); return this; }
360
+ body(fn) { this._body = fn; return this; }
361
+ named(n) { this._name = n; return this; }
362
+ call(...vals) {
363
+ if (typeof this._body === 'function') return this._body(...vals);
364
+ if (this._executor && this._body) {
365
+ const { Scope } = require('./executor');
366
+ const ls = new Scope('function', this._executor.globalScope, this._executor.globalScope);
367
+ this._args.forEach((a, i) => ls.set(a, vals[i]));
368
+ return this._executor.runFunctionNode({ args: this._args.map(n=>({name:n,rest:false,defaultValue:null})), body: this._body }, ls, vals);
369
+ }
370
+ return undefined;
371
+ }
372
+ toArrow() {
373
+ return (...args) => this.call(...args);
374
+ }
375
+ toString() { return `FuncDef[${this._name}(${this._args.join(',')})]`; }
376
+ }
377
+
378
+ /** Timer */
379
+ class NovaTimer {
380
+ constructor() { this._start = null; this._laps = []; }
381
+ start() { this._start = Date.now(); return this; }
382
+ stop() { return Date.now() - (this._start ?? Date.now()); }
383
+ lap() { const t = Date.now() - (this._start ?? Date.now()); this._laps.push(t); return t; }
384
+ reset() { this._start = null; this._laps = []; return this; }
385
+ get elapsed() { return this._start ? Date.now() - this._start : 0; }
386
+ get laps() { return new NovaArray(this._laps); }
387
+ toString() { return `Timer[${this.elapsed}ms]`; }
388
+ }
389
+
390
+ /** Counter */
391
+ class NovaCounter {
392
+ constructor(initial = 0, step = 1) { this._val = initial; this._step = step; this._min = -Infinity; this._max = Infinity; }
393
+ increment(n) { this._val = Math.min(this._max, this._val + (n ?? this._step)); return this; }
394
+ decrement(n) { this._val = Math.max(this._min, this._val - (n ?? this._step)); return this; }
395
+ reset(v) { this._val = v ?? 0; return this; }
396
+ clamp(lo,hi) { this._min = lo; this._max = hi; return this; }
397
+ get value() { return this._val; }
398
+ toString() { return `Counter[${this._val}]`; }
399
+ }
400
+
401
+ /** Stack */
402
+ class NovaStack {
403
+ constructor(...initial) { this._data = [...initial]; }
404
+ push(...v) { this._data.push(...v); return this; }
405
+ pop() { return this._data.pop() ?? null; }
406
+ peek() { return this._data[this._data.length - 1] ?? null; }
407
+ get size() { return this._data.length; }
408
+ get empty() { return this._data.length === 0; }
409
+ clear() { this._data = []; return this; }
410
+ toArray() { return new NovaArray([...this._data]); }
411
+ toString() { return `Stack[${this._data.length}]`; }
412
+ }
413
+
414
+ /** Queue */
415
+ class NovaQueue {
416
+ constructor(...initial) { this._data = [...initial]; }
417
+ enqueue(...v) { this._data.push(...v); return this; }
418
+ dequeue() { return this._data.shift() ?? null; }
419
+ peek() { return this._data[0] ?? null; }
420
+ get size() { return this._data.length; }
421
+ get empty() { return this._data.length === 0; }
422
+ clear() { this._data = []; return this; }
423
+ toArray() { return new NovaArray([...this._data]); }
424
+ toString() { return `Queue[${this._data.length}]`; }
425
+ }
426
+
427
+ /** LinkedList node */
428
+ class LLNode { constructor(v){ this.value=v; this.next=null; } }
429
+ /** LinkedList */
430
+ class NovaLinkedList {
431
+ constructor() { this.head = null; this.tail = null; this._size = 0; }
432
+ push(v) {
433
+ const n = new LLNode(v);
434
+ if (!this.tail) { this.head = this.tail = n; } else { this.tail.next = n; this.tail = n; }
435
+ this._size++;
436
+ return this;
437
+ }
438
+ pop() {
439
+ if (!this.head) return null;
440
+ if (this.head === this.tail) { const v = this.head.value; this.head = this.tail = null; this._size--; return v; }
441
+ let cur = this.head;
442
+ while (cur.next !== this.tail) cur = cur.next;
443
+ const v = this.tail.value; cur.next = null; this.tail = cur; this._size--;
444
+ return v;
445
+ }
446
+ shift() { if (!this.head) return null; const v = this.head.value; this.head = this.head.next; if (!this.head) this.tail = null; this._size--; return v; }
447
+ unshift(v){ const n = new LLNode(v); n.next = this.head; this.head = n; if (!this.tail) this.tail = n; this._size++; return this; }
448
+ find(fn) { let cur = this.head; while (cur) { if (fn(cur.value)) return cur.value; cur = cur.next; } return null; }
449
+ toArray() { const out=[]; let cur=this.head; while(cur){out.push(cur.value);cur=cur.next;} return new NovaArray(out); }
450
+ get size(){ return this._size; }
451
+ toString(){ return `LinkedList[${this._size}]`; }
452
+ }
453
+
454
+ /** State machine */
455
+ class NovaState {
456
+ constructor(initial) {
457
+ this._current = initial ?? 'idle';
458
+ this._transitions = {};
459
+ this._onEnter = {};
460
+ this._onExit = {};
461
+ this._history = [initial ?? 'idle'];
462
+ }
463
+ add(from, event, to) {
464
+ if (!this._transitions[from]) this._transitions[from] = {};
465
+ this._transitions[from][event] = to;
466
+ return this;
467
+ }
468
+ onEnter(state, fn) { this._onEnter[state] = fn; return this; }
469
+ onExit(state, fn) { this._onExit[state] = fn; return this; }
470
+ dispatch(event) {
471
+ const next = this._transitions[this._current]?.[event];
472
+ if (!next) return false;
473
+ if (this._onExit[this._current]) this._onExit[this._current](this._current);
474
+ this._current = next;
475
+ this._history.push(next);
476
+ if (this._onEnter[next]) this._onEnter[next](next);
477
+ return true;
478
+ }
479
+ get current() { return this._current; }
480
+ get history() { return new NovaArray(this._history); }
481
+ is(state) { return this._current === state; }
482
+ toString() { return `State[${this._current}]`; }
483
+ }
484
+
485
+ /** Observable — reactive value with subscribers */
486
+ class NovaObservable {
487
+ constructor(initial) { this._val = initial; this._subs = []; this._computed = []; }
488
+ get value() { return this._val; }
489
+ set value(v) { const old = this._val; this._val = v; this._subs.forEach(fn => fn(v, old)); this._computed.forEach(c => c._recompute()); }
490
+ subscribe(fn) { this._subs.push(fn); return () => this._subs = this._subs.filter(s=>s!==fn); }
491
+ pipe(fn) { const c = new NovaObservable(fn(this._val)); c._recompute = () => c.value = fn(this._val); this._computed.push(c); return c; }
492
+ once(fn) { const unsub = this.subscribe((v,o) => { fn(v,o); unsub(); }); return this; }
493
+ toString() { return `Observable[${this._val}]`; }
494
+ }
495
+
496
+ /** Validator */
497
+ class NovaValidator {
498
+ constructor() { this._rules = []; }
499
+ required() { this._rules.push(v => v != null && v !== '' ? null : 'required'); return this; }
500
+ type(t) { this._rules.push(v => typeof v === t ? null : `expected ${t}`); return this; }
501
+ min(n) { this._rules.push(v => v >= n ? null : `min ${n}`); return this; }
502
+ max(n) { this._rules.push(v => v <= n ? null : `max ${n}`); return this; }
503
+ minLen(n) { this._rules.push(v => String(v).length >= n ? null : `minLen ${n}`); return this; }
504
+ maxLen(n) { this._rules.push(v => String(v).length <= n ? null : `maxLen ${n}`); return this; }
505
+ pattern(re) { this._rules.push(v => new RegExp(re).test(String(v)) ? null : `pattern ${re}`); return this; }
506
+ custom(fn, msg) { this._rules.push(v => fn(v) ? null : (msg ?? 'invalid')); return this; }
507
+ email() { return this.pattern('[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}'); }
508
+ validate(v) {
509
+ const errors = this._rules.map(r => r(v)).filter(Boolean);
510
+ return new NovaObject({ valid: errors.length === 0, errors: new NovaArray(errors), value: v });
511
+ }
512
+ toString() { return `Validator[${this._rules.length} rules]`; }
513
+ }
514
+
515
+ /** DataStream — lazy collection with transformation */
516
+ class NovaDataStream {
517
+ constructor(source) {
518
+ this._source = source instanceof NovaArray ? source.inner : (Array.isArray(source) ? source : [source]);
519
+ this._ops = [];
520
+ }
521
+ map(fn) { this._ops.push({ type:'map', fn }); return this; }
522
+ filter(fn) { this._ops.push({ type:'filter', fn }); return this; }
523
+ take(n) { this._ops.push({ type:'take', n }); return this; }
524
+ skip(n) { this._ops.push({ type:'skip', n }); return this; }
525
+ flatMap(fn) { this._ops.push({ type:'flatMap',fn }); return this; }
526
+ distinct() { this._ops.push({ type:'distinct' }); return this; }
527
+ sort(fn) { this._ops.push({ type:'sort', fn }); return this; }
528
+ reverse() { this._ops.push({ type:'reverse' }); return this; }
529
+ zip(other) { this._ops.push({ type:'zip', other }); return this; }
530
+ collect() {
531
+ let data = [...this._source];
532
+ for (const op of this._ops) {
533
+ switch(op.type) {
534
+ case 'map': data = data.map(op.fn); break;
535
+ case 'filter': data = data.filter(op.fn); break;
536
+ case 'take': data = data.slice(0, op.n); break;
537
+ case 'skip': data = data.slice(op.n); break;
538
+ case 'flatMap': data = data.flatMap(op.fn); break;
539
+ case 'distinct': data = [...new Set(data)]; break;
540
+ case 'sort': data = [...data].sort(op.fn); break;
541
+ case 'reverse': data = [...data].reverse(); break;
542
+ case 'zip': {
543
+ const other = op.other instanceof NovaArray ? op.other.inner : op.other;
544
+ const len = Math.min(data.length, other.length);
545
+ data = Array.from({length:len}, (_,i) => new NovaArray([data[i], other[i]]));
546
+ break;
547
+ }
548
+ }
549
+ }
550
+ return new NovaArray(data);
551
+ }
552
+ reduce(fn, init) { return this.collect().inner.reduce(fn, init); }
553
+ forEach(fn) { this.collect().inner.forEach(fn); return this; }
554
+ first() { return this.collect().inner[0] ?? null; }
555
+ last() { const c = this.collect().inner; return c[c.length-1] ?? null; }
556
+ count() { return this.collect().inner.length; }
557
+ toString() { return `DataStream[${this._source.length} items, ${this._ops.length} ops]`; }
558
+ }
559
+
560
+ /** Transformer — bidirectional value transformation */
561
+ class NovaTransformer {
562
+ constructor() { this._encode = []; this._decode = []; }
563
+ encode(fn) { this._encode.push(fn); return this; }
564
+ decode(fn) { this._decode.push(fn); return this; }
565
+ to(v) { return this._encode.reduce((acc, fn) => fn(acc), v); }
566
+ from(v) { return this._decode.reduceRight((acc, fn) => fn(acc), v); }
567
+ // Preset transformers
568
+ static json() {
569
+ const t = new NovaTransformer();
570
+ t.encode(v => JSON.stringify(v && v.inner !== undefined ? v.inner : v));
571
+ t.decode(v => JSON.parse(v));
572
+ return t;
573
+ }
574
+ static base64() {
575
+ const t = new NovaTransformer();
576
+ t.encode(v => Buffer.from(String(v)).toString('base64'));
577
+ t.decode(v => Buffer.from(String(v), 'base64').toString('utf8'));
578
+ return t;
579
+ }
580
+ static upper() { const t = new NovaTransformer(); t.encode(v => String(v).toUpperCase()); return t; }
581
+ static trim_() { const t = new NovaTransformer(); t.encode(v => String(v).trim()); return t; }
582
+ static number_() { const t = new NovaTransformer(); t.encode(Number).decode(String); return t; }
583
+ toString() { return `Transformer[${this._encode.length}→${this._decode.length}]`; }
584
+ }
585
+
586
+ /** Router — simple pattern-matching router */
587
+ class NovaRouter {
588
+ constructor() { this._routes = []; this._fallback = null; }
589
+ on(pattern, fn) { this._routes.push({ pattern: new RegExp('^' + pattern + '$'), fn }); return this; }
590
+ default(fn) { this._fallback = fn; return this; }
591
+ dispatch(path, ...args) {
592
+ for (const r of this._routes) {
593
+ const m = String(path).match(r.pattern);
594
+ if (m) return r.fn(...m.slice(1), ...args);
595
+ }
596
+ if (this._fallback) return this._fallback(path, ...args);
597
+ return null;
598
+ }
599
+ toString() { return `Router[${this._routes.length} routes]`; }
600
+ }
601
+
602
+ /** EventBus — standalone pub/sub */
603
+ class NovaEventBus {
604
+ constructor() { this._handlers = {}; }
605
+ on(ev, fn) { (this._handlers[ev] = this._handlers[ev]||[]).push(fn); return this; }
606
+ once(ev, fn) { const wrap = (...a) => { fn(...a); this.off(ev, wrap); }; return this.on(ev, wrap); }
607
+ off(ev, fn) { if (this._handlers[ev]) this._handlers[ev] = this._handlers[ev].filter(h=>h!==fn); return this; }
608
+ emit(ev, ...a) { (this._handlers[ev]||[]).forEach(fn => fn(...a)); return this; }
609
+ events() { return new NovaArray(Object.keys(this._handlers)); }
610
+ toString() { return `EventBus[${Object.keys(this._handlers).length} events]`; }
611
+ }
612
+
613
+ /** Memo — memoized function */
614
+ class NovaMemo {
615
+ constructor(fn, keyFn) {
616
+ this._fn = fn;
617
+ this._cache = new Map();
618
+ this._keyFn = keyFn ?? ((...a) => JSON.stringify(a));
619
+ this._hits = 0; this._misses = 0;
620
+ }
621
+ call(...args) {
622
+ const key = this._keyFn(...args);
623
+ if (this._cache.has(key)) { this._hits++; return this._cache.get(key); }
624
+ this._misses++;
625
+ const result = this._fn(...args);
626
+ this._cache.set(key, result);
627
+ return result;
628
+ }
629
+ clear() { this._cache.clear(); return this; }
630
+ invalidate(k){ this._cache.delete(this._keyFn(k)); return this; }
631
+ get stats() { return new NovaObject({ hits: this._hits, misses: this._misses, size: this._cache.size }); }
632
+ toString() { return `Memo[${this._cache.size} cached]`; }
633
+ }
634
+
635
+ /** Lazy — deferred evaluation */
636
+ class NovaLazy {
637
+ constructor(fn) { this._fn = fn; this._val = undefined; this._evaluated = false; }
638
+ get value() { if (!this._evaluated) { this._val = this._fn(); this._evaluated = true; } return this._val; }
639
+ reset() { this._evaluated = false; this._val = undefined; return this; }
640
+ force() { return this.value; }
641
+ map(fn) { return new NovaLazy(() => fn(this.value)); }
642
+ toString() { return this._evaluated ? `Lazy[${this._val}]` : 'Lazy[?]'; }
643
+ }
644
+
645
+ /** Signal — reactive primitive (like a mini-observable) */
646
+ class NovaSignal {
647
+ constructor(initial) { this._val = initial; this._effects = new Set(); }
648
+ get value() { return this._val; }
649
+ set value(v) { this._val = v; this._effects.forEach(fn => fn(v)); }
650
+ effect(fn) { this._effects.add(fn); fn(this._val); return () => this._effects.delete(fn); }
651
+ derive(fn) { const s = new NovaSignal(fn(this._val)); this.effect(v => s.value = fn(v)); return s; }
652
+ toString() { return `Signal[${this._val}]`; }
653
+ }
654
+
655
+ /** MatchBlock — OOP pattern matching */
656
+ class NovaMatchBlock {
657
+ constructor(subject) {
658
+ this._subject = subject;
659
+ this._cases = [];
660
+ this._default = null;
661
+ }
662
+ when(pattern, fn) {
663
+ this._cases.push({ pattern, fn });
664
+ return this;
665
+ }
666
+ default(fn) { this._default = fn; return this; }
667
+ run() {
668
+ for (const c of this._cases) {
669
+ const p = c.pattern;
670
+ let match = false;
671
+ if (p instanceof NovaRange) match = p.includes(this._subject);
672
+ else if (typeof p === 'function') match = p(this._subject);
673
+ else if (Array.isArray(p) || p instanceof NovaArray) {
674
+ const arr = p instanceof NovaArray ? p.inner : p;
675
+ match = arr.some(v => v === this._subject);
676
+ }
677
+ else match = p === this._subject;
678
+ if (match) return c.fn(this._subject);
679
+ }
680
+ if (this._default) return this._default(this._subject);
681
+ return null;
682
+ }
683
+ toString() { return `MatchBlock[${this._cases.length} cases]`; }
684
+ }
685
+
686
+ // ═══════════════════════════════════════════════════════════
687
+ // Export
688
+ // ═══════════════════════════════════════════════════════════
689
+ module.exports = {
690
+ makeUnifiedRegistry,
691
+ // Statement-as-class exports
692
+ ForLoop: (opts) => new NovaForLoop(opts||{}),
693
+ WhileLoop: (opts) => new NovaWhileLoop(opts||{}),
694
+ IfBlock: (opts) => new NovaIfBlock(opts||{}),
695
+ TryCatch: (opts) => new NovaTryCatch(opts||{}),
696
+ Pipeline: (v) => new NovaPipeline(v),
697
+ FuncDef: (opts) => new NovaFuncDef(opts||{}),
698
+ MatchBlock: (v) => new NovaMatchBlock(v),
699
+ // Data structures
700
+ Timer: () => new NovaTimer(),
701
+ Counter: (n,s) => new NovaCounter(n,s),
702
+ Stack: (...v) => new NovaStack(...v),
703
+ Queue: (...v) => new NovaQueue(...v),
704
+ LinkedList: () => new NovaLinkedList(),
705
+ State: (s) => new NovaState(s),
706
+ Observable: (v) => new NovaObservable(v),
707
+ Validator: () => new NovaValidator(),
708
+ DataStream: (s) => new NovaDataStream(s),
709
+ Transformer: () => new NovaTransformer(),
710
+ TransformerJSON: () => NovaTransformer.json(),
711
+ TransformerBase64: () => NovaTransformer.base64(),
712
+ Router: () => new NovaRouter(),
713
+ EventBus: () => new NovaEventBus(),
714
+ Memo: (fn,k) => new NovaMemo(fn,k),
715
+ Lazy: (fn) => new NovaLazy(fn),
716
+ Signal: (v) => new NovaSignal(v),
717
+ };