@xnoxs/flux-lang 3.3.4 → 3.4.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.
@@ -0,0 +1 @@
1
+ function map(arr, fn) { return arr.map(fn); } function filter(arr, fn) { return arr.filter(fn); } function reduce(arr, fn, init) { return arguments.length >= 3 ? arr.reduce(fn, init) : arr.reduce(fn); } function some(arr, fn) { return arr.some(fn); } function join(arr, sep) { return arr.join(sep != null ? sep : ','); } function clamp(val, min, max) { return Math.min(Math.max(val, min), max); } function sum(arr) { return arr.reduce(function(a, b) { return a + b; }, 0); } function max(arr) { if (arguments.length > 1) return Math.max.apply(null, arguments); return Math.max.apply(null, arr); } function padStart(s, len, char) { return String(s).padStart(len, char || ' '); } function padEnd(s, len, char) { return String(s).padEnd(len, char || ' '); } function trim(s) { return String(s).trim(); } function trimEnd(s) { return String(s).trimEnd(); } 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 Os = require("os"); const { transpile, FLUX_VERSION, FLUX_STAGE } = require("./transpiler"); const { bundle } = require("./bundler"); const { format } = require("./formatter"); const { lint } = require("./linter"); const { runTests } = require("./test-runner"); const { loadConfig } = require("./config"); const { cmdAdd, cmdRemove, cmdInstall, cmdList, cmdSearch, cmdInfo, cmdPublish } = require("./pkg"); const _a = (FLUX_VERSION ?? "3.0.0"); const _b = (FLUX_STAGE ?? "self-hosted"); const _c = { reset: "\\x1b[0m", bold: "\\x1b[1m", dim: "\\x1b[2m", red: "\\x1b[31m", green: "\\x1b[32m", yellow: "\\x1b[33m", blue: "\\x1b[34m", cyan: "\\x1b[36m", white: "\\x1b[37m", gray: "\\x1b[90m", magenta: "\\x1b[35m" }; const _d = (process.env.NO_COLOR || !process.stdout.isTTY); function _e(_ai, _aj) { return (_d ? _aj : ((_ai + _aj) + _c.reset)); } function _f(_aj) { return _e(_c.bold, _aj); } function _g(_aj) { return _e(_c.gray, _aj); } function _h(_aj) { return _e(_c.green, _aj); } function _i(_aj) { return _e(_c.red, _aj); } function _j(_aj) { return _e(_c.cyan, _aj); } function _k(_aj) { return _e(_c.yellow, _aj); } function _l(_aj) { return _e(_c.blue, _aj); } function _m() { if (_d) { console.log((((("Flux Lang " + _a) + " [") + _b) + "]")); return; } console.log(_j(_f("███████╗██╗ ██╗ ██╗██╗ ██╗\n██╔════╝██║ ██║ ██║╚██╗██╔╝\n█████╗ ██║ ██║ ██║ ╚███╔╝\n██╔══╝ ██║ ██║ ██║ ██╔██╗\n██║ ███████╗╚██████╔╝██╔╝ ██╗\n╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝"))); console.log(_g(((((" Flux Lang v" + _a) + " [") + _b) + "] → JavaScript\n"))); } function _n() { _m(); console.log(_f("USAGE:")); console.log(" flux <command> [options]\n"); console.log(_f("COMPILER:")); const compilerCmds = [["compile <file.flux>", "Compile .flux → .js"], ["bundle <entry.flux>", "Bundle multiple files into one .js"], ["run <file.flux>", "Compile and run immediately"], ["watch <file.flux>", "Watch for changes, auto-compile"], ["check <file.flux>", "Type-check and static analysis"]]; for (const _ak of compilerCmds) { const [cmd, desc] = _ak; console.log((((" " + _h(("flux " + cmd).padEnd(36))) + " ") + _g(desc))); } console.log(); console.log(_f("TOOLING:")); const toolCmds = [["lint <file.flux>", "Full lint: types + style + immutability"], ["fmt <file.flux>", "Format source code in-place"], ["test [dir]", "Run *.test.flux files"], ["repl", "Interactive REPL mode"], ["tokens <file.flux>", "Show lexer token list"], ["ast <file.flux>", "Show Abstract Syntax Tree (JSON)"]]; for (const _ak of toolCmds) { const [cmd, desc] = _ak; console.log((((" " + _h(("flux " + cmd).padEnd(36))) + " ") + _g(desc))); } console.log(); console.log(_f("PACKAGE MANAGER:")); const pkgCmds = [["init [name]", "Scaffold a new Flux project"], ["add <pkg[@version]>", "Add a dependency"], ["remove <pkg>", "Remove a dependency"], ["install", "Install all dependencies"], ["list", "List installed packages"], ["search <query>", "Search the package registry"], ["info <pkg>", "Show package details"], ["publish", "Publish package to registry"]]; for (const _ak of pkgCmds) { const [cmd, desc] = _ak; console.log((((" " + _j(("flux " + cmd).padEnd(36))) + " ") + _g(desc))); } console.log(); console.log(_f("SELF-HOSTED:")); const selfCmds = [["self-hosted", "Show self-hosted compiler status"], ["self-hosted build", "Bootstrap: compile compiler with itself"], ["self-hosted verify", "Verify self-hosted output matches stage-0"]]; for (const _ak of selfCmds) { const [cmd, desc] = _ak; console.log((((" " + _k(("flux " + cmd).padEnd(36))) + " ") + _g(desc))); } console.log(); console.log(_f("OPTIONS:")); console.log(((" " + _k("--out, -o <file> ")) + " Output file")); console.log(((" " + _k("--sourcemap, -m ")) + " Generate .js.map")); console.log(((" " + _k("--watch, -w ")) + " Watch mode")); console.log(((" " + _k("--mangle ")) + " Minify identifiers")); console.log(((" " + _k("--typecheck ")) + " Enable type checking")); console.log(((" " + _k("--stdout ")) + " Print to terminal")); console.log(((" " + _k("--no-color ")) + " Disable colors")); console.log(); } function _o(_al) { const args = _al.slice(2); const opts = { out: null, sourcemap: false, mangle: false, typecheck: false, strict: false, stdout: false, watch: false, dev: false, verbose: false, jsx: false, jsxTarget: "browser" }; const positional = []; let i = 0; while ((i < args.length)) { const a = args[i]; if (((a == "--out") || (a == "-o"))) { i = (i + 1); opts.out = args[i]; } else if (((a == "--sourcemap") || (a == "-m"))) { opts.sourcemap = true; } else if ((a == "--mangle")) { opts.mangle = true; } else if (((a == "--typecheck") || (a == "-t"))) { opts.typecheck = true; } else if ((a == "--strict")) { opts.strict = true; } else if ((a == "--stdout")) { opts.stdout = true; } else if (((a == "--watch") || (a == "-w"))) { opts.watch = true; } else if ((a == "--dev")) { opts.dev = true; } else if (((a == "--verbose") || (a == "-v"))) { opts.verbose = true; } else if ((a == "--jsx")) { opts.jsx = true; } else if ((a == "--jsx-target")) { i = (i + 1); opts.jsxTarget = args[i]; } else if (!a.startsWith("--")) { positional.push(a); } i = (i + 1); } return { positional, opts }; } function _p(_am) { const abs = Path.resolve(_am); if (!Fs.existsSync(abs)) { console.error(_i(("✗ File not found: " + abs))); process.exit(1); } if (!_am.endsWith(".flux")) { console.warn(_k(("⚠ Not a .flux file: " + _am))); } return { source: Fs.readFileSync(abs, "utf8"), abs }; } function _q(_an, _ao) { if (_ao) { return Path.resolve(_ao); } const base = Path.basename(_an, ".flux"); return Path.join(Path.dirname(Path.resolve(_an)), (base + ".js")); } const _r = { ParseError: "Syntax error", LexerError: "Syntax error", CheckError: "Static error", TypeCheckError: "Type error", TypeError: "Type error" }; function _s(_ap, _aq, _am) { const lines = _aq.split("\n"); for (const _ar of _ap) { const kind = (_r[_ar.name] ?? "Error"); const stage = (_ar.stage ? _g(((" [" + _ar.stage) + "]")) : ""); console.error(); console.error((_i(_f(kind)) + stage)); if (_ar.line) { const fileLabel = (_am ? _j(Path.relative(process.cwd(), _am)) : ""); const locLabel = _k(((_ar.line + ":") + (_ar.col ?? 1))); if (fileLabel) { console.error((((" " + fileLabel) + ":") + locLabel)); } else { console.error((" Line " + locLabel)); } } console.error((" " + _ar.message)); if ((_ar.line && (_ar.line <= lines.length))) { const errLineIdx = (_ar.line - 1); const col = Math.max(0, ((_ar.col ?? 1) - 1)); const tokLen = Math.max(1, (_ar.len ?? 1)); if (((errLineIdx > 0) && (lines[(errLineIdx - 1)].trim() != ""))) { const prev = String((_ar.line - 1)).padStart(4); console.error(_g((((" " + prev) + " │ ") + lines[(errLineIdx - 1)]))); } const lineNum = String(_ar.line).padStart(4); console.error((_g(((" " + lineNum) + " │ ")) + lines[errLineIdx])); const squiggle = ("^" + "~".repeat(Math.max(0, (tokLen - 1)))); const pointer = (" ".repeat(col) + _i(squiggle)); console.error((_g(" │ ") + pointer)); if ((((errLineIdx + 1) < lines.length) && (lines[(errLineIdx + 1)].trim() != ""))) { const next = String((_ar.line + 1)).padStart(4); console.error(_g((((" " + next) + " │ ") + lines[(errLineIdx + 1)]))); } } if (_ar.hint) { console.error((_j(" Hint: ") + _g(_ar.hint))); } } console.error(); } function _t(_am, _as) { const { source: _aq, abs } = _p(_am); const cfg = loadConfig(Path.dirname(abs)); const outPath = _q(_am, _as.out); const mapPath = (outPath + ".map"); const t0 = Date.now(); const result = transpile(_aq, { sourcemap: (_as.sourcemap ?? cfg.sourcemap), mangle: (_as.mangle ?? cfg.mangle), typecheck: (_as.typecheck ?? cfg.typecheck), jsx: (_as.jsx ?? cfg.jsx), jsxTarget: (_as.jsxTarget ?? cfg.jsxTarget), sourceFile: Path.relative(Path.dirname(outPath), abs), outputFile: Path.basename(outPath) }); if (!result.success) { console.error(_i((("\n✗ Compile failed — " + result.errors.length) + " error(s)"))); _s(result.errors, _aq, abs); process.exit(1); } const elapsed = (Date.now() - t0); if (_as.stdout) { console.log(result.output); return; } Fs.writeFileSync(outPath, result.output, "utf8"); let extra = ""; if ((_as.sourcemap && result.sourceMap)) { Fs.writeFileSync(mapPath, result.sourceMap, "utf8"); extra = _g((" + " + Path.relative(process.cwd(), mapPath))); } const rel = Path.relative(process.cwd(), abs); const relO = Path.relative(process.cwd(), outPath); console.log((((((_h("✓ ") + _g((("(" + elapsed) + "ms) "))) + _l(rel)) + _g(" → ")) + _j(relO)) + extra)); if ((result.typeErrors && (result.typeErrors.length > 0))) { console.warn(_k((("\n⚠ " + result.typeErrors.length) + " type warning(s)"))); _s(result.typeErrors, _aq, abs); } } function _u(_am, _as) { const { source: _aq, abs } = _p(_am); const result = transpile(_aq, { jsx: (_as.jsx ?? false), jsxTarget: (_as.jsxTarget ?? "browser"), mangle: false }); if (!result.success) { console.error(_i("\n✗ Compile error")); _s(result.errors, _aq, abs); process.exit(1); } const tmpPath = Path.join(Os.tmpdir(), (("_flux_run_" + Date.now()) + ".js")); Fs.writeFileSync(tmpPath, result.output, "utf8"); console.log(_g((("▶ Running " + Path.basename(abs)) + " ...\n"))); try { require(tmpPath); } catch (_at) { console.error(_i(("\n[Runtime Error] " + _at.message))); process.exitCode = 1; } finally { try { Fs.unlinkSync(tmpPath); } catch (_au) { null; } } } function _v(_av) { const _aq = Fs.readFileSync(_av, "utf8"); const baseName = Path.basename(_av); const result = transpile(_aq, { check: true, typecheck: true }); if (!result.success) { const n = result.errors.length; const kind = (result.errors.some((_at) => (_at.name == "CheckError")) ? "static" : "syntax"); console.error(_i((((((("\n✗ " + baseName) + ": ") + n) + " ") + kind) + " error(s)"))); _s(result.errors, _aq, _av); return { ok: false, typeErrors: 0, warnings: 0 }; } let allOk = true; const typeErrors = (result.typeErrors ?? []); if ((typeErrors.length > 0)) { console.error(_i((((("\n✗ " + baseName) + ": ") + typeErrors.length) + " type error(s)"))); _s(typeErrors, _aq, _av); allOk = false; } const warnings = (result.typeWarnings ?? []); for (const _aw of warnings) { const fileRef = (_j(baseName) + (_aw.line ? _k((":" + _aw.line)) : "")); console.warn(((_k(" ⚠ ") + fileRef) + _g((" " + _aw.message)))); if (_aw.hint) { console.warn((_j(" Hint: ") + _g(_aw.hint))); } } const fnRe = /^(?:async )?function \w/gm; const clsRe = /^class \w/gm; const fns = (result.output.match(fnRe) ?? []).length; const cls = (result.output.match(clsRe) ?? []).length; if (allOk) { console.log((((_h("✓ ") + _j(baseName)) + _g(" — no errors")) + _g(((((((" Functions: " + fns) + " | Classes: ") + cls) + " | JS output: ") + result.output.split("\n").length) + " lines")))); } return { ok: allOk, typeErrors: typeErrors.length, warnings: warnings.length }; } function _w(_ax, _as) { if ((_ax.length == 0)) { console.error(_i("✗ No files specified")); process.exit(1); } let totalErrors = 0; let totalWarnings = 0; for (const _am of _ax) { const _av = Path.resolve(_am); if (!Fs.existsSync(_av)) { console.error(_i(("✗ File not found: " + _am))); totalErrors = (totalErrors + 1); continue; } const r = _v(_av); if (!r.ok) { totalErrors = (totalErrors + 1); } totalWarnings = (totalWarnings + r.warnings); } console.log(); if ((totalErrors > 0)) { console.error(_i((("✗ " + totalErrors) + " file(s) with errors"))); process.exit(1); } else { console.log((_h("✓ All files OK") + ((totalWarnings > 0) ? _k(((" (" + totalWarnings) + " warning(s))")) : ""))); } } function _x(_ax, _as) { let changed = 0; for (const _am of _ax) { const _av = Path.resolve(_am); if (!Fs.existsSync(_av)) { console.error(_i(("✗ Not found: " + _am))); continue; } const _aq = Fs.readFileSync(_av, "utf8"); const formatted = format(_aq); if ((formatted != _aq)) { if (!_as.stdout) { Fs.writeFileSync(_av, formatted, "utf8"); console.log(((_h("✓ ") + _g("Formatted ")) + _j(Path.relative(process.cwd(), _av)))); changed = (changed + 1); } else { console.log(formatted); } } else { console.log(((_g("○ ") + _g("No changes: ")) + Path.relative(process.cwd(), _av))); } } if ((!_as.stdout && (changed > 0))) { console.log(); console.log(_h((("✓ " + changed) + " file(s) formatted"))); } } function _y(_ax, _as) { let hasErrors = false; for (const _am of _ax) { const _av = Path.resolve(_am); if (!Fs.existsSync(_av)) { console.error(_i(("✗ Not found: " + _am))); continue; } const _aq = Fs.readFileSync(_av, "utf8"); const result = lint(_aq); const name = Path.relative(process.cwd(), _av); if (((result.errors.length == 0) && (result.warnings.length == 0))) { console.log(((_h("✓ ") + _j(name)) + _g(" — clean"))); } else { for (const _at of result.errors) { console.error((((_i(" error ") + _j(((name + ":") + (_at.line ?? "?")))) + " ") + _at.message)); hasErrors = true; } for (const _aw of result.warnings) { console.warn((((_k(" warn ") + _j(((name + ":") + (_aw.line ?? "?")))) + " ") + _aw.message)); } } } if (hasErrors) { process.exit(1); } } function _z(_ay, _as) { const _av = Path.resolve(_ay); if (!Fs.existsSync(_av)) { console.error(_i(("✗ File not found: " + _ay))); process.exit(1); } const outFile = (_as.out ?? Path.join(Path.dirname(_av), (Path.basename(_av, ".flux") + ".bundle.js"))); const t0 = Date.now(); const result = bundle(_av); if (!result.success) { console.error(_i("\n✗ Bundle failed:\n")); for (const _at of result.errors) { console.error(_i((" " + _at.message))); } process.exit(1); } const elapsed = (Date.now() - t0); if (_as.stdout) { console.log(result.code); return; } Fs.writeFileSync(outFile, result.code, "utf8"); const kb = (result.code.length / 1024).toFixed(1); console.log((((((_h("✓ Bundle done") + _g(((" (" + elapsed) + "ms) "))) + Path.basename(_av)) + _g(((" + " + (result.modules - 1)) + " module(s) → "))) + _j(Path.relative(process.cwd(), outFile))) + _g(((" [" + kb) + " KB]")))); } function _aa(_am, _as) { const _av = Path.resolve(_am); if (!Fs.existsSync(_av)) { console.error(_i(("✗ File not found: " + _am))); process.exit(1); } console.log(((_j("◉ Watching ") + Path.relative(process.cwd(), _av)) + _g(" (Ctrl+C to stop)\n"))); _t(_am, _as); let timer = null; function onDebounce() { console.log((_g((("\n" + new Date().toLocaleTimeString()) + " — ")) + _l("change detected"))); _t(_am, _as); } function onChange() { if (timer) { clearTimeout(timer); } timer = setTimeout(onDebounce, 80); } Fs.watch(_av, onChange); } function _ab(_am, _as) { const { source: _aq } = _p(_am); const { Lexer } = require(Path.join(__dirname, "lexer.js")); const lexer = new Lexer(_aq); const tokens = lexer.tokenize(); console.log(_g((("Tokens (" + tokens.length) + "):\n"))); for (const _az of tokens) { const loc = (_az.line ? _g((((" " + _az.line) + ":") + (_az.col ?? 1))) : ""); const val_ = ((_az.value != null) ? _j((" " + JSON.stringify(_az.value))) : ""); console.log((((" " + _k(_az.type.padEnd(16))) + val_) + loc)); } } function _ac(_am, _as) { const { source: _aq } = _p(_am); const result = transpile(_aq, { }); if (!result.success) { _s(result.errors, _aq, _am); process.exit(1); } console.log(JSON.stringify(result.ast, null, 2)); } function _ad(_as) { const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true, prompt: (_j("flux") + _g("> ")) }); console.log(); console.log((_f("Flux Lang Interactive REPL") + _g(((((" v" + _a) + " [") + _b) + "]")))); console.log(_g("Type Flux code to compile and run it. Ctrl+C or .exit to quit.\n")); rl.prompt(); let multiLine = ""; let inBlock = false; function onLine(_ba) { const line = _ba; if (((line.trim() == ".exit") || (line.trim() == ".quit"))) { console.log(_g("\nBye!")); process.exit(0); } if ((line.trim() == ".help")) { console.log(_g(" .exit — quit")); console.log(_g(" .clear — clear screen")); console.log(_g(" .help — this message")); rl.prompt(); return; } if ((line.trim() == ".clear")) { console.clear(); rl.prompt(); return; } const needsContinue = (line.trimEnd().endsWith(":") || inBlock); if ((needsContinue && (line.trim() != ""))) { multiLine = ((multiLine + line) + "\n"); inBlock = true; process.stdout.write(_g("... ")); return; } const src = (inBlock ? multiLine : line); multiLine = ""; inBlock = false; if (!src.trim()) { rl.prompt(); return; } try { const result = transpile(src, { check: false }); if (result.success) { const tmpPath = Path.join(Os.tmpdir(), (("_flux_repl_" + Date.now()) + ".js")); Fs.writeFileSync(tmpPath, result.output, "utf8"); try { const out = require(tmpPath); if ((out != undefined)) { console.log((_h("← ") + JSON.stringify(out))); } } catch (_at) { console.error((_i("Runtime: ") + _at.message)); } finally { try { Fs.unlinkSync(tmpPath); } catch (_au) { null; } } } else { for (const _at of result.errors) { console.error((_i("✗ ") + _at.message)); } } } catch (_bb) { console.error((_i("Error: ") + _bb.message)); } rl.prompt(); } function onClose() { console.log(_g("\nBye!")); process.exit(0); } rl.on("line", onLine); rl.on("close", onClose); } function _ae(_bc, _as) { const projectName = (_bc ?? "my-flux-app"); const dir = Path.resolve(projectName); if (Fs.existsSync(dir)) { console.error(_i(("✗ Directory already exists: " + projectName))); process.exit(1); } Fs.mkdirSync(dir, { recursive: true }); Fs.mkdirSync(Path.join(dir, "src"), { recursive: true }); Fs.mkdirSync(Path.join(dir, "tests"), { recursive: true }); const mainFlux = "// {projectName} — built with Flux Lang v{VERSION}\n// Run: flux run src/main.flux\n\n// ── Algebraic Data Types + Pattern Matching ───────────────────\ntype Shape = Circle(radius) | Rect(width, height) | Triangle(base, height)\n\nfn area(shape):\n match shape:\n when Circle(r): return Math.PI * r * r\n when Rect(w, h): return w * h\n when Triangle(b, h): return 0.5 * b * h\n\nfn describe(shape):\n match shape:\n when Circle(r): return \"Circle(r={r:.2f})\"\n when Rect(w, h): return \"Rect({w:.1f}x{h:.1f})\"\n when Triangle(b, h): return \"Triangle(b={b:.1f}, h={h:.1f})\"\n\n// ── Result type ───────────────────────────────────────────────\ntype Result = Ok(value) | Err(message)\n\nfn safeDivide(a, b):\n if b == 0: return Err(\"division by zero\")\n return Ok(a / b)\n\n// ── Utility functions ─────────────────────────────────────────\nfn greet(name): return \"Hello from Flux, {name}!\"\n\nfn formatList(items):\n if items.length == 0: return \"(empty)\"\n return \"[\" + items.join(\", \") + \"]\"\n\nfn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\n// ── Pipe operator + stdlib ────────────────────────────────────\nval numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\nval processed = numbers\n |> filter(n -> n > 3)\n |> map(n -> n * n)\n |> sort\n\n// ── Main ──────────────────────────────────────────────────────\nprint(greet(\"{projectName}\"))\nprint(\"Squares > 3: {formatList(processed)}\")\nprint(\"clamp(12, 0, 10) = {clamp(12, 0, 10)}\")\n\nval shapes = [Circle(5.0), Rect(8.0, 3.0), Triangle(6.0, 4.0)]\nfor shape in shapes:\n val a = area(shape)\n print(\"{describe(shape)} area={a:.2f}\")\n\nmatch safeDivide(10.0, 3.0):\n when Ok(v): print(\"10 / 3 = {v:.4f}\")\n when Err(e): print(\"Error: {e}\")"; const utilsFlux = "// Utility functions for {projectName}\n// Use with: flux bundle src/main.flux (bundles imports automatically)\n\nexport fn greet(name):\n return \"Hello from Flux, {name}!\"\n\nexport fn formatList(items):\n if items.length == 0: return \"(empty)\"\n return \"[\" + items.join(\", \") + \"]\"\n\nexport fn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\nexport fn sum(nums):\n return nums.reduce((acc, x) -> acc + x, 0)\n\nexport fn average(nums):\n if nums.length == 0: return 0\n return sum(nums) / nums.length"; const testFlux = "// Tests for {projectName}\n// Run: flux test tests/\n\n// ── Functions under test ──────────────────────────────────────\nfn add(a, b):\n return a + b\n\nfn mul(a, b):\n return a * b\n\nfn clamp(value, lo, hi):\n if value < lo: return lo\n if value > hi: return hi\n return value\n\nfn average(nums):\n if nums.length == 0: return 0\n return nums.reduce((s, x) -> s + x, 0) / nums.length\n\ntype Result = Ok(value) | Err(message)\n\nfn safeDivide(a, b):\n if b == 0: return Err(\"div by zero\")\n return Ok(a / b)\n\n// ── Test functions ────────────────────────────────────────────\nfn test_add():\n assert(add(1, 2) == 3, \"1+2=3\")\n assert(add(0, 0) == 0, \"0+0=0\")\n assert(add(-1, 1) == 0, \"-1+1=0\")\n\nfn test_mul():\n assert(mul(3, 4) == 12, \"3*4=12\")\n assert(mul(0, 5) == 0, \"0*5=0\")\n\nfn test_clamp():\n assert(clamp(5, 0, 10) == 5, \"within range\")\n assert(clamp(-1, 0, 10) == 0, \"below min\")\n assert(clamp(15, 0, 10) == 10, \"above max\")\n\nfn test_average():\n assert(average([2, 4, 6]) == 4, \"average of 2,4,6\")\n assert(average([]) == 0, \"empty list\")\n\nfn test_safe_divide():\n val ok = safeDivide(10, 2)\n match ok:\n when Ok(v): assert(v == 5, \"10/2=5\")\n when Err(e): assert(false, \"unexpected error\")\n val err = safeDivide(10, 0)\n match err:\n when Ok(v): assert(false, \"expected error\")\n when Err(e): assert(e == \"div by zero\", \"error message\")\n\nfn test_pipe_operator():\n val result = [1, 2, 3, 4, 5] |> filter(n -> n > 2) |> map(n -> n * 2)\n assert(result.length == 3, \"filter length\")\n assert(result[0] == 6, \"first element\")\n assert(result[2] == 10, \"last element\")"; const fluxJson = { name: projectName, version: "1.0.0", description: (("A Flux Lang v" + _a) + " project"), author: "", license: "MIT", entry: "src/main.flux", outDir: "dist", sourcemap: false, typecheck: true, scripts: { start: "flux run src/main.flux", build: "flux bundle src/main.flux -o dist/bundle.js", dev: "flux watch src/main.flux", check: "flux check src/main.flux", test: "flux test tests/", fmt: "flux fmt src/", lint: "flux lint src/" }, dependencies: { }, devDependencies: { "@xnoxs/flux-lang": ("^" + _a) } }; const gitignore = "node_modules/\ndist/\nflux_modules/\n*.js.map\n.DS_Store\n"; const readme = "# {projectName}\n\nA project built with [Flux Lang](https://flux-lang.dev) v{VERSION} — the self-hosted compiler.\n\n## Quick Start\n\n```bash\nflux run src/main.flux\n```\n\n## Project Structure\n\n```\n{projectName}/\n├── src/\n│ ├── main.flux # Entry point\n│ └── utils.flux # Utility functions\n├── tests/\n│ └── main.test.flux # Test suite\n├── flux.json # Project config\n└── README.md\n```\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `flux run src/main.flux` | Run the project |\n| `flux bundle src/main.flux -o dist/bundle.js` | Bundle to single file |\n| `flux watch src/main.flux` | Watch mode |\n| `flux check src/main.flux` | Type check + static analysis |\n| `flux test tests/` | Run all tests |\n| `flux fmt src/` | Format source code |\n| `flux lint src/` | Lint for issues |\n| `flux add <package>` | Add a dependency |"; const allFiles = [(projectName + "/src/main.flux"), (projectName + "/src/utils.flux"), (projectName + "/tests/main.test.flux"), (projectName + "/flux.json"), (projectName + "/.gitignore"), (projectName + "/README.md")]; Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8"); Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8"); Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8"); Fs.writeFileSync(Path.join(dir, "flux.json"), (JSON.stringify(fluxJson, null, 2) + "\n"), "utf8"); Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8"); Fs.writeFileSync(Path.join(dir, "README.md"), readme, "utf8"); console.log(); console.log((_h("✓ Created: ") + _f((projectName + "/")))); console.log(); console.log(_g(" Files:")); for (const _bd of allFiles) { console.log((" " + _j(_bd))); } console.log(); console.log(_f(" Next steps:")); console.log((" " + _k(("cd " + projectName)))); console.log((" " + _k("flux run src/main.flux"))); console.log(); console.log(_g(" Or run the test suite:")); console.log((" " + _k("flux test tests/"))); console.log(); } function _af(_be, _as) { const SELF = Path.join(__dirname, "."); const coreModules = ["css-preprocessor", "checker", "type-checker", "jsx", "lexer", "parser", "codegen", "transpiler"]; const extModules = ["formatter", "sourcemap", "stdlib", "mangler", "linter", "bundler", "test-runner"]; const newModules = ["config", "pkg", "cli"]; const allModules = [...coreModules, ...extModules, ...newModules]; if ((_be == "build")) { const { execSync } = require("child_process"); const BIN = Path.join(__dirname, "../../bin/flux.js"); console.log(); console.log(_f("⚡ Flux Bootstrap — Stage 0")); console.log(_g(" Compiling self-hosted sources with stage-0 compiler...\n")); let ok = 0; let failed = 0; for (const _bc of allModules) { const src = Path.join(SELF, (_bc + ".flux")); const out = Path.join(SELF, (_bc + ".js")); if (!Fs.existsSync(src)) { console.log(_g(((" ○ " + _bc) + ".flux (skipped — not found)"))); continue; } try { const cmd = "node \"${BIN}\" compile \"${src}\" -o \"${out}\" --no-mangle"; execSync(cmd, { cwd: Path.join(__dirname, "../.."), stdio: "pipe" }); console.log((((_h(" ✓ ") + _bc) + ".flux → ") + _g((_bc + ".js")))); ok = (ok + 1); } catch (_at) { console.error((((_i(" ✗ ") + _bc) + ".flux — ") + _at.message.split("\n")[0])); failed = (failed + 1); } } console.log(); if ((failed == 0)) { console.log((_h("✓ Bootstrap complete! ") + _g((ok + " modules compiled")))); console.log(); console.log(" Activate self-hosted mode:"); console.log((" " + _k("FLUX_SELF_HOSTED=1 flux <command>"))); } else { console.log(_i((((("✗ " + failed) + " module(s) failed, ") + ok) + " succeeded"))); } console.log(); return; } if ((_be == "verify")) { console.log(_j("\n Verifying self-hosted compiler output...\n")); try { const selfMod = require(Path.join(SELF, "transpiler.js")); const stage0Mod = require(Path.join(__dirname, "../transpiler.js")); const testSrc = "fn greet(name): return \"Hello, {name}!\"\nval msg = greet(\"Flux\")"; const r0 = stage0Mod.transpile(testSrc, { }); const r1 = selfMod.transpile(testSrc, { }); function norm(_aj) { return _aj.replace(/\/\/.*/g, "").replace(/\s+/g, " ").trim(); } if ((norm(r0.output) == norm(r1.output))) { console.log(_h("✓ Self-hosted output matches stage-0!")); console.log(_h("✓ Flux is fully self-hosting.")); } else { console.log(_k("⚠ Outputs differ (minor differences are OK)")); console.log((_g(" Stage-0: ") + r0.output.split("\n")[0])); console.log((_g(" Self-hosted:") + r1.output.split("\n")[0])); } } catch (_at) { console.error(_i(("✗ Verify failed: " + _at.message))); } console.log(); return; } console.log(); console.log(_f(" Flux Self-Hosted Compiler Status\n")); const selfActive = (process.env.FLUX_SELF_HOSTED == "1"); if (selfActive) { console.log(((" Mode: " + _h("● ACTIVE")) + _g(" (using self-hosted compiler)"))); } else { console.log((((" Mode: " + _g("○ INACTIVE")) + " ") + _g("(using stage-0 compiler)"))); console.log((" Toggle: " + _k("FLUX_SELF_HOSTED=1 flux <command>"))); console.log((" Build: " + _k("flux self-hosted build"))); } console.log(); console.log(_f(((" Core Pipeline (" + coreModules.length) + " modules)"))); for (const _bc of coreModules) { const jsPath = Path.join(SELF, (_bc + ".js")); const flxPath = Path.join(SELF, (_bc + ".flux")); const hasJs = Fs.existsSync(jsPath); const hasFlx = Fs.existsSync(flxPath); const kb = (hasJs ? (Fs.statSync(jsPath).size / 1024).toFixed(1) : "?"); const sym = (hasJs ? _h("✓") : _i("✗")); const note = (!hasFlx ? _g(" (no .flux source)") : ""); console.log((((((" " + sym) + " ") + (_bc + ".flux").padEnd(26)) + _g((kb + " KB"))) + note)); } console.log(); console.log(_f(((" Extended Toolchain (" + extModules.length) + " modules)"))); for (const _bc of extModules) { const jsPath = Path.join(SELF, (_bc + ".js")); const flxPath = Path.join(SELF, (_bc + ".flux")); const hasJs = Fs.existsSync(jsPath); const hasFlx = Fs.existsSync(flxPath); const kb = (hasJs ? (Fs.statSync(jsPath).size / 1024).toFixed(1) : "?"); const sym = (hasJs ? _h("✓") : _i("✗")); const note = (!hasFlx ? _g(" (no .flux source)") : ""); console.log((((((" " + sym) + " ") + (_bc + ".flux").padEnd(26)) + _g((kb + " KB"))) + note)); } console.log(); console.log(_f(((" Ecosystem (" + newModules.length) + " modules)"))); for (const _bc of newModules) { const jsPath = Path.join(SELF, (_bc + ".js")); const flxPath = Path.join(SELF, (_bc + ".flux")); const hasJs = Fs.existsSync(jsPath); const hasFlx = Fs.existsSync(flxPath); const kb = (hasJs ? (Fs.statSync(jsPath).size / 1024).toFixed(1) : "?"); const sym = (hasJs ? _h("✓") : _k("○")); console.log(((((" " + sym) + " ") + (_bc + ".flux").padEnd(26)) + (hasJs ? _g((kb + " KB")) : _k("not built")))); } console.log(); } function _ag(_as) { if (_d) { console.log(("flux-lang v" + _a)); return; } console.log((_j(_f("⚡ Flux Lang")) + _g(((((" v" + _a) + " [") + _b) + "]")))); } function _ah() { const { positional, opts: _as } = _o(process.argv); const cmd = (positional[0] ?? "help"); if (cmd === "compile") { return _t(positional[1], _as); } else if (cmd === "run") { return _u(positional[1], _as); } else if (cmd === "check") { return _w(positional.slice(1), _as); } else if (cmd === "fmt") { return _x(positional.slice(1), _as); } else if (cmd === "format") { return _x(positional.slice(1), _as); } else if (cmd === "lint") { return _y(positional.slice(1), _as); } else if (cmd === "bundle") { return _z(positional[1], _as); } else if (cmd === "watch") { return _aa(positional[1], _as); } else if (cmd === "tokens") { return _ab(positional[1], _as); } else if (cmd === "ast") { return _ac(positional[1], _as); } else if (cmd === "repl") { return _ad(_as); } else if (cmd === "init") { return _ae(positional[1], _as); } else if (cmd === "add") { return cmdAdd(positional.slice(1), _as); } else if (cmd === "remove") { return cmdRemove(positional.slice(1), _as); } else if (cmd === "rm") { return cmdRemove(positional.slice(1), _as); } else if (cmd === "install") { return cmdInstall(_as); } else if (cmd === "i") { return cmdInstall(_as); } else if (cmd === "list") { return cmdList(_as); } else if (cmd === "ls") { return cmdList(_as); } else if (cmd === "search") { return cmdSearch(positional[1], _as); } else if (cmd === "info") { return cmdInfo(positional[1], _as); } else if (cmd === "publish") { return cmdPublish(_as); } else if (cmd === "self-hosted") { return _af(positional[1], _as); } else if (cmd === "version") { return _ag(_as); } else if (cmd === "-v") { return _ag(_as); } else if (cmd === "--version") { return _ag(_as); } else if (cmd === "help") { return _n(); } else if (cmd === "--help") { return _n(); } else if (cmd === "-h") { return _n(); } else { console.error(_i(("✗ Unknown command: " + cmd))); console.error(_g(" Run: flux help")); process.exit(1); } } _ah();
@@ -3,9 +3,19 @@
3
3
  function map(arr, fn) { return arr.map(fn); }
