@xnoxs/flux-lang 4.0.2 → 4.0.3
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.
- package/dist/flux-cli.js +22 -17
- package/dist/flux.cjs.js +22 -17
- package/package.json +1 -1
- package/src/self/bundler.flux +4 -5
- package/src/self/bundler.js +1 -198
- package/src/self/codegen.flux +10 -1
- package/src/self/codegen.js +1 -799
package/dist/flux-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*!
|
|
3
|
-
* flux-lang v4.0.
|
|
3
|
+
* flux-lang v4.0.3
|
|
4
4
|
* Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.
|
|
5
5
|
* (c) 2026 Flux Lang Contributors
|
|
6
6
|
* Released under the MIT License
|
|
@@ -349,7 +349,7 @@ var require_lexer = __commonJS({
|
|
|
349
349
|
if (this.ch() === "\\") {
|
|
350
350
|
this.adv();
|
|
351
351
|
const e = this.adv();
|
|
352
|
-
s += { n: "\n", t: "
|
|
352
|
+
s += { n: "\n", t: " ", "`": "`", "\\": "\\" }[e] || "\\" + e;
|
|
353
353
|
} else {
|
|
354
354
|
s += this.adv();
|
|
355
355
|
}
|
|
@@ -385,7 +385,7 @@ var require_lexer = __commonJS({
|
|
|
385
385
|
this.pos += 2;
|
|
386
386
|
text += String.fromCharCode(parseInt(hex, 16));
|
|
387
387
|
} else {
|
|
388
|
-
text += { n: "\n", t: "
|
|
388
|
+
text += { n: "\n", t: " ", r: "\r", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
|
|
389
389
|
}
|
|
390
390
|
} else if (this.ch() === "{") {
|
|
391
391
|
parts.push({ type: "text", value: text });
|
|
@@ -473,8 +473,8 @@ var require_lexer = __commonJS({
|
|
|
473
473
|
if (bol) {
|
|
474
474
|
bol = false;
|
|
475
475
|
let indent = 0;
|
|
476
|
-
while (this.ch() === " " || this.ch() === "
|
|
477
|
-
indent += this.ch() === "
|
|
476
|
+
while (this.ch() === " " || this.ch() === " ") {
|
|
477
|
+
indent += this.ch() === " " ? 4 : 1;
|
|
478
478
|
this.adv();
|
|
479
479
|
}
|
|
480
480
|
if (this.ch() === "\n" || !this.ch()) {
|
|
@@ -515,7 +515,7 @@ var require_lexer = __commonJS({
|
|
|
515
515
|
}
|
|
516
516
|
continue;
|
|
517
517
|
}
|
|
518
|
-
if (cur === " " || cur === "
|
|
518
|
+
if (cur === " " || cur === " ") {
|
|
519
519
|
this.adv();
|
|
520
520
|
continue;
|
|
521
521
|
}
|
|
@@ -590,7 +590,7 @@ var require_lexer = __commonJS({
|
|
|
590
590
|
this.pos += 2;
|
|
591
591
|
s += String.fromCharCode(parseInt(hex, 16));
|
|
592
592
|
} else {
|
|
593
|
-
s += { n: "\n", t: "
|
|
593
|
+
s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
|
|
594
594
|
}
|
|
595
595
|
} else {
|
|
596
596
|
s += this.adv();
|
|
@@ -2652,6 +2652,7 @@ function _fmt(v, s) {
|
|
|
2652
2652
|
this.smBuilder = opts.smBuilder || null;
|
|
2653
2653
|
this._needsFmt = false;
|
|
2654
2654
|
this._loopDepth = 0;
|
|
2655
|
+
this._fnDepth = 0;
|
|
2655
2656
|
}
|
|
2656
2657
|
i() {
|
|
2657
2658
|
return this.ind.repeat(this.level);
|
|
@@ -2789,7 +2790,9 @@ function _fmt(v, s) {
|
|
|
2789
2790
|
} else {
|
|
2790
2791
|
this.emit(`${prefix}${asyncKw}function ${name}(${params}) {`);
|
|
2791
2792
|
this.in();
|
|
2793
|
+
this._fnDepth++;
|
|
2792
2794
|
for (const s of node.body) this.genStmt(s);
|
|
2795
|
+
this._fnDepth--;
|
|
2793
2796
|
this.out();
|
|
2794
2797
|
this.emit("}");
|
|
2795
2798
|
}
|
|
@@ -2981,8 +2984,10 @@ function _fmt(v, s) {
|
|
|
2981
2984
|
const exprSrc = this.genExpr(arm.body[0].expr);
|
|
2982
2985
|
if (this._loopDepth > 0) {
|
|
2983
2986
|
this.emit(`${exprSrc};`);
|
|
2984
|
-
} else {
|
|
2987
|
+
} else if (this._fnDepth > 0) {
|
|
2985
2988
|
this.emit(`return ${exprSrc};`);
|
|
2989
|
+
} else {
|
|
2990
|
+
this.emit(`${exprSrc};`);
|
|
2986
2991
|
}
|
|
2987
2992
|
} else {
|
|
2988
2993
|
arm.body.forEach((s) => this.genStmt(s));
|
|
@@ -3231,11 +3236,13 @@ function _fmt(v, s) {
|
|
|
3231
3236
|
const savedLevel = this.level;
|
|
3232
3237
|
const savedLoopDepth = this._loopDepth;
|
|
3233
3238
|
this._loopDepth = 0;
|
|
3239
|
+
this._fnDepth++;
|
|
3234
3240
|
this.emit("(() => {");
|
|
3235
3241
|
this.in();
|
|
3236
3242
|
this.genMatch(node);
|
|
3237
3243
|
this.out();
|
|
3238
3244
|
this.emit("})()");
|
|
3245
|
+
this._fnDepth--;
|
|
3239
3246
|
this._loopDepth = savedLoopDepth;
|
|
3240
3247
|
const block = this.lines.splice(saved).map((l) => l.trimStart()).join(" ");
|
|
3241
3248
|
this.level = savedLevel;
|
|
@@ -3569,7 +3576,7 @@ var require_jsx = __commonJS({
|
|
|
3569
3576
|
const next = this.src[this.pos + 1] || "";
|
|
3570
3577
|
if (!(next === ">" || next >= "a" && next <= "z" || next >= "A" && next <= "Z")) return false;
|
|
3571
3578
|
let i = this.pos - 1;
|
|
3572
|
-
while (i >= 0 && (this.src[i] === " " || this.src[i] === "
|
|
3579
|
+
while (i >= 0 && (this.src[i] === " " || this.src[i] === " ")) i--;
|
|
3573
3580
|
if (i < 0) return true;
|
|
3574
3581
|
const prev = this.src[i];
|
|
3575
3582
|
if ("=([{,:>\n?".includes(prev)) return true;
|
|
@@ -3798,7 +3805,7 @@ var require_jsx = __commonJS({
|
|
|
3798
3805
|
}
|
|
3799
3806
|
// ── Skip whitespace (not newlines) ────────────────────────────
|
|
3800
3807
|
skipWs() {
|
|
3801
|
-
while (this.pos < this.src.length && (this.src[this.pos] === " " || this.src[this.pos] === "
|
|
3808
|
+
while (this.pos < this.src.length && (this.src[this.pos] === " " || this.src[this.pos] === " ")) this.pos++;
|
|
3802
3809
|
}
|
|
3803
3810
|
};
|
|
3804
3811
|
var FLUX_H_BROWSER = `
|
|
@@ -4622,7 +4629,7 @@ ${innerCss}${ind}}
|
|
|
4622
4629
|
const charAfter = this.src[this.pos + 3] || "";
|
|
4623
4630
|
if (!/[a-zA-Z0-9_]/.test(charBefore) && !/[a-zA-Z0-9_]/.test(charAfter)) {
|
|
4624
4631
|
let j = this.pos + 3;
|
|
4625
|
-
while (j < this.src.length && (this.src[j] === " " || this.src[j] === "
|
|
4632
|
+
while (j < this.src.length && (this.src[j] === " " || this.src[j] === " " || this.src[j] === "\n" || this.src[j] === "\r")) j++;
|
|
4626
4633
|
if (this.src[j] === "{") {
|
|
4627
4634
|
j++;
|
|
4628
4635
|
let depth = 1;
|
|
@@ -7255,12 +7262,10 @@ var require_bundler = __commonJS({
|
|
|
7255
7262
|
}
|
|
7256
7263
|
for (const imp of imports) {
|
|
7257
7264
|
const srcId = toModuleId(imp.absPath);
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
lines.push(` var ${name} = ${srcId}._exports ? ${srcId}._exports.${name} : ${srcId}.${name};`);
|
|
7263
|
-
}
|
|
7265
|
+
for (const name of imp.names) {
|
|
7266
|
+
const localName = name.alias ?? name.name;
|
|
7267
|
+
const importedName = name.name;
|
|
7268
|
+
lines.push(` var ${localName} = ${srcId}._exports ? ${srcId}._exports.${importedName} : ${srcId}.${importedName};`);
|
|
7264
7269
|
}
|
|
7265
7270
|
}
|
|
7266
7271
|
if (imports.length > 0) lines.push("");
|
package/dist/flux.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* flux-lang v4.0.
|
|
2
|
+
* flux-lang v4.0.3
|
|
3
3
|
* Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.
|
|
4
4
|
* (c) 2026 Flux Lang Contributors
|
|
5
5
|
* Released under the MIT License
|
|
@@ -278,7 +278,7 @@ var require_lexer = __commonJS({
|
|
|
278
278
|
if (this.ch() === "\\") {
|
|
279
279
|
this.adv();
|
|
280
280
|
const e = this.adv();
|
|
281
|
-
s += { n: "\n", t: "
|
|
281
|
+
s += { n: "\n", t: " ", "`": "`", "\\": "\\" }[e] || "\\" + e;
|
|
282
282
|
} else {
|
|
283
283
|
s += this.adv();
|
|
284
284
|
}
|
|
@@ -314,7 +314,7 @@ var require_lexer = __commonJS({
|
|
|
314
314
|
this.pos += 2;
|
|
315
315
|
text += String.fromCharCode(parseInt(hex, 16));
|
|
316
316
|
} else {
|
|
317
|
-
text += { n: "\n", t: "
|
|
317
|
+
text += { n: "\n", t: " ", r: "\r", '"': '"', "'": "'", "\\": "\\", "{": "{", "}": "}" }[e] || "\\" + e;
|
|
318
318
|
}
|
|
319
319
|
} else if (this.ch() === "{") {
|
|
320
320
|
parts.push({ type: "text", value: text });
|
|
@@ -402,8 +402,8 @@ var require_lexer = __commonJS({
|
|
|
402
402
|
if (bol) {
|
|
403
403
|
bol = false;
|
|
404
404
|
let indent = 0;
|
|
405
|
-
while (this.ch() === " " || this.ch() === "
|
|
406
|
-
indent += this.ch() === "
|
|
405
|
+
while (this.ch() === " " || this.ch() === " ") {
|
|
406
|
+
indent += this.ch() === " " ? 4 : 1;
|
|
407
407
|
this.adv();
|
|
408
408
|
}
|
|
409
409
|
if (this.ch() === "\n" || !this.ch()) {
|
|
@@ -444,7 +444,7 @@ var require_lexer = __commonJS({
|
|
|
444
444
|
}
|
|
445
445
|
continue;
|
|
446
446
|
}
|
|
447
|
-
if (cur === " " || cur === "
|
|
447
|
+
if (cur === " " || cur === " ") {
|
|
448
448
|
this.adv();
|
|
449
449
|
continue;
|
|
450
450
|
}
|
|
@@ -519,7 +519,7 @@ var require_lexer = __commonJS({
|
|
|
519
519
|
this.pos += 2;
|
|
520
520
|
s += String.fromCharCode(parseInt(hex, 16));
|
|
521
521
|
} else {
|
|
522
|
-
s += { n: "\n", t: "
|
|
522
|
+
s += { n: "\n", t: " ", r: "\r", "'": "'", "\\": "\\" }[e] || "\\" + e;
|
|
523
523
|
}
|
|
524
524
|
} else {
|
|
525
525
|
s += this.adv();
|
|
@@ -2581,6 +2581,7 @@ function _fmt(v, s) {
|
|
|
2581
2581
|
this.smBuilder = opts.smBuilder || null;
|
|
2582
2582
|
this._needsFmt = false;
|
|
2583
2583
|
this._loopDepth = 0;
|
|
2584
|
+
this._fnDepth = 0;
|
|
2584
2585
|
}
|
|
2585
2586
|
i() {
|
|
2586
2587
|
return this.ind.repeat(this.level);
|
|
@@ -2718,7 +2719,9 @@ function _fmt(v, s) {
|
|
|
2718
2719
|
} else {
|
|
2719
2720
|
this.emit(`${prefix}${asyncKw}function ${name}(${params}) {`);
|
|
2720
2721
|
this.in();
|
|
2722
|
+
this._fnDepth++;
|
|
2721
2723
|
for (const s of node.body) this.genStmt(s);
|
|
2724
|
+
this._fnDepth--;
|
|
2722
2725
|
this.out();
|
|
2723
2726
|
this.emit("}");
|
|
2724
2727
|
}
|
|
@@ -2910,8 +2913,10 @@ function _fmt(v, s) {
|
|
|
2910
2913
|
const exprSrc = this.genExpr(arm.body[0].expr);
|
|
2911
2914
|
if (this._loopDepth > 0) {
|
|
2912
2915
|
this.emit(`${exprSrc};`);
|
|
2913
|
-
} else {
|
|
2916
|
+
} else if (this._fnDepth > 0) {
|
|
2914
2917
|
this.emit(`return ${exprSrc};`);
|
|
2918
|
+
} else {
|
|
2919
|
+
this.emit(`${exprSrc};`);
|
|
2915
2920
|
}
|
|
2916
2921
|
} else {
|
|
2917
2922
|
arm.body.forEach((s) => this.genStmt(s));
|
|
@@ -3160,11 +3165,13 @@ function _fmt(v, s) {
|
|
|
3160
3165
|
const savedLevel = this.level;
|
|
3161
3166
|
const savedLoopDepth = this._loopDepth;
|
|
3162
3167
|
this._loopDepth = 0;
|
|
3168
|
+
this._fnDepth++;
|
|
3163
3169
|
this.emit("(() => {");
|
|
3164
3170
|
this.in();
|
|
3165
3171
|
this.genMatch(node);
|
|
3166
3172
|
this.out();
|
|
3167
3173
|
this.emit("})()");
|
|
3174
|
+
this._fnDepth--;
|
|
3168
3175
|
this._loopDepth = savedLoopDepth;
|
|
3169
3176
|
const block = this.lines.splice(saved).map((l) => l.trimStart()).join(" ");
|
|
3170
3177
|
this.level = savedLevel;
|
|
@@ -3498,7 +3505,7 @@ var require_jsx = __commonJS({
|
|
|
3498
3505
|
const next = this.src[this.pos + 1] || "";
|
|
3499
3506
|
if (!(next === ">" || next >= "a" && next <= "z" || next >= "A" && next <= "Z")) return false;
|
|
3500
3507
|
let i = this.pos - 1;
|
|
3501
|
-
while (i >= 0 && (this.src[i] === " " || this.src[i] === "
|
|
3508
|
+
while (i >= 0 && (this.src[i] === " " || this.src[i] === " ")) i--;
|
|
3502
3509
|
if (i < 0) return true;
|
|
3503
3510
|
const prev = this.src[i];
|
|
3504
3511
|
if ("=([{,:>\n?".includes(prev)) return true;
|
|
@@ -3727,7 +3734,7 @@ var require_jsx = __commonJS({
|
|
|
3727
3734
|
}
|
|
3728
3735
|
// ── Skip whitespace (not newlines) ────────────────────────────
|
|
3729
3736
|
skipWs() {
|
|
3730
|
-
while (this.pos < this.src.length && (this.src[this.pos] === " " || this.src[this.pos] === "
|
|
3737
|
+
while (this.pos < this.src.length && (this.src[this.pos] === " " || this.src[this.pos] === " ")) this.pos++;
|
|
3731
3738
|
}
|
|
3732
3739
|
};
|
|
3733
3740
|
var FLUX_H_BROWSER = `
|
|
@@ -4551,7 +4558,7 @@ ${innerCss}${ind}}
|
|
|
4551
4558
|
const charAfter = this.src[this.pos + 3] || "";
|
|
4552
4559
|
if (!/[a-zA-Z0-9_]/.test(charBefore) && !/[a-zA-Z0-9_]/.test(charAfter)) {
|
|
4553
4560
|
let j = this.pos + 3;
|
|
4554
|
-
while (j < this.src.length && (this.src[j] === " " || this.src[j] === "
|
|
4561
|
+
while (j < this.src.length && (this.src[j] === " " || this.src[j] === " " || this.src[j] === "\n" || this.src[j] === "\r")) j++;
|
|
4555
4562
|
if (this.src[j] === "{") {
|
|
4556
4563
|
j++;
|
|
4557
4564
|
let depth = 1;
|
|
@@ -7276,12 +7283,10 @@ var require_bundler = __commonJS({
|
|
|
7276
7283
|
}
|
|
7277
7284
|
for (const imp of imports) {
|
|
7278
7285
|
const srcId = toModuleId(imp.absPath);
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
lines.push(` var ${name} = ${srcId}._exports ? ${srcId}._exports.${name} : ${srcId}.${name};`);
|
|
7284
|
-
}
|
|
7286
|
+
for (const name of imp.names) {
|
|
7287
|
+
const localName = name.alias ?? name.name;
|
|
7288
|
+
const importedName = name.name;
|
|
7289
|
+
lines.push(` var ${localName} = ${srcId}._exports ? ${srcId}._exports.${importedName} : ${srcId}.${importedName};`);
|
|
7285
7290
|
}
|
|
7286
7291
|
}
|
|
7287
7292
|
if (imports.length > 0) lines.push("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xnoxs/flux-lang",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "Flux — A modern language that transpiles to JavaScript. Python-clean syntax, TypeScript-level safety, Rust-inspired pattern matching.",
|
|
5
5
|
"main": "dist/flux.cjs.js",
|
|
6
6
|
"module": "dist/flux.esm.js",
|
package/src/self/bundler.flux
CHANGED
|
@@ -124,11 +124,10 @@ export class Bundler:
|
|
|
124
124
|
|
|
125
125
|
for imp in mod.imports:
|
|
126
126
|
val srcId = toModuleId(imp.absPath)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
lines.push(' var ' + name + ' = ' + srcId + '._exports ? ' + srcId + '._exports.' + name + ' : ' + srcId + '.' + name + ';')
|
|
127
|
+
for name in imp.names:
|
|
128
|
+
val localName = name.alias ?? name.name
|
|
129
|
+
val importedName = name.name
|
|
130
|
+
lines.push(' var ' + localName + ' = ' + srcId + '._exports ? ' + srcId + '._exports.' + importedName + ' : ' + srcId + '.' + importedName + ';')
|
|
132
131
|
|
|
133
132
|
if mod.imports.length > 0: lines.push('')
|
|
134
133
|
|
package/src/self/bundler.js
CHANGED
|
@@ -1,198 +1 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
function findIndex(arr, fn) { return arr.findIndex(fn); }
|
|
4
|
-
|
|
5
|
-
function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
|
|
6
|
-
|
|
7
|
-
function includes(arr, val) { return arr.includes(val); }
|
|
8
|
-
|
|
9
|
-
function trim(s) { return String(s).trim(); }
|
|
10
|
-
|
|
11
|
-
function startsWith(s, prefix) { return String(s).startsWith(prefix); }
|
|
12
|
-
|
|
13
|
-
function endsWith(s, suffix) { return String(s).endsWith(suffix); }
|
|
14
|
-
|
|
15
|
-
function repeat(s, n) { return String(s).repeat(n); }
|
|
16
|
-
// ── end stdlib ──
|
|
17
|
-
|
|
18
|
-
// Generated by Flux Transpiler v3.2.0
|
|
19
|
-
"use strict";
|
|
20
|
-
|
|
21
|
-
const Fs = require("fs");
|
|
22
|
-
const Path = require("path");
|
|
23
|
-
const { lexerize } = require("./lexer");
|
|
24
|
-
const { makeParser } = require("./parser");
|
|
25
|
-
const { makeCodeGen } = require("./codegen");
|
|
26
|
-
function toModuleId(absPath) {
|
|
27
|
-
const base = Path.basename(absPath, ".flux");
|
|
28
|
-
return ("_flux_" + base.replace(/[^a-zA-Z0-9]/g, "_"));
|
|
29
|
-
}
|
|
30
|
-
function extractModuleInfo(ast, fromFile) {
|
|
31
|
-
const imports = [];
|
|
32
|
-
const exports = [];
|
|
33
|
-
const body = [];
|
|
34
|
-
const dir = Path.dirname(fromFile);
|
|
35
|
-
for (const node of ast.body) {
|
|
36
|
-
if ((node.type == "ImportDecl")) {
|
|
37
|
-
let src = node.source;
|
|
38
|
-
if (!src.endsWith(".flux")) {
|
|
39
|
-
src = (src + ".flux");
|
|
40
|
-
}
|
|
41
|
-
const absPath = Path.resolve(dir, src);
|
|
42
|
-
imports.push({ names: node.names, source: node.source, absPath });
|
|
43
|
-
}
|
|
44
|
-
else if ((node.type == "ExportDecl")) {
|
|
45
|
-
const inner = node.decl;
|
|
46
|
-
if ((inner.type == "FnDecl")) {
|
|
47
|
-
exports.push(inner.name);
|
|
48
|
-
}
|
|
49
|
-
if ((inner.type == "ClassDecl")) {
|
|
50
|
-
exports.push(inner.name);
|
|
51
|
-
}
|
|
52
|
-
if ((inner.type == "VarDecl")) {
|
|
53
|
-
exports.push(inner.name);
|
|
54
|
-
}
|
|
55
|
-
body.push(inner);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
body.push(node);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return { cleanAst: { type: "Program", body }, imports, exports };
|
|
62
|
-
}
|
|
63
|
-
function codegenModule(ast) {
|
|
64
|
-
const cg = makeCodeGen({ indent: " " });
|
|
65
|
-
const result = cg.generate(ast);
|
|
66
|
-
const lines = result.code.split("\n");
|
|
67
|
-
const start = lines.findIndex((l) => (((l.trim() != "") && !l.includes("Generated by Flux")) && !l.includes("\"use strict\"")));
|
|
68
|
-
return lines.slice(start).join("\n");
|
|
69
|
-
}
|
|
70
|
-
class Bundler {
|
|
71
|
-
constructor(entryFile, options, modules, order, visited, inStack) {
|
|
72
|
-
this.entryFile = entryFile;
|
|
73
|
-
this.options = options;
|
|
74
|
-
this.modules = modules;
|
|
75
|
-
this.order = order;
|
|
76
|
-
this.visited = visited;
|
|
77
|
-
this.inStack = inStack;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
bundle() {
|
|
81
|
-
this.collect(this.entryFile);
|
|
82
|
-
return this.link();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
collect(absPath) {
|
|
86
|
-
if (this.visited.has(absPath)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (this.inStack.has(absPath)) {
|
|
90
|
-
throw new Error(((("[" + Path.basename(absPath)) + "] Circular dependency detected: ") + absPath));
|
|
91
|
-
}
|
|
92
|
-
if (!Fs.existsSync(absPath)) {
|
|
93
|
-
throw new Error(((("[" + Path.basename(absPath)) + "] File not found: ") + absPath));
|
|
94
|
-
}
|
|
95
|
-
this.inStack.add(absPath);
|
|
96
|
-
const source = Fs.readFileSync(absPath, "utf8");
|
|
97
|
-
let ast = null;
|
|
98
|
-
try {
|
|
99
|
-
const tokens = lexerize(source).tokenize();
|
|
100
|
-
ast = makeParser(tokens).parse();
|
|
101
|
-
}
|
|
102
|
-
catch (e) {
|
|
103
|
-
throw new Error(((("[" + Path.basename(absPath)) + "] Parse error: ") + e.message));
|
|
104
|
-
}
|
|
105
|
-
const info = extractModuleInfo(ast, absPath);
|
|
106
|
-
this.modules.set(absPath, { cleanAst: info.cleanAst, imports: info.imports, exports: info.exports, source, absPath });
|
|
107
|
-
for (const imp of info.imports) {
|
|
108
|
-
this.collect(imp.absPath);
|
|
109
|
-
}
|
|
110
|
-
this.inStack.delete(absPath);
|
|
111
|
-
this.visited.add(absPath);
|
|
112
|
-
this.order.push(absPath);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
link() {
|
|
116
|
-
const lines = [];
|
|
117
|
-
const banner = (this.options.banner != false);
|
|
118
|
-
if (banner) {
|
|
119
|
-
lines.push("// Generated by Flux Bundler (self-hosted)");
|
|
120
|
-
lines.push(("// Entry: " + Path.basename(this.entryFile)));
|
|
121
|
-
lines.push(("// Modules: " + this.order.length));
|
|
122
|
-
lines.push("\"use strict\";");
|
|
123
|
-
lines.push("");
|
|
124
|
-
}
|
|
125
|
-
lines.push("// flux_modules resolver");
|
|
126
|
-
lines.push(`(function()${var _p=require('path'),_fs=require('fs'),_M=require('module'),_d=_p.join(process.cwd(),'flux_modules','node_modules');if(_fs.existsSync(_d)){var _o=_M._resolveFilename.bind(_M);_M._resolveFilename=function(r,p,m,op){if(!r.startsWith('.')&&!r.startsWith('/')&&!r.startsWith('node:')){var _fp=_p.join(_d,r.split('/')[0]);if(_fs.existsSync(_fp)){try{return _o(_p.join(_d,r),p,m,op);}catch(_e){}}}return _o(r,p,m,op);};}})();`);
|
|
127
|
-
lines.push("");
|
|
128
|
-
lines.push("(function() {");
|
|
129
|
-
lines.push("");
|
|
130
|
-
for (const absPath of this.order) {
|
|
131
|
-
const mod = this.modules.get(absPath);
|
|
132
|
-
const isEntry = (absPath == this.entryFile);
|
|
133
|
-
const modId = toModuleId(absPath);
|
|
134
|
-
const relName = Path.relative(process.cwd(), absPath);
|
|
135
|
-
lines.push((" // " + "─".repeat(60)));
|
|
136
|
-
lines.push((" // Module: " + relName));
|
|
137
|
-
lines.push((" // " + "─".repeat(60)));
|
|
138
|
-
if (!isEntry) {
|
|
139
|
-
lines.push(((" var " + modId) + " = (function() {"));
|
|
140
|
-
lines.push(" var _exports = {};");
|
|
141
|
-
lines.push("");
|
|
142
|
-
}
|
|
143
|
-
for (const imp of mod.imports) {
|
|
144
|
-
const srcId = toModuleId(imp.absPath);
|
|
145
|
-
if ((imp.names.length == 1)) {
|
|
146
|
-
lines.push(((((" var " + imp.names[0]) + " = ") + srcId) + ";"));
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
for (const name of imp.names) {
|
|
150
|
-
lines.push(((((((((((((" var " + name) + " = ") + srcId) + "._exports ? ") + srcId) + "._exports.") + name) + " : ") + srcId) + ".") + name) + ";"));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if ((mod.imports.length > 0)) {
|
|
155
|
-
lines.push("");
|
|
156
|
-
}
|
|
157
|
-
const moduleCode = codegenModule(mod.cleanAst);
|
|
158
|
-
lines.push(moduleCode);
|
|
159
|
-
if (!isEntry) {
|
|
160
|
-
if ((mod.exports.length > 0)) {
|
|
161
|
-
lines.push("");
|
|
162
|
-
for (const expName of mod.exports) {
|
|
163
|
-
lines.push(((((" _exports." + expName) + " = ") + expName) + ";"));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
lines.push("");
|
|
167
|
-
lines.push(" return _exports;");
|
|
168
|
-
lines.push(" })()");
|
|
169
|
-
lines.push(((((" " + modId) + "._exports = ") + modId) + ";"));
|
|
170
|
-
}
|
|
171
|
-
lines.push("");
|
|
172
|
-
}
|
|
173
|
-
lines.push("})();");
|
|
174
|
-
return { code: lines.join("\n"), modules: this.order.length };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
module.exports.Bundler = Bundler;
|
|
180
|
-
function makeBundler(entryFile, options) {
|
|
181
|
-
return new Bundler(Path.resolve(entryFile), (options ?? { }), new Map(), [], new Set(), new Set());
|
|
182
|
-
}
|
|
183
|
-
module.exports.makeBundler = makeBundler;
|
|
184
|
-
function bundle(entryFile, options) {
|
|
185
|
-
const result = { success: false, code: "", modules: 0, errors: [] };
|
|
186
|
-
try {
|
|
187
|
-
const b = makeBundler(entryFile, options);
|
|
188
|
-
const out = b.bundle();
|
|
189
|
-
result.code = out.code;
|
|
190
|
-
result.modules = out.modules;
|
|
191
|
-
result.success = true;
|
|
192
|
-
}
|
|
193
|
-
catch (e) {
|
|
194
|
-
result.errors.push({ message: e.message, name: e.name, file: null });
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
module.exports.bundle = bundle;
|
|
1
|
+
function findIndex(arr, fn) { return arr.findIndex(fn); } function join(arr, sep) { return arr.join(sep != null ? sep : ','); } function includes(arr, val) { return arr.includes(val); } function trim(s) { return String(s).trim(); } function startsWith(s, prefix) { return String(s).startsWith(prefix); } function endsWith(s, suffix) { return String(s).endsWith(suffix); } function repeat(s, n) { return String(s).repeat(n); } "use strict"; const Fs = require("fs"); const Path = require("path"); const { lexerize } = require("./lexer"); const { makeParser } = require("./parser"); const { makeCodeGen } = require("./codegen"); function _a(_d) { const base = Path.basename(_d, ".flux"); return ("_flux_" + base.replace(/[^a-zA-Z0-9]/g, "_")); } function _b(_e, _f) { const imports = []; const exports = []; const body = []; const dir = Path.dirname(_f); for (const _g of _e.body) { if ((_g.type == "ImportDecl")) { let src = _g.source; if (!src.endsWith(".flux")) { src = (src + ".flux"); } const _d = Path.resolve(dir, src); imports.push({ names: _g.names, source: _g.source, absPath: _d }); } else if ((_g.type == "ExportDecl")) { const inner = _g.decl; if ((inner.type == "FnDecl")) { exports.push(inner.name); } if ((inner.type == "ClassDecl")) { exports.push(inner.name); } if ((inner.type == "VarDecl")) { exports.push(inner.name); } body.push(inner); } else { body.push(_g); } } return { cleanAst: { type: "Program", body }, imports, exports }; } function _c(_e) { const cg = makeCodeGen({ indent: " " }); const result = cg.generate(_e); const lines = result.code.split("\n"); const start = lines.findIndex((_h) => (((_h.trim() != "") && !_h.includes("Generated by Flux")) && !_h.includes("\"use strict\""))); return lines.slice(start).join("\n"); } class Bundler { constructor(entryFile, options, modules, order, visited, inStack) { this.entryFile = entryFile; this.options = options; this.modules = modules; this.order = order; this.visited = visited; this.inStack = inStack; } bundle() { this.collect(this.entryFile); return this.link(); } collect(_d) { if (this.visited.has(_d)) { return; } if (this.inStack.has(_d)) { throw new Error(((("[" + Path.basename(_d)) + "] Circular dependency detected: ") + _d)); } if (!Fs.existsSync(_d)) { throw new Error(((("[" + Path.basename(_d)) + "] File not found: ") + _d)); } this.inStack.add(_d); const source = Fs.readFileSync(_d, "utf8"); let _e = null; try { const tokens = lexerize(source).tokenize(); _e = makeParser(tokens).parse(); } catch (_i) { throw new Error(((("[" + Path.basename(_d)) + "] Parse error: ") + _i.message)); } const info = _b(_e, _d); this.modules.set(_d, { cleanAst: info.cleanAst, imports: info.imports, exports: info.exports, source, absPath: _d }); for (const _j of info.imports) { this.collect(_j.absPath); } this.inStack.delete(_d); this.visited.add(_d); this.order.push(_d); } link() { const lines = []; const banner = (this.options.banner != false); if (banner) { lines.push("// Generated by Flux Bundler (self-hosted)"); lines.push(("// Entry: " + Path.basename(this.entryFile))); lines.push(("// Modules: " + this.order.length)); lines.push("\"use strict\";"); lines.push(""); } lines.push("// flux_modules resolver"); lines.push(`(function()${var _p=require('path'),_fs=require('fs'),_M=require('module'),_d=_p.join(process.cwd(),'flux_modules','node_modules');if(_fs.existsSync(_d)){var _o=_M._resolveFilename.bind(_M);_M._resolveFilename=function(r,p,m,op){if(!r.startsWith('.')&&!r.startsWith('/')&&!r.startsWith('_g:')){var _fp=_p.join(_d,r.split('/')[0]);if(_fs.existsSync(_fp)){try{return _o(_p.join(_d,r),p,m,op);}catch(_e){}}}return _o(r,p,m,op);};}})();`); lines.push(""); lines.push("(function() {"); lines.push(""); for (const _d of this.order) { const mod = this.modules.get(_d); const isEntry = (_d == this.entryFile); const modId = _a(_d); const relName = Path.relative(process.cwd(), _d); lines.push((" // " + "─".repeat(60))); lines.push((" // Module: " + relName)); lines.push((" // " + "─".repeat(60))); if (!isEntry) { lines.push(((" var " + modId) + " = (function() {")); lines.push(" var _exports = {};"); lines.push(""); } for (const _j of mod.imports) { const srcId = _a(_j.absPath); for (const _k of _j.names) { const localName = (_k.alias ?? _k.name); const importedName = _k.name; lines.push(((((((((((((" var " + localName) + " = ") + srcId) + "._exports ? ") + srcId) + "._exports.") + importedName) + " : ") + srcId) + ".") + importedName) + ";")); } } if ((mod.imports.length > 0)) { lines.push(""); } const moduleCode = _c(mod.cleanAst); lines.push(moduleCode); if (!isEntry) { if ((mod.exports.length > 0)) { lines.push(""); for (const _l of mod.exports) { lines.push(((((" _exports." + _l) + " = ") + _l) + ";")); } } lines.push(""); lines.push(" return _exports;"); lines.push(" })()"); lines.push(((((" " + modId) + "._exports = ") + modId) + ";")); } lines.push(""); } lines.push("})();"); return { code: lines.join("\n"), modules: this.order.length }; } } module.exports.Bundler = Bundler; function makeBundler(_m, _n) { return new Bundler(Path.resolve(_m), (_n ?? { }), new Map(), [], new Set(), new Set()); } module.exports.makeBundler = makeBundler; function bundle(_m, _n) { const result = { success: false, code: "", modules: 0, errors: [] }; try { const b = makeBundler(_m, _n); const out = b.bundle(); result.code = out.code; result.modules = out.modules; result.success = true; } catch (_i) { result.errors.push({ message: _i.message, name: _i.name, file: null }); } return result; } module.exports.bundle = bundle;
|
package/src/self/codegen.flux
CHANGED
|
@@ -54,6 +54,7 @@ export class CodeGenerator:
|
|
|
54
54
|
smBuilder: any
|
|
55
55
|
_needsFmt: bool
|
|
56
56
|
_loopDepth: int
|
|
57
|
+
_fnDepth: int
|
|
57
58
|
_version: string
|
|
58
59
|
|
|
59
60
|
fn i():
|
|
@@ -166,7 +167,9 @@ export class CodeGenerator:
|
|
|
166
167
|
else:
|
|
167
168
|
self.emit(prefix + asyncKw + 'function ' + name + '(' + params + ') {')
|
|
168
169
|
self.indIn()
|
|
170
|
+
self._fnDepth = self._fnDepth + 1
|
|
169
171
|
for s in node.body: self.genStmt(s)
|
|
172
|
+
self._fnDepth = self._fnDepth - 1
|
|
170
173
|
self.indOut()
|
|
171
174
|
self.emit('}')
|
|
172
175
|
|
|
@@ -200,7 +203,9 @@ export class CodeGenerator:
|
|
|
200
203
|
else:
|
|
201
204
|
self.emit(staticKw + asyncKw + m.name + '(' + params + ') {')
|
|
202
205
|
self.indIn()
|
|
206
|
+
self._fnDepth = self._fnDepth + 1
|
|
203
207
|
for s in m.body: self.genStmt(s)
|
|
208
|
+
self._fnDepth = self._fnDepth - 1
|
|
204
209
|
self.indOut()
|
|
205
210
|
self.emit('}')
|
|
206
211
|
self.blank()
|
|
@@ -304,8 +309,10 @@ export class CodeGenerator:
|
|
|
304
309
|
val exprSrc = self.genExpr(arm.body[0].expr)
|
|
305
310
|
if self._loopDepth > 0:
|
|
306
311
|
self.emit(exprSrc + ';')
|
|
307
|
-
else:
|
|
312
|
+
else if self._fnDepth > 0:
|
|
308
313
|
self.emit('return ' + exprSrc + ';')
|
|
314
|
+
else:
|
|
315
|
+
self.emit(exprSrc + ';')
|
|
309
316
|
else:
|
|
310
317
|
for s in arm.body: self.genStmt(s)
|
|
311
318
|
self.indOut()
|
|
@@ -492,11 +499,13 @@ export class CodeGenerator:
|
|
|
492
499
|
val savedLevel = self.level
|
|
493
500
|
val savedLoop = self._loopDepth
|
|
494
501
|
self._loopDepth = 0
|
|
502
|
+
self._fnDepth = self._fnDepth + 1
|
|
495
503
|
self.emit('(() => {')
|
|
496
504
|
self.indIn()
|
|
497
505
|
self.genMatch(node)
|
|
498
506
|
self.indOut()
|
|
499
507
|
self.emit('})()')
|
|
508
|
+
self._fnDepth = self._fnDepth - 1
|
|
500
509
|
self._loopDepth = savedLoop
|
|
501
510
|
val block = self.lines.splice(saved).map(l -> l.trimStart()).join(' ')
|
|
502
511
|
self.level = savedLevel
|