@xnoxs/flux-lang 3.1.1

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 (56) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +1089 -0
  3. package/bin/flux.js +1397 -0
  4. package/dist/flux.cjs.js +6664 -0
  5. package/dist/flux.esm.js +6674 -0
  6. package/dist/flux.min.js +263 -0
  7. package/index.d.ts +202 -0
  8. package/index.js +26 -0
  9. package/package.json +77 -0
  10. package/scripts/build.js +76 -0
  11. package/src/bundler.js +216 -0
  12. package/src/checker.js +322 -0
  13. package/src/codegen.js +785 -0
  14. package/src/css-preprocessor.js +399 -0
  15. package/src/formatter.js +140 -0
  16. package/src/jsx.js +480 -0
  17. package/src/lexer.js +518 -0
  18. package/src/linter.js +758 -0
  19. package/src/mangler.js +280 -0
  20. package/src/parser.js +1671 -0
  21. package/src/self/bundler.flux +167 -0
  22. package/src/self/bundler.js +187 -0
  23. package/src/self/checker.flux +249 -0
  24. package/src/self/checker.js +338 -0
  25. package/src/self/codegen.flux +555 -0
  26. package/src/self/codegen.js +784 -0
  27. package/src/self/css-preprocessor.flux +373 -0
  28. package/src/self/css-preprocessor.js +387 -0
  29. package/src/self/formatter.flux +93 -0
  30. package/src/self/formatter.js +114 -0
  31. package/src/self/jsx.flux +430 -0
  32. package/src/self/jsx.js +396 -0
  33. package/src/self/lexer.flux +529 -0
  34. package/src/self/lexer.js +709 -0
  35. package/src/self/lexer.stage2.js +700 -0
  36. package/src/self/linter.flux +515 -0
  37. package/src/self/linter.js +804 -0
  38. package/src/self/mangler.flux +253 -0
  39. package/src/self/mangler.js +348 -0
  40. package/src/self/parser.flux +1146 -0
  41. package/src/self/parser.js +1571 -0
  42. package/src/self/sourcemap.flux +66 -0
  43. package/src/self/sourcemap.js +72 -0
  44. package/src/self/stdlib.flux +356 -0
  45. package/src/self/stdlib.js +396 -0
  46. package/src/self/test-runner.flux +201 -0
  47. package/src/self/test-runner.js +132 -0
  48. package/src/self/transpiler.flux +123 -0
  49. package/src/self/transpiler.js +83 -0
  50. package/src/self/type-checker.flux +821 -0
  51. package/src/self/type-checker.js +1106 -0
  52. package/src/sourcemap.js +82 -0
  53. package/src/stdlib.js +436 -0
  54. package/src/test-runner.js +239 -0
  55. package/src/transpiler.js +172 -0
  56. package/src/type-checker.js +1206 -0