4
4
 
5
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(); }
6
16
  // ── end stdlib ──
7
17
 
8
- // Generated by Flux Transpiler v3.1.0
18
+ // Generated by Flux Transpiler v3.2.0
9
19
  "use strict";
10
20
 
11
21
  const { Lexer, lexerize, T } = require("./lexer");
@@ -0,0 +1,112 @@
1
+ // ============================================================
2
+ // Flux Self-Hosted Config Reader
3
+ // src/self/config.flux — written in Flux, compiled by stage-0
4
+ //
5
+ // Reads flux.json project config and merges with CLI flags.
6
+ // Config file locations (searched in order):
7
+ // ./flux.json
8
+ // ./flux.config.js
9
+ // ============================================================
10
+
11
+ import Fs from "fs"
12
+ import Path from "path"
13
+
14
+ // ── Default config ────────────────────────────────────────────
15
+ export val DEFAULT_CONFIG = {
16
+ entry: "src/main.flux",
17
+ outDir: "dist",
18
+ sourcemap: false,
19
+ mangle: false,
20
+ jsx: false,
21
+ jsxTarget: "browser",
22
+ typecheck: true,
23
+ strict: false,
24
+ watch: false,
25
+ ignore: [],
26
+ selfHosted: false,
27
+ registry: "https://registry.flux-lang.dev",
28
+ pkg: {
29
+ name: "",
30
+ version: "1.0.0",
31
+ description: "",
32
+ author: "",
33
+ license: "MIT",
34
+ deps: {},
35
+ devDeps: {},
36
+ }
37
+ }
38
+
39
+ // ── Load flux.json ────────────────────────────────────────────
40
+ export fn loadConfig(cwd_):
41
+ val cwd = cwd_ ?? process.cwd()
42
+
43
+ // Try flux.json first
44
+ val jsonPath = Path.join(cwd, "flux.json")
45
+ if Fs.existsSync(jsonPath):
46
+ try:
47
+ val raw = Fs.readFileSync(jsonPath, "utf8")
48
+ val parsed = JSON.parse(raw)
49
+ return mergeConfig(DEFAULT_CONFIG, parsed)
50
+ catch(e):
51
+ throw new Error("Invalid flux.json: " + e.message)
52
+
53
+ // Try flux.config.js
54
+ val jsPath = Path.join(cwd, "flux.config.js")
55
+ if Fs.existsSync(jsPath):
56
+ try:
57
+ val loaded = require(jsPath)
58
+ return mergeConfig(DEFAULT_CONFIG, loaded)
59
+ catch(e2):
60
+ throw new Error("Invalid flux.config.js: " + e2.message)
61
+
62
+ return { ...DEFAULT_CONFIG }
63
+
64
+ // ── Deep merge config objects ─────────────────────────────────
65
+ export fn mergeConfig(base, overrides):
66
+ if not overrides: return { ...base }
67
+ val result = { ...base }
68
+ for key in Object.keys(overrides):
69
+ val val_ = overrides[key]
70
+ if val_ != null and val_ != undefined:
71
+ result[key] = val_
72
+ return result
73
+
74
+ // ── Write flux.json ───────────────────────────────────────────
75
+ export fn writeConfig(config, cwd_):
76
+ val cwd = cwd_ ?? process.cwd()
77
+ val jsonPath = Path.join(cwd, "flux.json")
78
+ val content = JSON.stringify(config, null, 2) + "\n"
79
+ Fs.writeFileSync(jsonPath, content, "utf8")
80
+
81
+ // ── Validate config ───────────────────────────────────────────
82
+ export fn validateConfig(config):
83
+ val errors = []
84
+
85
+ if config.entry and not config.entry.endsWith(".flux"):
86
+ errors.push("entry must be a .flux file")
87
+
88
+ if config.jsxTarget and not ["browser", "server", "react"].includes(config.jsxTarget):
89
+ errors.push("jsxTarget must be 'browser', 'server', or 'react'")
90
+
91
+ return {
92
+ valid: errors.length == 0,
93
+ errors: errors,
94
+ }
95
+
96
+ // ── Read flux.json package info ───────────────────────────────
97
+ export fn readPackage(cwd_):
98
+ val cwd = cwd_ ?? process.cwd()
99
+ val fluxJson = Path.join(cwd, "flux.json")
100
+ val pkgJson = Path.join(cwd, "package.json")
101
+
102
+ if Fs.existsSync(fluxJson):
103
+ try:
104
+ return JSON.parse(Fs.readFileSync(fluxJson, "utf8"))
105
+ catch(e): return null
106
+
107
+ if Fs.existsSync(pkgJson):
108
+ try:
109
+ return JSON.parse(Fs.readFileSync(pkgJson, "utf8"))
110
+ catch(e2): return null
111
+
112
+ return null
@@ -0,0 +1,99 @@
1
+ // ── Flux stdlib ──
2
+
3
+ function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
4
+
5
+ function includes(arr, val) { return arr.includes(val); }
6
+
7
+ function keys(obj) { return Object.keys(obj); }
8
+
9
+ function endsWith(s, suffix) { return String(s).endsWith(suffix); }
10
+ // ── end stdlib ──
11
+
12
+ // Generated by Flux Transpiler v3.2.0
13
+ "use strict";
14
+
15
+ const Fs = require("fs");
16
+ const Path = require("path");
17
+ const DEFAULT_CONFIG = { entry: "src/main.flux", outDir: "dist", sourcemap: false, mangle: false, jsx: false, jsxTarget: "browser", typecheck: true, strict: false, watch: false, ignore: [], selfHosted: false, registry: "https://registry.flux-lang.dev", pkg: { name: "", version: "1.0.0", description: "", author: "", license: "MIT", deps: { }, devDeps: { } } };
18
+ module.exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
19
+ function loadConfig(cwd_) {
20
+ const cwd = (cwd_ ?? process.cwd());
21
+ const jsonPath = Path.join(cwd, "flux.json");
22
+ if (Fs.existsSync(jsonPath)) {
23
+ try {
24
+ const raw = Fs.readFileSync(jsonPath, "utf8");
25
+ const parsed = JSON.parse(raw);
26
+ return mergeConfig(DEFAULT_CONFIG, parsed);
27
+ }
28
+ catch (e) {
29
+ throw new Error(("Invalid flux.json: " + e.message));
30
+ }
31
+ }
32
+ const jsPath = Path.join(cwd, "flux.config.js");
33
+ if (Fs.existsSync(jsPath)) {
34
+ try {
35
+ const loaded = require(jsPath);
36
+ return mergeConfig(DEFAULT_CONFIG, loaded);
37
+ }
38
+ catch (e2) {
39
+ throw new Error(("Invalid flux.config.js: " + e2.message));
40
+ }
41
+ }
42
+ return { ...DEFAULT_CONFIG };
43
+ }
44
+ module.exports.loadConfig = loadConfig;
45
+ function mergeConfig(base, overrides) {
46
+ if (!overrides) {
47
+ return { ...base };
48
+ }
49
+ const result = { ...base };
50
+ for (const key of Object.keys(overrides)) {
51
+ const val_ = overrides[key];
52
+ if (((val_ != null) && (val_ != undefined))) {
53
+ result[key] = val_;
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ module.exports.mergeConfig = mergeConfig;
59
+ function writeConfig(config, cwd_) {
60
+ const cwd = (cwd_ ?? process.cwd());
61
+ const jsonPath = Path.join(cwd, "flux.json");
62
+ const content = (JSON.stringify(config, null, 2) + "\n");
63
+ Fs.writeFileSync(jsonPath, content, "utf8");
64
+ }
65
+ module.exports.writeConfig = writeConfig;
66
+ function validateConfig(config) {
67
+ const errors = [];
68
+ if ((config.entry && !config.entry.endsWith(".flux"))) {
69
+ errors.push("entry must be a .flux file");
70
+ }
71
+ if ((config.jsxTarget && !["browser", "server", "react"].includes(config.jsxTarget))) {
72
+ errors.push("jsxTarget must be 'browser', 'server', or 'react'");
73
+ }
74
+ return { valid: (errors.length == 0), errors };
75
+ }
76
+ module.exports.validateConfig = validateConfig;
77
+ function readPackage(cwd_) {
78
+ const cwd = (cwd_ ?? process.cwd());
79
+ const fluxJson = Path.join(cwd, "flux.json");
80
+ const pkgJson = Path.join(cwd, "package.json");
81
+ if (Fs.existsSync(fluxJson)) {
82
+ try {
83
+ return JSON.parse(Fs.readFileSync(fluxJson, "utf8"));
84
+ }
85
+ catch (e) {
86
+ return null;
87
+ }
88
+ }
89
+ if (Fs.existsSync(pkgJson)) {
90
+ try {
91
+ return JSON.parse(Fs.readFileSync(pkgJson, "utf8"));
92
+ }
93
+ catch (e2) {
94
+ return null;
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+ module.exports.readPackage = readPackage;
@@ -1,9 +1,15 @@
1
1
  // ── Flux stdlib ──
2
2
 
3
3
  function includes(arr, val) { return arr.includes(val); }
4
+
5
+ function trim(s) { return String(s).trim(); }
6
+
7
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }
8
+
9
+ function repeat(s, n) { return String(s).repeat(n); }
4
10
  // ── end stdlib ──
5
11
 
6
- // Generated by Flux Transpiler v3.1.0
12
+ // Generated by Flux Transpiler v3.2.0
7
13
  "use strict";
8
14
 
9
15
  const CSS_PROP_MAP = { bg: "background", fg: "color", p: "padding", px: "padding-inline", py: "padding-block", pt: "padding-top", pb: "padding-bottom", pl: "padding-left", pr: "padding-right", m: "margin", mx: "margin-inline", my: "margin-block", mt: "margin-top", mb: "margin-bottom", ml: "margin-left", mr: "margin-right", radius: "border-radius", w: "width", h: "height", "min-w": "min-width", "max-w": "max-width", "min-h": "min-height", "max-h": "max-height", gap: "gap", "col-gap": "column-gap", "row-gap": "row-gap", text: "font-size", font: "font-family", weight: "font-weight", tracking: "letter-spacing", leading: "line-height", shadow: "box-shadow", opacity: "opacity", border: "border", outline: "outline", transition: "transition", cursor: "cursor", overflow: "overflow", "overflow-x": "overflow-x", "overflow-y": "overflow-y", z: "z-index", transform: "transform", content: "content", resize: "resize", appearance: "appearance", "object-fit": "object-fit", "accent-color": "accent-color", direction: "flex-direction", wrap: "flex-wrap", align: "align-items", justify: "justify-content", "align-self": "align-self", "justify-self": "justify-self", grow: "flex-grow", shrink: "flex-shrink", basis: "flex-basis", order: "order", cols: "grid-template-columns", rows: "grid-template-rows", "col-span": "grid-column", "row-span": "grid-row", "place-items": "place-items", "place-content": "place-content", "list-style": "list-style", "text-align": "text-align", decoration: "text-decoration", "text-transform": "text-transform", "white-space": "white-space", "word-break": "word-break", "user-select": "user-select", "pointer-events": "pointer-events", "vertical-align": "vertical-align", backdrop: "backdrop-filter", filter: "filter", clip: "clip-path", animation: "animation", position: "position", top: "top", right: "right", bottom: "bottom", left: "left", inset: "inset", color: "color", background: "background" };
@@ -3,9 +3,28 @@
3
3
  function map(arr, fn) { return arr.map(fn); }
4
4
 
5
5
  function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
6
+
7
+ function max(arr) {
8
+ if (arguments.length > 1) return Math.max.apply(null, arguments);
9
+ return Math.max.apply(null, arr);
10
+ }
11
+
12
+ function round(n, decimals) {
13
+ if (decimals == null) return Math.round(n);
14
+ var f = Math.pow(10, decimals);
15
+ return Math.round(n * f) / f;
16
+ }
17
+
18
+ function trimStart(s) { return String(s).trimStart(); }
19
+
20
+ function trimEnd(s) { return String(s).trimEnd(); }
21
+
22
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }
23
+
24
+ function repeat(s, n) { return String(s).repeat(n); }
6
25
  // ── end stdlib ──
7
26
 
8
- // Generated by Flux Transpiler v3.1.0
27
+ // Generated by Flux Transpiler v3.2.0
9
28
  "use strict";
10
29
 
11
30
  function normalizeOperators(line) {
package/src/self/jsx.js CHANGED
@@ -20,6 +20,12 @@ function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
20
20
  function flat(arr, depth) { return arr.flat(depth != null ? depth : 1); }
21
21
 
22
22
  function includes(arr, val) { return arr.includes(val); }
23
+
24
+ function entries(obj) { return Object.entries(obj); }
25
+
26
+ function trim(s) { return String(s).trim(); }
27
+
28
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }
23
29
  // ── end stdlib ──
24
30
 
25
31
 
package/src/self/lexer.js CHANGED
@@ -5,9 +5,13 @@ function map(arr, fn) { return arr.map(fn); }
5
5
  function some(arr, fn) { return arr.some(fn); }
6
6
 
7
7
  function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
8
+
9
+ function trim(s) { return String(s).trim(); }
10
+
11
+ function trimEnd(s) { return String(s).trimEnd(); }
8
12
  // ── end stdlib ──
9
13
 
10
- // Generated by Flux Transpiler v3.1.0
14
+ // Generated by Flux Transpiler v3.2.0
11
15
  "use strict";
12
16
 
13
17
  const T = { NUMBER: "NUMBER", STRING: "STRING", BOOL: "BOOL", NULL: "NULL", IDENT: "IDENT", VAR: "VAR", VAL: "VAL", FN: "FN", RETURN: "RETURN", IF: "IF", ELSE: "ELSE", FOR: "FOR", IN: "IN", WHILE: "WHILE", BREAK: "BREAK", CONTINUE: "CONTINUE", DO: "DO", CLASS: "CLASS", EXTENDS: "EXTENDS", SELF: "SELF", NEW: "NEW", INTERFACE: "INTERFACE", IMPLEMENTS: "IMPLEMENTS", PRIVATE: "PRIVATE", PUBLIC: "PUBLIC", PROTECTED: "PROTECTED", READONLY: "READONLY", STATIC: "STATIC", ABSTRACT: "ABSTRACT", OVERRIDE: "OVERRIDE", MATCH: "MATCH", WHEN: "WHEN", IMPORT: "IMPORT", EXPORT: "EXPORT", FROM: "FROM", AS: "AS", DEFAULT: "DEFAULT", AND: "AND", OR: "OR", NOT: "NOT", ASYNC: "ASYNC", AWAIT: "AWAIT", TRY: "TRY", CATCH: "CATCH", FINALLY: "FINALLY", THROW: "THROW", TYPEOF: "TYPEOF", INSTANCEOF: "INSTANCEOF", TYPE: "TYPE", ENUM: "ENUM", SATISFIES: "SATISFIES", IS: "IS", CONST: "CONST", PLUS: "PLUS", MINUS: "MINUS", STAR: "STAR", SLASH: "SLASH", PERCENT: "PERCENT", REGEX: "REGEX", STARSTAR: "STARSTAR", EQ: "EQ", EQEQ: "EQEQ", NEQ: "NEQ", EQEQEQ: "EQEQEQ", NEQEQ: "NEQEQ", LT: "LT", LTE: "LTE", GT: "GT", GTE: "GTE", PLUSEQ: "PLUSEQ", MINUSEQ: "MINUSEQ", STAREQ: "STAREQ", SLASHEQ: "SLASHEQ", PERCENTEQ: "PERCENTEQ", PLUSPLUS: "PLUSPLUS", MINUSMINUS: "MINUSMINUS", AMPERSAND: "AMPERSAND", ANDAND: "ANDAND", PIPEB: "PIPEB", OROR: "OROR", CARET: "CARET", TILDE: "TILDE", LSHIFT: "LSHIFT", RSHIFT: "RSHIFT", ARROW: "ARROW", FATARROW: "FATARROW", PIPE: "PIPE", DOTDOT: "DOTDOT", DOTDOTDOT: "DOTDOTDOT", WILDCARD: "WILDCARD", NULLISH: "NULLISH", QUESTIONDOT: "QUESTIONDOT", BANG: "BANG", AT: "AT", LPAREN: "LPAREN", RPAREN: "RPAREN", LBRACKET: "LBRACKET", RBRACKET: "RBRACKET", LBRACE: "LBRACE", RBRACE: "RBRACE", COMMA: "COMMA", DOT: "DOT", COLON: "COLON", QUESTION: "QUESTION", NEWLINE: "NEWLINE", INDENT: "INDENT", DEDENT: "DEDENT", EOF: "EOF" };
@@ -1,9 +1,13 @@
1
1
  // ── Flux stdlib ──
2
2
 
3
3
  function sort(arr, fn) { return arr.slice().sort(fn); }
4
+
5
+ function values(obj) { return Object.values(obj); }
6
+
7
+ function startsWith(s, prefix) { return String(s).startsWith(prefix); }
4
8
  // ── end stdlib ──
5
9
 
6
- // Generated by Flux Transpiler v3.1.0
10
+ // Generated by Flux Transpiler v3.2.0
7
11
  "use strict";
8
12
 
9
13
  const { lexerize } = require("./lexer");
@@ -15,6 +15,8 @@ function map(arr, fn) { return arr.map(fn); }
15
15
 
16
16
  function forEach(arr, fn) { arr.forEach(fn); return arr; }
17
17
 
18
+ function floor(n) { return Math.floor(n); }
19
+
18
20
  function fromEntries(entries) {
19
21
  return Object.fromEntries(entries);
20
22
  }
@@ -5,7 +5,7 @@ function map(arr, fn) { return arr.map(fn); }
5
5
  function join(arr, sep) { return arr.join(sep != null ? sep : ','); }
6
6
  // ── end stdlib ──
7
7
 
8
- // Generated by Flux Transpiler v3.1.0
8
+ // Generated by Flux Transpiler v3.2.0
9
9
  "use strict";
10
10
 
11
11
  const { T } = require("./lexer");