@vessel-dsp/compiler 0.0.0-stage → 0.3.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 (226) hide show
  1. package/README.md +118 -2
  2. package/dist/bake.d.ts +38 -0
  3. package/dist/bake.d.ts.map +1 -0
  4. package/dist/bake.js +101 -0
  5. package/dist/bake.js.map +1 -0
  6. package/dist/bbd-clock.d.ts +171 -0
  7. package/dist/bbd-clock.d.ts.map +1 -0
  8. package/dist/bbd-clock.js +1750 -0
  9. package/dist/bbd-clock.js.map +1 -0
  10. package/dist/block-row.d.ts +51 -0
  11. package/dist/block-row.d.ts.map +1 -0
  12. package/dist/block-row.js +17 -0
  13. package/dist/block-row.js.map +1 -0
  14. package/dist/bypass.d.ts +3 -0
  15. package/dist/bypass.d.ts.map +1 -0
  16. package/dist/bypass.js +228 -0
  17. package/dist/bypass.js.map +1 -0
  18. package/dist/compile.d.ts +24 -0
  19. package/dist/compile.d.ts.map +1 -0
  20. package/dist/compile.js +348 -0
  21. package/dist/compile.js.map +1 -0
  22. package/dist/converter-scale.d.ts +14 -0
  23. package/dist/converter-scale.d.ts.map +1 -0
  24. package/dist/converter-scale.js +133 -0
  25. package/dist/converter-scale.js.map +1 -0
  26. package/dist/couple.d.ts +28 -0
  27. package/dist/couple.d.ts.map +1 -0
  28. package/dist/couple.js +567 -0
  29. package/dist/couple.js.map +1 -0
  30. package/dist/dangling-active-terminal.d.ts +47 -0
  31. package/dist/dangling-active-terminal.d.ts.map +1 -0
  32. package/dist/dangling-active-terminal.js +542 -0
  33. package/dist/dangling-active-terminal.js.map +1 -0
  34. package/dist/declared-program.d.ts +23 -0
  35. package/dist/declared-program.d.ts.map +1 -0
  36. package/dist/declared-program.js +387 -0
  37. package/dist/declared-program.js.map +1 -0
  38. package/dist/denomination.d.ts +48 -0
  39. package/dist/denomination.d.ts.map +1 -0
  40. package/dist/denomination.js +27 -0
  41. package/dist/denomination.js.map +1 -0
  42. package/dist/device-laws.d.ts +237 -0
  43. package/dist/device-laws.d.ts.map +1 -0
  44. package/dist/device-laws.js +3513 -0
  45. package/dist/device-laws.js.map +1 -0
  46. package/dist/diagnostics.d.ts +13 -0
  47. package/dist/diagnostics.d.ts.map +1 -0
  48. package/dist/diagnostics.js +19 -0
  49. package/dist/diagnostics.js.map +1 -0
  50. package/dist/emit.d.ts +8 -0
  51. package/dist/emit.d.ts.map +1 -0
  52. package/dist/emit.js +43 -0
  53. package/dist/emit.js.map +1 -0
  54. package/dist/errors.d.ts +22 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +39 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/firmware-class.d.ts +69 -0
  59. package/dist/firmware-class.d.ts.map +1 -0
  60. package/dist/firmware-class.js +20 -0
  61. package/dist/firmware-class.js.map +1 -0
  62. package/dist/fixtures/circuits.d.ts +1742 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13896 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +261 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +315 -0
  69. package/dist/fixtures/expected.js.map +1 -0
  70. package/dist/fixtures/index.d.ts +4 -0
  71. package/dist/fixtures/index.d.ts.map +1 -0
  72. package/dist/fixtures/index.js +8 -0
  73. package/dist/fixtures/index.js.map +1 -0
  74. package/dist/fixtures/registry.d.ts +52 -0
  75. package/dist/fixtures/registry.d.ts.map +1 -0
  76. package/dist/fixtures/registry.js +341 -0
  77. package/dist/fixtures/registry.js.map +1 -0
  78. package/dist/generic-tube-fit.d.ts +12 -0
  79. package/dist/generic-tube-fit.d.ts.map +1 -0
  80. package/dist/generic-tube-fit.js +45 -0
  81. package/dist/generic-tube-fit.js.map +1 -0
  82. package/dist/grounded-clock-supply.d.ts +13 -0
  83. package/dist/grounded-clock-supply.d.ts.map +1 -0
  84. package/dist/grounded-clock-supply.js +45 -0
  85. package/dist/grounded-clock-supply.js.map +1 -0
  86. package/dist/identify.d.ts +50 -0
  87. package/dist/identify.d.ts.map +1 -0
  88. package/dist/identify.js +319 -0
  89. package/dist/identify.js.map +1 -0
  90. package/dist/index.d.ts +10 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +19 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/inert-controls.d.ts +15 -0
  95. package/dist/inert-controls.d.ts.map +1 -0
  96. package/dist/inert-controls.js +266 -0
  97. package/dist/inert-controls.js.map +1 -0
  98. package/dist/latch-seed.d.ts +53 -0
  99. package/dist/latch-seed.d.ts.map +1 -0
  100. package/dist/latch-seed.js +257 -0
  101. package/dist/latch-seed.js.map +1 -0
  102. package/dist/link.d.ts +7 -0
  103. package/dist/link.d.ts.map +1 -0
  104. package/dist/link.js +270 -0
  105. package/dist/link.js.map +1 -0
  106. package/dist/lower.d.ts +79 -0
  107. package/dist/lower.d.ts.map +1 -0
  108. package/dist/lower.js +1855 -0
  109. package/dist/lower.js.map +1 -0
  110. package/dist/netlist.d.ts +79 -0
  111. package/dist/netlist.d.ts.map +1 -0
  112. package/dist/netlist.js +4746 -0
  113. package/dist/netlist.js.map +1 -0
  114. package/dist/non-executable-clock-drivers.d.ts +8 -0
  115. package/dist/non-executable-clock-drivers.d.ts.map +1 -0
  116. package/dist/non-executable-clock-drivers.js +33 -0
  117. package/dist/non-executable-clock-drivers.js.map +1 -0
  118. package/dist/open-category.d.ts +98 -0
  119. package/dist/open-category.d.ts.map +1 -0
  120. package/dist/open-category.js +111 -0
  121. package/dist/open-category.js.map +1 -0
  122. package/dist/over-driven-node.d.ts +33 -0
  123. package/dist/over-driven-node.d.ts.map +1 -0
  124. package/dist/over-driven-node.js +188 -0
  125. package/dist/over-driven-node.js.map +1 -0
  126. package/dist/part-catalog.d.ts +15 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6712 -0
  129. package/dist/part-catalog.js.map +1 -0
  130. package/dist/part-number.d.ts +32 -0
  131. package/dist/part-number.d.ts.map +1 -0
  132. package/dist/part-number.js +80 -0
  133. package/dist/part-number.js.map +1 -0
  134. package/dist/partition.d.ts +7 -0
  135. package/dist/partition.d.ts.map +1 -0
  136. package/dist/partition.js +242 -0
  137. package/dist/partition.js.map +1 -0
  138. package/dist/port-full-scale.d.ts +70 -0
  139. package/dist/port-full-scale.d.ts.map +1 -0
  140. package/dist/port-full-scale.js +235 -0
  141. package/dist/port-full-scale.js.map +1 -0
  142. package/dist/pot-orientation.d.ts +114 -0
  143. package/dist/pot-orientation.d.ts.map +1 -0
  144. package/dist/pot-orientation.js +551 -0
  145. package/dist/pot-orientation.js.map +1 -0
  146. package/dist/power-domain-control.d.ts +40 -0
  147. package/dist/power-domain-control.d.ts.map +1 -0
  148. package/dist/power-domain-control.js +142 -0
  149. package/dist/power-domain-control.js.map +1 -0
  150. package/dist/proxy-declaration.d.ts +121 -0
  151. package/dist/proxy-declaration.d.ts.map +1 -0
  152. package/dist/proxy-declaration.js +50 -0
  153. package/dist/proxy-declaration.js.map +1 -0
  154. package/dist/registry.d.ts +323 -0
  155. package/dist/registry.d.ts.map +1 -0
  156. package/dist/registry.js +192 -0
  157. package/dist/registry.js.map +1 -0
  158. package/dist/sparse-schedule.d.ts +65 -0
  159. package/dist/sparse-schedule.d.ts.map +1 -0
  160. package/dist/sparse-schedule.js +421 -0
  161. package/dist/sparse-schedule.js.map +1 -0
  162. package/dist/speaker-load.d.ts +38 -0
  163. package/dist/speaker-load.d.ts.map +1 -0
  164. package/dist/speaker-load.js +97 -0
  165. package/dist/speaker-load.js.map +1 -0
  166. package/dist/stage-coverage.d.ts +21 -0
  167. package/dist/stage-coverage.d.ts.map +1 -0
  168. package/dist/stage-coverage.js +124 -0
  169. package/dist/stage-coverage.js.map +1 -0
  170. package/dist/stamp-partition.d.ts +314 -0
  171. package/dist/stamp-partition.d.ts.map +1 -0
  172. package/dist/stamp-partition.js +472 -0
  173. package/dist/stamp-partition.js.map +1 -0
  174. package/dist/supply-reference.d.ts +19 -0
  175. package/dist/supply-reference.d.ts.map +1 -0
  176. package/dist/supply-reference.js +66 -0
  177. package/dist/supply-reference.js.map +1 -0
  178. package/dist/supply-short.d.ts +32 -0
  179. package/dist/supply-short.d.ts.map +1 -0
  180. package/dist/supply-short.js +118 -0
  181. package/dist/supply-short.js.map +1 -0
  182. package/dist/supply-stamps.d.ts +51 -0
  183. package/dist/supply-stamps.d.ts.map +1 -0
  184. package/dist/supply-stamps.js +363 -0
  185. package/dist/supply-stamps.js.map +1 -0
  186. package/dist/terminal-role.d.ts +109 -0
  187. package/dist/terminal-role.d.ts.map +1 -0
  188. package/dist/terminal-role.js +46 -0
  189. package/dist/terminal-role.js.map +1 -0
  190. package/dist/terminal-roles.d.ts +59 -0
  191. package/dist/terminal-roles.d.ts.map +1 -0
  192. package/dist/terminal-roles.js +92 -0
  193. package/dist/terminal-roles.js.map +1 -0
  194. package/dist/transformer.d.ts +181 -0
  195. package/dist/transformer.d.ts.map +1 -0
  196. package/dist/transformer.js +476 -0
  197. package/dist/transformer.js.map +1 -0
  198. package/dist/types.d.ts +3157 -0
  199. package/dist/types.d.ts.map +1 -0
  200. package/dist/types.js +11 -0
  201. package/dist/types.js.map +1 -0
  202. package/dist/unbounded-operating-point.d.ts +35 -0
  203. package/dist/unbounded-operating-point.d.ts.map +1 -0
  204. package/dist/unbounded-operating-point.js +181 -0
  205. package/dist/unbounded-operating-point.js.map +1 -0
  206. package/dist/unexecuted-region.d.ts +3 -0
  207. package/dist/unexecuted-region.d.ts.map +1 -0
  208. package/dist/unexecuted-region.js +122 -0
  209. package/dist/unexecuted-region.js.map +1 -0
  210. package/dist/unimplemented-control-role.d.ts +3 -0
  211. package/dist/unimplemented-control-role.d.ts.map +1 -0
  212. package/dist/unimplemented-control-role.js +61 -0
  213. package/dist/unimplemented-control-role.js.map +1 -0
  214. package/dist/unreachable-output.d.ts +3 -0
  215. package/dist/unreachable-output.d.ts.map +1 -0
  216. package/dist/unreachable-output.js +97 -0
  217. package/dist/unreachable-output.js.map +1 -0
  218. package/dist/unreadable-terminal-role.d.ts +67 -0
  219. package/dist/unreadable-terminal-role.d.ts.map +1 -0
  220. package/dist/unreadable-terminal-role.js +409 -0
  221. package/dist/unreadable-terminal-role.js.map +1 -0
  222. package/dist/unverified-pinout.d.ts +27 -0
  223. package/dist/unverified-pinout.d.ts.map +1 -0
  224. package/dist/unverified-pinout.js +121 -0
  225. package/dist/unverified-pinout.js.map +1 -0
  226. package/package.json +75 -5
