@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.
- package/README.md +118 -2
- package/dist/bake.d.ts +38 -0
- package/dist/bake.d.ts.map +1 -0
- package/dist/bake.js +101 -0
- package/dist/bake.js.map +1 -0
- package/dist/bbd-clock.d.ts +171 -0
- package/dist/bbd-clock.d.ts.map +1 -0
- package/dist/bbd-clock.js +1750 -0
- package/dist/bbd-clock.js.map +1 -0
- package/dist/block-row.d.ts +51 -0
- package/dist/block-row.d.ts.map +1 -0
- package/dist/block-row.js +17 -0
- package/dist/block-row.js.map +1 -0
- package/dist/bypass.d.ts +3 -0
- package/dist/bypass.d.ts.map +1 -0
- package/dist/bypass.js +228 -0
- package/dist/bypass.js.map +1 -0
- package/dist/compile.d.ts +24 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +348 -0
- package/dist/compile.js.map +1 -0
- package/dist/converter-scale.d.ts +14 -0
- package/dist/converter-scale.d.ts.map +1 -0
- package/dist/converter-scale.js +133 -0
- package/dist/converter-scale.js.map +1 -0
- package/dist/couple.d.ts +28 -0
- package/dist/couple.d.ts.map +1 -0
- package/dist/couple.js +567 -0
- package/dist/couple.js.map +1 -0
- package/dist/dangling-active-terminal.d.ts +47 -0
- package/dist/dangling-active-terminal.d.ts.map +1 -0
- package/dist/dangling-active-terminal.js +542 -0
- package/dist/dangling-active-terminal.js.map +1 -0
- package/dist/declared-program.d.ts +23 -0
- package/dist/declared-program.d.ts.map +1 -0
- package/dist/declared-program.js +387 -0
- package/dist/declared-program.js.map +1 -0
- package/dist/denomination.d.ts +48 -0
- package/dist/denomination.d.ts.map +1 -0
- package/dist/denomination.js +27 -0
- package/dist/denomination.js.map +1 -0
- package/dist/device-laws.d.ts +237 -0
- package/dist/device-laws.d.ts.map +1 -0
- package/dist/device-laws.js +3513 -0
- package/dist/device-laws.js.map +1 -0
- package/dist/diagnostics.d.ts +13 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +19 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emit.d.ts +8 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +43 -0
- package/dist/emit.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/firmware-class.d.ts +69 -0
- package/dist/firmware-class.d.ts.map +1 -0
- package/dist/firmware-class.js +20 -0
- package/dist/firmware-class.js.map +1 -0
- package/dist/fixtures/circuits.d.ts +1742 -0
- package/dist/fixtures/circuits.d.ts.map +1 -0
- package/dist/fixtures/circuits.js +13896 -0
- package/dist/fixtures/circuits.js.map +1 -0
- package/dist/fixtures/expected.d.ts +261 -0
- package/dist/fixtures/expected.d.ts.map +1 -0
- package/dist/fixtures/expected.js +315 -0
- package/dist/fixtures/expected.js.map +1 -0
- package/dist/fixtures/index.d.ts +4 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +8 -0
- package/dist/fixtures/index.js.map +1 -0
- package/dist/fixtures/registry.d.ts +52 -0
- package/dist/fixtures/registry.d.ts.map +1 -0
- package/dist/fixtures/registry.js +341 -0
- package/dist/fixtures/registry.js.map +1 -0
- package/dist/generic-tube-fit.d.ts +12 -0
- package/dist/generic-tube-fit.d.ts.map +1 -0
- package/dist/generic-tube-fit.js +45 -0
- package/dist/generic-tube-fit.js.map +1 -0
- package/dist/grounded-clock-supply.d.ts +13 -0
- package/dist/grounded-clock-supply.d.ts.map +1 -0
- package/dist/grounded-clock-supply.js +45 -0
- package/dist/grounded-clock-supply.js.map +1 -0
- package/dist/identify.d.ts +50 -0
- package/dist/identify.d.ts.map +1 -0
- package/dist/identify.js +319 -0
- package/dist/identify.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/inert-controls.d.ts +15 -0
- package/dist/inert-controls.d.ts.map +1 -0
- package/dist/inert-controls.js +266 -0
- package/dist/inert-controls.js.map +1 -0
- package/dist/latch-seed.d.ts +53 -0
- package/dist/latch-seed.d.ts.map +1 -0
- package/dist/latch-seed.js +257 -0
- package/dist/latch-seed.js.map +1 -0
- package/dist/link.d.ts +7 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +270 -0
- package/dist/link.js.map +1 -0
- package/dist/lower.d.ts +79 -0
- package/dist/lower.d.ts.map +1 -0
- package/dist/lower.js +1855 -0
- package/dist/lower.js.map +1 -0
- package/dist/netlist.d.ts +79 -0
- package/dist/netlist.d.ts.map +1 -0
- package/dist/netlist.js +4746 -0
- package/dist/netlist.js.map +1 -0
- package/dist/non-executable-clock-drivers.d.ts +8 -0
- package/dist/non-executable-clock-drivers.d.ts.map +1 -0
- package/dist/non-executable-clock-drivers.js +33 -0
- package/dist/non-executable-clock-drivers.js.map +1 -0
- package/dist/open-category.d.ts +98 -0
- package/dist/open-category.d.ts.map +1 -0
- package/dist/open-category.js +111 -0
- package/dist/open-category.js.map +1 -0
- package/dist/over-driven-node.d.ts +33 -0
- package/dist/over-driven-node.d.ts.map +1 -0
- package/dist/over-driven-node.js +188 -0
- package/dist/over-driven-node.js.map +1 -0
- package/dist/part-catalog.d.ts +15 -0
- package/dist/part-catalog.d.ts.map +1 -0
- package/dist/part-catalog.js +6712 -0
- package/dist/part-catalog.js.map +1 -0
- package/dist/part-number.d.ts +32 -0
- package/dist/part-number.d.ts.map +1 -0
- package/dist/part-number.js +80 -0
- package/dist/part-number.js.map +1 -0
- package/dist/partition.d.ts +7 -0
- package/dist/partition.d.ts.map +1 -0
- package/dist/partition.js +242 -0
- package/dist/partition.js.map +1 -0
- package/dist/port-full-scale.d.ts +70 -0
- package/dist/port-full-scale.d.ts.map +1 -0
- package/dist/port-full-scale.js +235 -0
- package/dist/port-full-scale.js.map +1 -0
- package/dist/pot-orientation.d.ts +114 -0
- package/dist/pot-orientation.d.ts.map +1 -0
- package/dist/pot-orientation.js +551 -0
- package/dist/pot-orientation.js.map +1 -0
- package/dist/power-domain-control.d.ts +40 -0
- package/dist/power-domain-control.d.ts.map +1 -0
- package/dist/power-domain-control.js +142 -0
- package/dist/power-domain-control.js.map +1 -0
- package/dist/proxy-declaration.d.ts +121 -0
- package/dist/proxy-declaration.d.ts.map +1 -0
- package/dist/proxy-declaration.js +50 -0
- package/dist/proxy-declaration.js.map +1 -0
- package/dist/registry.d.ts +323 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +192 -0
- package/dist/registry.js.map +1 -0
- package/dist/sparse-schedule.d.ts +65 -0
- package/dist/sparse-schedule.d.ts.map +1 -0
- package/dist/sparse-schedule.js +421 -0
- package/dist/sparse-schedule.js.map +1 -0
- package/dist/speaker-load.d.ts +38 -0
- package/dist/speaker-load.d.ts.map +1 -0
- package/dist/speaker-load.js +97 -0
- package/dist/speaker-load.js.map +1 -0
- package/dist/stage-coverage.d.ts +21 -0
- package/dist/stage-coverage.d.ts.map +1 -0
- package/dist/stage-coverage.js +124 -0
- package/dist/stage-coverage.js.map +1 -0
- package/dist/stamp-partition.d.ts +314 -0
- package/dist/stamp-partition.d.ts.map +1 -0
- package/dist/stamp-partition.js +472 -0
- package/dist/stamp-partition.js.map +1 -0
- package/dist/supply-reference.d.ts +19 -0
- package/dist/supply-reference.d.ts.map +1 -0
- package/dist/supply-reference.js +66 -0
- package/dist/supply-reference.js.map +1 -0
- package/dist/supply-short.d.ts +32 -0
- package/dist/supply-short.d.ts.map +1 -0
- package/dist/supply-short.js +118 -0
- package/dist/supply-short.js.map +1 -0
- package/dist/supply-stamps.d.ts +51 -0
- package/dist/supply-stamps.d.ts.map +1 -0
- package/dist/supply-stamps.js +363 -0
- package/dist/supply-stamps.js.map +1 -0
- package/dist/terminal-role.d.ts +109 -0
- package/dist/terminal-role.d.ts.map +1 -0
- package/dist/terminal-role.js +46 -0
- package/dist/terminal-role.js.map +1 -0
- package/dist/terminal-roles.d.ts +59 -0
- package/dist/terminal-roles.d.ts.map +1 -0
- package/dist/terminal-roles.js +92 -0
- package/dist/terminal-roles.js.map +1 -0
- package/dist/transformer.d.ts +181 -0
- package/dist/transformer.d.ts.map +1 -0
- package/dist/transformer.js +476 -0
- package/dist/transformer.js.map +1 -0
- package/dist/types.d.ts +3157 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/unbounded-operating-point.d.ts +35 -0
- package/dist/unbounded-operating-point.d.ts.map +1 -0
- package/dist/unbounded-operating-point.js +181 -0
- package/dist/unbounded-operating-point.js.map +1 -0
- package/dist/unexecuted-region.d.ts +3 -0
- package/dist/unexecuted-region.d.ts.map +1 -0
- package/dist/unexecuted-region.js +122 -0
- package/dist/unexecuted-region.js.map +1 -0
- package/dist/unimplemented-control-role.d.ts +3 -0
- package/dist/unimplemented-control-role.d.ts.map +1 -0
- package/dist/unimplemented-control-role.js +61 -0
- package/dist/unimplemented-control-role.js.map +1 -0
- package/dist/unreachable-output.d.ts +3 -0
- package/dist/unreachable-output.d.ts.map +1 -0
- package/dist/unreachable-output.js +97 -0
- package/dist/unreachable-output.js.map +1 -0
- package/dist/unreadable-terminal-role.d.ts +67 -0
- package/dist/unreadable-terminal-role.d.ts.map +1 -0
- package/dist/unreadable-terminal-role.js +409 -0
- package/dist/unreadable-terminal-role.js.map +1 -0
- package/dist/unverified-pinout.d.ts +27 -0
- package/dist/unverified-pinout.d.ts.map +1 -0
- package/dist/unverified-pinout.js +121 -0
- package/dist/unverified-pinout.js.map +1 -0
- package/package.json +75 -5
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// A component's declared program, checked against the vocabulary that can actually execute it.
|
|
2
|
+
//
|
|
3
|
+
// The format carries an op as a name plus an untyped bag, because `@vessel-dsp/core` has no
|
|
4
|
+
// opinion about a vocabulary that belongs to the runtime. That is the right split, and it puts the
|
|
5
|
+
// whole burden of the check here: everything downstream of this file sees a `PrimitiveOp` or a
|
|
6
|
+
// refusal, never a declaration that has not been read.
|
|
7
|
+
//
|
|
8
|
+
// **Why this refuses rather than drops.** An `ic` with no model is opened with a warning and the
|
|
9
|
+
// packet renders silence -- the gap CLAUDE.md records as costing a session on 2026-09-10, where
|
|
10
|
+
// the engine could not tell an unimplemented DSP pedal from an analog pedal with a severed net. A
|
|
11
|
+
// *declared* program is different in kind: the source has stated what the chip does, so failing to
|
|
12
|
+
// execute it is this compiler's gap and not the document's, and the console/ROM invariant applies
|
|
13
|
+
// in full. An op this pipeline cannot place is named, never silently discarded.
|
|
14
|
+
/**
|
|
15
|
+
* Every op name the runtime can execute, as a map that the type checker keeps exhaustive.
|
|
16
|
+
*
|
|
17
|
+
* **Not a hand-written list.** Keying a `Record` on `PrimitiveOp["op"]` means adding an op to the
|
|
18
|
+
* union and forgetting it here is a type error, which is the only version of this table that
|
|
19
|
+
* cannot go stale. A hand-listed array of strings would compile forever after the union moved --
|
|
20
|
+
* and a validator that silently stops recognising a new op is worse than none, because it refuses
|
|
21
|
+
* a correct declaration and names the source as the defect.
|
|
22
|
+
*/
|
|
23
|
+
const OP_READERS = {
|
|
24
|
+
"delay-tap": (op) => {
|
|
25
|
+
const line = readLine(op);
|
|
26
|
+
if (line === null)
|
|
27
|
+
return NO_LINE;
|
|
28
|
+
const length = readLength(op);
|
|
29
|
+
if (typeof length === "string")
|
|
30
|
+
return length;
|
|
31
|
+
const out = readOut(op);
|
|
32
|
+
if (typeof out === "string")
|
|
33
|
+
return out;
|
|
34
|
+
return { op: "delay-tap", line, length, out };
|
|
35
|
+
},
|
|
36
|
+
"delay-tap-fractional": (op) => {
|
|
37
|
+
const line = readLine(op);
|
|
38
|
+
if (line === null)
|
|
39
|
+
return NO_LINE;
|
|
40
|
+
const length = readLength(op);
|
|
41
|
+
if (typeof length === "string")
|
|
42
|
+
return length;
|
|
43
|
+
const out = readOut(op);
|
|
44
|
+
if (typeof out === "string")
|
|
45
|
+
return out;
|
|
46
|
+
return { op: "delay-tap-fractional", line, length, out };
|
|
47
|
+
},
|
|
48
|
+
"delay-tap-reverse": (op) => {
|
|
49
|
+
const line = readLine(op);
|
|
50
|
+
if (line === null)
|
|
51
|
+
return NO_LINE;
|
|
52
|
+
const length = readLength(op);
|
|
53
|
+
if (typeof length === "string")
|
|
54
|
+
return length;
|
|
55
|
+
const out = readOut(op);
|
|
56
|
+
if (typeof out === "string")
|
|
57
|
+
return out;
|
|
58
|
+
return { op: "delay-tap-reverse", line, length, out };
|
|
59
|
+
},
|
|
60
|
+
"hold-loop": (op, parameters) => {
|
|
61
|
+
const line = readLine(op);
|
|
62
|
+
if (line === null)
|
|
63
|
+
return NO_LINE;
|
|
64
|
+
const input = readSource(op.input, "input");
|
|
65
|
+
if (typeof input === "string")
|
|
66
|
+
return input;
|
|
67
|
+
const raw = op.gate;
|
|
68
|
+
if (raw === null || typeof raw !== "object")
|
|
69
|
+
return 'declares no "gate" parameter';
|
|
70
|
+
const gate = readGainParameter(raw, parameters, "gate");
|
|
71
|
+
if (typeof gate === "string")
|
|
72
|
+
return gate;
|
|
73
|
+
const out = readOut(op);
|
|
74
|
+
if (typeof out === "string")
|
|
75
|
+
return out;
|
|
76
|
+
return { op: "hold-loop", line, input, gate, out };
|
|
77
|
+
},
|
|
78
|
+
"delay-push": (op) => {
|
|
79
|
+
const line = readLine(op);
|
|
80
|
+
if (line === null)
|
|
81
|
+
return NO_LINE;
|
|
82
|
+
const input = readSource(op.input, "input");
|
|
83
|
+
if (typeof input === "string")
|
|
84
|
+
return input;
|
|
85
|
+
return { op: "delay-push", line, input };
|
|
86
|
+
},
|
|
87
|
+
mix: (op, parameters) => {
|
|
88
|
+
const terms = readTerms(op, parameters);
|
|
89
|
+
if (typeof terms === "string")
|
|
90
|
+
return terms;
|
|
91
|
+
const out = readOut(op);
|
|
92
|
+
if (typeof out === "string")
|
|
93
|
+
return out;
|
|
94
|
+
return { op: "mix", terms, out };
|
|
95
|
+
},
|
|
96
|
+
"filter-dcblock": (op) => {
|
|
97
|
+
const input = readSource(op.input, "input");
|
|
98
|
+
if (typeof input === "string")
|
|
99
|
+
return input;
|
|
100
|
+
const out = readOut(op);
|
|
101
|
+
if (typeof out === "string")
|
|
102
|
+
return out;
|
|
103
|
+
return { op: "filter-dcblock", input, out };
|
|
104
|
+
},
|
|
105
|
+
comb: (op) => {
|
|
106
|
+
const index = readNumber(op.index, "index");
|
|
107
|
+
if (typeof index === "string")
|
|
108
|
+
return index;
|
|
109
|
+
const decaySeconds = readNumber(op.decaySeconds, "decaySeconds");
|
|
110
|
+
if (typeof decaySeconds === "string")
|
|
111
|
+
return decaySeconds;
|
|
112
|
+
const input = readSource(op.input, "input");
|
|
113
|
+
if (typeof input === "string")
|
|
114
|
+
return input;
|
|
115
|
+
const out = readOut(op);
|
|
116
|
+
if (typeof out === "string")
|
|
117
|
+
return out;
|
|
118
|
+
return { op: "comb", index, decaySeconds, input, out };
|
|
119
|
+
},
|
|
120
|
+
allpass: (op) => {
|
|
121
|
+
const index = readNumber(op.index, "index");
|
|
122
|
+
if (typeof index === "string")
|
|
123
|
+
return index;
|
|
124
|
+
const input = readSource(op.input, "input");
|
|
125
|
+
if (typeof input === "string")
|
|
126
|
+
return input;
|
|
127
|
+
const out = readOut(op);
|
|
128
|
+
if (typeof out === "string")
|
|
129
|
+
return out;
|
|
130
|
+
return { op: "allpass", index, input, out };
|
|
131
|
+
},
|
|
132
|
+
"pitch-shift": (op) => {
|
|
133
|
+
const ratio = readNumber(op.ratio, "ratio");
|
|
134
|
+
if (typeof ratio === "string")
|
|
135
|
+
return ratio;
|
|
136
|
+
const input = readSource(op.input, "input");
|
|
137
|
+
if (typeof input === "string")
|
|
138
|
+
return input;
|
|
139
|
+
const out = readOut(op);
|
|
140
|
+
if (typeof out === "string")
|
|
141
|
+
return out;
|
|
142
|
+
return { op: "pitch-shift", ratio, input, out };
|
|
143
|
+
},
|
|
144
|
+
"pitch-tracker": (op) => {
|
|
145
|
+
const input = readSource(op.input, "input");
|
|
146
|
+
if (typeof input === "string")
|
|
147
|
+
return input;
|
|
148
|
+
const out = readOut(op);
|
|
149
|
+
if (typeof out === "string")
|
|
150
|
+
return out;
|
|
151
|
+
return { op: "pitch-tracker", input, out };
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
/** The declared op names, for a refusal that can tell a reader what it could have written. */
|
|
155
|
+
const KNOWN_OPS = Object.keys(OP_READERS).sort();
|
|
156
|
+
/**
|
|
157
|
+
* Read a declaration into executable ops, or name the first thing that stopped it.
|
|
158
|
+
*
|
|
159
|
+
* Positions are checked in declaration order and the check stops at the first failure, because a
|
|
160
|
+
* list of every defect in a document nobody has fixed once is noise. The reason names the position
|
|
161
|
+
* and the op index, which is what locates it in the source.
|
|
162
|
+
*/
|
|
163
|
+
export function checkDeclaredProgram(program) {
|
|
164
|
+
const positions = [];
|
|
165
|
+
for (const position of program.positions) {
|
|
166
|
+
// Core refuses an empty `ops` at parse, so an empty list here means stage 1 dropped
|
|
167
|
+
// every entry as unreadable. Letting it through would publish an unwritten temporary,
|
|
168
|
+
// which is a packet that compiles clean and renders silence -- the failure this whole
|
|
169
|
+
// file exists to make impossible.
|
|
170
|
+
if (position.ops.length === 0) {
|
|
171
|
+
return {
|
|
172
|
+
ok: false,
|
|
173
|
+
reason: `position "${position.id}" carries no readable op`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const ops = [];
|
|
177
|
+
for (const [index, declared] of position.ops.entries()) {
|
|
178
|
+
const reader = Object.hasOwn(OP_READERS, declared.op)
|
|
179
|
+
? OP_READERS[declared.op]
|
|
180
|
+
: undefined;
|
|
181
|
+
if (reader === undefined) {
|
|
182
|
+
return {
|
|
183
|
+
ok: false,
|
|
184
|
+
reason: `position "${position.id}" op ${index} declares "${declared.op}", which this runtime does not implement; it executes ${KNOWN_OPS.join(", ")}`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const read = reader(declared, position.parameters);
|
|
188
|
+
if (typeof read === "string") {
|
|
189
|
+
return {
|
|
190
|
+
ok: false,
|
|
191
|
+
reason: `position "${position.id}" op ${index} ("${declared.op}"): ${read}`,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
ops.push(read);
|
|
195
|
+
}
|
|
196
|
+
// **Temporaries are sized to the op list**, one slot per op, in both consoles. An `out` or a
|
|
197
|
+
// temp source past it is a write or read of a slot that does not exist: the C++ console
|
|
198
|
+
// throws on the first sample and the TS console silently grows its array, so the two
|
|
199
|
+
// disagree and the Studio crashes where a render passes. `boss-dd-5` v1.46's HOLD wrote
|
|
200
|
+
// slot 3 of a two-op program.
|
|
201
|
+
for (const [index, op] of ops.entries()) {
|
|
202
|
+
const slots = [
|
|
203
|
+
...("out" in op ? [["out", op.out]] : []),
|
|
204
|
+
...tempSources(op).map((slot) => ["temp source", slot]),
|
|
205
|
+
];
|
|
206
|
+
for (const [what, slot] of slots) {
|
|
207
|
+
if (slot < ops.length)
|
|
208
|
+
continue;
|
|
209
|
+
return {
|
|
210
|
+
ok: false,
|
|
211
|
+
reason: `position "${position.id}" op ${index} ("${op.op}") names ${what} ${slot}, outside its ${ops.length} temporaries (one per op)`,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// A delay op naming a line the position does not declare has no length to read, and
|
|
216
|
+
// taking it as zero would render a silent pedal that compiled cleanly.
|
|
217
|
+
const declaredLines = new Set(Object.keys(position.lines));
|
|
218
|
+
for (const [index, op] of ops.entries()) {
|
|
219
|
+
if (!("line" in op))
|
|
220
|
+
continue;
|
|
221
|
+
if (!declaredLines.has(op.line)) {
|
|
222
|
+
return {
|
|
223
|
+
ok: false,
|
|
224
|
+
reason: `position "${position.id}" op ${index} ("${op.op}") reads delay line "${op.line}", which the position does not declare; it declares ${declaredLines.size === 0 ? "none" : [...declaredLines].join(", ")}`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// A reverse tap keeps its segment phase on the line it reads, so a second one on the same
|
|
229
|
+
// line would advance that phase twice a sample and play at double speed.
|
|
230
|
+
const reversed = new Set();
|
|
231
|
+
for (const [index, op] of ops.entries()) {
|
|
232
|
+
if (op.op !== "delay-tap-reverse")
|
|
233
|
+
continue;
|
|
234
|
+
if (reversed.has(op.line)) {
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
reason: `position "${position.id}" op ${index} is a second "delay-tap-reverse" on line "${op.line}"; a line carries at most one, because its reverse phase lives on the line`,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
reversed.add(op.line);
|
|
241
|
+
}
|
|
242
|
+
// A hold sampler owns its line: its record position lives there, so a second writer
|
|
243
|
+
// would overwrite the recording it is looping.
|
|
244
|
+
const held = new Set();
|
|
245
|
+
for (const [index, op] of ops.entries()) {
|
|
246
|
+
if (op.op !== "hold-loop")
|
|
247
|
+
continue;
|
|
248
|
+
const shared = held.has(op.line) || ops.some((other) => other.op === "delay-push" && other.line === op.line);
|
|
249
|
+
if (shared) {
|
|
250
|
+
return {
|
|
251
|
+
ok: false,
|
|
252
|
+
reason: `position "${position.id}" op ${index} ("hold-loop") shares line "${op.line}" with another writer; a hold sampler owns its line`,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
held.add(op.line);
|
|
256
|
+
}
|
|
257
|
+
positions.push({
|
|
258
|
+
id: position.id,
|
|
259
|
+
ops,
|
|
260
|
+
lines: [...declaredLines],
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return { ok: true, positions };
|
|
264
|
+
}
|
|
265
|
+
/** The temp slots an op reads. */
|
|
266
|
+
function tempSources(op) {
|
|
267
|
+
const sources = [];
|
|
268
|
+
if ("input" in op)
|
|
269
|
+
sources.push(op.input);
|
|
270
|
+
if (op.op === "mix")
|
|
271
|
+
sources.push(...op.terms.map((term) => term.source));
|
|
272
|
+
return sources.flatMap((source) => (source.kind === "temp" ? [source.index] : []));
|
|
273
|
+
}
|
|
274
|
+
/** The reason every delay op gives when it names no line, stated once. */
|
|
275
|
+
const NO_LINE = 'declares no delay line name ("line")';
|
|
276
|
+
function readLine(op) {
|
|
277
|
+
const value = op.line;
|
|
278
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
279
|
+
}
|
|
280
|
+
function readOut(op) {
|
|
281
|
+
return readIndex(op.out, "out");
|
|
282
|
+
}
|
|
283
|
+
function readNumber(value, field) {
|
|
284
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
285
|
+
? value
|
|
286
|
+
: `declares no finite "${field}"`;
|
|
287
|
+
}
|
|
288
|
+
function readIndex(value, field) {
|
|
289
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0
|
|
290
|
+
? value
|
|
291
|
+
: `declares no non-negative integer "${field}"`;
|
|
292
|
+
}
|
|
293
|
+
function readLength(op) {
|
|
294
|
+
const value = op.length;
|
|
295
|
+
if (value === null || typeof value !== "object") {
|
|
296
|
+
return 'declares no "length"';
|
|
297
|
+
}
|
|
298
|
+
const mode = value.mode;
|
|
299
|
+
// Whole-value comparison against the closed set, which is the rule this repository runs on
|
|
300
|
+
// every other typed vocabulary.
|
|
301
|
+
if (mode === "capacity" ||
|
|
302
|
+
mode === "clock" ||
|
|
303
|
+
mode === "modulation" ||
|
|
304
|
+
mode === "parameter") {
|
|
305
|
+
return { mode };
|
|
306
|
+
}
|
|
307
|
+
return `declares length mode ${JSON.stringify(mode)}, which is not one of capacity, clock, modulation, parameter`;
|
|
308
|
+
}
|
|
309
|
+
function readSource(value, field) {
|
|
310
|
+
if (value === null || typeof value !== "object") {
|
|
311
|
+
return `declares no "${field}"`;
|
|
312
|
+
}
|
|
313
|
+
const kind = value.kind;
|
|
314
|
+
if (kind === "input")
|
|
315
|
+
return { kind: "input" };
|
|
316
|
+
if (kind === "const") {
|
|
317
|
+
const amount = readNumber(value.value, `${field}.value`);
|
|
318
|
+
return typeof amount === "string" ? amount : { kind: "const", value: amount };
|
|
319
|
+
}
|
|
320
|
+
if (kind === "temp") {
|
|
321
|
+
const index = readIndex(value.index, `${field}.index`);
|
|
322
|
+
return typeof index === "string" ? index : { kind: "temp", index };
|
|
323
|
+
}
|
|
324
|
+
return `declares ${field} kind ${JSON.stringify(kind)}, which is not one of input, const, temp`;
|
|
325
|
+
}
|
|
326
|
+
function readTerms(op, parameters) {
|
|
327
|
+
const value = op.terms;
|
|
328
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
329
|
+
return 'declares no non-empty "terms"';
|
|
330
|
+
}
|
|
331
|
+
const terms = [];
|
|
332
|
+
for (const [index, entry] of value.entries()) {
|
|
333
|
+
if (entry === null || typeof entry !== "object") {
|
|
334
|
+
return `term ${index} is not an object`;
|
|
335
|
+
}
|
|
336
|
+
const source = readSource(entry.source, `terms[${index}].source`);
|
|
337
|
+
if (typeof source === "string")
|
|
338
|
+
return source;
|
|
339
|
+
const rawGain = entry.gain;
|
|
340
|
+
if (rawGain !== null && typeof rawGain === "object") {
|
|
341
|
+
const sweep = readGainParameter(rawGain, parameters, `terms[${index}].gain`);
|
|
342
|
+
if (typeof sweep === "string")
|
|
343
|
+
return sweep;
|
|
344
|
+
terms.push({ source, gain: sweep.min, sweep });
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const gain = readNumber(rawGain, `terms[${index}].gain`);
|
|
348
|
+
if (typeof gain === "string")
|
|
349
|
+
return gain;
|
|
350
|
+
terms.push({ source, gain });
|
|
351
|
+
}
|
|
352
|
+
return terms;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* A gain that names a position parameter, resolved to the knob that sweeps it, or why not.
|
|
356
|
+
*
|
|
357
|
+
* Four refusals, each a declaration that cannot be executed faithfully. A name the position does
|
|
358
|
+
* not declare has nothing to read. A parameter with no `source` is not set, by the format's own
|
|
359
|
+
* rule, so a gain cannot be read from it. A parameter no control sweeps is a fixed number and
|
|
360
|
+
* belongs in `gain` as one. And a `node` read has no port a gain could arrive through: the
|
|
361
|
+
* control-to-chip path would have to be modelled, which is exactly what `scanned` says it is not.
|
|
362
|
+
*/
|
|
363
|
+
function readGainParameter(raw, parameters, field) {
|
|
364
|
+
const name = raw.parameter;
|
|
365
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
366
|
+
return `${field} is an object but names no "parameter"`;
|
|
367
|
+
}
|
|
368
|
+
const parameter = parameters[name];
|
|
369
|
+
if (parameter === undefined) {
|
|
370
|
+
const declared = Object.keys(parameters);
|
|
371
|
+
return `${field} names parameter "${name}", which the position does not declare; it declares ${declared.length === 0 ? "none" : declared.join(", ")}`;
|
|
372
|
+
}
|
|
373
|
+
if (parameter.source === undefined) {
|
|
374
|
+
return `${field} names parameter "${name}", which cites no source and so is not set`;
|
|
375
|
+
}
|
|
376
|
+
if (parameter.control === undefined) {
|
|
377
|
+
return `${field} names parameter "${name}", which no control sweeps; a fixed gain is written as a number`;
|
|
378
|
+
}
|
|
379
|
+
if (parameter.read !== "scanned") {
|
|
380
|
+
return `${field} names parameter "${name}", read from a node; a gain has no node port, so only a scanned control can sweep one`;
|
|
381
|
+
}
|
|
382
|
+
if (!Number.isFinite(parameter.min) || !Number.isFinite(parameter.max)) {
|
|
383
|
+
return `${field} names parameter "${name}", whose range is not two finite numbers`;
|
|
384
|
+
}
|
|
385
|
+
return { controlId: parameter.control, min: parameter.min, max: parameter.max };
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=declared-program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declared-program.js","sourceRoot":"","sources":["../src/declared-program.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A number that knows what it is *per*.
|
|
3
|
+
*
|
|
4
|
+
* **Not a branded `number`, and the standard recipe fails here for a reason worth stating.** A
|
|
5
|
+
* branded number is still a number, so TypeScript permits `>=` between two of them — which is
|
|
6
|
+
* exactly the comparison this exists to reject. Tested before writing: the branded form blocks
|
|
7
|
+
* `const x: PerBlock = 5000` and waves through `saving >= measured`, so it fails at the only case
|
|
8
|
+
* it is for.
|
|
9
|
+
*
|
|
10
|
+
* The error it prevents is a class, not an incident. On 2026-09-11 a saving was registered per
|
|
11
|
+
* BLOCK and measured per PACKET; pre-registration, the control set and rule 32 all passed it,
|
|
12
|
+
* because **each was correct at the level it was stated**. 84% became 0.3%. The same shape cost
|
|
13
|
+
* two more hours the same day: a bound wrong by 64x (per-sample read as per-render) and an
|
|
14
|
+
* attribution reading 106.2% (per-drive against a shared window — a signal larger than its own
|
|
15
|
+
* total). A `PerBlock` and a `PerPacket` as distinct types could not have been compared at all.
|
|
16
|
+
*
|
|
17
|
+
* **The cost, stated honestly.** An opaque type is more invasive than a brand: arithmetic needs
|
|
18
|
+
* `.value`, and it is not erased — it allocates. Confine it to comparisons, thresholds and
|
|
19
|
+
* recorded figures. Never put one in an inner loop.
|
|
20
|
+
*/
|
|
21
|
+
export type Per<T extends string> = {
|
|
22
|
+
readonly denomination: T;
|
|
23
|
+
readonly value: number;
|
|
24
|
+
};
|
|
25
|
+
export type PerBlock = Per<"block">;
|
|
26
|
+
export type PerPacket = Per<"packet">;
|
|
27
|
+
export type PerSample = Per<"sample">;
|
|
28
|
+
export type PerRender = Per<"render">;
|
|
29
|
+
export type PerDrive = Per<"drive">;
|
|
30
|
+
export type SharedWindow = Per<"shared-window">;
|
|
31
|
+
export declare const perBlock: (value: number) => PerBlock;
|
|
32
|
+
export declare const perPacket: (value: number) => PerPacket;
|
|
33
|
+
export declare const perSample: (value: number) => PerSample;
|
|
34
|
+
export declare const perRender: (value: number) => PerRender;
|
|
35
|
+
export declare const perDrive: (value: number) => PerDrive;
|
|
36
|
+
export declare const sharedWindow: (value: number) => SharedWindow;
|
|
37
|
+
/**
|
|
38
|
+
* Comparison, legal only WITHIN one denomination.
|
|
39
|
+
*
|
|
40
|
+
* **`NoInfer` on the second operand is load-bearing.** Without it `T` widens to the union of both
|
|
41
|
+
* arguments and the guard accepts precisely what it exists to reject — the second of the two
|
|
42
|
+
* designs tried here, and it passed its own negative control before `NoInfer` was added.
|
|
43
|
+
*/
|
|
44
|
+
export declare const atLeast: <T extends string>(a: Per<T>, b: Per<NoInfer<T>>) => boolean;
|
|
45
|
+
/** Deliberately requires the share: the error was this conversion performed implicitly. */
|
|
46
|
+
export declare const blockToPacket: (v: PerBlock, shareOfPacket: number) => PerPacket;
|
|
47
|
+
export declare const sampleToRender: (v: PerSample, samples: number) => PerRender;
|
|
48
|
+
//# sourceMappingURL=denomination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"denomination.d.ts","sourceRoot":"","sources":["../src/denomination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,MAAM,IAAI;IACnC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;AACpC,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtC,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtC,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtC,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;AACpC,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;AAEhD,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,KAAG,QAA8C,CAAC;AACxF,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,SAAgD,CAAC;AAC3F,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,SAAgD,CAAC;AAC3F,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,SAAgD,CAAC;AAC3F,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,KAAG,QAA8C,CAAC;AACxF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,YAG3C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAG,OACvD,CAAC;AAEpB,2FAA2F;AAC3F,eAAO,MAAM,aAAa,GAAI,GAAG,QAAQ,EAAE,eAAe,MAAM,KAAG,SAGjE,CAAC;AAEH,eAAO,MAAM,cAAc,GAAI,GAAG,SAAS,EAAE,SAAS,MAAM,KAAG,SAG7D,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const perBlock = (value) => ({ denomination: "block", value });
|
|
2
|
+
export const perPacket = (value) => ({ denomination: "packet", value });
|
|
3
|
+
export const perSample = (value) => ({ denomination: "sample", value });
|
|
4
|
+
export const perRender = (value) => ({ denomination: "render", value });
|
|
5
|
+
export const perDrive = (value) => ({ denomination: "drive", value });
|
|
6
|
+
export const sharedWindow = (value) => ({
|
|
7
|
+
denomination: "shared-window",
|
|
8
|
+
value,
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Comparison, legal only WITHIN one denomination.
|
|
12
|
+
*
|
|
13
|
+
* **`NoInfer` on the second operand is load-bearing.** Without it `T` widens to the union of both
|
|
14
|
+
* arguments and the guard accepts precisely what it exists to reject — the second of the two
|
|
15
|
+
* designs tried here, and it passed its own negative control before `NoInfer` was added.
|
|
16
|
+
*/
|
|
17
|
+
export const atLeast = (a, b) => a.value >= b.value;
|
|
18
|
+
/** Deliberately requires the share: the error was this conversion performed implicitly. */
|
|
19
|
+
export const blockToPacket = (v, shareOfPacket) => ({
|
|
20
|
+
denomination: "packet",
|
|
21
|
+
value: v.value * shareOfPacket,
|
|
22
|
+
});
|
|
23
|
+
export const sampleToRender = (v, samples) => ({
|
|
24
|
+
denomination: "render",
|
|
25
|
+
value: v.value * samples,
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=denomination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"denomination.js","sourceRoot":"","sources":["../src/denomination.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAY,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAa,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAa,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAa,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAY,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAa,EAAgB,EAAE,CAAC,CAAC;IAC7D,YAAY,EAAE,eAAe;IAC7B,KAAK;CACL,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAmB,CAAS,EAAE,CAAkB,EAAW,EAAE,CACnF,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;AAEpB,2FAA2F;AAC3F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAW,EAAE,aAAqB,EAAa,EAAE,CAAC,CAAC;IAChF,YAAY,EAAE,QAAQ;IACtB,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,aAAa;CAC9B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAY,EAAE,OAAe,EAAa,EAAE,CAAC,CAAC;IAC5E,YAAY,EAAE,QAAQ;IACtB,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,OAAO;CACxB,CAAC,CAAC"}
|