@tilua/compiler 2.0.0 → 2.1.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.
@@ -1929,7 +1929,7 @@ async function loadLowerings(modules) {
1929
1929
  }
1930
1930
 
1931
1931
  // src/bundle.ts
1932
- import { readFileSync } from "fs";
1932
+ import { readFileSync, statSync } from "fs";
1933
1933
  import { dirname, relative, resolve as resolve2 } from "path";
1934
1934
  import {
1935
1935
  parse,
@@ -2222,7 +2222,22 @@ ${G} = {
2222
2222
  }
2223
2223
  `;
2224
2224
  }
2225
+ function stampOf(file) {
2226
+ try {
2227
+ const at = statSync(file);
2228
+ return `${at.size}:${at.mtimeMs}`;
2229
+ } catch {
2230
+ return void 0;
2231
+ }
2232
+ }
2233
+ var parsedFiles = /* @__PURE__ */ new Map();
2225
2234
  function parseFile(file, diagnostics, directives) {
2235
+ const stamp = stampOf(file);
2236
+ const cached = stamp !== void 0 ? parsedFiles.get(file) : void 0;
2237
+ if (cached && cached.stamp === stamp) {
2238
+ directives.set(file, cached.directives);
2239
+ return { program: cached.program, text: cached.text };
2240
+ }
2226
2241
  let text;
2227
2242
  try {
2228
2243
  text = readFileSync(file, "utf8");
@@ -2232,7 +2247,9 @@ function parseFile(file, diagnostics, directives) {
2232
2247
  }
2233
2248
  try {
2234
2249
  const program2 = parse(text);
2235
- directives.set(file, directivesOf(text));
2250
+ const found = directivesOf(text);
2251
+ directives.set(file, found);
2252
+ if (stamp !== void 0) parsedFiles.set(file, { stamp, program: program2, text, directives: found });
2236
2253
  return { program: program2, text };
2237
2254
  } catch (error) {
2238
2255
  if (error instanceof ParseError || error instanceof LexError) {
@@ -2246,22 +2263,93 @@ function parseFile(file, diagnostics, directives) {
2246
2263
  function importedSpecifiers(program2) {
2247
2264
  return program2.body.statements.flatMap((s) => s.type === "ImportStatement" || s.type === "ExportAllStatement" || s.type === "ExportNamedStatement" && s.source ? [s.source.value] : []);
2248
2265
  }
2266
+ var libraryCache = /* @__PURE__ */ new Map();
2267
+ function parsedLibrary(file) {
2268
+ let stamp;
2269
+ try {
2270
+ const at = statSync(file);
2271
+ stamp = `${at.size}:${at.mtimeMs}`;
2272
+ } catch {
2273
+ stamp = "";
2274
+ }
2275
+ const cached = libraryCache.get(file);
2276
+ if (cached && cached.stamp === stamp) return cached.program;
2277
+ const program2 = parse(readFileSync(file, "utf8"));
2278
+ libraryCache.set(file, { stamp, program: program2 });
2279
+ return program2;
2280
+ }
2281
+ var moduleAnalyses = /* @__PURE__ */ new Map();
2249
2282
  function analyzeModules(modules, config) {
2250
2283
  const out = [];
2251
2284
  const analyses = /* @__PURE__ */ new Map();
2252
2285
  const libraries = config ? resolveTypeLibraries(config) : { files: [], lowerings: [], problems: [] };
2253
2286
  for (const p of libraries.problems) out.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
2254
- const libs = libraries.files.map((file) => parse(readFileSync(file, "utf8")));
2287
+ const libs = libraries.files.map(parsedLibrary);
2255
2288
  const globals = libs.flatMap((lib) => lib.body.statements.flatMap((s) => s.type === "DeclareStatement" ? [s.name] : []));
2256
2289
  const byFile = new Map(modules.map((m) => [m.file, m]));
2257
2290
  const exportsCache = /* @__PURE__ */ new Map();
2258
2291
  const inProgress = /* @__PURE__ */ new Set();
2292
+ const analyzed = /* @__PURE__ */ new Map();
2293
+ let partials = 0;
2294
+ const readWhile = /* @__PURE__ */ new Map();
2295
+ const settingFor = `${libraries.files.join("|")}#${config?.directory ?? ""}#${JSON.stringify(config?.paths ?? {})}`;
2296
+ const analyzeModule = (file, program2) => {
2297
+ const done = analyzed.get(file);
2298
+ if (done) return done;
2299
+ const remembered = moduleAnalyses.get(file);
2300
+ if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program2 && [...remembered.read].every(([read, stamp]) => stampOf(read) === stamp)) {
2301
+ analyzed.set(file, remembered.result);
2302
+ readWhile.set(file, remembered.read);
2303
+ return remembered.result;
2304
+ }
2305
+ const scopes = analyzeScopes(program2, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2306
+ const said = [];
2307
+ for (const d of scopes.diagnostics) {
2308
+ if (d.kind !== "undeclared") continue;
2309
+ said.push({ file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2310
+ }
2311
+ const before = partials;
2312
+ const types = analyzeTypes(program2, scopes, {
2313
+ libs,
2314
+ resolveModule: resolverFor(file),
2315
+ reportUnknownTypes: libs.length > 0
2316
+ });
2317
+ for (const d of types.diagnostics) {
2318
+ const at = d.node;
2319
+ said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2320
+ }
2321
+ const result = { types, diagnostics: said };
2322
+ if (partials === before) {
2323
+ analyzed.set(file, result);
2324
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2325
+ const own = stampOf(file);
2326
+ if (own !== void 0) read.set(file, own);
2327
+ readWhile.set(file, read);
2328
+ if ([...read.values()].every((stamp) => stamp !== void 0)) {
2329
+ moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program: program2, read, result });
2330
+ }
2331
+ }
2332
+ return result;
2333
+ };
2259
2334
  const resolverFor = (file) => (specifier) => {
2260
2335
  const target = resolveModulePath(file, specifier, config);
2261
2336
  if (!target) return void 0;
2262
- if (inProgress.has(target)) return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2337
+ const noteRead = () => {
2338
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2339
+ readWhile.set(file, read);
2340
+ const stamp = stampOf(target);
2341
+ if (stamp !== void 0) read.set(target, stamp);
2342
+ for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
2343
+ };
2344
+ if (inProgress.has(target)) {
2345
+ partials++;
2346
+ return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2347
+ }
2263
2348
  const cached = exportsCache.get(target);
2264
- if (cached) return cached;
2349
+ if (cached) {
2350
+ noteRead();
2351
+ return cached;
2352
+ }
2265
2353
  let program2 = byFile.get(target)?.program;
2266
2354
  if (!program2) {
2267
2355
  try {
@@ -2273,30 +2361,19 @@ function analyzeModules(modules, config) {
2273
2361
  inProgress.add(target);
2274
2362
  try {
2275
2363
  const scopes = analyzeScopes(program2, { builtinGlobals: globals });
2276
- const types = analyzeTypes(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2364
+ const types = byFile.has(target) ? analyzeModule(target, program2).types : analyzeTypes(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2277
2365
  const exports = moduleExports(program2, scopes, types, resolverFor(target));
2278
2366
  exportsCache.set(target, exports);
2367
+ noteRead();
2279
2368
  return exports;
2280
2369
  } finally {
2281
2370
  inProgress.delete(target);
2282
2371
  }
2283
2372
  };
2284
2373
  for (const module of modules) {
2285
- const scopes = analyzeScopes(module.program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2286
- for (const d of scopes.diagnostics) {
2287
- if (d.kind !== "undeclared") continue;
2288
- out.push({ file: module.file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2289
- }
2290
- const types = analyzeTypes(module.program, scopes, {
2291
- libs,
2292
- resolveModule: resolverFor(module.file),
2293
- reportUnknownTypes: libs.length > 0
2294
- });
2374
+ const { types, diagnostics } = analyzeModule(module.file, module.program);
2295
2375
  analyses.set(module.file, types);
2296
- for (const d of types.diagnostics) {
2297
- const at = d.node;
2298
- out.push({ file: module.file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2299
- }
2376
+ out.push(...diagnostics);
2300
2377
  }
2301
2378
  return { types: analyses, diagnostics: out, lowerings: [...libraries.lowerings] };
2302
2379
  }
package/dist/cli.cjs CHANGED
@@ -2216,7 +2216,22 @@ ${G} = {
2216
2216
  }
2217
2217
  `;
2218
2218
  }
2219
+ function stampOf(file) {
2220
+ try {
2221
+ const at = (0, import_node_fs.statSync)(file);
2222
+ return `${at.size}:${at.mtimeMs}`;
2223
+ } catch {
2224
+ return void 0;
2225
+ }
2226
+ }
2227
+ var parsedFiles = /* @__PURE__ */ new Map();
2219
2228
  function parseFile(file, diagnostics, directives) {
2229
+ const stamp = stampOf(file);
2230
+ const cached = stamp !== void 0 ? parsedFiles.get(file) : void 0;
2231
+ if (cached && cached.stamp === stamp) {
2232
+ directives.set(file, cached.directives);
2233
+ return { program: cached.program, text: cached.text };
2234
+ }
2220
2235
  let text;
2221
2236
  try {
2222
2237
  text = (0, import_node_fs.readFileSync)(file, "utf8");
@@ -2226,7 +2241,9 @@ function parseFile(file, diagnostics, directives) {
2226
2241
  }
2227
2242
  try {
2228
2243
  const program = (0, import_parser3.parse)(text);
2229
- directives.set(file, (0, import_parser3.directivesOf)(text));
2244
+ const found = (0, import_parser3.directivesOf)(text);
2245
+ directives.set(file, found);
2246
+ if (stamp !== void 0) parsedFiles.set(file, { stamp, program, text, directives: found });
2230
2247
  return { program, text };
2231
2248
  } catch (error) {
2232
2249
  if (error instanceof import_parser3.ParseError || error instanceof import_parser3.LexError) {
@@ -2240,22 +2257,93 @@ function parseFile(file, diagnostics, directives) {
2240
2257
  function importedSpecifiers(program) {
2241
2258
  return program.body.statements.flatMap((s) => s.type === "ImportStatement" || s.type === "ExportAllStatement" || s.type === "ExportNamedStatement" && s.source ? [s.source.value] : []);
2242
2259
  }
2260
+ var libraryCache = /* @__PURE__ */ new Map();
2261
+ function parsedLibrary(file) {
2262
+ let stamp;
2263
+ try {
2264
+ const at = (0, import_node_fs.statSync)(file);
2265
+ stamp = `${at.size}:${at.mtimeMs}`;
2266
+ } catch {
2267
+ stamp = "";
2268
+ }
2269
+ const cached = libraryCache.get(file);
2270
+ if (cached && cached.stamp === stamp) return cached.program;
2271
+ const program = (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8"));
2272
+ libraryCache.set(file, { stamp, program });
2273
+ return program;
2274
+ }
2275
+ var moduleAnalyses = /* @__PURE__ */ new Map();
2243
2276
  function analyzeModules(modules, config2) {
2244
2277
  const out2 = [];
2245
2278
  const analyses = /* @__PURE__ */ new Map();
2246
2279
  const libraries = config2 ? (0, import_parser3.resolveTypeLibraries)(config2) : { files: [], lowerings: [], problems: [] };
2247
2280
  for (const p of libraries.problems) out2.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
2248
- const libs = libraries.files.map((file) => (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8")));
2281
+ const libs = libraries.files.map(parsedLibrary);
2249
2282
  const globals = libs.flatMap((lib) => lib.body.statements.flatMap((s) => s.type === "DeclareStatement" ? [s.name] : []));
2250
2283
  const byFile = new Map(modules.map((m) => [m.file, m]));
2251
2284
  const exportsCache = /* @__PURE__ */ new Map();
2252
2285
  const inProgress = /* @__PURE__ */ new Set();
2286
+ const analyzed = /* @__PURE__ */ new Map();
2287
+ let partials = 0;
2288
+ const readWhile = /* @__PURE__ */ new Map();
2289
+ const settingFor = `${libraries.files.join("|")}#${config2?.directory ?? ""}#${JSON.stringify(config2?.paths ?? {})}`;
2290
+ const analyzeModule = (file, program) => {
2291
+ const done = analyzed.get(file);
2292
+ if (done) return done;
2293
+ const remembered = moduleAnalyses.get(file);
2294
+ if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program && [...remembered.read].every(([read, stamp]) => stampOf(read) === stamp)) {
2295
+ analyzed.set(file, remembered.result);
2296
+ readWhile.set(file, remembered.read);
2297
+ return remembered.result;
2298
+ }
2299
+ const scopes = (0, import_parser3.analyzeScopes)(program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2300
+ const said = [];
2301
+ for (const d of scopes.diagnostics) {
2302
+ if (d.kind !== "undeclared") continue;
2303
+ said.push({ file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2304
+ }
2305
+ const before = partials;
2306
+ const types = (0, import_parser3.analyzeTypes)(program, scopes, {
2307
+ libs,
2308
+ resolveModule: resolverFor(file),
2309
+ reportUnknownTypes: libs.length > 0
2310
+ });
2311
+ for (const d of types.diagnostics) {
2312
+ const at = d.node;
2313
+ said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2314
+ }
2315
+ const result = { types, diagnostics: said };
2316
+ if (partials === before) {
2317
+ analyzed.set(file, result);
2318
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2319
+ const own = stampOf(file);
2320
+ if (own !== void 0) read.set(file, own);
2321
+ readWhile.set(file, read);
2322
+ if ([...read.values()].every((stamp) => stamp !== void 0)) {
2323
+ moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program, read, result });
2324
+ }
2325
+ }
2326
+ return result;
2327
+ };
2253
2328
  const resolverFor = (file) => (specifier) => {
2254
2329
  const target = (0, import_parser3.resolveModulePath)(file, specifier, config2);
2255
2330
  if (!target) return void 0;
2256
- if (inProgress.has(target)) return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2331
+ const noteRead = () => {
2332
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2333
+ readWhile.set(file, read);
2334
+ const stamp = stampOf(target);
2335
+ if (stamp !== void 0) read.set(target, stamp);
2336
+ for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
2337
+ };
2338
+ if (inProgress.has(target)) {
2339
+ partials++;
2340
+ return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2341
+ }
2257
2342
  const cached = exportsCache.get(target);
2258
- if (cached) return cached;
2343
+ if (cached) {
2344
+ noteRead();
2345
+ return cached;
2346
+ }
2259
2347
  let program = byFile.get(target)?.program;
2260
2348
  if (!program) {
2261
2349
  try {
@@ -2267,30 +2355,19 @@ function analyzeModules(modules, config2) {
2267
2355
  inProgress.add(target);
2268
2356
  try {
2269
2357
  const scopes = (0, import_parser3.analyzeScopes)(program, { builtinGlobals: globals });
2270
- const types = (0, import_parser3.analyzeTypes)(program, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2358
+ const types = byFile.has(target) ? analyzeModule(target, program).types : (0, import_parser3.analyzeTypes)(program, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2271
2359
  const exports2 = (0, import_parser3.moduleExports)(program, scopes, types, resolverFor(target));
2272
2360
  exportsCache.set(target, exports2);
2361
+ noteRead();
2273
2362
  return exports2;
2274
2363
  } finally {
2275
2364
  inProgress.delete(target);
2276
2365
  }
2277
2366
  };
2278
2367
  for (const module2 of modules) {
2279
- const scopes = (0, import_parser3.analyzeScopes)(module2.program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2280
- for (const d of scopes.diagnostics) {
2281
- if (d.kind !== "undeclared") continue;
2282
- out2.push({ file: module2.file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2283
- }
2284
- const types = (0, import_parser3.analyzeTypes)(module2.program, scopes, {
2285
- libs,
2286
- resolveModule: resolverFor(module2.file),
2287
- reportUnknownTypes: libs.length > 0
2288
- });
2368
+ const { types, diagnostics } = analyzeModule(module2.file, module2.program);
2289
2369
  analyses.set(module2.file, types);
2290
- for (const d of types.diagnostics) {
2291
- const at = d.node;
2292
- out2.push({ file: module2.file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2293
- }
2370
+ out2.push(...diagnostics);
2294
2371
  }
2295
2372
  return { types: analyses, diagnostics: out2, lowerings: [...libraries.lowerings] };
2296
2373
  }
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  bundle
4
- } from "./chunk-KG6W5XKA.js";
4
+ } from "./chunk-TBSJRVKA.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { writeFileSync } from "fs";
package/dist/index.cjs CHANGED
@@ -2240,7 +2240,22 @@ ${G} = {
2240
2240
  }
2241
2241
  `;
2242
2242
  }
2243
+ function stampOf(file) {
2244
+ try {
2245
+ const at = (0, import_node_fs.statSync)(file);
2246
+ return `${at.size}:${at.mtimeMs}`;
2247
+ } catch {
2248
+ return void 0;
2249
+ }
2250
+ }
2251
+ var parsedFiles = /* @__PURE__ */ new Map();
2243
2252
  function parseFile(file, diagnostics, directives) {
2253
+ const stamp = stampOf(file);
2254
+ const cached = stamp !== void 0 ? parsedFiles.get(file) : void 0;
2255
+ if (cached && cached.stamp === stamp) {
2256
+ directives.set(file, cached.directives);
2257
+ return { program: cached.program, text: cached.text };
2258
+ }
2244
2259
  let text;
2245
2260
  try {
2246
2261
  text = (0, import_node_fs.readFileSync)(file, "utf8");
@@ -2250,7 +2265,9 @@ function parseFile(file, diagnostics, directives) {
2250
2265
  }
2251
2266
  try {
2252
2267
  const program2 = (0, import_parser3.parse)(text);
2253
- directives.set(file, (0, import_parser3.directivesOf)(text));
2268
+ const found = (0, import_parser3.directivesOf)(text);
2269
+ directives.set(file, found);
2270
+ if (stamp !== void 0) parsedFiles.set(file, { stamp, program: program2, text, directives: found });
2254
2271
  return { program: program2, text };
2255
2272
  } catch (error) {
2256
2273
  if (error instanceof import_parser3.ParseError || error instanceof import_parser3.LexError) {
@@ -2264,22 +2281,93 @@ function parseFile(file, diagnostics, directives) {
2264
2281
  function importedSpecifiers(program2) {
2265
2282
  return program2.body.statements.flatMap((s) => s.type === "ImportStatement" || s.type === "ExportAllStatement" || s.type === "ExportNamedStatement" && s.source ? [s.source.value] : []);
2266
2283
  }
2284
+ var libraryCache = /* @__PURE__ */ new Map();
2285
+ function parsedLibrary(file) {
2286
+ let stamp;
2287
+ try {
2288
+ const at = (0, import_node_fs.statSync)(file);
2289
+ stamp = `${at.size}:${at.mtimeMs}`;
2290
+ } catch {
2291
+ stamp = "";
2292
+ }
2293
+ const cached = libraryCache.get(file);
2294
+ if (cached && cached.stamp === stamp) return cached.program;
2295
+ const program2 = (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8"));
2296
+ libraryCache.set(file, { stamp, program: program2 });
2297
+ return program2;
2298
+ }
2299
+ var moduleAnalyses = /* @__PURE__ */ new Map();
2267
2300
  function analyzeModules(modules, config) {
2268
2301
  const out = [];
2269
2302
  const analyses = /* @__PURE__ */ new Map();
2270
2303
  const libraries = config ? (0, import_parser3.resolveTypeLibraries)(config) : { files: [], lowerings: [], problems: [] };
2271
2304
  for (const p of libraries.problems) out.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
2272
- const libs = libraries.files.map((file) => (0, import_parser3.parse)((0, import_node_fs.readFileSync)(file, "utf8")));
2305
+ const libs = libraries.files.map(parsedLibrary);
2273
2306
  const globals = libs.flatMap((lib) => lib.body.statements.flatMap((s) => s.type === "DeclareStatement" ? [s.name] : []));
2274
2307
  const byFile = new Map(modules.map((m) => [m.file, m]));
2275
2308
  const exportsCache = /* @__PURE__ */ new Map();
2276
2309
  const inProgress = /* @__PURE__ */ new Set();
2310
+ const analyzed = /* @__PURE__ */ new Map();
2311
+ let partials = 0;
2312
+ const readWhile = /* @__PURE__ */ new Map();
2313
+ const settingFor = `${libraries.files.join("|")}#${config?.directory ?? ""}#${JSON.stringify(config?.paths ?? {})}`;
2314
+ const analyzeModule = (file, program2) => {
2315
+ const done = analyzed.get(file);
2316
+ if (done) return done;
2317
+ const remembered = moduleAnalyses.get(file);
2318
+ if (remembered && remembered.setting === settingFor && libs.length === remembered.libs.length && remembered.libs.every((lib, i) => lib === libs[i]) && remembered.program === program2 && [...remembered.read].every(([read, stamp]) => stampOf(read) === stamp)) {
2319
+ analyzed.set(file, remembered.result);
2320
+ readWhile.set(file, remembered.read);
2321
+ return remembered.result;
2322
+ }
2323
+ const scopes = (0, import_parser3.analyzeScopes)(program2, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2324
+ const said = [];
2325
+ for (const d of scopes.diagnostics) {
2326
+ if (d.kind !== "undeclared") continue;
2327
+ said.push({ file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2328
+ }
2329
+ const before = partials;
2330
+ const types = (0, import_parser3.analyzeTypes)(program2, scopes, {
2331
+ libs,
2332
+ resolveModule: resolverFor(file),
2333
+ reportUnknownTypes: libs.length > 0
2334
+ });
2335
+ for (const d of types.diagnostics) {
2336
+ const at = d.node;
2337
+ said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2338
+ }
2339
+ const result = { types, diagnostics: said };
2340
+ if (partials === before) {
2341
+ analyzed.set(file, result);
2342
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2343
+ const own = stampOf(file);
2344
+ if (own !== void 0) read.set(file, own);
2345
+ readWhile.set(file, read);
2346
+ if ([...read.values()].every((stamp) => stamp !== void 0)) {
2347
+ moduleAnalyses.set(file, { setting: settingFor, libs: [...libs], program: program2, read, result });
2348
+ }
2349
+ }
2350
+ return result;
2351
+ };
2277
2352
  const resolverFor = (file) => (specifier) => {
2278
2353
  const target = (0, import_parser3.resolveModulePath)(file, specifier, config);
2279
2354
  if (!target) return void 0;
2280
- if (inProgress.has(target)) return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2355
+ const noteRead = () => {
2356
+ const read = readWhile.get(file) ?? /* @__PURE__ */ new Map();
2357
+ readWhile.set(file, read);
2358
+ const stamp = stampOf(target);
2359
+ if (stamp !== void 0) read.set(target, stamp);
2360
+ for (const [below, belowStamp] of readWhile.get(target) ?? []) read.set(below, belowStamp);
2361
+ };
2362
+ if (inProgress.has(target)) {
2363
+ partials++;
2364
+ return { values: /* @__PURE__ */ new Map(), types: /* @__PURE__ */ new Map(), partial: true };
2365
+ }
2281
2366
  const cached = exportsCache.get(target);
2282
- if (cached) return cached;
2367
+ if (cached) {
2368
+ noteRead();
2369
+ return cached;
2370
+ }
2283
2371
  let program2 = byFile.get(target)?.program;
2284
2372
  if (!program2) {
2285
2373
  try {
@@ -2291,30 +2379,19 @@ function analyzeModules(modules, config) {
2291
2379
  inProgress.add(target);
2292
2380
  try {
2293
2381
  const scopes = (0, import_parser3.analyzeScopes)(program2, { builtinGlobals: globals });
2294
- const types = (0, import_parser3.analyzeTypes)(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2382
+ const types = byFile.has(target) ? analyzeModule(target, program2).types : (0, import_parser3.analyzeTypes)(program2, scopes, { libs, resolveModule: resolverFor(target), diagnostics: false });
2295
2383
  const exports2 = (0, import_parser3.moduleExports)(program2, scopes, types, resolverFor(target));
2296
2384
  exportsCache.set(target, exports2);
2385
+ noteRead();
2297
2386
  return exports2;
2298
2387
  } finally {
2299
2388
  inProgress.delete(target);
2300
2389
  }
2301
2390
  };
2302
2391
  for (const module2 of modules) {
2303
- const scopes = (0, import_parser3.analyzeScopes)(module2.program, { builtinGlobals: globals, reportUndeclared: libs.length > 0 });
2304
- for (const d of scopes.diagnostics) {
2305
- if (d.kind !== "undeclared") continue;
2306
- out.push({ file: module2.file, message: d.message, line: d.node.line.start, column: d.node.column.start, category: "type" });
2307
- }
2308
- const types = (0, import_parser3.analyzeTypes)(module2.program, scopes, {
2309
- libs,
2310
- resolveModule: resolverFor(module2.file),
2311
- reportUnknownTypes: libs.length > 0
2312
- });
2392
+ const { types, diagnostics } = analyzeModule(module2.file, module2.program);
2313
2393
  analyses.set(module2.file, types);
2314
- for (const d of types.diagnostics) {
2315
- const at = d.node;
2316
- out.push({ file: module2.file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
2317
- }
2394
+ out.push(...diagnostics);
2318
2395
  }
2319
2396
  return { types: analyses, diagnostics: out, lowerings: [...libraries.lowerings] };
2320
2397
  }
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  lower,
5
5
  program,
6
6
  resolveConfig
7
- } from "./chunk-KG6W5XKA.js";
7
+ } from "./chunk-TBSJRVKA.js";
8
8
 
9
9
  // src/compile.ts
10
10
  import { readFileSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tilua/compiler",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Compiles tilua to Luau: lowers the @tilua/parser AST to a luau-parser AST and prints it",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  "type": "module",
38
38
  "dependencies": {
39
39
  "luau-parser": "^1.0.3",
40
- "@tilua/parser": "^2.0.0"
40
+ "@tilua/parser": "^2.1.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.20.2",