@@ -0,0 +1,47 @@
1
+ import type { Block, CompileWarning, NodeId, Program } from "./types";
2
+ /**
3
+ * Active-device stamps with a terminal on a node no other stamp touches.
4
+ *
5
+ * **Read from the lowered stamps, not the netlist.** The sibling rule in `over-driven-node.ts`
6
+ * learned this the hard way: `boss-sd-1` declares two supplies on one node and lowering collapses
7
+ * them, so a netlist-level count reported a contradiction that the compiled circuit does not
8
+ * contain. Stamps are what the runtime executes, so they are the only thing that can say whether a
9
+ * terminal really reaches nothing.
10
+ *
11
+ * Per block, because regions are independent solves and the same node id in two regions is two
12
+ * different unknowns.
13
+ *
14
+ * **Op-amp supply pins are excluded, and that exclusion is measured rather than assumed.** An
15
+ * `ideal-opamp` stamp carries no supply nodes at all — its rails are voltages resolved from the
16
+ * circuit's supply set — so a dangling `vcc` is invisible to the solve and cannot be what makes a
17
+ * packet silent. Including it flagged `mxr-distortion-plus` and `mxr-micro-amp`, both of which
18
+ * render plausibly, for a pin the model does not read. The exclusion is free here: those nodes
19
+ * never appear in a stamp.
20
+ *
21
+ * Ground is skipped: every device returns there and it is touched by everything.
22
+ */
23
+ export declare function findDanglingActiveTerminals(program: Program): readonly CompileWarning[];
24
+ /**
25
+ * Every node a stamp names, from the closed field list above.
26
+ *
27
+ * Exported because `scripts/report-net-graph-health.ts` needs the same answer: its dangling-net
28
+ * count is a gate for source re-capture, and counting *declared* terminals lets a package shell
29
+ * that lowers to no stamp hold a severed net's count down. One enumerator, so the gate and this
30
+ * rule cannot drift apart.
31
+ */
32
+ export declare function stampNodes(stamp: Extract<Block, {
33
+ kind: "mna";
34
+ }>["stamps"][number]): readonly NodeId[];
35
+ /**
36
+ * Adds an implicit high-value DC-bias conductance for every op-amp in `program` whose operating
37
+ * point is genuinely undefined by the topology -- see this section's header for the two shapes
38
+ * and why. Runs once, after linking, on the program the runtime will actually execute; every
39
+ * later Program-consuming warning (including this file's own `findDanglingActiveTerminals`) sees
40
+ * the bridged circuit, because that is the circuit that now exists.
41
+ *
42
+ * **Fires on any op-amp matching either condition, corpus-wide.** There is no packet slug, part
43
+ * number, or component name anywhere in this function -- the two conditions are read entirely off
44
+ * stamp connectivity, the same evidence discipline `findDanglingActiveTerminals` already keeps.
45
+ */
46
+ export declare function synthesizeOpampImplicitBias(program: Program): Program;
47
+ //# sourceMappingURL=dangling-active-terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dangling-active-terminal.d.ts","sourceRoot":"","sources":["../src/dangling-active-terminal.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,OAAO,GACd,SAAS,cAAc,EAAE,CAsC3B;AAyED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GACtD,SAAS,MAAM,EAAE,CAQnB;AAmTD;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAOrE"}
@@ -0,0 +1,542 @@
1
+ // An active device with a signal terminal wired to nothing, which cannot work.
2
+ //
3
+ // A collector with nowhere to go, a gate driven by nothing, a drain reaching no load: the device
4
+ // is present, it is stamped, and it cannot do its job. `gmin` is why this renders instead of
5
+ // failing — every node gets a `1e-12 S` path to ground before the matrix is read, so the row is
6
+ // never empty, Newton converges, no sample is held, and the output is silence rather than a
7
+ // diagnostic.
8
+ //
9
+ // **A general "dangling terminal" warning was measured and rejected first.** 2020 dangling nodes
10
+ // across 73 of 102 readable packets, with a median of 2 in not-plausible rows against 0 in
11
+ // plausible ones, and `boss-mt-2` carrying 11 while rendering fine. Most are harmless — a test
12
+ // point, an unpopulated position, an unused pin on a dual op-amp — so the rule had no useful
13
+ // signal-to-noise ratio.
14
+ //
15
+ // Narrowing it to **active devices** changes that, because a passive dangling end is often
16
+ // deliberate and an active one is a stage that does nothing. Measured over the compiled corpus:
17
+ //
18
+ // ```
19
+ // flagged 9 of 52
20
+ // also renders implausibly 8
21
+ // ```
22
+ //
23
+ // `tycobrahe-octavia` is the sharpest case: `Q2.collector` touches no other device, so the
24
+ // transistor cannot conduct, its transformer primary never swings, and the pedal draws 10 uA where
25
+ // a two-transistor germanium fuzz should draw milliamps. `boss-ds-1` is the loudest: nearly every
26
+ // transistor terminal in the packet dangles, which is also why it partitions into 82 regions.
27
+ //
28
+ // Evidence is stamp connectivity and nothing else. No component name, no `Description`, no part
29
+ // number.
30
+ import { withStamp } from "./couple.js";
31
+ import { GROUND } from "./types.js";
32
+ import { blockRow, describeRow } from "./block-row.js";
33
+ /**
34
+ * Active-device stamps with a terminal on a node no other stamp touches.
35
+ *
36
+ * **Read from the lowered stamps, not the netlist.** The sibling rule in `over-driven-node.ts`
37
+ * learned this the hard way: `boss-sd-1` declares two supplies on one node and lowering collapses
38
+ * them, so a netlist-level count reported a contradiction that the compiled circuit does not
39
+ * contain. Stamps are what the runtime executes, so they are the only thing that can say whether a
40
+ * terminal really reaches nothing.
41
+ *
42
+ * Per block, because regions are independent solves and the same node id in two regions is two
43
+ * different unknowns.
44
+ *
45
+ * **Op-amp supply pins are excluded, and that exclusion is measured rather than assumed.** An
46
+ * `ideal-opamp` stamp carries no supply nodes at all — its rails are voltages resolved from the
47
+ * circuit's supply set — so a dangling `vcc` is invisible to the solve and cannot be what makes a
48
+ * packet silent. Including it flagged `mxr-distortion-plus` and `mxr-micro-amp`, both of which
49
+ * render plausibly, for a pin the model does not read. The exclusion is free here: those nodes
50
+ * never appear in a stamp.
51
+ *
52
+ * Ground is skipped: every device returns there and it is touched by everything.
53
+ */
54
+ export function findDanglingActiveTerminals(program) {
55
+ const warnings = [];
56
+ for (const block of program.blocks) {
57
+ if (block.kind !== "mna") {
58
+ continue;
59
+ }
60
+ const touchCount = new Map();
61
+ for (const stamp of block.stamps) {
62
+ for (const node of new Set(stampNodes(stamp))) {
63
+ touchCount.set(node, (touchCount.get(node) ?? 0) + 1);
64
+ }
65
+ }
66
+ for (const stamp of block.stamps) {
67
+ const active = activeTerminals(stamp);
68
+ if (active === null) {
69
+ continue;
70
+ }
71
+ const dangling = active.terminals.filter(([, node]) => node !== 0 && touchCount.get(node) === 1);
72
+ if (dangling.length === 0) {
73
+ continue;
74
+ }
75
+ warnings.push({
76
+ code: "active-device-terminal-unwired",
77
+ device: null,
78
+ detail:
79
+ // Named by the source node, not the row it landed on: this message exists to
80
+ // send someone to a net in the `.vdsp`, and a row index is not a net.
81
+ `in block ${block.id}, ${active.label} has ${dangling
82
+ .map(([role, node]) => `${role} on node ${describeRow(block, blockRow(node))}`)
83
+ .join(" and ")}, which no other element touches: the device is stamped and ` +
84
+ "cannot conduct, so the circuit renders silence rather than failing, because " +
85
+ "gmin gives the node a path to ground and the solve converges",
86
+ });
87
+ }
88
+ }
89
+ return warnings;
90
+ }
91
+ /**
92
+ * Every node a stamp touches, so a node's fan-out can be counted.
93
+ *
94
+ * **Field names come from a closed set, never from scraping integers.** A first version collected
95
+ * every non-negative integer field, which silently counted `sourceIndex` and `stateIndex` as node
96
+ * touches — so a stamp with `sourceIndex: 10` inflated node 10's fan-out and hid
97
+ * `tycobrahe-octavia`'s dangling `Q2.collector`, the packet this rule was built for. An index and a
98
+ * node are both small integers and nothing but the field name distinguishes them.
99
+ */
100
+ const nodeFields = new Set([
101
+ "a",
102
+ "b",
103
+ "anode",
104
+ "cathode",
105
+ "node",
106
+ "positive",
107
+ "negative",
108
+ "common",
109
+ "throwNode",
110
+ "base",
111
+ "collector",
112
+ "emitter",
113
+ "gate",
114
+ "drain",
115
+ "source",
116
+ "plus",
117
+ "minus",
118
+ "output",
119
+ "primaryPlus",
120
+ "primaryMinus",
121
+ "secondaryPlus",
122
+ "secondaryMinus",
123
+ "grid",
124
+ "plate",
125
+ "screen",
126
+ // Below: derived by enumerating every integer-valued field of every stamp the pedal corpus
127
+ // emits, then keeping the ones whose value indexes a node rather than a quantity. Their
128
+ // absence meant a net held up only by a `vccs`, `compandor`, `ota`, `bbd`, `clock-driver`,
129
+ // `optocoupler` or `logic-divider` terminal read as unoccupied, so this rule could call a
130
+ // wired terminal dangling. `deluxe-memory-man`'s compander summing node is one such net.
131
+ "control",
132
+ "clk1",
133
+ "clk2",
134
+ "input",
135
+ "out1",
136
+ "out2",
137
+ "cp1",
138
+ "cp2",
139
+ "vgg",
140
+ "vdd",
141
+ "ox1",
142
+ "rectIn",
143
+ "rectCap",
144
+ "cellIn",
145
+ "sumNode",
146
+ "vref",
147
+ "vee",
148
+ "bias",
149
+ "clockNode",
150
+ "qNode",
151
+ "gndNode",
152
+ "ledAnode",
153
+ "ledCathode",
154
+ "ldrA",
155
+ "ldrB",
156
+ "outP",
157
+ "outN",
158
+ "inP",
159
+ "inN",
160
+ ]);
161
+ /**
162
+ * Every node a stamp names, from the closed field list above.
163
+ *
164
+ * Exported because `scripts/report-net-graph-health.ts` needs the same answer: its dangling-net
165
+ * count is a gate for source re-capture, and counting *declared* terminals lets a package shell
166
+ * that lowers to no stamp hold a severed net's count down. One enumerator, so the gate and this
167
+ * rule cannot drift apart.
168
+ */
169
+ export function stampNodes(stamp) {
170
+ const nodes = [];
171
+ for (const [key, value] of Object.entries(stamp)) {
172
+ if (nodeFields.has(key) && typeof value === "number") {
173
+ nodes.push(value);
174
+ }
175
+ }
176
+ return nodes;
177
+ }
178
+ /**
179
+ * A stamp's signal terminals when it is an active device, or `null` when it is not.
180
+ *
181
+ * Deliberately excludes `dc-source`, `input-source` and `transformer`: a supply's job is to sit on
182
+ * one node, an input source drives one, and a transformer winding with a dangling end is a real but
183
+ * different question — `tycobrahe-octavia`'s shield is exactly that and is not a defect.
184
+ */
185
+ function activeTerminals(stamp) {
186
+ switch (stamp.kind) {
187
+ case "bjt":
188
+ return {
189
+ label: `bjt#${stamp.base}/${stamp.collector}/${stamp.emitter}`,
190
+ terminals: [
191
+ ["base", stamp.base],
192
+ ["collector", stamp.collector],
193
+ ["emitter", stamp.emitter],
194
+ ],
195
+ };
196
+ case "fet":
197
+ return {
198
+ label: `fet#${stamp.gate}/${stamp.drain}/${stamp.source}`,
199
+ terminals: [
200
+ ["gate", stamp.gate],
201
+ ["drain", stamp.drain],
202
+ ["source", stamp.source],
203
+ ],
204
+ };
205
+ case "ideal-opamp":
206
+ // The output is a driven node and the inputs are read, so all three are signal pins.
207
+ // The supply pins are absent from the stamp entirely, which is why they cannot be
208
+ // checked here and why excluding them costs nothing.
209
+ return {
210
+ label: `ideal-opamp#${stamp.sourceIndex}`,
211
+ terminals: [
212
+ ["noninverting input", stamp.plus],
213
+ ["inverting input", stamp.minus],
214
+ ["output", stamp.output],
215
+ ],
216
+ };
217
+ // **Kinds added 2026-09-12.** The switch previously covered bjt, fet, ideal-opamp and vccs
218
+ // only, so a diode, triode, pentode, tube-diode, optocoupler or OTA with a terminal on a
219
+ // node nothing else touches was reported by NOTHING. Measured over the corpus, that is 61
220
+ // devices across 29 packets -- 40 diodes, 11 triodes, 6 OTAs, 4 optocouplers -- including
221
+ // `boss-bf-2`'s five 1S2473 signal diodes sitting on private node pairs, and
222
+ // `mxr-dyna-comp`'s CA3080, the compressor's core device, with two unwired terminals.
223
+ //
224
+ // A diode is two-terminal and passive-looking, which is presumably why it was left out. It
225
+ // is still the difference between a clipping stage and an open circuit.
226
+ case "diode":
227
+ return {
228
+ label: `diode#${stamp.anode}/${stamp.cathode}`,
229
+ terminals: [
230
+ ["anode", stamp.anode],
231
+ ["cathode", stamp.cathode],
232
+ ],
233
+ };
234
+ case "tube-diode":
235
+ return {
236
+ label: `tube-diode#${stamp.plate}/${stamp.cathode}`,
237
+ terminals: [
238
+ ["plate", stamp.plate],
239
+ ["cathode", stamp.cathode],
240
+ ],
241
+ };
242
+ case "triode":
243
+ return {
244
+ label: `triode#${stamp.grid}/${stamp.plate}/${stamp.cathode}`,
245
+ terminals: [
246
+ ["grid", stamp.grid],
247
+ ["plate", stamp.plate],
248
+ ["cathode", stamp.cathode],
249
+ ],
250
+ };
251
+ case "pentode":
252
+ // The suppressor is commonly tied to the cathode inside the envelope and is not a
253
+ // separate stamp terminal, so the four checked here are the four the stamp carries.
254
+ return {
255
+ label: `pentode#${stamp.grid}/${stamp.plate}/${stamp.cathode}`,
256
+ terminals: [
257
+ ["grid", stamp.grid],
258
+ ["plate", stamp.plate],
259
+ ["cathode", stamp.cathode],
260
+ ["screen", stamp.screen],
261
+ ],
262
+ };
263
+ case "optocoupler":
264
+ // Both halves, because they fail differently and independently: an unwired LED side is
265
+ // a control that never modulates, an unwired cell side is an audio path that never
266
+ // varies. `fender-super-reverb`'s tremolo is exactly this shape.
267
+ return {
268
+ label: `optocoupler#${stamp.ledAnode}/${stamp.ldrA}`,
269
+ terminals: [
270
+ ["LED anode", stamp.ledAnode],
271
+ ["LED cathode", stamp.ledCathode],
272
+ ["cell A", stamp.ldrA],
273
+ ["cell B", stamp.ldrB],
274
+ ],
275
+ };
276
+ case "ota":
277
+ // `bias` and `vee` are supply pins but, unlike an op-amp's, they are present in the
278
+ // stamp and a dangling bias current input silences the device outright.
279
+ return {
280
+ label: `ota#${stamp.plus}/${stamp.minus}/${stamp.output}`,
281
+ terminals: [
282
+ ["noninverting input", stamp.plus],
283
+ ["inverting input", stamp.minus],
284
+ ["output", stamp.output],
285
+ ["bias", stamp.bias],
286
+ ],
287
+ };
288
+ case "vccs":
289
+ return {
290
+ label: `vccs#${stamp.outP}/${stamp.outN}/${stamp.inP}/${stamp.inN}`,
291
+ terminals: [
292
+ ["positive output", stamp.outP],
293
+ ["negative output", stamp.outN],
294
+ ["positive input", stamp.inP],
295
+ ["negative input", stamp.inN],
296
+ ],
297
+ };
298
+ default:
299
+ return null;
300
+ }
301
+ }
302
+ // --- implicit op-amp DC-bias synthesis --------------------------------------------------------
303
+ //
304
+ // Two op-amp topologies have no DC-conducting path to define their operating point at all:
305
+ //
306
+ // (a) no path from the output back to the inverting input except through a capacitor, so the
307
+ // feedback is AC-only and any standing differential integrates without bound
308
+ // (`opamp-operating-point-unbounded`, `unbounded-operating-point.ts`'s netlist-level
309
+ // warning, measured on `ibanez-pql` and `boss-mt-2`);
310
+ // (b) no path from the non-inverting input to any reference at all -- not a rail, not ground,
311
+ // not another stage's driven output -- so the input floats and the solver is free to put
312
+ // it anywhere (the floating-input case, first measured by hand on `tape-echo` and
313
+ // `mxr-noise-gate-line-driver`).
314
+ //
315
+ // Both were previously diagnostics only. `boss-cs-3` and `boss-oc-2` are two more instances --
316
+ // found by the same measurement, not special-cased -- where the ideal-op-amp law's implicit
317
+ // assumption of zero input bias current and infinite open-loop gain leaves the DC point
318
+ // genuinely undefined, and the runtime's universal `gmin` (`1e-12 S`, see this file's header) is
319
+ // far too weak to pin it inside an ordinary render: against a typical corpus feedback or coupling
320
+ // capacitor, `gmin` alone needs an RC time constant of thousands of seconds.
321
+ //
322
+ // **The fix is topological, not numerical.** A real op-amp stage in either shape needs *some*
323
+ // finite DC path -- a bleeder resistor across an integrator's feedback cap, or a bias resistor to
324
+ // ground on a coupled input -- and a source that omits one is missing an implicit fact about how
325
+ // the real device settles, not a fact this compiler can read off the netlist. So this synthesizes
326
+ // the same kind of implicit reference `gmin` already is, sized to matter: strong enough to settle
327
+ // within a render, weak enough to load no real audio path measurably.
328
+ //
329
+ // **Read from the lowered stamps, for the same reason the rest of this file is.** A pot's two
330
+ // halves, a BBD's clock-gated conductance, a switch's selected throw -- all of that is already
331
+ // resolved into plain stamps here, so this needs no per-device-kind wiring knowledge beyond what
332
+ // `stampNodes` already extracts.
333
+ //
334
+ // **This does not retract `opamp-operating-point-unbounded`.** That warning is computed from the
335
+ // *declared* netlist, before this stage runs, and it remains true of the source: nothing the
336
+ // designer drew pins this operating point, however solvable the compiler has since made it. The
337
+ // two are the same relationship `gmin` already has with `active-device-terminal-unwired` -- a
338
+ // dangling collector is still genuinely dangling once `gmin` lets the solve converge.
339
+ /** 10 M-ohm. See the section header for why this value and not `gmin`. */
340
+ const IMPLICIT_BIAS_SIEMENS = 1e-7;
341
+ /**
342
+ * Every node id this block's `dc-source`/`ac-source` stamps declare as a fixed rail, plus
343
+ * ground. Shared by both conduction graphs below: a rail is either the thing a route must not be
344
+ * allowed to pass through unbroken (case a) or a legitimate destination (case b), and both need
345
+ * the same set to say so.
346
+ */
347
+ function railsOf(block) {
348
+ const rails = new Set([GROUND]);
349
+ for (const stamp of block.stamps) {
350
+ if (stamp.kind !== "dc-source" && stamp.kind !== "ac-source") {
351
+ continue;
352
+ }
353
+ if (stamp.positive !== GROUND) {
354
+ rails.add(stamp.positive);
355
+ }
356
+ if (stamp.negative !== GROUND) {
357
+ rails.add(stamp.negative);
358
+ }
359
+ }
360
+ return rails;
361
+ }
362
+ /**
363
+ * One block's DC (or, with `capacitorsConduct`, AC) conduction graph at stamp granularity.
364
+ *
365
+ * **No op-amp is a conductor** -- excluded the same way `unbounded-operating-point.ts` excludes
366
+ * one, and for the same reason: an op-amp's inputs draw no current, so linking its own terminals
367
+ * would invent a path through the device and let an op-amp bootstrap its own reference. **No
368
+ * transformer winding is either**, though `stampNodes` would otherwise link all four of its
369
+ * terminals: a transformer's primary and secondary are galvanically isolated at DC, and the
370
+ * generic all-pairs treatment below has no notion of which pairs are actually the same winding,
371
+ * so the conservative answer is to treat it as no path at all rather than invent one across the
372
+ * isolation barrier.
373
+ *
374
+ * **`rails` says whether a rail is a hole or a normal node.** Passing the block's real rails
375
+ * (from `railsOf`) makes every edge touching one vanish -- "rails are not routes", the exclusion
376
+ * `findUnboundedOpamps` needs so that a path reaching the input through a fixed potential does
377
+ * not count as feedback. Passing an empty set makes rails ordinary graph nodes, reachable like
378
+ * anything else -- what the floating-input case needs, since reaching ground is exactly the
379
+ * question it asks.
380
+ */
381
+ function stampConductionGraph(block, options) {
382
+ const adjacency = new Map();
383
+ const link = (a, b) => {
384
+ if (a === b || options.rails.has(a) || options.rails.has(b)) {
385
+ return;
386
+ }
387
+ for (const [from, to] of [
388
+ [a, b],
389
+ [b, a],
390
+ ]) {
391
+ const edges = adjacency.get(from);
392
+ if (edges === undefined) {
393
+ adjacency.set(from, [to]);
394
+ }
395
+ else {
396
+ edges.push(to);
397
+ }
398
+ }
399
+ };
400
+ for (const stamp of block.stamps) {
401
+ if (stamp.kind === "ideal-opamp" || stamp.kind === "transformer") {
402
+ continue;
403
+ }
404
+ if (stamp.kind === "capacitor" && !options.capacitorsConduct) {
405
+ continue;
406
+ }
407
+ const nodes = [...new Set(stampNodes(stamp))];
408
+ for (let i = 0; i < nodes.length; i += 1) {
409
+ for (let j = i + 1; j < nodes.length; j += 1) {
410
+ link(nodes[i], nodes[j]);
411
+ }
412
+ }
413
+ }
414
+ return adjacency;
415
+ }
416
+ /** Every node reachable from `from`, breadth-first. */
417
+ function reachableSet(graph, from) {
418
+ const seen = new Set([from]);
419
+ const queue = [from];
420
+ let head = 0;
421
+ while (head < queue.length) {
422
+ const node = queue[head];
423
+ head += 1;
424
+ for (const next of graph.get(node) ?? []) {
425
+ if (!seen.has(next)) {
426
+ seen.add(next);
427
+ queue.push(next);
428
+ }
429
+ }
430
+ }
431
+ return seen;
432
+ }
433
+ /**
434
+ * Whether `start` reaches any node in `targets`, stopping expansion at ground -- the same rule
435
+ * `report-compiler-coverage.ts`'s `reachesSupplyNode` uses, so a route through ground cannot
436
+ * smuggle two otherwise-unrelated nets together into one answer.
437
+ */
438
+ function reachesAny(graph, start, targets) {
439
+ if (targets.has(start)) {
440
+ return true;
441
+ }
442
+ const seen = new Set([start]);
443
+ const queue = [start];
444
+ let head = 0;
445
+ while (head < queue.length) {
446
+ const at = queue[head];
447
+ head += 1;
448
+ if (at === GROUND) {
449
+ continue;
450
+ }
451
+ for (const next of graph.get(at) ?? []) {
452
+ if (targets.has(next)) {
453
+ return true;
454
+ }
455
+ if (!seen.has(next)) {
456
+ seen.add(next);
457
+ queue.push(next);
458
+ }
459
+ }
460
+ }
461
+ return false;
462
+ }
463
+ /**
464
+ * Adds an implicit high-value DC-bias conductance for every op-amp in `program` whose operating
465
+ * point is genuinely undefined by the topology -- see this section's header for the two shapes
466
+ * and why. Runs once, after linking, on the program the runtime will actually execute; every
467
+ * later Program-consuming warning (including this file's own `findDanglingActiveTerminals`) sees
468
+ * the bridged circuit, because that is the circuit that now exists.
469
+ *
470
+ * **Fires on any op-amp matching either condition, corpus-wide.** There is no packet slug, part
471
+ * number, or component name anywhere in this function -- the two conditions are read entirely off
472
+ * stamp connectivity, the same evidence discipline `findDanglingActiveTerminals` already keeps.
473
+ */
474
+ export function synthesizeOpampImplicitBias(program) {
475
+ return {
476
+ ...program,
477
+ blocks: program.blocks.map((block) => block.kind === "mna" ? synthesizeForBlock(block) : block),
478
+ };
479
+ }
480
+ function synthesizeForBlock(block) {
481
+ const opamps = block.stamps.filter((stamp) => stamp.kind === "ideal-opamp");
482
+ if (opamps.length === 0) {
483
+ return block;
484
+ }
485
+ const rails = railsOf(block);
486
+ const opampOutputs = new Set(opamps.map((stamp) => stamp.output));
487
+ // Case (b)'s references: a rail, ground, or another stage's driven output -- the same set
488
+ // `findFloatingOpampInputs` builds. A plus input that only reaches its own op-amp's output
489
+ // would be a self-satisfying test, but that can only happen through a resistor, which is real
490
+ // feedback and does define the point, so no exclusion for it is needed here.
491
+ const floatingReferences = new Set([...rails, ...opampOutputs]);
492
+ const dcNormal = stampConductionGraph(block, {
493
+ capacitorsConduct: false,
494
+ rails: new Set(),
495
+ });
496
+ // Case (a)'s graphs: rails are holes, and the audio-path test needs both a DC and an AC
497
+ // version of the same rail-excluded graph.
498
+ const dcHoles = stampConductionGraph(block, { capacitorsConduct: false, rails });
499
+ const acHoles = stampConductionGraph(block, { capacitorsConduct: true, rails });
500
+ const fromInput = block.inputNode === null
501
+ ? new Set()
502
+ : reachableSet(acHoles, block.inputNode);
503
+ const toOutput = block.outputNode === null
504
+ ? new Set()
505
+ : reachableSet(acHoles, block.outputNode);
506
+ let next = block;
507
+ for (const stamp of opamps) {
508
+ const { plus, minus, output } = stamp;
509
+ if (!reachesAny(dcNormal, plus, floatingReferences)) {
510
+ next = withStamp(next, {
511
+ kind: "conductance",
512
+ a: plus,
513
+ b: GROUND,
514
+ siemens: IMPLICIT_BIAS_SIEMENS,
515
+ });
516
+ }
517
+ // A port on a rail is a different defect (`over-driven-node.ts`'s business), not this
518
+ // one's, the same exclusion `findUnboundedOpamps` makes.
519
+ if (rails.has(output) || rails.has(minus)) {
520
+ continue;
521
+ }
522
+ if (reachableSet(dcHoles, output).has(minus)) {
523
+ continue;
524
+ }
525
+ // Off the signal path does not count: an LFO integrator is supposed to run away and be
526
+ // reset by its comparator, and a comparator is open-loop by design. Both have no DC
527
+ // feedback and neither is a defect -- 38 of 51 corpus op-amps with no DC feedback are off
528
+ // the signal path this same exclusion removes in `unbounded-operating-point.ts`.
529
+ const carriesAudio = (fromInput.has(plus) || fromInput.has(minus)) && toOutput.has(output);
530
+ if (!carriesAudio) {
531
+ continue;
532
+ }
533
+ next = withStamp(next, {
534
+ kind: "conductance",
535
+ a: output,
536
+ b: minus,
537
+ siemens: IMPLICIT_BIAS_SIEMENS,
538
+ });
539
+ }
540
+ return next;
541
+ }
542
+ //# sourceMappingURL=dangling-active-terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dangling-active-terminal.js","sourceRoot":"","sources":["../src/dangling-active-terminal.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,iGAAiG;AACjG,6FAA6F;AAC7F,gGAAgG;AAChG,4FAA4F;AAC5F,cAAc;AACd,EAAE;AACF,iGAAiG;AACjG,2FAA2F;AAC3F,+FAA+F;AAC/F,6FAA6F;AAC7F,yBAAyB;AACzB,EAAE;AACF,2FAA2F;AAC3F,gGAAgG;AAChG,EAAE;AACF,MAAM;AACN,wCAAwC;AACxC,kCAAkC;AAClC,MAAM;AACN,EAAE;AACF,2FAA2F;AAC3F,mGAAmG;AACnG,kGAAkG;AAClG,8FAA8F;AAC9F,EAAE;AACF,gGAAgG;AAChG,UAAU;AAEV,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,2BAA2B,CAC1C,OAAgB;IAEhB,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC1B,SAAS;QACV,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC7C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC/C,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACvD,CAAC;QACF,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACrB,SAAS;YACV,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CACvC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CACtD,CAAC;YACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,SAAS;YACV,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,gCAAgC;gBACtC,MAAM,EAAE,IAAI;gBACZ,MAAM;gBACL,6EAA6E;gBAC7E,sEAAsE;gBACtE,YAAY,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,QAAQ,QAAQ;qBACnD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,YAAY,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;qBAC9E,IAAI,CAAC,OAAO,CAAC,8DAA8D;oBAC7E,8EAA8E;oBAC9E,8DAA8D;aAC/D,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC;IAC/C,GAAG;IACH,GAAG;IACH,OAAO;IACP,SAAS;IACT,MAAM;IACN,UAAU;IACV,UAAU;IACV,QAAQ;IACR,WAAW;IACX,MAAM;IACN,WAAW;IACX,SAAS;IACT,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,QAAQ;IACR,aAAa;IACb,cAAc;IACd,eAAe;IACf,gBAAgB;IAChB,MAAM;IACN,OAAO;IACP,QAAQ;IACR,2FAA2F;IAC3F,wFAAwF;IACxF,2FAA2F;IAC3F,0FAA0F;IAC1F,yFAAyF;IACzF,SAAS;IACT,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,SAAS;IACT,MAAM;IACN,KAAK;IACL,MAAM;IACN,WAAW;IACX,OAAO;IACP,SAAS;IACT,UAAU;IACV,YAAY;IACZ,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;CACL,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACzB,KAAwD;IAExD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CACvB,KAAwD;IAIxD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,KAAK;YACT,OAAO;gBACN,KAAK,EAAE,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,EAAE;gBAC9D,SAAS,EAAE;oBACV,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;oBACpB,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC;oBAC9B,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;iBAC1B;aACD,CAAC;QACH,KAAK,KAAK;YACT,OAAO;gBACN,KAAK,EAAE,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE;gBACzD,SAAS,EAAE;oBACV,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;oBACpB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;oBACtB,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;iBACxB;aACD,CAAC;QACH,KAAK,aAAa;YACjB,qFAAqF;YACrF,kFAAkF;YAClF,qDAAqD;YACrD,OAAO;gBACN,KAAK,EAAE,eAAe,KAAK,CAAC,WAAW,EAAE;gBACzC,SAAS,EAAE;oBACV,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC;oBAClC,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC;oBAChC,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;iBACxB;aACD,CAAC;QACH,2FAA2F;QAC3F,yFAAyF;QACzF,0FAA0F;QAC1F,0FAA0F;QAC1F,6EAA6E;QAC7E,sFAAsF;QACtF,EAAE;QACF,2FAA2F;QAC3F,wEAAwE;QACxE,KAAK,OAAO;YACX,OAAO;gBACN,KAAK,EAAE,SAAS,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;gBAC9C,SAAS,EAAE;oBACV,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;oBACtB,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;iBAC1B;aACD,CAAC;QACH,KAAK,YAAY;YAChB,OAAO;gBACN,KAAK,EAAE,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;gBACnD,SAAS,EAAE;oBACV,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;oBACtB,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;iBAC1B;aACD,CAAC;QACH,KAAK,QAAQ;YACZ,OAAO;gBACN,KAAK,EAAE,UAAU,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;gBAC7D,SAAS,EAAE;oBACV,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;oBACpB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;oBACtB,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;iBAC1B;aACD,CAAC;QACH,KAAK,SAAS;YACb,kFAAkF;YAClF,oFAAoF;YACpF,OAAO;gBACN,KAAK,EAAE,WAAW,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE;gBAC9D,SAAS,EAAE;oBACV,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;oBACpB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;oBACtB,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;oBAC1B,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;iBACxB;aACD,CAAC;QACH,KAAK,aAAa;YACjB,uFAAuF;YACvF,mFAAmF;YACnF,iEAAiE;YACjE,OAAO;gBACN,KAAK,EAAE,eAAe,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;gBACpD,SAAS,EAAE;oBACV,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC;oBAC7B,CAAC,aAAa,EAAE,KAAK,CAAC,UAAU,CAAC;oBACjC,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;oBACtB,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;iBACtB;aACD,CAAC;QACH,KAAK,KAAK;YACT,oFAAoF;YACpF,wEAAwE;YACxE,OAAO;gBACN,KAAK,EAAE,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE;gBACzD,SAAS,EAAE;oBACV,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC;oBAClC,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC;oBAChC,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;oBACxB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;iBACpB;aACD,CAAC;QACH,KAAK,MAAM;YACV,OAAO;gBACN,KAAK,EAAE,QAAQ,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE;gBACnE,SAAS,EAAE;oBACV,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC;oBAC/B,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC;oBAC/B,CAAC,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC;oBAC7B,CAAC,gBAAgB,EAAE,KAAK,CAAC,GAAG,CAAC;iBAC7B;aACD,CAAC;QACH;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC;AAED,iGAAiG;AACjG,EAAE;AACF,2FAA2F;AAC3F,EAAE;AACF,+FAA+F;AAC/F,mFAAmF;AACnF,2FAA2F;AAC3F,4DAA4D;AAC5D,gGAAgG;AAChG,+FAA+F;AAC/F,wFAAwF;AACxF,uCAAuC;AACvC,EAAE;AACF,+FAA+F;AAC/F,4FAA4F;AAC5F,wFAAwF;AACxF,iGAAiG;AACjG,kGAAkG;AAClG,6EAA6E;AAC7E,EAAE;AACF,8FAA8F;AAC9F,kGAAkG;AAClG,iGAAiG;AACjG,kGAAkG;AAClG,kGAAkG;AAClG,sEAAsE;AACtE,EAAE;AACF,8FAA8F;AAC9F,+FAA+F;AAC/F,iGAAiG;AACjG,iCAAiC;AACjC,EAAE;AACF,iGAAiG;AACjG,6FAA6F;AAC7F,gGAAgG;AAChG,8FAA8F;AAC9F,sFAAsF;AAEtF,0EAA0E;AAC1E,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAKnC;;;;;GAKG;AACH,SAAS,OAAO,CAAC,KAAe;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9D,SAAS;QACV,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC/B,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC/B,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,oBAAoB,CAC5B,KAAe,EACf,OAAqF;IAErF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAS,EAAQ,EAAE;QAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,OAAO;QACR,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI;YACxB,CAAC,CAAC,EAAE,CAAC,CAAC;YACN,CAAC,CAAC,EAAE,CAAC,CAAC;SACG,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAClE,SAAS;QACV,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC9D,SAAS;QACV,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC,CAAC;YAC9C,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,uDAAuD;AACvD,SAAS,YAAY,CAAC,KAAY,EAAE,IAAY;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAW,CAAC;QACnC,IAAI,IAAI,CAAC,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAClB,KAAY,EACZ,KAAa,EACb,OAA4B;IAE5B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAW,CAAC;QACjC,IAAI,IAAI,CAAC,CAAC;QACV,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;YACnB,SAAS;QACV,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC;YACb,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC3D,OAAO;QACN,GAAG,OAAO;QACV,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACpC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CACxD;KACD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAe;IAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CACjC,CAAC,KAAK,EAA2D,EAAE,CAClE,KAAK,CAAC,IAAI,KAAK,aAAa,CAC7B,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1E,0FAA0F;IAC1F,2FAA2F;IAC3F,8FAA8F;IAC9F,6EAA6E;IAC7E,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,KAAK,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IACxE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,EAAE;QAC5C,iBAAiB,EAAE,KAAK;QACxB,KAAK,EAAE,IAAI,GAAG,EAAE;KAChB,CAAC,CAAC;IAEH,wFAAwF;IACxF,2CAA2C;IAC3C,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChF,MAAM,SAAS,GACd,KAAK,CAAC,SAAS,KAAK,IAAI;QACvB,CAAC,CAAC,IAAI,GAAG,EAAU;QACnB,CAAC,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,QAAQ,GACb,KAAK,CAAC,UAAU,KAAK,IAAI;QACxB,CAAC,CAAC,IAAI,GAAG,EAAU;QACnB,CAAC,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAE5C,IAAI,IAAI,GAAa,KAAK,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAEtC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAAE,CAAC;YACrD,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE;gBACtB,IAAI,EAAE,aAAa;gBACnB,CAAC,EAAE,IAAI;gBACP,CAAC,EAAE,MAAM;gBACT,OAAO,EAAE,qBAAqB;aAC9B,CAAC,CAAC;QACJ,CAAC;QAED,sFAAsF;QACtF,yDAAyD;QACzD,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,SAAS;QACV,CAAC;QACD,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,SAAS;QACV,CAAC;QACD,uFAAuF;QACvF,oFAAoF;QACpF,0FAA0F;QAC1F,iFAAiF;QACjF,MAAM,YAAY,GACjB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,SAAS;QACV,CAAC;QACD,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE;YACtB,IAAI,EAAE,aAAa;YACnB,CAAC,EAAE,MAAM;YACT,CAAC,EAAE,KAAK;YACR,OAAO,EAAE,qBAAqB;SAC9B,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { DeclaredProgram, PrimitiveOp } from "./types";
2
+ /** A declaration that checked out, or the first reason it did not. */
3
+ export type DeclaredProgramCheck = {
4
+ readonly ok: true;
5
+ readonly positions: readonly CheckedPosition[];
6
+ } | {
7
+ readonly ok: false;
8
+ readonly reason: string;
9
+ };
10
+ export type CheckedPosition = {
11
+ readonly id: string;
12
+ readonly ops: readonly PrimitiveOp[];
13
+ readonly lines: readonly string[];
14
+ };
15
+ /**
16
+ * Read a declaration into executable ops, or name the first thing that stopped it.
17
+ *
18
+ * Positions are checked in declaration order and the check stops at the first failure, because a
19
+ * list of every defect in a document nobody has fixed once is noise. The reason names the position
20
+ * and the op index, which is what locates it in the source.
21
+ */
22
+ export declare function checkDeclaredProgram(program: DeclaredProgram): DeclaredProgramCheck;
23
+ //# sourceMappingURL=declared-program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declared-program.d.ts","sourceRoot":"","sources":["../src/declared-program.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIX,eAAe,EAIf,WAAW,EACX,MAAM,SAAS,CAAC;AAEjB,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAC7B;IACA,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,SAAS,WAAW,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAuHF;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,eAAe,GACtB,oBAAoB,CAiGtB"}