parseman 0.61.3 → 0.61.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4064,7 +4064,7 @@ function regex(pattern, flags = "") {
4064
4064
  }
4065
4065
 
4066
4066
  // src/version.ts
4067
- var PARSEMAN_VERSION = "0.61.3";
4067
+ var PARSEMAN_VERSION = "0.61.4";
4068
4068
 
4069
4069
  // src/table/lex-body.ts
4070
4070
  function buildLexBodyRecognizer(spec, constants) {
package/dist/cli/index.js CHANGED
@@ -5700,7 +5700,7 @@ function regex(pattern, flags = "") {
5700
5700
  }
5701
5701
 
5702
5702
  // src/version.ts
5703
- var PARSEMAN_VERSION = "0.61.3";
5703
+ var PARSEMAN_VERSION = "0.61.4";
5704
5704
 
5705
5705
  // src/table/lex-body.ts
5706
5706
  function buildLexBodyRecognizer(spec, constants) {
package/dist/index.js CHANGED
@@ -5653,7 +5653,7 @@ function sourceLeaf(root, fn) {
5653
5653
  }
5654
5654
 
5655
5655
  // src/version.ts
5656
- var PARSEMAN_VERSION = "0.61.3";
5656
+ var PARSEMAN_VERSION = "0.61.4";
5657
5657
 
5658
5658
  // src/table/lex-body.ts
5659
5659
  function buildLexBodyRecognizer(spec, constants) {
@@ -83,13 +83,29 @@ export type ParsecraftPluginOptions = {
83
83
  };
84
84
  /** A corpus a build parses to rank selective-assembly sites — see `assemblyProfile`. */
85
85
  export type AssemblyProfile = {
86
- /** The rule each corpus file is parsed from, e.g. `'Stylesheet'`. A grammar
87
- * without this rule keeps the static ranking. */
86
+ /** The rule each corpus file is parsed from, e.g. `'Stylesheet'`. A grammar without
87
+ * this rule keeps the static ranking. A build fails when grammars were profiled and
88
+ * none has the rule. A direct `transformMacro` caller gets `assemblyProfile:
89
+ * 'no-entry'` on the result instead, and has to read it. */
88
90
  readonly entry: string;
89
91
  /** Paths of representative inputs. At least one must have content, and each that
90
92
  * does has to parse in full without recovery, or the build fails. A file with only
91
- * whitespace counts as empty. */
93
+ * whitespace counts as empty. A callback the corpus doesn't reach is never run, so
94
+ * nothing checks it. */
92
95
  readonly files: readonly string[];
96
+ /**
97
+ * The values of names a grammar's reducers and gates import, for the corpus run.
98
+ * Their source runs at build time with no module around it, so a grammar whose
99
+ * callbacks read imported helpers passes those helpers here. See
100
+ * `docs/guide/macro-mode.md` for what this does and doesn't cover.
101
+ *
102
+ * It's one flat namespace, so two modules can't bind one name to different helpers.
103
+ * A name that's already a global fails the build. A helper named like a global and
104
+ * left out of `scope` silently uses the global. A direct `node()` builder doesn't
105
+ * run in the corpus run: a plain node stands in for it, so a helper only a builder
106
+ * reads is neither needed here nor checked.
107
+ */
108
+ readonly scope?: Readonly<Record<string, unknown>>;
93
109
  };
94
110
  declare const _default: import("unplugin").UnpluginInstance<ParsecraftPluginOptions, boolean>;
95
111
  export default _default;
@@ -98,6 +114,9 @@ export type TransformMacroResult = {
98
114
  map: ReturnType<MagicString['generateMap']>;
99
115
  /** Diagnostics for macro-referencing shapes that fell back to the interpreter. */
100
116
  warnings: string[];
117
+ /** With an `assemblyProfile`: `'ran'` when a grammar here parsed the corpus,
118
+ * `'no-entry'` when the grammars that could have don't have its `entry` rule. */
119
+ assemblyProfile?: 'ran' | 'no-entry';
101
120
  /** The sites the module's `assemblyBudget` bought, by program offset, in rank order. */
102
121
  assemblySites: number[];
103
122
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAyBA,OAAO,WAAW,MAAM,cAAc,CAAA;AActC,OAAO,EAAsC,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAA;AA6BxF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AACzE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAAE,CAAA;AAChH,kDAAkD;AAClD,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;AACxD,eAAO,MAAM,sBAAsB,mBAAmB,CAAA;AAQtD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AA+BD,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,wFAAwF;AACxF,MAAM,MAAM,eAAe,GAAG;IAC5B;qDACiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;qCAEiC;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC,CAAA;;;AA+kBD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,wFAAwF;IACxF,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AA0CD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,EACvB,eAAe,CAAC,EAAE,eAAe,EACjC,cAAc,SAA0B,EACxC,WAAW,CAAC,EAAE,WAAW,GACxB,oBAAoB,GAAG,IAAI,CAW7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AA0BA,OAAO,WAAW,MAAM,cAAc,CAAA;AActC,OAAO,EAAsC,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAA;AA6BxF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AACzE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAAE,CAAA;AAChH,kDAAkD;AAClD,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;AACxD,eAAO,MAAM,sBAAsB,mBAAmB,CAAA;AAQtD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AA+BD,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,wFAAwF;AACxF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;gEAG4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;4BAGwB;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACnD,CAAA;;;AA4lBD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB;qFACiF;IACjF,eAAe,CAAC,EAAE,KAAK,GAAG,UAAU,CAAA;IACpC,wFAAwF;IACxF,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AA0CD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,EACvB,eAAe,CAAC,EAAE,eAAe,EACjC,cAAc,SAA0B,EACxC,WAAW,CAAC,EAAE,WAAW,GACxB,oBAAoB,GAAG,IAAI,CAW7B"}
@@ -5622,7 +5622,7 @@ function sourceLeaf(root, fn) {
5622
5622
  }
5623
5623
 
5624
5624
  // src/version.ts
5625
- var PARSEMAN_VERSION = "0.61.3";
5625
+ var PARSEMAN_VERSION = "0.61.4";
5626
5626
 
5627
5627
  // src/table/lex-body.ts
5628
5628
  function buildLexBodyRecognizer(spec, constants) {
@@ -23293,6 +23293,7 @@ async function emitCarriedSidecars(sinks, bundle) {
23293
23293
  var SIDECAR_FRAMEWORKS = /* @__PURE__ */ new Set(["rollup", "rolldown", "vite"]);
23294
23294
  var plugin_default = createUnplugin((opts = {}, meta) => {
23295
23295
  const sinks = SIDECAR_FRAMEWORKS.has(meta.framework) ? /* @__PURE__ */ new Map() : void 0;
23296
+ const profiled = /* @__PURE__ */ new Map();
23296
23297
  const generateBundle = sinks === void 0 ? void 0 : {
23297
23298
  generateBundle: {
23298
23299
  order: "post",
@@ -23311,8 +23312,15 @@ var plugin_default = createUnplugin((opts = {}, meta) => {
23311
23312
  transformInclude(id) {
23312
23313
  return /\.[jt]sx?$/.test(id) && !id.includes("node_modules");
23313
23314
  },
23315
+ buildEnd(error) {
23316
+ if (error) return;
23317
+ const ids = [...this.getModuleIds?.() ?? profiled.keys()].filter((id) => profiled.has(id));
23318
+ if (ids.length === 0 || ids.some((id) => profiled.get(id) === "ran")) return;
23319
+ throw new Error(`assemblyProfile: no grammar has rule "${opts.assemblyProfile?.entry}", so the corpus never ran (${ids.join(", ")})`);
23320
+ },
23314
23321
  transform(code, id) {
23315
23322
  sinks?.delete(id);
23323
+ profiled.delete(id);
23316
23324
  if (!code.includes("parseman")) return null;
23317
23325
  if (!code.includes("macro")) return null;
23318
23326
  for (const file of opts.assemblyProfile?.files ?? []) this?.addWatchFile?.(file);
@@ -23320,6 +23328,7 @@ var plugin_default = createUnplugin((opts = {}, meta) => {
23320
23328
  const sink = sinks && /* @__PURE__ */ new Map();
23321
23329
  const result = transformMacro(code, id, moduleAliases, opts.warnUnloweredRegex === true, opts.recovery === true, opts.grammarCoverage === true, opts.assemblyProfile, opts.assemblyBudget, sink);
23322
23330
  if (sinks && sink && sink.size > 0) sinks.set(id, sink);
23331
+ if (result?.assemblyProfile !== void 0) profiled.set(id, result.assemblyProfile);
23323
23332
  if (result?.warnings.length) {
23324
23333
  for (const w of result.warnings) {
23325
23334
  if (typeof this?.warn === "function") this.warn(`[parseman] ${w}`);
@@ -24384,8 +24393,14 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
24384
24393
  assemblySites.push(...sites);
24385
24394
  return sites;
24386
24395
  };
24396
+ let profileOutcome;
24387
24397
  const profileOf = (compiled) => {
24388
- if (assemblyProfile === void 0 || compiled.hostMode !== "ast" || compiled.prog.lines === 1 || !(assemblyProfile.entry in compiled.prog.rules)) return void 0;
24398
+ if (assemblyProfile === void 0 || compiled.hostMode !== "ast" || compiled.prog.lines === 1) return void 0;
24399
+ if (!(assemblyProfile.entry in compiled.prog.rules)) {
24400
+ profileOutcome ??= "no-entry";
24401
+ return void 0;
24402
+ }
24403
+ profileOutcome = "ran";
24389
24404
  const refuse = (why) => {
24390
24405
  throw new Error(`${id} \u2014 assemblyProfile: ${why}`);
24391
24406
  };
@@ -24405,26 +24420,36 @@ ${names.map((n) => ` - ${n}`).join("\n")}` : " (it is not a static combinator/v
24405
24420
  }
24406
24421
  });
24407
24422
  });
24408
- return countSiteVisits(compiled.prog, (rules3) => {
24409
- const entry = rules3[assemblyProfile.entry];
24410
- corpusTexts(assemblyProfile).forEach((text, i) => {
24411
- const file = assemblyProfile.files[i];
24412
- if (text.trim() === "") return;
24413
- let result2;
24414
- try {
24415
- result2 = run(entry, text);
24416
- } catch (e) {
24417
- const source = String(thrower).replace(/\s+/g, " ").slice(0, 200);
24418
- throw new Error(`${id} \u2014 assemblyProfile: ${thrower === void 0 ? "the parse" : `gate or reducer \`${source}\``} threw on ${file}: ${String(e)}`, { cause: e });
24419
- }
24420
- if (!result2.ok || result2.unconsumedFrom !== null) {
24421
- refuse(`${file} does not parse from rule "${assemblyProfile.entry}": it stops at offset ${result2.ok ? result2.unconsumedFrom : result2.span.end}`);
24422
- }
24423
- if (result2.errors.length > 0) {
24424
- refuse(`${file} parses only by recovering from ${result2.errors.length} error(s), first at offset ${result2.errors[0].span.start}`);
24425
- }
24426
- });
24427
- }, fns);
24423
+ const scope3 = assemblyProfile.scope ?? {};
24424
+ const names = Object.keys(scope3);
24425
+ for (const name of names) {
24426
+ if (name in globalThis) refuse(`\`scope\` name "${name}" is already a global; a callback couldn't tell which one it reads`);
24427
+ }
24428
+ try {
24429
+ for (const name of names) Object.defineProperty(globalThis, name, { value: scope3[name], configurable: true });
24430
+ return countSiteVisits(compiled.prog, (rules3) => {
24431
+ const entry = rules3[assemblyProfile.entry];
24432
+ corpusTexts(assemblyProfile).forEach((text, i) => {
24433
+ const file = assemblyProfile.files[i];
24434
+ if (text.trim() === "") return;
24435
+ let result2;
24436
+ try {
24437
+ result2 = run(entry, text);
24438
+ } catch (e) {
24439
+ const source = String(thrower).replace(/\s+/g, " ").slice(0, 200);
24440
+ throw new Error(`${id} \u2014 assemblyProfile: ${thrower === void 0 ? "the parse" : `gate or reducer \`${source}\``} threw on ${file}: ${String(e)}`, { cause: e });
24441
+ }
24442
+ if (!result2.ok || result2.unconsumedFrom !== null) {
24443
+ refuse(`${file} does not parse from rule "${assemblyProfile.entry}": it stops at offset ${result2.ok ? result2.unconsumedFrom : result2.span.end}`);
24444
+ }
24445
+ if (result2.errors.length > 0) {
24446
+ refuse(`${file} parses only by recovering from ${result2.errors.length} error(s), first at offset ${result2.errors[0].span.start}`);
24447
+ }
24448
+ });
24449
+ }, fns);
24450
+ } finally {
24451
+ for (const name of names) Reflect.deleteProperty(globalThis, name);
24452
+ }
24428
24453
  };
24429
24454
  const assembledReplacement = (compiled, metadata, select) => select.size === 0 ? compiled.replacementWithMetadata(metadata) : supercompileRuleMapReplacement(compiled.prog, compiled.replacementWithMetadata(metadata, { select }), select);
24430
24455
  const compileComposeLeafCall = (init) => {
@@ -24937,7 +24962,8 @@ ${lines2.join("\n")}`);
24937
24962
  assemblySites: applied.length > 0 ? assemblySites : [],
24938
24963
  code: ms.toString(),
24939
24964
  map: ms.generateMap({ hires: true }),
24940
- warnings
24965
+ warnings,
24966
+ ...profileOutcome === void 0 ? {} : { assemblyProfile: profileOutcome }
24941
24967
  };
24942
24968
  }
24943
24969
  export {