@vessel-dsp/compiler 0.0.0-stage → 0.2.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 +314 -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 +344 -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 +3497 -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 +1721 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13404 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +257 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +311 -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 +7 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6639 -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,319 @@
1
+ // Stage 2: Device -> PartIdentity | null.
2
+ //
3
+ // The only stage in the pipeline that asks "what is this thing". Everything else is
4
+ // arithmetic on a graph. Passives and discretes never reach it: an R, C, D or
5
+ // transistor's law follows from its typed kind plus parameters, so identification
6
+ // exists solely for parts whose behaviour is genuinely not in the netlist.
7
+ //
8
+ // The evidence ladder, hardest first. Each rung refuses to reach the next:
9
+ //
10
+ // 1. exact part id a manufacturer number, compared whole and case-folded
11
+ // 2. declared type a value from the source's closed type vocabulary
12
+ // 3. pinout signature terminal role tokens, compared as whole tokens
13
+ //
14
+ // There is no fourth rung and no score. A ranked guess has no consumer, and a wrong
15
+ // identity is worse than none: it renders a plausible wrong pedal instead of
16
+ // refusing. Returning `null` is a correct, expected answer.
17
+ //
18
+ // Topology is deliberately absent. It was measured at length and the conclusions were
19
+ // that similarity cannot gate a decision, that a memory and its clock driver are
20
+ // automorphic across their shared net so no graph function separates them, and that
21
+ // with n=1 to 3 instances per family a structural signature cannot be told from
22
+ // memorisation. If a topology rung is ever added it belongs here and nowhere else.
23
+ import { canonicalPartId } from "./part-number.js";
24
+ import { foldPartId, foldToken, } from "./registry.js";
25
+ import { opampNeedsRegistrySections } from "./unreadable-terminal-role.js";
26
+ /** Kinds whose behaviour is not determined by the netlist and so need a part. */
27
+ export function requiresIdentification(device) {
28
+ return device.kind === "ic" || device.kind === "power-amp";
29
+ }
30
+ /**
31
+ * Kinds whose behaviour a registry **may** extend, as opposed to supply outright.
32
+ *
33
+ * `ic` and `power-amp` have no behaviour except a part's, so for them the registry is the only
34
+ * source and its silence is a refusal -- that is `requiresIdentification` above. An `ota` is
35
+ * different in both directions: it carries a universal device-class law
36
+ * (`I_out = gm * (V+ - V-)`), so an unregistered one must still work; and a registered one can be
37
+ * *more* than that law, because a single `ota` stamp cannot carry a second section. A BA662A is
38
+ * an OTA **plus** a Darlington buffer, and before this `boss-cs-2`'s `bufferinput`/`buffertie`
39
+ * net was touched by no stamp in the compiled program at all.
40
+ *
41
+ * So this is consulted only where a `sections` model is being looked up. It deliberately does not
42
+ * widen `requiresIdentification`: doing that put OTAs through the `ic` shell/isolation predicates
43
+ * and the unmatched-pinout refusal, which cost `electro-harmonix-small-stone` all five of its
44
+ * CA3094 stamps at once.
45
+ */
46
+ export function mayCarryRegistrySections(device) {
47
+ return (requiresIdentification(device) ||
48
+ device.kind === "ota" ||
49
+ // An optocoupler is the `ota` case in both directions: it has a universal law of its own,
50
+ // so an unregistered discrete LED/LDR pair must still work, and a registered VTL5C1 can be
51
+ // more than that law. 13 corpus packets declare `kind: optocoupler` against a registry part
52
+ // and reach their sections through here.
53
+ device.kind === "optocoupler" ||
54
+ // Only an op-amp its own device-class law cannot bind; see
55
+ // `opampNeedsRegistrySections` for why this is scoped rather than a kind test.
56
+ opampNeedsRegistrySections(device));
57
+ }
58
+ /**
59
+ * An op-amp whose registered *part* says it is not an op-amp, so the part's law overrides the
60
+ * device-class law even though the class law can read the terminals.
61
+ *
62
+ * The class law is `ideal-opamp`; a `sections` entry whose law kind is not that is the part
63
+ * disagreeing with the drawn kind. That is typed evidence the part carries and the document's
64
+ * `kind: opamp` is a drawing convenience: an LM339 drawn as an op-amp is still an
65
+ * open-collector comparator, and the ideal-op-amp output that stamps binds the shared node is
66
+ * a voltage source where the real part is a sink-or-float. `moogerfooger-mf-102`'s `U2A`/`U2C`
67
+ * wire-OR onto one pull-up resistor because the LM339's outputs *are* open-collector; a voltage
68
+ * source makes that node over-determined and the packet renders silence.
69
+ *
70
+ * Match is the same whole-token exact part id (rung 1) or canonical die (rung 4) the evidence
71
+ * ladder uses, so a prose mention can never admit one. The default registry is consulted with the
72
+ * arity deliberately unconstrained: an arity *mismatch* against a comparator entry still wants the
73
+ * registration question to end where it would today -- rung 3 -- rather than falling through to
74
+ * `declaredType`, whose class would re-stamp the drawn `opamp`.
75
+ */
76
+ /**
77
+ * A bipolar transistor whose exact part id the registry expands into sections -- a bias-resistor
78
+ * built-in transistor (a "digital transistor") such as Toshiba's RN1307, whose datasheet puts a
79
+ * series base resistor and a base-emitter resistor inside the package. The class law is a bare
80
+ * transistor and cannot know they are there; the part number can. Every other BJT keeps its class
81
+ * law untouched, because no other BJT has a sections entry.
82
+ */
83
+ export function bjtPartRegisteredAsSections(device, registry) {
84
+ if (device.kind !== "bjt")
85
+ return false;
86
+ const partNumber = device.identity.partNumber;
87
+ if (partNumber === null)
88
+ return false;
89
+ const canonical = foldPartId(canonicalPartId(partNumber));
90
+ return registry.entries.some((entry) => entry.model.kind === "sections" &&
91
+ entry.partIds.some((id) => foldPartId(canonicalPartId(id)) === canonical));
92
+ }
93
+ export function opampPartRegisteredAsOtherLaw(device, registry) {
94
+ if (device.kind !== "opamp") {
95
+ return false;
96
+ }
97
+ const partNumber = device.identity.partNumber;
98
+ if (partNumber === null) {
99
+ return false;
100
+ }
101
+ const folded = foldPartId(partNumber);
102
+ const canonical = foldPartId(canonicalPartId(partNumber));
103
+ for (const entry of registry.entries) {
104
+ if (entry.model.kind !== "sections") {
105
+ continue;
106
+ }
107
+ const matches = entry.partIds.some((id) => foldPartId(id) === folded) ||
108
+ entry.partIds.some((id) => foldPartId(canonicalPartId(id)) === canonical);
109
+ if (matches && entry.model.sections.some((section) => section.law.kind !== "ideal-opamp")) {
110
+ return true;
111
+ }
112
+ }
113
+ return false;
114
+ }
115
+ /**
116
+ * An op-amp the device-class law already binds, whose matched registry entry would say nothing
117
+ * new: a `sections` entry that is empty or every-section `ideal-opamp` is the class law in another
118
+ * spelling, so taking the entry would move the program (new section device ids, a registry arity
119
+ * read) without changing a stamp. Keeping the class law makes this route zero-change for every
120
+ * packet whose op-amps are actually op-amps -- measured wrong once already on 2026-09-02, when
121
+ * widening the gate to every `opamp` moved 14 packets before `opampNeedsRegistrySections`
122
+ * scoped it.
123
+ */
124
+ function opampKeepsItsClass(device, entry) {
125
+ return (device.kind === "opamp" &&
126
+ !opampNeedsRegistrySections(device) &&
127
+ entry.model.kind === "sections" &&
128
+ entry.model.sections.every((section) => section.law.kind === "ideal-opamp"));
129
+ }
130
+ export function identify(device, registry) {
131
+ if (!mayCarryRegistrySections(device) &&
132
+ !opampPartRegisteredAsOtherLaw(device, registry) &&
133
+ !bjtPartRegisteredAsSections(device, registry)) {
134
+ return null;
135
+ }
136
+ const partNumber = device.identity.partNumber;
137
+ if (partNumber !== null) {
138
+ const folded = foldPartId(partNumber);
139
+ // 1. Try to find an entry with matching partId AND matching terminal arity (or macro kind)
140
+ for (const entry of registry.entries) {
141
+ if (entry.partIds.some((id) => foldPartId(id) === folded)) {
142
+ if (entry.model.kind === "sections" || entry.model.kind === "sections-core") {
143
+ if (device.nodes.length === entry.model.pinout.length) {
144
+ // A part the op-amp class law binds already keeps that law unless the
145
+ // registry says the part is not an op-amp; see `opampKeepsItsClass`.
146
+ if (opampKeepsItsClass(device, entry)) {
147
+ continue;
148
+ }
149
+ const resolvedId = entry.partIds[0] ?? partNumber;
150
+ return { partId: resolvedId, evidence: "exact-part" };
151
+ }
152
+ }
153
+ else if (entry.model.kind === "macro") {
154
+ const resolvedId = entry.partIds[0] ?? partNumber;
155
+ return { partId: resolvedId, evidence: "exact-part" };
156
+ }
157
+ }
158
+ }
159
+ // 2. Fall back to standard matching on partId only if not an incompatible sections model
160
+ for (const entry of registry.entries) {
161
+ if (entry.partIds.some((id) => foldPartId(id) === folded)) {
162
+ if (entry.model.kind !== "sections" ||
163
+ device.nodes.length === entry.model.pinout.length) {
164
+ if (opampKeepsItsClass(device, entry)) {
165
+ continue;
166
+ }
167
+ const resolvedId = entry.partIds[0] ?? partNumber;
168
+ return { partId: resolvedId, evidence: "exact-part" };
169
+ }
170
+ }
171
+ }
172
+ // 3. **The rung is terminal, which is what "each rung refuses to reach the next" means.**
173
+ //
174
+ // Both loops above give up when a registered part's entry is a `sections` model whose
175
+ // pinout does not fit this component's terminal count -- and until 2026-09-04 that fell
176
+ // through to declared type and then to *pin names*, which is weaker evidence about a
177
+ // component whose part number the registry already knows. `moogerfooger-mf-102`'s `U4A`
178
+ // is the proof: it declares `PartNumber: LM13600` with five of that OTA's pins, no
179
+ // entry has a five-pin LM13600, and rung 3 matched its
180
+ // `nonInverting/inverting/output/vplus/vminus` naming against the **LM311 comparator**
181
+ // signature -- so a dual OTA was one lowering away from being stamped as a comparator.
182
+ // A pinout signature cannot tell an OTA from a comparator; both are five pins with those
183
+ // names, which is exactly the case this file records as "a wrong identity is worse than
184
+ // none".
185
+ //
186
+ // So a known part number ends identification here. An entry whose arity does not fit is a
187
+ // registry coverage gap, and it is reported as one downstream -- `sectionDevices` refuses
188
+ // by name for a part it cannot expand, and an OTA keeps its correct device-class law --
189
+ // rather than becoming grounds to guess a different part from pin names.
190
+ for (const entry of registry.entries) {
191
+ if (entry.partIds.some((id) => foldPartId(id) === folded)) {
192
+ if (opampKeepsItsClass(device, entry)) {
193
+ continue;
194
+ }
195
+ return {
196
+ partId: entry.partIds[0] ?? partNumber,
197
+ evidence: "exact-part",
198
+ };
199
+ }
200
+ }
201
+ // 4. **Canonicalised ordering code -> die identity.** Tried only after both exact rungs,
202
+ // because rule 49's asymmetry runs the whole length of this file: a missed match is a
203
+ // diagnosable refusal and a wrong match executes silently, so exact evidence always wins
204
+ // and this rung never guesses. It strips trailing package markings and a fixed vocabulary
205
+ // of grade suffixes; it does NOT match on prefixes, because `M5K4164` against
206
+ // `M5K4164ANL-15` is a prefix match and a different die.
207
+ //
208
+ // **It exists because a package suffix decided whether a pedal got a DSP model.**
209
+ // `boss-rv-6` declares `UPD800402GJ-211` and `boss-st-2` declares
210
+ // `uPD800402GJ-211-UEN-A(ESC)` -- the same silicon. Neither matched the catalog's
211
+ // `UPD800402GJ-211-UEN-A`, so both fell through to `declaredType` below, and because the
212
+ // two packets declare different classes, `rv-6`'s 144-pin reverb DSP was resolved as a
213
+ // bucket-brigade delay line and rendered a 50 ms delay its chip never made.
214
+ const canonical = foldPartId(canonicalPartId(partNumber));
215
+ for (const entry of registry.entries) {
216
+ if (entry.partIds.some((id) => foldPartId(canonicalPartId(id)) === canonical)) {
217
+ if (opampKeepsItsClass(device, entry)) {
218
+ continue;
219
+ }
220
+ return {
221
+ partId: entry.partIds[0] ?? partNumber,
222
+ evidence: "exact-part",
223
+ };
224
+ }
225
+ }
226
+ }
227
+ // **A NAMED PART NUMBER THAT MATCHED NOTHING ENDS IDENTIFICATION HERE.**
228
+ //
229
+ // Falling through to `declaredType` after an unmatched part number is how `boss-rv-6`'s
230
+ // 144-pin reverb DSP became a bucket-brigade delay line: the ordering code matched no entry,
231
+ // so the class decided the model, and the class said `Circuit.DelayMemoryChip`. The same path
232
+ // is still live for `boss-dd-3t`, whose `U1` declares `PartNumber: undisclosed-roland-boss-dsp`
233
+ // and whose DRAM declares `PartNumber: excluded-dd3b-dram-context` -- **prose in a typed
234
+ // field**, one lookup away from executing as a delay line (format item 8).
235
+ //
236
+ // **This is the rung order of the whole file applied once more** (rule 49): a device that
237
+ // names its part has given the strongest evidence available, and when that evidence matches
238
+ // nothing the honest answer is "no identity", not a weaker guess from a different field. The
239
+ // consequence is an open device with a reason a reader can act on, which is the outcome this
240
+ // programme exists to produce -- never a plausible model nobody asked for.
241
+ // **The narrow form, and the wide one was measured and rejected.** Refusing *all* fall-through
242
+ // after an unmatched part number stops two documents compiling, and one of them is a false
243
+ // positive: `belton-brick-reverb` declares `PartNumber: unspecified-op-amp-section` on an
244
+ // op-amp whose `Circuit.OpAmp` class resolves it perfectly well. Prose in the part-number field
245
+ // is a source defect (format item 8), not grounds to refuse a device its class already
246
+ // identifies.
247
+ //
248
+ // **What the class may NOT supply is a MACRO.** A generic class law says "this is an op-amp",
249
+ // which the class genuinely knows. A macro says "this is *this specific chip* and here is its
250
+ // behaviour" -- an identity claim, and the one piece of evidence that could support it just
251
+ // failed to match. That asymmetry is the whole rule: `boss-rv-6`'s reverb DSP became a
252
+ // bucket-brigade delay line through exactly this door, and `boss-dd-3t`'s
253
+ // `undisclosed-roland-boss-dsp` is still standing in it.
254
+ const partNumberUnmatched = partNumber !== null && partNumber.trim() !== "";
255
+ const declaredType = device.identity.declaredType;
256
+ if (declaredType !== null) {
257
+ const folded = foldToken(declaredType);
258
+ // 1. Try to find an entry with matching declaredType AND matching terminal arity (only for "sections" kind)
259
+ for (const entry of registry.entries) {
260
+ if (!(partNumberUnmatched && entry.model.kind === "macro") &&
261
+ entry.declaredTypes.some((type) => foldToken(type) === folded) &&
262
+ (entry.model.kind === "sections" || entry.model.kind === "sections-core") &&
263
+ device.nodes.length === entry.model.pinout.length) {
264
+ const resolvedId = entry.declaredTypes[0] ?? declaredType;
265
+ return { partId: resolvedId, evidence: "declared-type" };
266
+ }
267
+ }
268
+ // 2. Fall back to standard matching on declaredType only (backward compatibility)
269
+ for (const entry of registry.entries) {
270
+ if (partNumberUnmatched && entry.model.kind === "macro")
271
+ continue;
272
+ if (entry.declaredTypes.some((type) => foldToken(type) === folded)) {
273
+ const resolvedId = entry.declaredTypes[0] ?? declaredType;
274
+ return { partId: resolvedId, evidence: "declared-type" };
275
+ }
276
+ }
277
+ }
278
+ for (const entry of registry.entries) {
279
+ if (entry.terminalRoleGroups.length === 0) {
280
+ continue;
281
+ }
282
+ if (matchesTerminalRoles(device, entry)) {
283
+ const partId = entry.partIds[0] ?? entry.declaredTypes[0];
284
+ if (partId !== undefined) {
285
+ return { partId, evidence: "pinout" };
286
+ }
287
+ }
288
+ }
289
+ return null;
290
+ }
291
+ /**
292
+ * A pinout match is exact, not "these roles are present among possibly others". Two
293
+ * directions, both whole-token and case-folded on both sides: every required group must
294
+ * be satisfied by an alias, and every role the device declares must be covered by some
295
+ * group. The second direction is the guard against a superset: a five-terminal part that
296
+ * carries `in`/`gnd`/`out` plus two more would otherwise satisfy a three-group
297
+ * regulator's signature and be stamped with a regulator's law. Presence alone is a
298
+ * substring-shaped trap wearing role tokens.
299
+ *
300
+ * A part that declares more terminals than groups on purpose -- the MN3101 clock driver,
301
+ * six named roles on an eight-pin body, two power pins the entry does not model -- still
302
+ * matches, because its *extra terminals* carry no role token (a bare `pin` number folds
303
+ * to null and is not in `present`); the test is on roles, not on pin count.
304
+ *
305
+ * Whole-token comparison cannot invent a match the way a substring search can, but it is
306
+ * coverage-limited: the transcriber must have used a spelling the registry lists. That is
307
+ * a known and accepted bound, not a defect to paper over.
308
+ */
309
+ function matchesTerminalRoles(device, entry) {
310
+ const present = device.identity.terminalRoles
311
+ .filter((role) => role !== null)
312
+ .map(foldToken);
313
+ if (present.length === 0) {
314
+ return false;
315
+ }
316
+ const covered = (role) => entry.terminalRoleGroups.some((group) => group.some((alias) => foldToken(alias) === role));
317
+ return (entry.terminalRoleGroups.every((group) => group.some((alias) => present.includes(foldToken(alias)))) && present.every(covered));
318
+ }
319
+ //# sourceMappingURL=identify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identify.js","sourceRoot":"","sources":["../src/identify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export { compile, compileToArtifact, type CompileOptions } from "./compile";
2
+ export { emit } from "./emit";
3
+ export { parseQuantity, readNetlist } from "./netlist";
4
+ export { emptyRegistry, foldPartId, foldToken, registryEntryFor, registryLawFor, type PartEntry, type PartRegistry, type PartSection, } from "./registry";
5
+ export { canonicalPartId } from "./part-number";
6
+ export { pedalPartCatalog, zenerCatalogPartIds } from "./part-catalog";
7
+ export { resolveSupplyStamps, type RefusedSupply, type ResolvedSupply, type SupplyAddress, type SupplyRefusalReason, type SupplyResolution, } from "./supply-stamps";
8
+ export { attachDeviceLaws } from "./device-laws";
9
+ export * from "./types";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACN,aAAa,EACb,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACN,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ // Public surface of the v2 compiler: `.vdsp` source text to a compiled Program.
2
+ //
3
+ // This is the whole of what leaves the module. `@vessel-dsp/runtime`, the browser
4
+ // surface and the report scripts import from here; nothing outside `src/compiler/`
5
+ // reaches a stage file directly. Report-only helpers live in `./diagnostics`, and the
6
+ // synthetic circuits the tests and the parity instruments share live in `./fixtures`.
7
+ //
8
+ // Adding a name here is a public-API decision. A stage that needs to be reached from a
9
+ // script is a diagnostics export, not a public one.
10
+ export { compile, compileToArtifact } from "./compile.js";
11
+ export { emit } from "./emit.js";
12
+ export { parseQuantity, readNetlist } from "./netlist.js";
13
+ export { emptyRegistry, foldPartId, foldToken, registryEntryFor, registryLawFor, } from "./registry.js";
14
+ export { canonicalPartId } from "./part-number.js";
15
+ export { pedalPartCatalog, zenerCatalogPartIds } from "./part-catalog.js";
16
+ export { resolveSupplyStamps, } from "./supply-stamps.js";
17
+ export { attachDeviceLaws } from "./device-laws.js";
18
+ export * from "./types.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,kFAAkF;AAClF,mFAAmF;AACnF,sFAAsF;AACtF,sFAAsF;AACtF,EAAE;AACF,uFAAuF;AACvF,oDAAoD;AAEpD,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAuB,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACN,aAAa,EACb,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,GAId,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACN,mBAAmB,GAMnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,cAAc,SAAS,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { InertControlWarning, Netlist, Program } from "./types";
2
+ /**
3
+ * A pot whose wiper node touches nothing else is electrically a fixed resistor.
4
+ *
5
+ * The two halves of the track are in series with a floating junction between them, so
6
+ * whatever the wiper takes from one half it gives back to the other and their sum is
7
+ * the whole track no matter where the knob sits. The pot still stamps, still solves,
8
+ * and still moves its two conductances -- it just cannot change any node voltage, which
9
+ * is why listening finds it and the matrix does not.
10
+ *
11
+ * A wiper tied back to one of its own ends is a rheostat and genuinely varies, so it
12
+ * has degree 2 and is correctly not reported here.
13
+ */
14
+ export declare function findInertControls(netlist: Netlist, program: Program): readonly InertControlWarning[];
15
+ //# sourceMappingURL=inert-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inert-controls.d.ts","sourceRoot":"","sources":["../src/inert-controls.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAGX,mBAAmB,EACnB,OAAO,EAEP,OAAO,EACP,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd,SAAS,mBAAmB,EAAE,CAwGhC"}