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,499 +0,0 @@
1
- const { Parser } = require("./parser.js");
2
- const { CustomError, formatError } = require("./error.js");
3
-
4
- class Emitter {
5
- constructor(source) {
6
- this.source = source;
7
- this.parser = new Parser(source);
8
- this.ast = this.parser.parse();
9
- this.output = []; // Array of code segments
10
- this.indent = 0;
11
- this.rawsrc = source;
12
- }
13
-
14
- /**
15
- * Main entry point to compile the AST to JS code.
16
- * @returns {string} The transpiled JavaScript code.
17
- */
18
- emit() {
19
- this.emitProgram(this.ast);
20
- return this.output.join("");
21
- }
22
-
23
- // --- Utility Methods ---
24
-
25
- indentUp() {
26
- this.indent++;
27
- }
28
-
29
- indentDown() {
30
- this.indent--;
31
- }
32
-
33
- line(code = "") {
34
- this.output.push("\n");
35
- this.output.push(" ".repeat(this.indent));
36
- this.output.push(code);
37
- }
38
-
39
- // --- AST Node Emitters ---
40
-
41
- emitProgram(node) {
42
- this.line("// Transpiled from Nova Language");
43
-
44
- // Wrap the entire transpiled code in an async IIFE
45
- // to simulate a simple execution environment.
46
- this.line("(async function() {");
47
- this.indentUp();
48
-
49
- for (const statement of node.nodes) {
50
- this.emitStatement(statement);
51
- // Ensure there's a semicolon after every statement (if it wasn't added by the statement emitter)
52
- if (this.output.at(-1) !== ";") this.output.push(";");
53
- }
54
-
55
- this.indentDown();
56
- this.line("})();");
57
- }
58
-
59
- emitStatement(node) {
60
- if (!node) return;
61
-
62
- switch (node.kind) {
63
- case "declare":
64
- this.emitDeclaration(node);
65
- break;
66
- case "branch":
67
- this.emitBranch(node);
68
- break;
69
- case "function":
70
- this.emitFunctionDeclaration(node);
71
- break;
72
- case "class":
73
- this.emitClassDeclaration(node);
74
- break;
75
- case "return":
76
- this.emitReturn(node);
77
- break;
78
- case "throw":
79
- this.emitThrow(node);
80
- break;
81
- case "try":
82
- this.emitTry(node);
83
- break;
84
- case "exec":
85
- this.emitExecution(node);
86
- break;
87
- default:
88
- this.error(`Unknown statement kind: ${node.kind}`, node);
89
- }
90
- }
91
-
92
- emitExpression(node) {
93
- if (!node) return;
94
-
95
- switch (node.kind) {
96
- case "value":
97
- this.emitValue(node);
98
- break;
99
- case "ref":
100
- this.output.push(node.name);
101
- break;
102
- case "array":
103
- this.emitArray(node);
104
- break;
105
- case "object":
106
- this.emitObject(node);
107
- break;
108
- case "binary":
109
- this.emitBinary(node);
110
- break;
111
- case "unary":
112
- this.emitUnary(node);
113
- break;
114
- case "call":
115
- this.emitCall(node);
116
- break;
117
- case "prop":
118
- this.emitPropertyAccess(node);
119
- break;
120
- case "subscript":
121
- this.emitSubscript(node);
122
- break;
123
- case "assign":
124
- this.emitAssignment(node);
125
- break;
126
- case "postfix":
127
- this.emitPostfix(node);
128
- break;
129
- case "arrowfunc":
130
- this.emitArrowFunction(node);
131
- break;
132
- case "template":
133
- this.emitTemplateLiteral(node);
134
- break;
135
- case "await":
136
- this.output.push("await ");
137
- this.emitExpression(node.operand);
138
- break;
139
- default:
140
- this.error(`Unknown expression kind: ${node.kind}`, node);
141
- }
142
- }
143
-
144
- // --- Specific Statement Emitters ---
145
-
146
- emitDeclaration(node) {
147
- this.line(`${node.isConst ? "const" : "let"} `);
148
-
149
- // Handle destructuring
150
- if (node.destructure) {
151
- if (node.destructure.kind === "objpattern") {
152
- this.output.push("{");
153
- node.destructure.props.forEach(({ key, alias }, i) => {
154
- this.output.push(key);
155
- if (key !== alias) this.output.push(`: ${alias}`);
156
- if (i < node.destructure.props.length - 1) this.output.push(", ");
157
- });
158
- this.output.push("}");
159
- } else if (node.destructure.kind === "arrpattern") {
160
- this.output.push("[");
161
- node.destructure.elements.forEach((name, i) => {
162
- this.output.push(name);
163
- if (i < node.destructure.elements.length - 1) this.output.push(", ");
164
- });
165
- this.output.push("]");
166
- }
167
- } else {
168
- // Normal declaration
169
- this.output.push(node.name);
170
- }
171
-
172
- if (node.value) {
173
- this.output.push(" = ");
174
- this.emitExpression(node.value);
175
- }
176
- this.output.push(";");
177
- }
178
-
179
- emitBranch(node) {
180
- let current = node;
181
-
182
- while (current) {
183
- this.line(); // New line for the block structure
184
-
185
- switch (current.type) {
186
- case "if":
187
- case "unless": // In Nova, 'unless' is a branch, but in JS it's '!condition'
188
- this.output.push(current.type === "if" ? "if (" : "if (!(");
189
- this.emitExpression(current.args);
190
- this.output.push(current.type === "if" ? ") " : ")) ");
191
- this.emitBlock(current.body);
192
- break;
193
- case "else":
194
- this.output.push("else ");
195
- this.emitBlock(current.body);
196
- break;
197
- case "while":
198
- case "until": // In Nova, 'until' is a loop, in JS it's 'while (!condition)'
199
- this.output.push(current.type === "while" ? "while (" : "while (!(");
200
- this.emitExpression(current.args[0]);
201
- this.output.push(current.type === "while" ? ") " : ")) ");
202
- this.emitBlock(current.body);
203
- break;
204
- case "do":
205
- this.output.push("do ");
206
- this.emitBlock(current.body);
207
- this.line(`while (`);
208
- this.emitExpression(current.args[0]);
209
- this.output.push(");");
210
- break;
211
- case "repeat":
212
- // Transpile 'repeat (N) { ... }' to a 'for' loop
213
- const countName = `_i_${node.line}_${node.column}`;
214
- this.output.push(`for (let ${countName} = 0; ${countName} < `);
215
- this.emitExpression(current.args[0]);
216
- this.output.push(`; ${countName}++) `);
217
- this.emitBlock(current.body);
218
- break;
219
- case "for":
220
- // for loops: args = [init, condition, update]
221
- const [initNode, condNode, updateNode] = current.args;
222
- this.output.push("for (");
223
- this.emitStatement(initNode); // Emits with 'let/const' and ';'
224
- this.output.push(" ");
225
-
226
- if (condNode) this.emitExpression(condNode); // Condition
227
- this.output.push("; ");
228
-
229
- // Update statement: We only want the expression part, no 'let/var' or ';'
230
- if (updateNode) {
231
- const temp = this.output;
232
- this.output = [];
233
- this.emitStatement(updateNode);
234
- const updateExpr = this.output.join("").replace(/;$/, "").trim();
235
- this.output = temp;
236
- this.output.push(updateExpr);
237
- }
238
- this.output.push(") ");
239
- this.emitBlock(current.body);
240
- break;
241
- default:
242
- this.error(`Unknown branch type '${current.type}'`, node);
243
- }
244
-
245
- // Handle chaining (e.g., else if, else)
246
- if (current.next && current.next.type !== "else") {
247
- this.output.push(" else ");
248
- }
249
- current = current.next;
250
- }
251
- }
252
-
253
- emitBlock(body) {
254
- this.output.push("{");
255
- this.indentUp();
256
- for (const stmt of body) {
257
- this.emitStatement(stmt);
258
- if (this.output.at(-1) !== ";") this.output.push(";");
259
- }
260
- this.indentDown();
261
- this.line("}");
262
- }
263
-
264
- emitFunctionDeclaration(node) {
265
- // If it's an 'async' function, add the keyword.
266
- this.line(
267
- `${node.isAsync ? "async " : ""}function ${node.name}(${node.args.join(", ")}) `,
268
- );
269
- this.emitBlock(node.body);
270
- }
271
-
272
- emitClassDeclaration(node) {
273
- this.line(`class ${node.name}`);
274
-
275
- if (node.superClass) {
276
- this.output.push(" extends ");
277
- this.emitExpression(node.superClass); // superClass is a 'ref' node
278
- }
279
-
280
- this.output.push(" {");
281
- this.indentUp();
282
-
283
- // Find constructor (if defined as a method)
284
- const constructorMethod = node.members.find(
285
- (m) => m.name === "constructor",
286
- );
287
- if (constructorMethod) {
288
- this.line(`constructor(${constructorMethod.args.join(", ")}) {`);
289
- this.indentUp();
290
-
291
- // Handle 'super' call if extending
292
- if (node.superClass) {
293
- this.line("super(...arguments);");
294
- }
295
-
296
- // Emit constructor body
297
- for (const stmt of constructorMethod.body) {
298
- this.emitStatement(stmt);
299
- }
300
-
301
- this.indentDown();
302
- this.line("}");
303
- } else if (node.superClass) {
304
- // Nova requires an explicit constructor for 'super' (or implicit no-arg call in JS)
305
- // For simplicity in transpilation, we add a base constructor if extending.
306
- this.line(`constructor(...args) { super(...args); }`);
307
- }
308
-
309
- // Emit all other members
310
- for (const member of node.members) {
311
- if (member.name === "constructor") continue; // Skip if handled above
312
-
313
- if (member.kind === "function") {
314
- this.line(` ${member.name}(${member.args.join(", ")}) {`);
315
- this.indentUp();
316
- for (const stmt of member.body) {
317
- this.emitStatement(stmt);
318
- }
319
- this.indentDown();
320
- this.line(" }");
321
- } else if (member.kind === "declare") {
322
- // Simple property declaration (will be initialized in the constructor for full ES5/ES6 compatibility)
323
- // For ES2022+ property support, you could use: this.line(`${member.name} = `); this.emitExpression(member.value); this.output.push(';');
324
- // For simplicity, we'll assume the executor handles field initialization. For a pure JS target, we emit nothing here.
325
- }
326
- }
327
-
328
- this.indentDown();
329
- this.line("}");
330
- }
331
-
332
- emitReturn(node) {
333
- this.line(node.terminate ? "return " : "return ");
334
- if (node.value) this.emitExpression(node.value);
335
- this.output.push(";");
336
- }
337
-
338
- emitThrow(node) {
339
- this.line("throw ");
340
- this.emitExpression(node.value);
341
- this.output.push(";");
342
- }
343
-
344
- emitTry(node) {
345
- this.line("try ");
346
- this.emitBlock(node.tryBody);
347
-
348
- if (node.catchBody) {
349
- this.line(`catch (${node.catchName}) `);
350
- this.emitBlock(node.catchBody);
351
- }
352
-
353
- if (node.finallyBody) {
354
- this.line("finally ");
355
- this.emitBlock(node.finallyBody);
356
- }
357
- }
358
-
359
- emitExecution(node) {
360
- this.line();
361
- this.emitExpression(node.expr);
362
- this.output.push(";");
363
- }
364
-
365
- // --- Specific Expression Emitters ---
366
-
367
- emitValue(node) {
368
- const val = node.value;
369
- switch (typeof val) {
370
- case "number":
371
- this.output.push(val);
372
- break;
373
- case "string":
374
- this.output.push(`"${val}"`);
375
- break;
376
- case "symbol":
377
- // Map Nova literals to JS literals
378
- if (val.toString() === "Symbol(NOVA_TRUE)") this.output.push("true");
379
- else if (val.toString() === "Symbol(NOVA_FALSE)")
380
- this.output.push("false");
381
- else if (val.toString() === "Symbol(NOVA_NULL)")
382
- this.output.push("null");
383
- else this.error(`Unknown literal symbol: ${val.toString()}`, node);
384
- break;
385
- default:
386
- this.error(`Unknown value type: ${typeof val}`, node);
387
- }
388
- }
389
-
390
- emitTemplateLiteral(node) {
391
- // Use standard JS template literal syntax: backticks and ${} for expressions
392
- this.output.push("`");
393
- for (const part of node.parts) {
394
- if (part.kind === "value" && typeof part.value === "string") {
395
- this.output.push(part.value);
396
- } else {
397
- this.output.push("${");
398
- this.emitExpression(part);
399
- this.output.push("}");
400
- }
401
- }
402
- this.output.push("`");
403
- }
404
-
405
- emitArray(node) {
406
- this.output.push("[");
407
- node.elements.forEach((el, i) => {
408
- this.emitExpression(el);
409
- if (i < node.elements.length - 1) this.output.push(", ");
410
- });
411
- this.output.push("]");
412
- }
413
-
414
- emitObject(node) {
415
- this.output.push("{");
416
- const props = Object.entries(node.props);
417
- props.forEach(([key, value], i) => {
418
- this.output.push(`${key}: `);
419
- this.emitExpression(value);
420
- if (i < props.length - 1) this.output.push(", ");
421
- });
422
- this.output.push("}");
423
- }
424
-
425
- emitBinary(node) {
426
- this.output.push("(");
427
- this.emitExpression(node.left);
428
- this.output.push(` ${node.operator} `);
429
- this.emitExpression(node.right);
430
- this.output.push(")");
431
- }
432
-
433
- emitUnary(node) {
434
- this.output.push(node.operator);
435
- this.emitExpression(node.operand);
436
- }
437
-
438
- emitCall(node) {
439
- if (typeof node.name === "string") {
440
- this.output.push(node.name);
441
- } else {
442
- this.emitExpression(node.name); // Handles prop/subscript calls
443
- }
444
- this.output.push("(");
445
- node.args.forEach((arg, i) => {
446
- this.emitExpression(arg);
447
- if (i < node.args.length - 1) this.output.push(", ");
448
- });
449
- this.output.push(")");
450
- }
451
-
452
- emitPropertyAccess(node) {
453
- this.emitExpression(node.object);
454
- this.output.push(`.${node.name}`);
455
- }
456
-
457
- emitSubscript(node) {
458
- this.emitExpression(node.object);
459
- this.output.push("[");
460
- this.emitExpression(node.index);
461
- this.output.push("]");
462
- }
463
-
464
- emitAssignment(node) {
465
- this.emitExpression(node.name); // LHS: ref, prop, or subscript node
466
- this.output.push(` = `);
467
- this.emitExpression(node.value);
468
- }
469
-
470
- emitPostfix(node) {
471
- this.emitExpression(node.operand);
472
- this.output.push(node.operator);
473
- }
474
-
475
- emitArrowFunction(node) {
476
- this.output.push(`(${node.args.join(", ")}) => `);
477
- // If the body is a single return statement, use concise body
478
- const isConcise =
479
- node.body.length === 1 &&
480
- node.body[0].kind === "return" &&
481
- node.body[0].terminate;
482
-
483
- if (isConcise) {
484
- this.emitExpression(node.body[0].value);
485
- } else {
486
- this.emitBlock(node.body);
487
- }
488
- }
489
-
490
- // --- Error Handling ---
491
-
492
- error(msg, node) {
493
- throw new (CustomError("EmitterError"))(
494
- formatError("EmitterError", msg, node.line, node.column, this.rawsrc),
495
- );
496
- }
497
- }
498
-
499
- module.exports = { Emitter };
@@ -1,86 +0,0 @@
1
- // ===== error.js =====
2
- const RESERVED_WORDS = new Set([
3
- "break",
4
- "case",
5
- "catch",
6
- "class",
7
- "const",
8
- "continue",
9
- "debugger",
10
- "default",
11
- "delete",
12
- "do",
13
- "else",
14
- "export",
15
- "extends",
16
- "finally",
17
- "for",
18
- "function",
19
- "if",
20
- "import",
21
- "in",
22
- "instanceof",
23
- "new",
24
- "return",
25
- "super",
26
- "switch",
27
- "this",
28
- "throw",
29
- "try",
30
- "typeof",
31
- "var",
32
- "void",
33
- "while",
34
- "with",
35
- "yield",
36
- "let",
37
- "enum",
38
- "await",
39
- "implements",
40
- "package",
41
- "protected",
42
- "static",
43
- "interface",
44
- "private",
45
- "public",
46
- "null",
47
- "true",
48
- "false",
49
- ]);
50
-
51
- function sanitizeName(name) {
52
- let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "");
53
- if (!/^[a-zA-Z_$]/.test(sanitized)) sanitized = "_" + sanitized;
54
- if (RESERVED_WORDS.has(sanitized)) sanitized += "_";
55
- return sanitized || "_CustomError";
56
- }
57
-
58
- function CustomError(name) {
59
- const safeName = sanitizeName(name);
60
- return eval(`
61
- (class ${safeName} extends Error {
62
- constructor(message) {
63
- super(message);
64
- this.name = "${safeName}";
65
- if (Error.captureStackTrace) {
66
- Error.captureStackTrace(this, this.constructor);
67
- }
68
- }
69
- })
70
- `);
71
- }
72
-
73
- let NovaException = CustomError("Exception");
74
-
75
- // 🔥 new addition — shared formatter
76
- function formatError(kind, msg, line, column, rawsrc) {
77
- const lineText = rawsrc.split("\n")[line - 1] ?? "";
78
- return (
79
- `[Nova${kind} ${line}:${column}] ${msg}\n` +
80
- ` error at:\n` +
81
- ` ${lineText}\n` +
82
- ` ${" ".repeat(Math.max(column - 1, 0))}^^`
83
- );
84
- }
85
-
86
- module.exports = { CustomError, formatError, NovaException };