@xnoxs/flux-lang 4.0.2 → 4.0.4

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