@mojir/lits 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +18 -22
  2. package/dist/bundler.esm.js +2 -0
  3. package/dist/bundler.esm.js.map +1 -0
  4. package/dist/bundler.js +2 -0
  5. package/dist/bundler.js.map +1 -0
  6. package/dist/cli/cli/src/js-interop/Cli/Fs/index.d.ts +2 -2
  7. package/dist/cli/cli/src/js-interop/Cli/Proc/index.d.ts +2 -2
  8. package/dist/cli/cli/src/js-interop/Cli/index.d.ts +2 -3
  9. package/dist/cli/cli.js +2642 -2313
  10. package/dist/cli/reference/api.d.ts +3 -3
  11. package/dist/cli/reference/examples.d.ts +2 -2
  12. package/dist/cli/reference/index.d.ts +0 -1
  13. package/dist/cli/src/Lits/Lits.d.ts +6 -7
  14. package/dist/cli/src/builtin/index.d.ts +1 -1
  15. package/dist/cli/src/builtin/specialExpressionTypes.d.ts +15 -15
  16. package/dist/cli/src/builtin/specialExpressions/import.d.ts +6 -0
  17. package/dist/cli/src/bundler/index.d.ts +9 -0
  18. package/dist/cli/src/bundler/interface.d.ts +15 -0
  19. package/dist/cli/src/bundler.d.ts +3 -0
  20. package/dist/cli/src/evaluator/ContextStack.d.ts +10 -4
  21. package/dist/cli/src/index.d.ts +2 -0
  22. package/dist/cli/src/js-interop/Cli/Fs/index.d.ts +2 -2
  23. package/dist/cli/src/js-interop/Cli/Proc/index.d.ts +2 -2
  24. package/dist/cli/src/js-interop/Cli/index.d.ts +2 -3
  25. package/dist/cli/src/parser/ParserContext.d.ts +1 -1
  26. package/dist/cli/src/parser/getPrecedence.d.ts +3 -0
  27. package/dist/cli/src/parser/index.d.ts +2 -0
  28. package/dist/cli/src/parser/subParsers/parseExpression.d.ts +5 -0
  29. package/dist/cli/src/parser/types.d.ts +0 -3
  30. package/dist/cli/src/tokenizer/reservedNames.d.ts +0 -1
  31. package/dist/full.esm.js +1 -1
  32. package/dist/full.esm.js.map +1 -1
  33. package/dist/full.js +1 -1
  34. package/dist/full.js.map +1 -1
  35. package/dist/index.esm.js +1 -1
  36. package/dist/index.esm.js.map +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/lits.iife.js +1 -1
  40. package/dist/lits.iife.js.map +1 -1
  41. package/dist/modules/assert.esm.js +1 -1
  42. package/dist/modules/assert.esm.js.map +1 -1
  43. package/dist/modules/assert.js +1 -1
  44. package/dist/modules/assert.js.map +1 -1
  45. package/dist/modules/bitwise.esm.js +1 -1
  46. package/dist/modules/bitwise.esm.js.map +1 -1
  47. package/dist/modules/bitwise.js +1 -1
  48. package/dist/modules/bitwise.js.map +1 -1
  49. package/dist/modules/cli/src/js-interop/Cli/Fs/index.d.ts +2 -2
  50. package/dist/modules/cli/src/js-interop/Cli/Proc/index.d.ts +2 -2
  51. package/dist/modules/cli/src/js-interop/Cli/index.d.ts +2 -3
  52. package/dist/modules/collection.esm.js +1 -1
  53. package/dist/modules/collection.esm.js.map +1 -1
  54. package/dist/modules/collection.js +1 -1
  55. package/dist/modules/collection.js.map +1 -1
  56. package/dist/modules/functional.esm.js +1 -1
  57. package/dist/modules/functional.esm.js.map +1 -1
  58. package/dist/modules/functional.js +1 -1
  59. package/dist/modules/functional.js.map +1 -1
  60. package/dist/modules/grid.esm.js +1 -1
  61. package/dist/modules/grid.esm.js.map +1 -1
  62. package/dist/modules/grid.js +1 -1
  63. package/dist/modules/grid.js.map +1 -1
  64. package/dist/modules/linear-algebra.esm.js +1 -1
  65. package/dist/modules/linear-algebra.esm.js.map +1 -1
  66. package/dist/modules/linear-algebra.js +1 -1
  67. package/dist/modules/linear-algebra.js.map +1 -1
  68. package/dist/modules/math.esm.js +1 -1
  69. package/dist/modules/math.esm.js.map +1 -1
  70. package/dist/modules/math.js +1 -1
  71. package/dist/modules/math.js.map +1 -1
  72. package/dist/modules/matrix.esm.js +1 -1
  73. package/dist/modules/matrix.esm.js.map +1 -1
  74. package/dist/modules/matrix.js +1 -1
  75. package/dist/modules/matrix.js.map +1 -1
  76. package/dist/modules/number-theory.esm.js +1 -1
  77. package/dist/modules/number-theory.esm.js.map +1 -1
  78. package/dist/modules/number-theory.js +1 -1
  79. package/dist/modules/number-theory.js.map +1 -1
  80. package/dist/modules/random.esm.js +1 -1
  81. package/dist/modules/random.esm.js.map +1 -1
  82. package/dist/modules/random.js +1 -1
  83. package/dist/modules/random.js.map +1 -1
  84. package/dist/modules/reference/api.d.ts +3 -3
  85. package/dist/modules/reference/index.d.ts +0 -1
  86. package/dist/modules/sequence.esm.js +1 -1
  87. package/dist/modules/sequence.esm.js.map +1 -1
  88. package/dist/modules/sequence.js +1 -1
  89. package/dist/modules/sequence.js.map +1 -1
  90. package/dist/modules/src/Lits/Lits.d.ts +6 -7
  91. package/dist/modules/src/builtin/index.d.ts +1 -1
  92. package/dist/modules/src/builtin/specialExpressionTypes.d.ts +15 -15
  93. package/dist/modules/src/builtin/specialExpressions/import.d.ts +6 -0
  94. package/dist/modules/src/bundler/index.d.ts +9 -0
  95. package/dist/modules/src/bundler/interface.d.ts +15 -0
  96. package/dist/modules/src/bundler.d.ts +3 -0
  97. package/dist/modules/src/evaluator/ContextStack.d.ts +10 -4
  98. package/dist/modules/src/index.d.ts +2 -0
  99. package/dist/modules/src/parser/ParserContext.d.ts +1 -1
  100. package/dist/modules/src/parser/getPrecedence.d.ts +3 -0
  101. package/dist/modules/src/parser/index.d.ts +2 -0
  102. package/dist/modules/src/parser/subParsers/parseExpression.d.ts +5 -0
  103. package/dist/modules/src/parser/types.d.ts +0 -3
  104. package/dist/modules/src/tokenizer/reservedNames.d.ts +0 -1
  105. package/dist/modules/string.esm.js +1 -1
  106. package/dist/modules/string.esm.js.map +1 -1
  107. package/dist/modules/string.js +1 -1
  108. package/dist/modules/string.js.map +1 -1
  109. package/dist/modules/vector.esm.js +1 -1
  110. package/dist/modules/vector.esm.js.map +1 -1
  111. package/dist/modules/vector.js +1 -1
  112. package/dist/modules/vector.js.map +1 -1
  113. package/dist/reference/api.d.ts +3 -3
  114. package/dist/reference/index.d.ts +0 -1
  115. package/dist/src/Lits/Lits.d.ts +6 -7
  116. package/dist/src/builtin/index.d.ts +1 -1
  117. package/dist/src/builtin/specialExpressionTypes.d.ts +15 -15
  118. package/dist/src/builtin/specialExpressions/import.d.ts +6 -0
  119. package/dist/src/bundler/index.d.ts +9 -0
  120. package/dist/src/bundler/interface.d.ts +15 -0
  121. package/dist/src/bundler.d.ts +3 -0
  122. package/dist/src/evaluator/ContextStack.d.ts +10 -4
  123. package/dist/src/index.d.ts +2 -0
  124. package/dist/src/parser/ParserContext.d.ts +1 -1
  125. package/dist/src/parser/getPrecedence.d.ts +3 -0
  126. package/dist/src/parser/index.d.ts +2 -0
  127. package/dist/src/parser/subParsers/parseExpression.d.ts +5 -0
  128. package/dist/src/parser/types.d.ts +0 -3
  129. package/dist/src/tokenizer/reservedNames.d.ts +0 -1
  130. package/dist/testFramework.esm.js +1 -1
  131. package/dist/testFramework.esm.js.map +1 -1
  132. package/dist/testFramework.js +1 -1
  133. package/dist/testFramework.js.map +1 -1
  134. package/package.json +6 -1
  135. package/dist/cli/cli/src/js-interop/utils.d.ts +0 -2
  136. package/dist/cli/src/builtin/specialExpressions/def.d.ts +0 -6
  137. package/dist/cli/src/js-interop/utils.d.ts +0 -2
  138. package/dist/cli/src/parser/subParsers/getPrecedence.d.ts +0 -3
  139. package/dist/modules/cli/src/js-interop/utils.d.ts +0 -2
  140. package/dist/modules/src/builtin/specialExpressions/def.d.ts +0 -6
  141. package/dist/modules/src/parser/subParsers/getPrecedence.d.ts +0 -3
  142. package/dist/src/builtin/specialExpressions/def.d.ts +0 -6
  143. package/dist/src/parser/subParsers/getPrecedence.d.ts +0 -3