@@ -0,0 +1,784 @@
1
+ // ── Flux stdlib ──
2
+
3
+ function map(arr, fn) { return arr.map(fn); }
4
+
5
+ function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
6
+ // ── end stdlib ──
7
+
8
+ // Generated by Flux Transpiler v3.1.0
9
+ "use strict";
10
+
11
+ const { Lexer, lexerize, T } = require("./lexer");
12
+ const { Parser, makeParser } = require("./parser");
13
+ function extractFormatSpec(raw) {
14
+ const ci = raw.lastIndexOf(":");
15
+ if ((ci < 1)) {
16
+ return null;
17
+ }
18
+ const spec = raw.slice((ci + 1)).trim();
19
+ if ((((spec.length > 0) && /[.<>^,dbeEfFgGoOxXs%bcn]/.test(spec)) && /^([.<>^0\-+ #,]*[0-9]*\.?[0-9]*[dbeEfFgGoOxXs%bcn]?[,]?)$/.test(spec))) {
20
+ return { expr: raw.slice(0, ci).trim(), fmt: spec };
21
+ }
22
+ return null;
23
+ }
24
+ const FMT_HELPER = "function _fmt(v, s) {\n if (s === ',') return (+v).toLocaleString();\n if (s === '%') return ((+v)*100).toFixed(0)+'%';\n var m = s.match(/^([0-9,]*)?\\.([0-9]+)([fdgGeEb%x])$/);\n if (m) {\n var d=+m[2], t=m[3], comma=s[0]===',';\n if (t==='f'||t==='d') return comma ? (+v).toLocaleString(void 0,{minimumFractionDigits:d,maximumFractionDigits:d}) : (+v).toFixed(d);\n if (t==='e'||t==='E') return (+v).toExponential(d);\n if (t==='%') return ((+v)*100).toFixed(d)+'%';\n if (t==='b') return Math.round(+v).toString(2);\n if (t==='x') return Math.round(+v).toString(16);\n }\n var m2 = s.match(/^([0-9]*)d$/); if (m2) return Math.round(+v).toString();\n return String(v);\n}";
25
+ function buildClassRegistry(ast) {
26
+ const reg = { };
27
+ for (const node of ast.body) {
28
+ const n = ((node.type == "ExportDecl") ? node.decl : node);
29
+ if ((n.type == "ClassDecl")) {
30
+ reg[n.name] = { fields: n.fields, superClass: n.superClass };
31
+ }
32
+ }
33
+ return reg;
34
+ }
35
+ function getAllFields(name, reg, visited) {
36
+ const vis = (visited ?? new Set([]));
37
+ if (((!name || !reg[name]) || vis.has(name))) {
38
+ return [];
39
+ }
40
+ vis.add(name);
41
+ const parent = getAllFields(reg[name].superClass, reg, vis);
42
+ return [...parent, ...reg[name].fields];
43
+ }
44
+ class CodeGenerator {
45
+ constructor(ind, level, lines, clsReg, smBuilder, _needsFmt, _loopDepth) {
46
+ this.ind = ind;
47
+ this.level = level;
48
+ this.lines = lines;
49
+ this.clsReg = clsReg;
50
+ this.smBuilder = smBuilder;
51
+ this._needsFmt = _needsFmt;
52
+ this._loopDepth = _loopDepth;
53
+ }
54
+
55
+ i() {
56
+ let s = "";
57
+ let n = this.level;
58
+ while ((n > 0)) {
59
+ s += this.ind;
60
+ n = (n - 1);
61
+ }
62
+ return s;
63
+ }
64
+
65
+ emit(s) {
66
+ this.lines.push((this.i() + s));
67
+ }
68
+
69
+ emitRaw(s) {
70
+ this.lines.push(s);
71
+ }
72
+
73
+ blank() {
74
+ this.lines.push("");
75
+ }
76
+
77
+ indIn() {
78
+ this.level = (this.level + 1);
79
+ }
80
+
81
+ indOut() {
82
+ if ((this.level > 0)) {
83
+ this.level = (this.level - 1);
84
+ }
85
+ }
86
+
87
+ generate(ast) {
88
+ this.clsReg = buildClassRegistry(ast);
89
+ this.lines = [];
90
+ this.level = 0;
91
+ this._needsFmt = false;
92
+ this.emit("// Generated by Flux Transpiler v3.1.0 (self-hosted)");
93
+ this.emit("\"use strict\";");
94
+ this.blank();
95
+ for (const node of ast.body) {
96
+ this.genStmt(node);
97
+ }
98
+ if (this._needsFmt) {
99
+ this.lines.splice(2, 0, FMT_HELPER);
100
+ }
101
+ return { code: this.lines.join("\n"), smBuilder: this.smBuilder };
102
+ }
103
+
104
+ genStmt(node) {
105
+ if ((node.type == "VarDecl")) {
106
+ this.genVar(node);
107
+ }
108
+ else if ((node.type == "DestructureDecl")) {
109
+ this.genDestructure(node);
110
+ }
111
+ else if ((node.type == "FnDecl")) {
112
+ this.genFn(node, "");
113
+ }
114
+ else if ((node.type == "ClassDecl")) {
115
+ this.genClass(node);
116
+ }
117
+ else if ((node.type == "IfStmt")) {
118
+ this.genIf(node);
119
+ }
120
+ else if ((node.type == "ForInStmt")) {
121
+ this.genFor(node);
122
+ }
123
+ else if ((node.type == "WhileStmt")) {
124
+ this.genWhile(node);
125
+ }
126
+ else if ((node.type == "MatchStmt")) {
127
+ this.genMatch(node);
128
+ }
129
+ else if ((node.type == "ReturnStmt")) {
130
+ this.genReturn(node);
131
+ }
132
+ else if ((node.type == "TryCatchStmt")) {
133
+ this.genTryCatch(node);
134
+ }
135
+ else if ((node.type == "ThrowStmt")) {
136
+ this.genThrow(node);
137
+ }
138
+ else if ((node.type == "DoWhileStmt")) {
139
+ this.genDoWhile(node);
140
+ }
141
+ else if ((node.type == "BreakStmt")) {
142
+ this.emit("break;");
143
+ }
144
+ else if ((node.type == "ContinueStmt")) {
145
+ this.emit("continue;");
146
+ }
147
+ else if ((node.type == "ImportDecl")) {
148
+ this.genImport(node);
149
+ }
150
+ else if ((node.type == "ExportDecl")) {
151
+ this.genExport(node);
152
+ }
153
+ else if ((node.type == "TypeDecl")) {
154
+ this.genTypeDecl(node);
155
+ }
156
+ else if ((node.type == "InterfaceDecl")) {
157
+ this.genInterfaceDecl(node);
158
+ }
159
+ else if ((node.type == "EnumDecl")) {
160
+ this.genEnumDecl(node);
161
+ }
162
+ else if ((node.type == "ExprStmt")) {
163
+ this.emit((this.genExpr(node.expr) + ";"));
164
+ }
165
+ else {
166
+ throw new Error(`Unknown statement: ${node.type}`);
167
+ }
168
+ }
169
+
170
+ genVar(node) {
171
+ const kw = ((node.kind == "val") ? "const" : "let");
172
+ const init = (node.init ? (" = " + this.genExpr(node.init)) : "");
173
+ this.emit(((((kw + " ") + node.name) + init) + ";"));
174
+ }
175
+
176
+ genObjPair(p) {
177
+ if (p.spread) {
178
+ return ("..." + this.genExpr(p.value));
179
+ }
180
+ const isIdent = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(p.key);
181
+ const keyStr = (isIdent ? p.key : (("\"" + p.key) + "\""));
182
+ if ((((isIdent && p.value) && (p.value.type == "Identifier")) && (p.value.name == p.key))) {
183
+ return p.key;
184
+ }
185
+ return ((keyStr + ": ") + this.genExpr(p.value));
186
+ }
187
+
188
+ genDestructProp(p) {
189
+ if (p.rest) {
190
+ return ("..." + p.key);
191
+ }
192
+ let s = ((p.alias != p.key) ? ((p.key + ": ") + p.alias) : p.key);
193
+ if (p.defaultVal) {
194
+ s = ((s + " = ") + this.genExpr(p.defaultVal));
195
+ }
196
+ return s;
197
+ }
198
+
199
+ genDestructItem(p) {
200
+ if (!p) {
201
+ return "";
202
+ }
203
+ if (p.rest) {
204
+ return ("..." + p.name);
205
+ }
206
+ let s = p.name;
207
+ if (p.defaultVal) {
208
+ s = ((s + " = ") + this.genExpr(p.defaultVal));
209
+ }
210
+ return s;
211
+ }
212
+
213
+ genDestructure(node) {
214
+ const kw = ((node.kind == "val") ? "const" : "let");
215
+ const init = this.genExpr(node.init);
216
+ if ((node.patternType == "object")) {
217
+ const props = node.pattern.map((p) => this.genDestructProp(p)).join(", ");
218
+ this.emit((((((kw + " { ") + props) + " } = ") + init) + ";"));
219
+ }
220
+ else {
221
+ const items = node.pattern.map((p) => this.genDestructItem(p)).join(", ");
222
+ this.emit((((((kw + " [") + items) + "] = ") + init) + ";"));
223
+ }
224
+ }
225
+
226
+ genFn(node, prefix) {
227
+ const asyncKw = (node.async ? "async " : "");
228
+ const name = (node.name ?? "");
229
+ const params = node.params.map((p) => (p.rest ? ("..." + p.name) : (p.defaultVal ? ((p.name + " = ") + this.genExpr(p.defaultVal)) : p.name))).join(", ");
230
+ if (node.inline) {
231
+ this.emit(((((((((prefix + asyncKw) + "function ") + name) + "(") + params) + ") { return ") + this.genExpr(node.body)) + "; }"));
232
+ }
233
+ else {
234
+ this.emit(((((((prefix + asyncKw) + "function ") + name) + "(") + params) + ") {"));
235
+ this.indIn();
236
+ for (const s of node.body) {
237
+ this.genStmt(s);
238
+ }
239
+ this.indOut();
240
+ this.emit("}");
241
+ }
242
+ }
243
+
244
+ genClass(node) {
245
+ const ext = (node.superClass ? (" extends " + node.superClass) : "");
246
+ this.emit(((("class " + node.name) + ext) + " {"));
247
+ this.indIn();
248
+ const allFields = getAllFields(node.name, this.clsReg, null);
249
+ if ((allFields.length > 0)) {
250
+ const params = allFields.map((f) => f.name).join(", ");
251
+ this.emit((("constructor(" + params) + ") {"));
252
+ this.indIn();
253
+ if ((node.superClass && this.clsReg[node.superClass])) {
254
+ const parentFields = getAllFields(node.superClass, this.clsReg, null);
255
+ if ((parentFields.length > 0)) {
256
+ this.emit((("super(" + parentFields.map((f) => f.name).join(", ")) + ");"));
257
+ }
258
+ }
259
+ for (const f of node.fields) {
260
+ this.emit((((("this." + f.name) + " = ") + f.name) + ";"));
261
+ }
262
+ this.indOut();
263
+ this.emit("}");
264
+ this.blank();
265
+ }
266
+ for (const m of node.methods) {
267
+ const asyncKw = (m.async ? "async " : "");
268
+ const staticKw = ((m.modifiers && m.modifiers.has("static")) ? "static " : "");
269
+ const params = m.params.map((p) => (p.rest ? ("..." + p.name) : (p.defaultVal ? ((p.name + " = ") + this.genExpr(p.defaultVal)) : p.name))).join(", ");
270
+ if (m.inline) {
271
+ this.emit((((((((staticKw + asyncKw) + m.name) + "(") + params) + ") { return ") + this.genExpr(m.body)) + "; }"));
272
+ }
273
+ else {
274
+ this.emit((((((staticKw + asyncKw) + m.name) + "(") + params) + ") {"));
275
+ this.indIn();
276
+ for (const s of m.body) {
277
+ this.genStmt(s);
278
+ }
279
+ this.indOut();
280
+ this.emit("}");
281
+ }
282
+ this.blank();
283
+ }
284
+ this.indOut();
285
+ this.emit("}");
286
+ this.blank();
287
+ }
288
+
289
+ genIf(node) {
290
+ this.emit((("if (" + this.genExpr(node.cond)) + ") {"));
291
+ this.indIn();
292
+ for (const s of node.then) {
293
+ this.genStmt(s);
294
+ }
295
+ this.indOut();
296
+ this.emit("}");
297
+ for (const ei of node.elseifs) {
298
+ this.emitRaw((((this.i() + "else if (") + this.genExpr(ei.cond)) + ") {"));
299
+ this.indIn();
300
+ for (const s of ei.body) {
301
+ this.genStmt(s);
302
+ }
303
+ this.indOut();
304
+ this.emit("}");
305
+ }
306
+ if (node.else_) {
307
+ this.emitRaw((this.i() + "else {"));
308
+ this.indIn();
309
+ for (const s of node.else_) {
310
+ this.genStmt(s);
311
+ }
312
+ this.indOut();
313
+ this.emit("}");
314
+ }
315
+ }
316
+
317
+ genFor(node) {
318
+ const varName = node["var"];
319
+ const iter = node.iter;
320
+ if ((iter.type == "RangeExpr")) {
321
+ const s = this.genExpr(iter.start);
322
+ const e = this.genExpr(iter.end);
323
+ this.emit((((((((((("for (let " + varName) + " = ") + s) + "; ") + varName) + " < ") + e) + "; ") + varName) + "++) {"));
324
+ }
325
+ else if (node.isAwait) {
326
+ this.emit((((("for await (const " + varName) + " of ") + this.genExpr(iter)) + ") {"));
327
+ }
328
+ else {
329
+ this.emit((((("for (const " + varName) + " of ") + this.genExpr(iter)) + ") {"));
330
+ }
331
+ this._loopDepth = (this._loopDepth + 1);
332
+ this.indIn();
333
+ for (const s of node.body) {
334
+ this.genStmt(s);
335
+ }
336
+ this.indOut();
337
+ this._loopDepth = (this._loopDepth - 1);
338
+ this.emit("}");
339
+ }
340
+
341
+ genWhile(node) {
342
+ this.emit((("while (" + this.genExpr(node.cond)) + ") {"));
343
+ this._loopDepth = (this._loopDepth + 1);
344
+ this.indIn();
345
+ for (const s of node.body) {
346
+ this.genStmt(s);
347
+ }
348
+ this.indOut();
349
+ this._loopDepth = (this._loopDepth - 1);
350
+ this.emit("}");
351
+ }
352
+
353
+ genMatch(node) {
354
+ const subj = this.genExpr(node.subject);
355
+ const arms = node.arms;
356
+ let hasOpenIf = false;
357
+ for (const arm of arms) {
358
+ const pat = arm.pattern;
359
+ let cond = "";
360
+ const bindings = [];
361
+ if ((pat.type == "WildcardPat")) {
362
+ cond = "";
363
+ }
364
+ else if ((pat.type == "RangePat")) {
365
+ const lo = this.genExpr(pat.start);
366
+ const hi = this.genExpr(pat.end);
367
+ cond = ((((((subj + " >= ") + lo) + " && ") + subj) + " <= ") + hi);
368
+ }
369
+ else if ((pat.type == "VariantPat")) {
370
+ cond = (((subj + "?.__type === \"") + pat.variant) + "\"");
371
+ let bi = 0;
372
+ for (const b of pat.bindings) {
373
+ bindings.push((((((("const " + b) + " = ") + subj) + ".__args[") + bi) + "];"));
374
+ bi = (bi + 1);
375
+ }
376
+ }
377
+ else {
378
+ const patExpr = this.genExpr(pat.value);
379
+ if (((pat.value.type == "Identifier") && /^[A-Z]/.test(pat.value.name))) {
380
+ cond = (((((((("(" + subj) + " === ") + patExpr) + " || ") + subj) + "?.__type === \"") + pat.value.name) + "\")");
381
+ }
382
+ else {
383
+ cond = ((subj + " === ") + patExpr);
384
+ }
385
+ }
386
+ if (arm.guard) {
387
+ const guardSrc = this.genExpr(arm.guard);
388
+ if ((bindings.length > 0)) {
389
+ const rebindings = bindings.map((bx) => bx.replace("const ", "var ")).join(" ");
390
+ const iife = (((("(function(){ " + rebindings) + " return (") + guardSrc) + "); }())");
391
+ cond = (cond ? ((("(" + cond) + ") && ") + iife) : iife);
392
+ }
393
+ else {
394
+ cond = (cond ? (((("(" + cond) + ") && (") + guardSrc) + ")") : guardSrc);
395
+ }
396
+ }
397
+ if ((!hasOpenIf && cond)) {
398
+ this.emit((("if (" + cond) + ") {"));
399
+ hasOpenIf = true;
400
+ }
401
+ else if ((!hasOpenIf && !cond)) {
402
+ this.emit("if (true) {");
403
+ hasOpenIf = true;
404
+ }
405
+ else if ((hasOpenIf && cond)) {
406
+ this.emitRaw((((this.i() + "else if (") + cond) + ") {"));
407
+ }
408
+ else {
409
+ this.emitRaw((this.i() + "else {"));
410
+ }
411
+ this.indIn();
412
+ for (const b of bindings) {
413
+ this.emit(b);
414
+ }
415
+ if (arm.inline) {
416
+ const exprSrc = this.genExpr(arm.body[0].expr);
417
+ if ((this._loopDepth > 0)) {
418
+ this.emit((exprSrc + ";"));
419
+ }
420
+ else {
421
+ this.emit((("return " + exprSrc) + ";"));
422
+ }
423
+ }
424
+ else {
425
+ for (const s of arm.body) {
426
+ this.genStmt(s);
427
+ }
428
+ }
429
+ this.indOut();
430
+ this.emit("}");
431
+ }
432
+ }
433
+
434
+ genInterfaceDecl(node) {
435
+ this.blank();
436
+ this.emit(("// interface " + node.name));
437
+ this.blank();
438
+ }
439
+
440
+ genEnumDecl(node) {
441
+ this.blank();
442
+ const pairs = node.members.map((m) => ((m.name + ": ") + this.genExpr(m.value))).join(", ");
443
+ this.emit((((("const " + node.name) + " = Object.freeze({ ") + pairs) + " });"));
444
+ this.blank();
445
+ }
446
+
447
+ genTypeDecl(node) {
448
+ this.blank();
449
+ this.emit(("// ADT type: " + node.name));
450
+ for (const v of node.variants) {
451
+ if ((v.fields.length == 0)) {
452
+ this.emit((((("const " + v.name) + " = Object.freeze({ __type: \"") + v.name) + "\", __args: [] });"));
453
+ }
454
+ else {
455
+ const params = v.fields.join(", ");
456
+ const argsArr = (("[" + v.fields.join(", ")) + "]");
457
+ const fieldsObj = v.fields.map((f) => ((f + ": ") + f)).join(", ");
458
+ this.emit((((((((((("function " + v.name) + "(") + params) + ") { return Object.freeze({ __type: \"") + v.name) + "\", __args: ") + argsArr) + ", ") + fieldsObj) + " }); }"));
459
+ }
460
+ }
461
+ this.blank();
462
+ }
463
+
464
+ genReturn(node) {
465
+ if (node.value) {
466
+ this.emit((("return " + this.genExpr(node.value)) + ";"));
467
+ }
468
+ else {
469
+ this.emit("return;");
470
+ }
471
+ }
472
+
473
+ genTryCatch(node) {
474
+ this.emit("try {");
475
+ this.indIn();
476
+ for (const s of node.tryBody) {
477
+ this.genStmt(s);
478
+ }
479
+ this.indOut();
480
+ this.emit("}");
481
+ if (node.catchBody) {
482
+ const param = (node.catchParam ? (("(" + node.catchParam) + ")") : "(_err)");
483
+ this.emitRaw((((this.i() + "catch ") + param) + " {"));
484
+ this.indIn();
485
+ for (const s of node.catchBody) {
486
+ this.genStmt(s);
487
+ }
488
+ this.indOut();
489
+ this.emit("}");
490
+ }
491
+ if (node.finallyBody) {
492
+ this.emitRaw((this.i() + "finally {"));
493
+ this.indIn();
494
+ for (const s of node.finallyBody) {
495
+ this.genStmt(s);
496
+ }
497
+ this.indOut();
498
+ this.emit("}");
499
+ }
500
+ }
501
+
502
+ genThrow(node) {
503
+ this.emit((("throw " + this.genExpr(node.value)) + ";"));
504
+ }
505
+
506
+ genDoWhile(node) {
507
+ this.emit("do {");
508
+ this.indIn();
509
+ for (const s of node.body) {
510
+ this.genStmt(s);
511
+ }
512
+ this.indOut();
513
+ this.emit((("} while (" + this.genExpr(node.cond)) + ");"));
514
+ }
515
+
516
+ genImport(node) {
517
+ const src = String(node.source);
518
+ if (node.namespaceName) {
519
+ this.emit((((("const " + node.namespaceName) + " = require(\"") + src) + "\");"));
520
+ }
521
+ else if (node.defaultName) {
522
+ this.emit((((("const " + node.defaultName) + " = require(\"") + src) + "\");"));
523
+ }
524
+ else if (node.names.length) {
525
+ const parts = node.names.map((n) => ((typeof n == "string") ? n : ((n.name != n.alias) ? ((n.name + ": ") + n.alias) : n.name))).join(", ");
526
+ this.emit((((("const { " + parts) + " } = require(\"") + src) + "\");"));
527
+ }
528
+ }
529
+
530
+ genExport(node) {
531
+ if (node.isDefault) {
532
+ this.emit((("module.exports = " + this.genExpr(node.decl)) + ";"));
533
+ return;
534
+ }
535
+ const decl = node.decl;
536
+ if ((decl.type == "FnDecl")) {
537
+ const asyncKw = (decl.async ? "async " : "");
538
+ const params = decl.params.map((p) => (p.rest ? ("..." + p.name) : (p.defaultVal ? ((p.name + " = ") + this.genExpr(p.defaultVal)) : p.name))).join(", ");
539
+ if (decl.inline) {
540
+ this.emit((((((((asyncKw + "function ") + decl.name) + "(") + params) + ") { return ") + this.genExpr(decl.body)) + "; }"));
541
+ }
542
+ else {
543
+ this.emit((((((asyncKw + "function ") + decl.name) + "(") + params) + ") {"));
544
+ this.indIn();
545
+ for (const s of decl.body) {
546
+ this.genStmt(s);
547
+ }
548
+ this.indOut();
549
+ this.emit("}");
550
+ }
551
+ this.emit((((("module.exports." + decl.name) + " = ") + decl.name) + ";"));
552
+ }
553
+ else if ((decl.type == "ClassDecl")) {
554
+ this.genClass(decl);
555
+ this.emit((((("module.exports." + decl.name) + " = ") + decl.name) + ";"));
556
+ }
557
+ else if ((decl.type == "TypeDecl")) {
558
+ this.genTypeDecl(decl);
559
+ for (const v of decl.variants) {
560
+ this.emit((((("module.exports." + v.name) + " = ") + v.name) + ";"));
561
+ }
562
+ }
563
+ else if ((decl.type == "InterfaceDecl")) {
564
+ this.genInterfaceDecl(decl);
565
+ }
566
+ else if ((decl.type == "EnumDecl")) {
567
+ this.genEnumDecl(decl);
568
+ this.emit((((("module.exports." + decl.name) + " = ") + decl.name) + ";"));
569
+ }
570
+ else if ((decl.type == "VarDecl")) {
571
+ const kw = ((decl.kind == "val") ? "const" : "let");
572
+ this.emit((((((kw + " ") + decl.name) + " = ") + this.genExpr(decl.init)) + ";"));
573
+ this.emit((((("module.exports." + decl.name) + " = ") + decl.name) + ";"));
574
+ }
575
+ else {
576
+ this.genStmt(decl);
577
+ }
578
+ }
579
+
580
+ genExpr(node) {
581
+ if (!node) {
582
+ return "undefined";
583
+ }
584
+ if ((node.type == "NumberLit")) {
585
+ return String(node.value);
586
+ }
587
+ if ((node.type == "BoolLit")) {
588
+ return String(node.value);
589
+ }
590
+ if ((node.type == "NullLit")) {
591
+ return "null";
592
+ }
593
+ if ((node.type == "SelfExpr")) {
594
+ return "this";
595
+ }
596
+ if ((node.type == "Identifier")) {
597
+ return ((node.name == "print") ? "console.log" : node.name);
598
+ }
599
+ if ((node.type == "StringLit")) {
600
+ return JSON.stringify(node.value);
601
+ }
602
+ if ((node.type == "RegexLit")) {
603
+ return ((("/" + node.value.pattern) + "/") + node.value.flags);
604
+ }
605
+ if ((node.type == "TemplateLit")) {
606
+ return this.genTemplate(node.parts);
607
+ }
608
+ if ((node.type == "BinaryExpr")) {
609
+ return (((((("(" + this.genExpr(node.left)) + " ") + node.op) + " ") + this.genExpr(node.right)) + ")");
610
+ }
611
+ if ((node.type == "UnaryExpr")) {
612
+ return (node.op + this.genExpr(node.operand));
613
+ }
614
+ if ((node.type == "UpdateExpr")) {
615
+ if (node.prefix) {
616
+ return (node.op + this.genExpr(node.operand));
617
+ }
618
+ return (this.genExpr(node.operand) + node.op);
619
+ }
620
+ if ((node.type == "TernaryExpr")) {
621
+ return (((((("(" + this.genExpr(node.cond)) + " ? ") + this.genExpr(node.then)) + " : ") + this.genExpr(node.else_)) + ")");
622
+ }
623
+ if ((node.type == "AssignExpr")) {
624
+ return ((((this.genExpr(node.target) + " ") + node.op) + " ") + this.genExpr(node.value));
625
+ }
626
+ if ((node.type == "AwaitExpr")) {
627
+ return ("await " + this.genExpr(node.operand));
628
+ }
629
+ if ((node.type == "TypeofExpr")) {
630
+ return ("typeof " + this.genExpr(node.operand));
631
+ }
632
+ if ((node.type == "SpreadExpr")) {
633
+ return ("..." + this.genExpr(node.expr));
634
+ }
635
+ if ((node.type == "CallExpr")) {
636
+ const callee = this.genExpr(node.callee);
637
+ const args = node.args.map((a) => this.genExpr(a)).join(", ");
638
+ return (((callee + "(") + args) + ")");
639
+ }
640
+ if ((node.type == "MemberExpr")) {
641
+ const objSrc = this.genExpr(node.obj);
642
+ const wrapped = ((node.obj.type == "NumberLit") ? (("(" + objSrc) + ")") : objSrc);
643
+ return ((wrapped + ".") + node.prop);
644
+ }
645
+ if ((node.type == "OptMemberExpr")) {
646
+ return ((this.genExpr(node.obj) + "?.") + node.prop);
647
+ }
648
+ if ((node.type == "OptIndexExpr")) {
649
+ return (((this.genExpr(node.obj) + "?.[") + this.genExpr(node.idx)) + "]");
650
+ }
651
+ if ((node.type == "OptCallExpr")) {
652
+ const args = node.args.map((a) => this.genExpr(a)).join(", ");
653
+ return (((this.genExpr(node.callee) + "?.(") + args) + ")");
654
+ }
655
+ if ((node.type == "IndexExpr")) {
656
+ return (((this.genExpr(node.obj) + "[") + this.genExpr(node.idx)) + "]");
657
+ }
658
+ if ((node.type == "NewExpr")) {
659
+ const args = node.args.map((a) => this.genExpr(a)).join(", ");
660
+ return (((("new " + node.callee) + "(") + args) + ")");
661
+ }
662
+ if ((node.type == "LambdaExpr")) {
663
+ const params = node.params.map((p) => (p.rest ? ("..." + p.name) : p.name)).join(", ");
664
+ return ((("(" + params) + ") => ") + this.genExpr(node.body));
665
+ }
666
+ if ((node.type == "FnDecl")) {
667
+ const asyncKw = (node.async ? "async " : "");
668
+ const params = node.params.map((p) => (p.rest ? ("..." + p.name) : (p.defaultVal ? ((p.name + " = ") + this.genExpr(p.defaultVal)) : p.name))).join(", ");
669
+ if (node.inline) {
670
+ return (((((asyncKw + "function(") + params) + ") { return ") + this.genExpr(node.body)) + "; }");
671
+ }
672
+ const saved = this.lines.length;
673
+ const savedLevel = this.level;
674
+ this.emit((((asyncKw + "function(") + params) + ") {"));
675
+ this.indIn();
676
+ for (const s of node.body) {
677
+ this.genStmt(s);
678
+ }
679
+ this.indOut();
680
+ this.emit("}");
681
+ const block = this.lines.splice(saved).map((l) => l.trimStart()).join(" ");
682
+ this.level = savedLevel;
683
+ return block;
684
+ }
685
+ if ((node.type == "MatchStmt")) {
686
+ const saved = this.lines.length;
687
+ const savedLevel = this.level;
688
+ const savedLoop = this._loopDepth;
689
+ this._loopDepth = 0;
690
+ this.emit("(() => {");
691
+ this.indIn();
692
+ this.genMatch(node);
693
+ this.indOut();
694
+ this.emit("})()");
695
+ this._loopDepth = savedLoop;
696
+ const block = this.lines.splice(saved).map((l) => l.trimStart()).join(" ");
697
+ this.level = savedLevel;
698
+ return block;
699
+ }
700
+ if ((node.type == "ArrayExpr")) {
701
+ return (("[" + node.items.map((i) => this.genExpr(i)).join(", ")) + "]");
702
+ }
703
+ if ((node.type == "ObjectExpr")) {
704
+ const pairs = node.pairs.map((p) => this.genObjPair(p)).join(", ");
705
+ return (("{ " + pairs) + " }");
706
+ }
707
+ if ((node.type == "RangeExpr")) {
708
+ return (((((("Array.from({ length: " + this.genExpr(node.end)) + " - ") + this.genExpr(node.start)) + " }, (_, i) => i + ") + this.genExpr(node.start)) + ")");
709
+ }
710
+ if ((node.type == "PipeExpr")) {
711
+ return this.genPipe(node);
712
+ }
713
+ if ((node.type == "CastExpr")) {
714
+ return this.genExpr(node.expr);
715
+ }
716
+ if ((node.type == "AsConstExpr")) {
717
+ return (("Object.freeze(" + this.genExpr(node.expr)) + ")");
718
+ }
719
+ if ((node.type == "SatisfiesExpr")) {
720
+ return this.genExpr(node.expr);
721
+ }
722
+ if ((node.type == "IsExpr")) {
723
+ return this.genExpr(node.expr);
724
+ }
725
+ if ((node.type == "NonNullExpr")) {
726
+ return this.genExpr(node.expr);
727
+ }
728
+ throw new Error(`Unknown expression: ${node.type}`);
729
+ }
730
+
731
+ genTemplate(parts) {
732
+ let result = "`";
733
+ for (const p of parts) {
734
+ if ((p.type == "text")) {
735
+ result += p.value.replace(/`/g, "\\`").replace(/\$/g, "\\$");
736
+ }
737
+ else {
738
+ const fmtInfo = extractFormatSpec(p.value);
739
+ const exprSrc = (fmtInfo ? fmtInfo.expr : p.value);
740
+ const fmt = (fmtInfo ? fmtInfo.fmt : null);
741
+ try {
742
+ const tokens = lexerize(exprSrc).tokenize();
743
+ const expr = makeParser(tokens).parseExpr();
744
+ const gen = this.genExpr(expr);
745
+ if (fmt) {
746
+ this._needsFmt = true;
747
+ result += ((((("$" + "{_fmt(") + gen) + ", ") + JSON.stringify(fmt)) + ")}");
748
+ }
749
+ else {
750
+ result += ((("$" + "{") + gen) + "}");
751
+ }
752
+ }
753
+ catch (err) {
754
+ result += ((("$" + "{") + p.value) + "}");
755
+ }
756
+ }
757
+ }
758
+ result += "`";
759
+ return result;
760
+ }
761
+
762
+ genPipe(node) {
763
+ const left = this.genExpr(node.left);
764
+ const right = node.right;
765
+ if ((right.type == "Identifier")) {
766
+ return (((this.genExpr(right) + "(") + left) + ")");
767
+ }
768
+ if ((right.type == "CallExpr")) {
769
+ const fn_ = this.genExpr(right.callee);
770
+ const rest = right.args.map((a) => this.genExpr(a)).join(", ");
771
+ return (rest ? (((((fn_ + "(") + left) + ", ") + rest) + ")") : (((fn_ + "(") + left) + ")"));
772
+ }
773
+ return (((("(" + this.genExpr(right)) + ")(") + left) + ")");
774
+ }
775
+
776
+ }
777
+
778
+ module.exports.CodeGenerator = CodeGenerator;
779
+ function makeCodeGen(opts) {
780
+ const ind = (opts?.indent ?? " ");
781
+ const smb = (opts?.smBuilder ?? null);
782
+ return new CodeGenerator(ind, 0, [], { }, smb, false, 0);
783
+ }
784
+ module.exports.makeCodeGen = makeCodeGen;