package/README.md CHANGED
@@ -164,8 +164,8 @@ A vector is simply a non-empty array containing only numbers. The `vec` module p
164
164
 
165
165
  ```lits
166
166
  // Import vector and linear algebra modules
167
- let vec = import("vector");
168
- let lin = import("linear-algebra");
167
+ let vec = import(vector);
168
+ let lin = import(linear-algebra);
169
169
 
170
170
  // Vectors are just number arrays
171
171
  [1, 2, 3, 4, 5]; // This is a vector
@@ -218,7 +218,7 @@ A matrix is a 2D array where each row is a vector (non-empty array of numbers) a
218
218
 
219
219
  ```lits
220
220
  // Import matrix module
221
- let mat = import("matrix");
221
+ let mat = import(matrix);
222
222
 
223
223
  // Matrices are 2D number arrays with consistent row lengths
224
224
  [[1, 2], [3, 4]]; // This is a 2x2 matrix
@@ -1302,7 +1302,7 @@ Here's the complete precedence table, from highest to lowest:
1302
1302
  3 > 2 && 1 < 2; // => true && true = true
1303
1303
 
1304
1304
  // Pipe has very low precedence
1305
- let vec = import("vector");
1305
+ let vec = import(vector);
1306
1306
  [1, 2, 3] |> map(_, inc) |> vec.sum; // Evaluates left to right
1307
1307
 
1308
1308
  // Conditional has lowest precedence
@@ -1383,13 +1383,15 @@ let config = {
1383
1383
  // back into working Lits values, preserving their functionality
1384
1384
  ```
1385
1385
 
1386
- ## Modules and Exports
1386
+ ## File Value
1387
+
1388
+ A Lits file evaluates to the value of its last expression:
1387
1389
 
1388
1390
  ```lits
1389
- // Export variables and functions
1390
- export let pi = 3.14159;
1391
- export let square = x -> x * x;
1392
- // Exported values become available to other modules
1391
+ let pi = 3.14159;
1392
+ let square = x -> x * x;
1393
+ // The file's value is the result of the last expression
1394
+ {pi: pi, square: square}
1393
1395
  ```
1394
1396
 
1395
1397
  ## Examples
@@ -1442,7 +1444,7 @@ let longWords = text
1442
1444
  ### Data Transformation
1443
1445
 
1444
1446
  ```lits
1445
- let su = import("sequence");
1447
+ let su = import(sequence);
1446
1448
  let users = [
1447
1449
  { name: "Alice", age: 30, department: "Engineering" },
1448
1450
  { name: "Bob", age: 25, department: "Marketing" },
@@ -1496,8 +1498,8 @@ import { matrixModule } from '@mojir/lits/modules/matrix';
1496
1498
 
1497
1499
  const lits = new Lits({ modules: [vectorModule, matrixModule] });
1498
1500
 
1499
- // Now you can use import("vector") and import("matrix") in Lits code
1500
- lits.run('let v = import("vector"); v.dot([1, 2, 3], [4, 5, 6])'); // => 32
1501
+ // Now you can use import(vector) and import(matrix) in Lits code
1502
+ lits.run('let v = import(vector); v.dot([1, 2, 3], [4, 5, 6])'); // => 32
1501
1503
  ```
1502
1504
 
1503
1505
  ### Using Lits in JavaScript
@@ -1527,10 +1529,8 @@ const result3 = lits.run('myAlert("Hello from Lits!")', {
1527
1529
  }
1528
1530
  });
1529
1531
 
1530
- // Parse and evaluate separately for better performance
1531
- const tokens = lits.tokenize('+(5, 3)');
1532
- const ast = lits.parse(tokens);
1533
- const result4 = lits.evaluate(ast, {});
1532
+ // Execute Lits code
1533
+ const result4 = lits.run('+(5, 3)');
1534
1534
  ```
1535
1535
 
1536
1536
  ### Lits Class Methods
@@ -1538,10 +1538,7 @@ const result4 = lits.evaluate(ast, {});
1538
1538
  ```typescript
1539
1539
  interface Lits {
1540
1540
  // Execute Lits code directly
1541
- run(program: string, params?: ContextParams & FilePathParams): unknown
1542
-
1543
- // Get execution context after running code
1544
- context(programOrAst: string | Ast, params?: ContextParams & FilePathParams): Context
1541
+ run(programOrBundle: string | LitsBundle, params?: ContextParams & FilePathParams): unknown
1545
1542
 
1546
1543
  // Find undefined symbols in code
1547
1544
  getUndefinedSymbols(programOrAst: string | Ast, params?: ContextParams): Set<string>
@@ -1549,7 +1546,6 @@ interface Lits {
1549
1546
  // Parse pipeline
1550
1547
  tokenize(program: string, params?: FilePathParams & MinifyParams): TokenStream
1551
1548
  parse(tokenStream: TokenStream): Ast
1552
- evaluate(ast: Ast, params: ContextParams): unknown
1553
1549
 
1554
1550
  // Apply Lits function with JavaScript arguments
1555
1551
  apply(fn: LitsFunction, fnParams: unknown[], params?: ContextParams): unknown
@@ -1569,7 +1565,7 @@ interface ContextParams {
1569
1565
  contexts?: Context[] // Additional context layers
1570
1566
  values?: Record<string, unknown> // JavaScript values to expose
1571
1567
  jsFunctions?: Record<string, JsFunction> // JavaScript functions to expose
1572
- globalModuleScope?: boolean // Module scoping behavior
1568
+ globalModuleScope?: boolean // Make top-level let bindings persist in global context
1573
1569
  }
1574
1570
 
1575
1571
  interface JsFunction {
@@ -0,0 +1,2 @@
1
+ import e from"node:fs";import t from"node:path";const n=new Set(["assert","grid","random","vector","linear-algebra","matrix","number-theory","math","functional","string","collection","sequence","bitwise"]),r=/import\(\s*"([^"]+)"\s*\)|import\(\s*'([^']+)'\s*\)/g;function o(o){const i=t.resolve(o),s=t.dirname(i),c=new Map,a=new Map,f=new Map;!function n(o,i){if(i.includes(o)){const e=[...i.slice(i.indexOf(o)),o];throw new Error(`Circular dependency detected: ${e.join(" → ")}`)}if(c.has(o))return;if(!e.existsSync(o))throw new Error(`File not found: ${o}`);const s=e.readFileSync(o,"utf-8");c.set(o,s);const a=new Set;f.set(o,a);const u=t.dirname(o);for(const e of s.matchAll(r)){const r=e[1]??e[2],s=t.resolve(u,r);a.add(s),n(s,[...i,o])}}(i,[]),function(e){const t=new Set;for(const r of c.keys()){if(r===i)continue;let o=l(r,e);for(;n.has(o)||t.has(o);)o=`_${o}`;t.add(o),a.set(r,o)}}(s);const u=function(e){const t=[],n=new Set,r=new Set;return function o(i){if(n.has(i))return;if(r.has(i))throw new Error(`Circular dependency detected during topological sort: ${i}`);r.add(i);const s=f.get(i);if(s)for(const e of s)o(e);r.delete(i),n.add(i),i!==e&&t.push(i)}(e),t}(i).map(e=>{const t=p(c.get(e),e);return[a.get(e),t]});return{program:p(c.get(i),i),fileModules:u};function l(e,n){const r=t.relative(n,e);if(!r.startsWith(".."))return d(r);return d(e.split(t.sep).slice(-2).join("/"))}function d(e){return e.endsWith(".lits")?e.slice(0,-5):e}function p(e,n){const o=t.dirname(n);return e.replace(r,(e,n,r)=>{const i=n??r,s=t.resolve(o,i),c=a.get(s);if(!c)throw new Error(`No canonical name for: ${s}`);return`import(${c})`})}}function i(e){return"object"==typeof e&&null!==e&&"string"==typeof e.program&&Array.isArray(e.fileModules)}export{o as bundle,i as isLitsBundle};
2
+ //# sourceMappingURL=bundler.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler.esm.js","sources":["../src/bundler/index.ts","../src/bundler/interface.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { LitsBundle } from './interface'\n\nconst builtinModuleNames = new Set([\n 'assert',\n 'grid',\n 'random',\n 'vector',\n 'linear-algebra',\n 'matrix',\n 'number-theory',\n 'math',\n 'functional',\n 'string',\n 'collection',\n 'sequence',\n 'bitwise',\n])\n\n/**\n * Regex to match `import(\"...\")` or `import('...')` calls in Lits source.\n * Captures the file path inside the quotes.\n */\nconst fileImportPattern = /import\\(\\s*\"([^\"]+)\"\\s*\\)|import\\(\\s*'([^']+)'\\s*\\)/g\n\n/**\n * Bundles a Lits entry file and all its file imports into a LitsBundle.\n *\n * Resolves all `import(\"./path/to/file.lits\")` calls recursively,\n * deduplicates, detects circular dependencies, topologically sorts,\n * and rewrites file imports to bare symbol imports.\n */\nexport function bundle(entryPath: string): LitsBundle {\n const absoluteEntryPath = path.resolve(entryPath)\n const entryDir = path.dirname(absoluteEntryPath)\n\n // Map from absolute file path → source code\n const fileSources = new Map<string, string>()\n // Map from absolute file path → canonical module name\n const canonicalNames = new Map<string, string>()\n // Adjacency list: file → set of files it imports\n const dependencies = new Map<string, Set<string>>()\n\n // Phase 1: Resolve all file imports recursively\n resolveFile(absoluteEntryPath, [])\n\n // Phase 2: Build canonical names\n buildCanonicalNames(entryDir)\n\n // Phase 3: Topological sort (exclude entry file — it becomes the program)\n const sorted = topologicalSort(absoluteEntryPath)\n\n // Phase 4: Rewrite imports and build bundle\n const fileModules: [string, string][] = sorted.map((filePath) => {\n const source = fileSources.get(filePath)!\n const rewritten = rewriteImports(source, filePath)\n return [canonicalNames.get(filePath)!, rewritten]\n })\n\n const entrySource = fileSources.get(absoluteEntryPath)!\n const program = rewriteImports(entrySource, absoluteEntryPath)\n\n return { program, fileModules }\n\n // --- Helper functions (closures over the maps above) ---\n\n function resolveFile(absoluteFilePath: string, stack: string[]): void {\n // Circular dependency detection\n if (stack.includes(absoluteFilePath)) {\n const cycle = [...stack.slice(stack.indexOf(absoluteFilePath)), absoluteFilePath]\n throw new Error(`Circular dependency detected: ${cycle.join(' → ')}`)\n }\n\n // Already resolved (deduplication)\n if (fileSources.has(absoluteFilePath)) {\n return\n }\n\n if (!fs.existsSync(absoluteFilePath)) {\n throw new Error(`File not found: ${absoluteFilePath}`)\n }\n\n const source = fs.readFileSync(absoluteFilePath, 'utf-8')\n fileSources.set(absoluteFilePath, source)\n\n const deps = new Set<string>()\n dependencies.set(absoluteFilePath, deps)\n\n const dir = path.dirname(absoluteFilePath)\n\n for (const match of source.matchAll(fileImportPattern)) {\n const importPath = (match[1] ?? match[2])!\n const resolvedPath = path.resolve(dir, importPath)\n\n deps.add(resolvedPath)\n resolveFile(resolvedPath, [...stack, absoluteFilePath])\n }\n }\n\n function buildCanonicalNames(entryDirectory: string): void {\n const usedNames = new Set<string>()\n\n for (const absoluteFilePath of fileSources.keys()) {\n // Skip the entry file — it doesn't need a canonical name\n if (absoluteFilePath === absoluteEntryPath) {\n continue\n }\n\n let name = deriveCanonicalName(absoluteFilePath, entryDirectory)\n\n // Resolve collisions with builtin modules\n while (builtinModuleNames.has(name) || usedNames.has(name)) {\n name = `_${name}`\n }\n\n usedNames.add(name)\n canonicalNames.set(absoluteFilePath, name)\n }\n }\n\n function deriveCanonicalName(absoluteFilePath: string, entryDirectory: string): string {\n const relativePath = path.relative(entryDirectory, absoluteFilePath)\n\n // If the file is under the entry directory (no leading ..)\n if (!relativePath.startsWith('..')) {\n // Strip .lits extension\n return stripExtension(relativePath)\n }\n\n // File is outside the entry directory — use last N path segments\n const segments = absoluteFilePath.split(path.sep)\n // Use last 2 segments (directory + filename) for readability\n const fallback = segments.slice(-2).join('/')\n return stripExtension(fallback)\n }\n\n function stripExtension(filePath: string): string {\n if (filePath.endsWith('.lits')) {\n return filePath.slice(0, -5)\n }\n return filePath\n }\n\n function topologicalSort(entryFilePath: string): string[] {\n const result: string[] = []\n const visited = new Set<string>()\n const visiting = new Set<string>()\n\n function visit(filePath: string): void {\n if (visited.has(filePath)) {\n return\n }\n /* v8 ignore next 3 */\n if (visiting.has(filePath))\n throw new Error(`Circular dependency detected during topological sort: ${filePath}`)\n\n visiting.add(filePath)\n\n const deps = dependencies.get(filePath)\n if (deps) {\n for (const dep of deps) {\n visit(dep)\n }\n }\n\n visiting.delete(filePath)\n visited.add(filePath)\n\n // Don't add the entry file — it becomes the program\n if (filePath !== entryFilePath) {\n result.push(filePath)\n }\n }\n\n // Start from entry file to ensure all reachable files are visited\n visit(entryFilePath)\n\n return result\n }\n\n function rewriteImports(source: string, sourceFilePath: string): string {\n const dir = path.dirname(sourceFilePath)\n\n return source.replace(fileImportPattern, (_fullMatch, doubleQuoted: string | undefined, singleQuoted: string | undefined) => {\n const importPath = (doubleQuoted ?? singleQuoted)!\n const resolvedPath = path.resolve(dir, importPath)\n const canonicalName = canonicalNames.get(resolvedPath)\n\n /* v8 ignore next 3 */\n if (!canonicalName)\n throw new Error(`No canonical name for: ${resolvedPath}`)\n\n return `import(${canonicalName})`\n })\n }\n}\n","/**\n * A bundle produced by the bundler. Contains the main program source\n * with file imports rewritten to canonical module names, plus an ordered\n * array of file module sources keyed by canonical name.\n *\n * The bundle is pure JSON — fully serializable and portable\n * (e.g., build on a server, run in a browser).\n */\nexport interface LitsBundle {\n /** The main program source, with file imports rewritten to bare symbols. */\n program: string\n /** Ordered array of [canonicalName, source] pairs. Dependencies come before dependents. */\n fileModules: [string, string][]\n}\n\nexport function isLitsBundle(value: unknown): value is LitsBundle {\n return (\n typeof value === 'object'\n && value !== null\n && typeof (value as LitsBundle).program === 'string'\n && Array.isArray((value as LitsBundle).fileModules)\n )\n}\n"],"names":["builtinModuleNames","Set","fileImportPattern","bundle","entryPath","absoluteEntryPath","path","resolve","entryDir","dirname","fileSources","Map","canonicalNames","dependencies","resolveFile","absoluteFilePath","stack","includes","cycle","slice","indexOf","Error","join","has","fs","existsSync","source","readFileSync","set","deps","dir","match","matchAll","importPath","resolvedPath","add","entryDirectory","usedNames","keys","name","deriveCanonicalName","buildCanonicalNames","fileModules","entryFilePath","result","visited","visiting","visit","filePath","get","dep","delete","push","topologicalSort","map","rewritten","rewriteImports","program","relativePath","relative","startsWith","stripExtension","split","sep","endsWith","sourceFilePath","replace","_fullMatch","doubleQuoted","singleQuoted","canonicalName","isLitsBundle","value","Array","isArray"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("node:fs"),t=require("node:path");const n=new Set(["assert","grid","random","vector","linear-algebra","matrix","number-theory","math","functional","string","collection","sequence","bitwise"]),r=/import\(\s*"([^"]+)"\s*\)|import\(\s*'([^']+)'\s*\)/g;exports.bundle=function(o){const s=t.resolve(o),i=t.dirname(s),c=new Map,a=new Map,u=new Map;!function n(o,s){if(s.includes(o)){const e=[...s.slice(s.indexOf(o)),o];throw new Error(`Circular dependency detected: ${e.join(" → ")}`)}if(c.has(o))return;if(!e.existsSync(o))throw new Error(`File not found: ${o}`);const i=e.readFileSync(o,"utf-8");c.set(o,i);const a=new Set;u.set(o,a);const f=t.dirname(o);for(const e of i.matchAll(r)){const r=e[1]??e[2],i=t.resolve(f,r);a.add(i),n(i,[...s,o])}}(s,[]),function(e){const t=new Set;for(const r of c.keys()){if(r===s)continue;let o=l(r,e);for(;n.has(o)||t.has(o);)o=`_${o}`;t.add(o),a.set(r,o)}}(i);const f=function(e){const t=[],n=new Set,r=new Set;return function o(s){if(n.has(s))return;if(r.has(s))throw new Error(`Circular dependency detected during topological sort: ${s}`);r.add(s);const i=u.get(s);if(i)for(const e of i)o(e);r.delete(s),n.add(s),s!==e&&t.push(s)}(e),t}(s).map(e=>{const t=p(c.get(e),e);return[a.get(e),t]});return{program:p(c.get(s),s),fileModules:f};function l(e,n){const r=t.relative(n,e);if(!r.startsWith(".."))return d(r);return d(e.split(t.sep).slice(-2).join("/"))}function d(e){return e.endsWith(".lits")?e.slice(0,-5):e}function p(e,n){const o=t.dirname(n);return e.replace(r,(e,n,r)=>{const s=n??r,i=t.resolve(o,s),c=a.get(i);if(!c)throw new Error(`No canonical name for: ${i}`);return`import(${c})`})}},exports.isLitsBundle=function(e){return"object"==typeof e&&null!==e&&"string"==typeof e.program&&Array.isArray(e.fileModules)};
2
+ //# sourceMappingURL=bundler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler.js","sources":["../src/bundler/index.ts","../src/bundler/interface.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { LitsBundle } from './interface'\n\nconst builtinModuleNames = new Set([\n 'assert',\n 'grid',\n 'random',\n 'vector',\n 'linear-algebra',\n 'matrix',\n 'number-theory',\n 'math',\n 'functional',\n 'string',\n 'collection',\n 'sequence',\n 'bitwise',\n])\n\n/**\n * Regex to match `import(\"...\")` or `import('...')` calls in Lits source.\n * Captures the file path inside the quotes.\n */\nconst fileImportPattern = /import\\(\\s*\"([^\"]+)\"\\s*\\)|import\\(\\s*'([^']+)'\\s*\\)/g\n\n/**\n * Bundles a Lits entry file and all its file imports into a LitsBundle.\n *\n * Resolves all `import(\"./path/to/file.lits\")` calls recursively,\n * deduplicates, detects circular dependencies, topologically sorts,\n * and rewrites file imports to bare symbol imports.\n */\nexport function bundle(entryPath: string): LitsBundle {\n const absoluteEntryPath = path.resolve(entryPath)\n const entryDir = path.dirname(absoluteEntryPath)\n\n // Map from absolute file path → source code\n const fileSources = new Map<string, string>()\n // Map from absolute file path → canonical module name\n const canonicalNames = new Map<string, string>()\n // Adjacency list: file → set of files it imports\n const dependencies = new Map<string, Set<string>>()\n\n // Phase 1: Resolve all file imports recursively\n resolveFile(absoluteEntryPath, [])\n\n // Phase 2: Build canonical names\n buildCanonicalNames(entryDir)\n\n // Phase 3: Topological sort (exclude entry file — it becomes the program)\n const sorted = topologicalSort(absoluteEntryPath)\n\n // Phase 4: Rewrite imports and build bundle\n const fileModules: [string, string][] = sorted.map((filePath) => {\n const source = fileSources.get(filePath)!\n const rewritten = rewriteImports(source, filePath)\n return [canonicalNames.get(filePath)!, rewritten]\n })\n\n const entrySource = fileSources.get(absoluteEntryPath)!\n const program = rewriteImports(entrySource, absoluteEntryPath)\n\n return { program, fileModules }\n\n // --- Helper functions (closures over the maps above) ---\n\n function resolveFile(absoluteFilePath: string, stack: string[]): void {\n // Circular dependency detection\n if (stack.includes(absoluteFilePath)) {\n const cycle = [...stack.slice(stack.indexOf(absoluteFilePath)), absoluteFilePath]\n throw new Error(`Circular dependency detected: ${cycle.join(' → ')}`)\n }\n\n // Already resolved (deduplication)\n if (fileSources.has(absoluteFilePath)) {\n return\n }\n\n if (!fs.existsSync(absoluteFilePath)) {\n throw new Error(`File not found: ${absoluteFilePath}`)\n }\n\n const source = fs.readFileSync(absoluteFilePath, 'utf-8')\n fileSources.set(absoluteFilePath, source)\n\n const deps = new Set<string>()\n dependencies.set(absoluteFilePath, deps)\n\n const dir = path.dirname(absoluteFilePath)\n\n for (const match of source.matchAll(fileImportPattern)) {\n const importPath = (match[1] ?? match[2])!\n const resolvedPath = path.resolve(dir, importPath)\n\n deps.add(resolvedPath)\n resolveFile(resolvedPath, [...stack, absoluteFilePath])\n }\n }\n\n function buildCanonicalNames(entryDirectory: string): void {\n const usedNames = new Set<string>()\n\n for (const absoluteFilePath of fileSources.keys()) {\n // Skip the entry file — it doesn't need a canonical name\n if (absoluteFilePath === absoluteEntryPath) {\n continue\n }\n\n let name = deriveCanonicalName(absoluteFilePath, entryDirectory)\n\n // Resolve collisions with builtin modules\n while (builtinModuleNames.has(name) || usedNames.has(name)) {\n name = `_${name}`\n }\n\n usedNames.add(name)\n canonicalNames.set(absoluteFilePath, name)\n }\n }\n\n function deriveCanonicalName(absoluteFilePath: string, entryDirectory: string): string {\n const relativePath = path.relative(entryDirectory, absoluteFilePath)\n\n // If the file is under the entry directory (no leading ..)\n if (!relativePath.startsWith('..')) {\n // Strip .lits extension\n return stripExtension(relativePath)\n }\n\n // File is outside the entry directory — use last N path segments\n const segments = absoluteFilePath.split(path.sep)\n // Use last 2 segments (directory + filename) for readability\n const fallback = segments.slice(-2).join('/')\n return stripExtension(fallback)\n }\n\n function stripExtension(filePath: string): string {\n if (filePath.endsWith('.lits')) {\n return filePath.slice(0, -5)\n }\n return filePath\n }\n\n function topologicalSort(entryFilePath: string): string[] {\n const result: string[] = []\n const visited = new Set<string>()\n const visiting = new Set<string>()\n\n function visit(filePath: string): void {\n if (visited.has(filePath)) {\n return\n }\n /* v8 ignore next 3 */\n if (visiting.has(filePath))\n throw new Error(`Circular dependency detected during topological sort: ${filePath}`)\n\n visiting.add(filePath)\n\n const deps = dependencies.get(filePath)\n if (deps) {\n for (const dep of deps) {\n visit(dep)\n }\n }\n\n visiting.delete(filePath)\n visited.add(filePath)\n\n // Don't add the entry file — it becomes the program\n if (filePath !== entryFilePath) {\n result.push(filePath)\n }\n }\n\n // Start from entry file to ensure all reachable files are visited\n visit(entryFilePath)\n\n return result\n }\n\n function rewriteImports(source: string, sourceFilePath: string): string {\n const dir = path.dirname(sourceFilePath)\n\n return source.replace(fileImportPattern, (_fullMatch, doubleQuoted: string | undefined, singleQuoted: string | undefined) => {\n const importPath = (doubleQuoted ?? singleQuoted)!\n const resolvedPath = path.resolve(dir, importPath)\n const canonicalName = canonicalNames.get(resolvedPath)\n\n /* v8 ignore next 3 */\n if (!canonicalName)\n throw new Error(`No canonical name for: ${resolvedPath}`)\n\n return `import(${canonicalName})`\n })\n }\n}\n","/**\n * A bundle produced by the bundler. Contains the main program source\n * with file imports rewritten to canonical module names, plus an ordered\n * array of file module sources keyed by canonical name.\n *\n * The bundle is pure JSON — fully serializable and portable\n * (e.g., build on a server, run in a browser).\n */\nexport interface LitsBundle {\n /** The main program source, with file imports rewritten to bare symbols. */\n program: string\n /** Ordered array of [canonicalName, source] pairs. Dependencies come before dependents. */\n fileModules: [string, string][]\n}\n\nexport function isLitsBundle(value: unknown): value is LitsBundle {\n return (\n typeof value === 'object'\n && value !== null\n && typeof (value as LitsBundle).program === 'string'\n && Array.isArray((value as LitsBundle).fileModules)\n )\n}\n"],"names":["builtinModuleNames","Set","fileImportPattern","entryPath","absoluteEntryPath","path","resolve","entryDir","dirname","fileSources","Map","canonicalNames","dependencies","resolveFile","absoluteFilePath","stack","includes","cycle","slice","indexOf","Error","join","has","fs","existsSync","source","readFileSync","set","deps","dir","match","matchAll","importPath","resolvedPath","add","entryDirectory","usedNames","keys","name","deriveCanonicalName","buildCanonicalNames","fileModules","entryFilePath","result","visited","visiting","visit","filePath","get","dep","delete","push","topologicalSort","map","rewritten","rewriteImports","program","relativePath","relative","startsWith","stripExtension","split","sep","endsWith","sourceFilePath","replace","_fullMatch","doubleQuoted","singleQuoted","canonicalName","value","Array","isArray"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import type { GetFsModule } from '../../utils';
2
- export declare const getFsModule: GetFsModule;
1
+ import type { LitsModule } from '../../../../../src/builtin/modules/interface';
2
+ export declare function getFsModule(): LitsModule;
@@ -1,3 +1,3 @@
1
- import type { GetFsModule } from '../../utils';
1
+ import type { LitsModule } from '../../../../../src/builtin/modules/interface';
2
2
  export declare function sys_cwd(): string;
3
- export declare const getProcModule: GetFsModule;
3
+ export declare function getProcModule(): LitsModule;
@@ -1,3 +1,2 @@
1
- export declare function getCliModule(): {
2
- [x: string]: unknown;
3
- };
1
+ import type { LitsModule } from '../../../../src/builtin/modules/interface';
2
+ export declare function getCliModules(): LitsModule[];