@jhlagado/azm 0.2.12 → 0.2.13
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/dist/src/api-compile.d.ts +7 -1
- package/dist/src/api-compile.js +17 -5
- package/dist/src/api-register-contracts.js +69 -2
- package/dist/src/api-tooling.d.ts +1 -1
- package/dist/src/cli/artifact-files.d.ts +1 -0
- package/dist/src/cli/artifact-files.js +5 -0
- package/dist/src/cli/parse-args.d.ts +6 -1
- package/dist/src/cli/parse-args.js +59 -0
- package/dist/src/cli/run.js +2 -2
- package/dist/src/cli/usage.js +5 -0
- package/dist/src/cli/write-artifacts.d.ts +1 -1
- package/dist/src/cli/write-artifacts.js +15 -2
- package/dist/src/expansion/op-expansion.js +12 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/outputs/types.d.ts +13 -1
- package/dist/src/register-contracts/analyze-helpers.d.ts +6 -1
- package/dist/src/register-contracts/analyze-helpers.js +67 -0
- package/dist/src/register-contracts/analyze.d.ts +8 -1
- package/dist/src/register-contracts/analyze.js +353 -16
- package/dist/src/register-contracts/interfaceContracts.js +45 -0
- package/dist/src/register-contracts/liveness.js +23 -0
- package/dist/src/register-contracts/policy.d.ts +2 -0
- package/dist/src/register-contracts/policy.js +54 -0
- package/dist/src/register-contracts/programModel-boundaries.d.ts +5 -1
- package/dist/src/register-contracts/programModel-boundaries.js +20 -5
- package/dist/src/register-contracts/programModel-routines.js +37 -6
- package/dist/src/register-contracts/ratchet.d.ts +3 -0
- package/dist/src/register-contracts/ratchet.js +88 -0
- package/dist/src/register-contracts/report.d.ts +8 -1
- package/dist/src/register-contracts/report.js +174 -0
- package/dist/src/register-contracts/smartCommentParsing.js +22 -0
- package/dist/src/register-contracts/summary-boundary.js +9 -2
- package/dist/src/register-contracts/tooling.d.ts +2 -1
- package/dist/src/register-contracts/tooling.js +2 -0
- package/dist/src/register-contracts/types.d.ts +157 -0
- package/dist/src/syntax/parse-line.js +3 -0
- package/docs/codebase/02-source-loading-and-parsing.md +10 -6
- package/docs/codebase/04-ops-and-register-contracts.md +49 -4
- package/docs/codebase/05-interfaces-and-output-artifacts.md +56 -6
- package/docs/codebase/06-verification-and-maintenance.md +10 -2
- package/docs/codebase/appendices/a-directory-file-reference.md +3 -1
- package/docs/codebase/appendices/b-compile-flow-reference.md +7 -5
- package/docs/codebase/appendices/c-public-surface-reference.md +19 -5
- package/package.json +1 -1
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { Z80Instruction } from '../z80/instruction.js';
|
|
2
2
|
export type RegisterContractsMode = 'off' | 'audit' | 'warn' | 'error' | 'strict';
|
|
3
|
+
export type RegisterContractsReportFormat = 'text' | 'json';
|
|
4
|
+
export type RegisterContractsInferenceFormat = 'json' | 'markdown';
|
|
5
|
+
export type RegisterContractsPolicyMode = 'off' | 'audit' | 'strict';
|
|
6
|
+
export interface RegisterContractsPolicy {
|
|
7
|
+
strict?: readonly string[];
|
|
8
|
+
audit?: readonly string[];
|
|
9
|
+
off?: readonly string[];
|
|
10
|
+
}
|
|
3
11
|
/** @deprecated Use RegisterContractsMode. */
|
|
4
12
|
export type RegisterCareMode = RegisterContractsMode;
|
|
5
13
|
export type RegisterContractsUnit = 'A' | 'B' | 'C' | 'D' | 'E' | 'H' | 'L' | 'IXH' | 'IXL' | 'IYH' | 'IYL' | 'SPH' | 'SPL' | 'carry' | 'zero' | 'sign' | 'parity' | 'halfCarry';
|
|
@@ -28,6 +36,10 @@ export type SmartComment = {
|
|
|
28
36
|
kind: 'expectOut';
|
|
29
37
|
carriers: RegisterContractsUnit[];
|
|
30
38
|
name?: string;
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'rcIgnoreNext';
|
|
41
|
+
findingKind: RegisterContractsFindingKind;
|
|
42
|
+
reason: string;
|
|
31
43
|
};
|
|
32
44
|
export interface LocatedSmartComment {
|
|
33
45
|
file: string;
|
|
@@ -47,6 +59,9 @@ export interface RegisterContractsInstruction {
|
|
|
47
59
|
file: string;
|
|
48
60
|
line: number;
|
|
49
61
|
column: number;
|
|
62
|
+
sourceUnit?: string;
|
|
63
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
64
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
50
65
|
labels: string[];
|
|
51
66
|
constants?: ReadonlyMap<string, number>;
|
|
52
67
|
}
|
|
@@ -60,6 +75,9 @@ export interface RegisterContractsRoutine {
|
|
|
60
75
|
constants?: ReadonlyMap<string, number>;
|
|
61
76
|
span: {
|
|
62
77
|
file: string;
|
|
78
|
+
sourceUnit?: string;
|
|
79
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
80
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
63
81
|
start: {
|
|
64
82
|
line: number;
|
|
65
83
|
column: number;
|
|
@@ -78,6 +96,9 @@ export interface RegisterContractsDirectCall {
|
|
|
78
96
|
file: string;
|
|
79
97
|
line: number;
|
|
80
98
|
column: number;
|
|
99
|
+
sourceUnit?: string;
|
|
100
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
101
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
81
102
|
}
|
|
82
103
|
/** @deprecated Use RegisterContractsDirectCall. */
|
|
83
104
|
export type RegisterCareDirectCall = RegisterContractsDirectCall;
|
|
@@ -143,9 +164,13 @@ export interface RoutineSummary {
|
|
|
143
164
|
outputCandidates?: RegisterContractsUnit[];
|
|
144
165
|
}
|
|
145
166
|
export interface RegisterContractsOutputCandidate {
|
|
167
|
+
kind?: 'output_candidate';
|
|
146
168
|
file: string;
|
|
147
169
|
line: number;
|
|
148
170
|
column: number;
|
|
171
|
+
sourceUnit?: string;
|
|
172
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
173
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
149
174
|
routine: string;
|
|
150
175
|
carriers: RegisterContractsUnit[];
|
|
151
176
|
autoFixable?: boolean;
|
|
@@ -154,35 +179,167 @@ export interface RegisterContractsOutputCandidate {
|
|
|
154
179
|
/** @deprecated Use RegisterContractsOutputCandidate. */
|
|
155
180
|
export type RegisterCareOutputCandidate = RegisterContractsOutputCandidate;
|
|
156
181
|
export interface RegisterContractsConflict {
|
|
182
|
+
kind?: 'definite_contract_violation' | 'flag_lifetime_risk';
|
|
157
183
|
file: string;
|
|
158
184
|
line: number;
|
|
159
185
|
column: number;
|
|
186
|
+
sourceUnit?: string;
|
|
187
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
188
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
189
|
+
routine?: string;
|
|
160
190
|
callTarget: string;
|
|
161
191
|
carriers: RegisterContractsUnit[];
|
|
162
192
|
message: string;
|
|
163
193
|
}
|
|
164
194
|
/** @deprecated Use RegisterContractsConflict. */
|
|
165
195
|
export type RegisterCareConflict = RegisterContractsConflict;
|
|
196
|
+
export type RegisterContractsFindingKind = 'definite_contract_violation' | 'flag_lifetime_risk' | 'missing_callee_contract' | 'unknown_control_flow' | 'external_interface_unknown' | 'output_candidate';
|
|
197
|
+
interface RegisterContractsFindingBase {
|
|
198
|
+
kind: RegisterContractsFindingKind;
|
|
199
|
+
file: string;
|
|
200
|
+
line: number;
|
|
201
|
+
column: number;
|
|
202
|
+
sourceUnit?: string;
|
|
203
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
204
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
205
|
+
message: string;
|
|
206
|
+
routine?: string;
|
|
207
|
+
carriers?: RegisterContractsUnit[];
|
|
208
|
+
}
|
|
209
|
+
export interface RegisterContractsConflictFinding extends RegisterContractsFindingBase {
|
|
210
|
+
kind: 'definite_contract_violation' | 'flag_lifetime_risk';
|
|
211
|
+
callTarget: string;
|
|
212
|
+
}
|
|
213
|
+
export interface RegisterContractsUnknownBoundaryFinding extends RegisterContractsFindingBase {
|
|
214
|
+
kind: 'missing_callee_contract' | 'external_interface_unknown';
|
|
215
|
+
callTarget: string;
|
|
216
|
+
subject: string;
|
|
217
|
+
}
|
|
218
|
+
export interface RegisterContractsStackFinding extends RegisterContractsFindingBase {
|
|
219
|
+
kind: 'unknown_control_flow';
|
|
220
|
+
routine: string;
|
|
221
|
+
stackBalanced: boolean;
|
|
222
|
+
hasUnknownStackEffect?: boolean;
|
|
223
|
+
}
|
|
224
|
+
export interface RegisterContractsOutputCandidateFinding extends RegisterContractsFindingBase {
|
|
225
|
+
kind: 'output_candidate';
|
|
226
|
+
routine: string;
|
|
227
|
+
autoFixable?: boolean;
|
|
228
|
+
}
|
|
229
|
+
export type RegisterContractsFinding = RegisterContractsConflictFinding | RegisterContractsUnknownBoundaryFinding | RegisterContractsStackFinding | RegisterContractsOutputCandidateFinding;
|
|
166
230
|
export interface RegisterContractsReportModel {
|
|
167
231
|
entryFile: string;
|
|
168
232
|
mode: RegisterContractsMode;
|
|
169
233
|
profile?: string;
|
|
170
234
|
summaries: RoutineSummary[];
|
|
235
|
+
findings?: RegisterContractsFinding[];
|
|
236
|
+
suppressedFindings?: RegisterContractsSuppressedFinding[];
|
|
171
237
|
conflicts: RegisterContractsConflict[];
|
|
172
238
|
outputCandidates?: RegisterContractsOutputCandidate[];
|
|
173
239
|
unknownCalls: string[];
|
|
240
|
+
ratchet?: RegisterContractsRatchetResult;
|
|
241
|
+
}
|
|
242
|
+
export interface RegisterContractsJsonLocation {
|
|
243
|
+
file: string;
|
|
244
|
+
line: number;
|
|
245
|
+
column: number;
|
|
246
|
+
sourceUnit?: string;
|
|
247
|
+
sourceRelation?: 'entry' | 'include' | 'import';
|
|
248
|
+
sourceUnitRelation?: 'entry' | 'include' | 'import';
|
|
249
|
+
}
|
|
250
|
+
export interface RegisterContractsJsonRemediation {
|
|
251
|
+
category: 'add_contract' | 'fix_call_or_contract' | 'review_control_flow' | 'review_output_contract';
|
|
252
|
+
hint: string;
|
|
253
|
+
}
|
|
254
|
+
export interface RegisterContractsJsonFinding {
|
|
255
|
+
kind: RegisterContractsFindingKind;
|
|
256
|
+
location: RegisterContractsJsonLocation;
|
|
257
|
+
message: string;
|
|
258
|
+
routine?: string;
|
|
259
|
+
callTarget?: string;
|
|
260
|
+
subject?: string;
|
|
261
|
+
carriers?: RegisterContractsUnit[];
|
|
262
|
+
stackBalanced?: boolean;
|
|
263
|
+
hasUnknownStackEffect?: boolean;
|
|
264
|
+
autoFixable?: boolean;
|
|
265
|
+
remediation: RegisterContractsJsonRemediation;
|
|
266
|
+
}
|
|
267
|
+
export interface RegisterContractsSuppression {
|
|
268
|
+
file: string;
|
|
269
|
+
line: number;
|
|
270
|
+
column: number;
|
|
271
|
+
findingKind: RegisterContractsFindingKind;
|
|
272
|
+
reason: string;
|
|
273
|
+
}
|
|
274
|
+
export interface RegisterContractsSuppressedFinding {
|
|
275
|
+
finding: RegisterContractsFinding;
|
|
276
|
+
suppression: RegisterContractsSuppression;
|
|
277
|
+
}
|
|
278
|
+
export interface RegisterContractsJsonReportModel {
|
|
279
|
+
format: 'azm-register-contracts-report';
|
|
280
|
+
version: 1;
|
|
281
|
+
entryFile: string;
|
|
282
|
+
mode: RegisterContractsMode;
|
|
283
|
+
profile?: string;
|
|
284
|
+
summaries: RoutineSummary[];
|
|
285
|
+
findings: RegisterContractsJsonFinding[];
|
|
286
|
+
suppressedFindings?: Array<{
|
|
287
|
+
finding: RegisterContractsJsonFinding;
|
|
288
|
+
suppression: RegisterContractsSuppression;
|
|
289
|
+
}>;
|
|
290
|
+
unknownCalls: string[];
|
|
291
|
+
ratchet?: RegisterContractsRatchetResult;
|
|
292
|
+
}
|
|
293
|
+
export interface RegisterContractsInferenceRoutine {
|
|
294
|
+
name: string;
|
|
295
|
+
in: RegisterContractsUnit[];
|
|
296
|
+
out: RegisterContractsUnit[];
|
|
297
|
+
clobbers: RegisterContractsUnit[];
|
|
298
|
+
preserves: RegisterContractsUnit[];
|
|
299
|
+
confidence: 'explicit' | 'inferred' | 'draft';
|
|
300
|
+
callerImpact: {
|
|
301
|
+
outputCandidateCount: number;
|
|
302
|
+
outputCandidateCarriers: RegisterContractsUnit[];
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
export interface RegisterContractsInferenceModel {
|
|
306
|
+
format: 'azm-register-contracts-inference';
|
|
307
|
+
version: 1;
|
|
308
|
+
routines: RegisterContractsInferenceRoutine[];
|
|
309
|
+
}
|
|
310
|
+
export interface RegisterContractsRatchetEntry {
|
|
311
|
+
identity: string;
|
|
312
|
+
finding: RegisterContractsJsonFinding;
|
|
313
|
+
}
|
|
314
|
+
export interface RegisterContractsRatchetResult {
|
|
315
|
+
baselineFile?: string;
|
|
316
|
+
newFindings: RegisterContractsRatchetEntry[];
|
|
317
|
+
removedFindings: RegisterContractsRatchetEntry[];
|
|
318
|
+
changedFindings: Array<{
|
|
319
|
+
identity: string;
|
|
320
|
+
baseline: RegisterContractsJsonFinding;
|
|
321
|
+
current: RegisterContractsJsonFinding;
|
|
322
|
+
}>;
|
|
174
323
|
}
|
|
175
324
|
export interface AnalyzeRegisterContractsOptions {
|
|
176
325
|
mode: RegisterContractsMode;
|
|
326
|
+
policy?: RegisterContractsPolicy;
|
|
177
327
|
emitReport: boolean;
|
|
328
|
+
reportFormat?: RegisterContractsReportFormat;
|
|
178
329
|
emitInterface: boolean;
|
|
330
|
+
emitInference?: boolean;
|
|
331
|
+
inferenceFormat?: RegisterContractsInferenceFormat;
|
|
179
332
|
emitAnnotations?: boolean;
|
|
180
333
|
fixRegisterContracts?: boolean;
|
|
181
334
|
registerContractsProfile?: 'mon3';
|
|
182
335
|
interfaceContracts?: RoutineContract[];
|
|
183
336
|
acceptedOutputCandidates?: ReadonlyMap<string, RegisterContractsUnit[]>;
|
|
337
|
+
baselineReport?: RegisterContractsJsonReportModel;
|
|
338
|
+
baselineFile?: string;
|
|
339
|
+
ratchet?: boolean;
|
|
184
340
|
}
|
|
185
341
|
export interface RegisterContractsAnnotationFile {
|
|
186
342
|
readonly path: string;
|
|
187
343
|
readonly text: string;
|
|
188
344
|
}
|
|
345
|
+
export {};
|
|
@@ -67,6 +67,9 @@ function commentOnlyLine(line) {
|
|
|
67
67
|
column: firstNonWhitespaceColumn(line.text),
|
|
68
68
|
...(line.sourceUnit !== undefined ? { sourceUnit: line.sourceUnit } : {}),
|
|
69
69
|
...(line.sourceRelation !== undefined ? { sourceRelation: line.sourceRelation } : {}),
|
|
70
|
+
...(line.sourceUnitRelation !== undefined
|
|
71
|
+
? { sourceUnitRelation: line.sourceUnitRelation }
|
|
72
|
+
: {}),
|
|
70
73
|
},
|
|
71
74
|
},
|
|
72
75
|
],
|
|
@@ -107,10 +107,13 @@ been identified.
|
|
|
107
107
|
|
|
108
108
|
`src/source/logical-lines.ts` scans a `SourceFile` into `LogicalLine` objects. A
|
|
109
109
|
logical line records the source name, line number and original text. Tooling
|
|
110
|
-
loads can also attach `sourceUnit` and `
|
|
110
|
+
loads can also attach `sourceUnit`, `sourceRelation` and `sourceUnitRelation`:
|
|
111
111
|
|
|
112
112
|
- `sourceUnit` is the owning file for the current tooling unit
|
|
113
|
-
- `sourceRelation`
|
|
113
|
+
- `sourceRelation` says how this physical file entered the current expansion
|
|
114
|
+
step: `entry`, `include` or `import`
|
|
115
|
+
- `sourceUnitRelation` says how the owning source unit entered the load:
|
|
116
|
+
`entry` or `import`
|
|
114
117
|
|
|
115
118
|
This thin structure gives every later diagnostic a stable location and enough
|
|
116
119
|
provenance for tooling features that need to reason about module ownership.
|
|
@@ -176,10 +179,11 @@ line is a label, instruction, directive, layout declaration or comment item.
|
|
|
176
179
|
- comments
|
|
177
180
|
|
|
178
181
|
Each item carries a source span where appropriate. Tooling spans now preserve
|
|
179
|
-
optional `sourceUnit` and `
|
|
180
|
-
Assembly uses item kind to decide size and emission.
|
|
181
|
-
uses instruction, label and comment items to build
|
|
182
|
-
spans to connect emitted bytes back to files and
|
|
182
|
+
optional `sourceUnit`, `sourceRelation` and `sourceUnitRelation` fields when
|
|
183
|
+
the loader attached them. Assembly uses item kind to decide size and emission.
|
|
184
|
+
Register contract analysis uses instruction, label and comment items to build
|
|
185
|
+
routines. D8 map output uses spans to connect emitted bytes back to files and
|
|
186
|
+
lines.
|
|
183
187
|
|
|
184
188
|
## Top-Level Parse Order
|
|
185
189
|
|
|
@@ -168,7 +168,10 @@ without exposing them outside the module.
|
|
|
168
168
|
`src/register-contracts/smartComments.ts` reads AZMDoc comments from the comment maps
|
|
169
169
|
captured during loading. Comment-block splitting and token parsing live in
|
|
170
170
|
`smartCommentBlocks.ts` and `smartCommentParsing.ts`. External `.asmi`
|
|
171
|
-
contracts are parsed in `interfaceContracts.ts`.
|
|
171
|
+
contracts are parsed in `interfaceContracts.ts`. The same parser also accepts
|
|
172
|
+
inline suppression comments in the form
|
|
173
|
+
`;! rc-ignore-next <finding-kind>: <reason>` for the next finding at that
|
|
174
|
+
location.
|
|
172
175
|
|
|
173
176
|
Contracts can describe:
|
|
174
177
|
|
|
@@ -184,6 +187,11 @@ routine contract. Source comments attach to routines in the current program.
|
|
|
184
187
|
The compact source form can place several clauses on one `;!` line, for
|
|
185
188
|
example `;! in A; out A; clobbers F`.
|
|
186
189
|
|
|
190
|
+
`.asmi` parsing stays strict. Files may contain `extern` or `service rst`
|
|
191
|
+
boundaries, `in`, `out`, `clobbers` and `preserves` clauses, then `end`.
|
|
192
|
+
Comment lines are rejected so interface files stay machine-generated and
|
|
193
|
+
deterministic.
|
|
194
|
+
|
|
187
195
|
## Effects, Summaries and Liveness
|
|
188
196
|
|
|
189
197
|
Register contract analysis depends on `src/z80/effects.ts`. Effects describe which registers
|
|
@@ -212,10 +220,36 @@ summaries before the final pass. Strict mode uses `stackBalanced` and
|
|
|
212
220
|
`hasUnknownStackEffect` to distinguish balanced stack use from a routine whose
|
|
213
221
|
boundary may leave the stack in an unknown state.
|
|
214
222
|
|
|
223
|
+
The analysis now emits typed findings rather than only free-form conflict text.
|
|
224
|
+
The current finding set covers:
|
|
225
|
+
|
|
226
|
+
- `definite_contract_violation`
|
|
227
|
+
- `flag_lifetime_risk`
|
|
228
|
+
- `missing_callee_contract`
|
|
229
|
+
- `external_interface_unknown`
|
|
230
|
+
- `unknown_control_flow`
|
|
231
|
+
- `output_candidate`
|
|
232
|
+
|
|
233
|
+
Policy and suppression handling operate on those finding kinds. Report JSON,
|
|
234
|
+
tooling consumers and baseline ratchets all use the same typed finding model.
|
|
235
|
+
|
|
236
|
+
`policy.ts` resolves per-file register-contract modes from `strict`, `audit`
|
|
237
|
+
and `off` glob lists. Specific patterns win over broad patterns, then stricter
|
|
238
|
+
matches win ties. This lets one compile run audit imported wrappers while
|
|
239
|
+
keeping core files in strict mode or disabling analysis for known external
|
|
240
|
+
shims. When policy disables a file, unresolved call targets in that file no
|
|
241
|
+
longer surface as ordinary unknown-symbol diagnostics.
|
|
242
|
+
|
|
215
243
|
## Reports, Interfaces and Tooling
|
|
216
244
|
|
|
217
|
-
`report.ts` renders human-readable `.regcontracts.txt` reports
|
|
218
|
-
|
|
245
|
+
`report.ts` renders human-readable `.regcontracts.txt` reports, JSON report
|
|
246
|
+
payloads, `.asmi` interface metadata and review-oriented inference exports. The
|
|
247
|
+
text and JSON reports share one model with routine summaries, findings,
|
|
248
|
+
suppressed findings, unknown calls and optional ratchet results. Inference
|
|
249
|
+
exports are lighter-weight routine summaries for review workflows and can be
|
|
250
|
+
rendered as JSON or Markdown.
|
|
251
|
+
|
|
252
|
+
`report.ts` also renders generated source contracts as one compact `;!` line,
|
|
219
253
|
joining `in`, `out`, `maybe-out` and `clobbers` clauses with semicolons.
|
|
220
254
|
When a routine may clobber the full flag set, the source form uses `F` as the
|
|
221
255
|
compact carrier name. `annotate.ts`, `annotations.ts`, `fix.ts` and
|
|
@@ -225,7 +259,12 @@ conservative fixes.
|
|
|
225
259
|
The CLI can request these behaviours through:
|
|
226
260
|
|
|
227
261
|
- `--reg-report`
|
|
262
|
+
- `--reg-report-format`
|
|
263
|
+
- `--reg-baseline`
|
|
264
|
+
- `--reg-ratchet`
|
|
228
265
|
- `--reg-interface`
|
|
266
|
+
- `--reg-infer`
|
|
267
|
+
- `--reg-infer-format`
|
|
229
268
|
- `--contracts`
|
|
230
269
|
- `--fix`
|
|
231
270
|
- `--accept-out`
|
|
@@ -236,6 +275,11 @@ file, line, column, message, fixability and optional text edits. An editor can
|
|
|
236
275
|
show the same register contract information that the CLI reports while using
|
|
237
276
|
normal editor actions for accepted fixes.
|
|
238
277
|
|
|
278
|
+
`analyzeRegisterContractsForTools()` now also returns the structured findings
|
|
279
|
+
list and output candidate list beside candidate diagnostics and code actions, so
|
|
280
|
+
tooling integrations can render the same categorised analysis that the CLI
|
|
281
|
+
writes to report artifacts.
|
|
282
|
+
|
|
239
283
|
## Changing Ops or Register Contracts
|
|
240
284
|
|
|
241
285
|
Op changes belong in `src/expansion/`, with tests under
|
|
@@ -249,7 +293,8 @@ Register contract changes usually begin in one of these files:
|
|
|
249
293
|
`instruction-operands.ts`, `instruction-predicates.ts`
|
|
250
294
|
- Summary inference: `summary.ts`
|
|
251
295
|
- Caller liveness: `liveness.ts`
|
|
252
|
-
-
|
|
296
|
+
- Policy selection and ratchets: `policy.ts`, `ratchet.ts`
|
|
297
|
+
- Output text and structured exports: `report.ts`
|
|
253
298
|
- Source edits: `annotate.ts`, `fix.ts`, `annotations.ts`
|
|
254
299
|
- Tooling surface: `tooling.ts`
|
|
255
300
|
|
|
@@ -68,6 +68,14 @@ when artifact writing succeeds.
|
|
|
68
68
|
artifact suppression, include paths, source-root, case-style linting, directive
|
|
69
69
|
aliases and register contract options.
|
|
70
70
|
|
|
71
|
+
Register-contract parsing now includes:
|
|
72
|
+
|
|
73
|
+
- report format selection with `--reg-report-format text|json`
|
|
74
|
+
- baseline comparison with `--reg-baseline <report.json>`
|
|
75
|
+
- ratcheting with `--reg-ratchet`
|
|
76
|
+
- inference export with `--reg-infer`
|
|
77
|
+
- inference format selection with `--reg-infer-format json|markdown`
|
|
78
|
+
|
|
71
79
|
`src/cli/write-artifacts.ts` maps parsed options into
|
|
72
80
|
`CompileNextFunctionOptions` and calculates the output stem.
|
|
73
81
|
`src/cli/artifact-files.ts` writes in-memory artifacts to disk. If the user
|
|
@@ -76,6 +84,13 @@ path and side artifacts use the same base. If the user supplies only
|
|
|
76
84
|
`program.asm`, AZM writes outputs next to the entry source using the source
|
|
77
85
|
stem.
|
|
78
86
|
|
|
87
|
+
Register-contract side artifacts now use suffixes derived from the selected
|
|
88
|
+
format:
|
|
89
|
+
|
|
90
|
+
- `.regcontracts.txt` or `.regcontracts.json` for reports
|
|
91
|
+
- `.asmi` for inferred interfaces
|
|
92
|
+
- `.regcontracts.inference.json` or `.regcontracts.inference.md` for review exports
|
|
93
|
+
|
|
79
94
|
## Compile API
|
|
80
95
|
|
|
81
96
|
`src/api-compile.ts` exports:
|
|
@@ -103,8 +118,14 @@ Important options include:
|
|
|
103
118
|
| `d8mInputs` | Artifact paths recorded in D8 metadata. |
|
|
104
119
|
| `emitBin`, `emitHex`, `emitD8m`, `emitAsm80` | Artifact selection. |
|
|
105
120
|
| `registerContracts` | Register contract mode. |
|
|
106
|
-
| `
|
|
121
|
+
| `registerContractsPolicy` | Per-file strict, audit and off policy. |
|
|
122
|
+
| `emitRegisterReport` | Emit text or JSON report artifact. |
|
|
123
|
+
| `registerContractsReportFormat` | Report format, `text` or `json`. |
|
|
124
|
+
| `registerContractsBaseline` | Baseline JSON report for ratcheting. |
|
|
125
|
+
| `registerContractsRatchet` | Fail when findings increase. |
|
|
107
126
|
| `emitRegisterInterface` | Emit `.asmi` artifact. |
|
|
127
|
+
| `emitRegisterInference` | Emit inference review artifact. |
|
|
128
|
+
| `registerContractsInferenceFormat` | Inference format, `json` or `markdown`. |
|
|
108
129
|
| `emitRegisterAnnotations` | Emit source annotation artifact. |
|
|
109
130
|
| `fixRegisterContracts` | Apply conservative source fixes. |
|
|
110
131
|
| `acceptRegisterOutputCandidates` | Promote selected output candidates. |
|
|
@@ -125,6 +146,11 @@ Diagnostics describe every warning or error observed during loading, analysis,
|
|
|
125
146
|
register contract analysis, assembly or artifact creation. Artifacts contain the
|
|
126
147
|
in-memory outputs requested by options.
|
|
127
148
|
|
|
149
|
+
When analysis is enabled, `compile()` can now suppress ordinary unresolved-call
|
|
150
|
+
diagnostics for files whose register-contract policy resolves to `off`. That
|
|
151
|
+
keeps policy-controlled external boundaries in the register-contract report path
|
|
152
|
+
rather than duplicating them as symbol failures.
|
|
153
|
+
|
|
128
154
|
The older option names `registerCare`, `registerCareProfile` and
|
|
129
155
|
`registerCareInterfaces` remain as deprecated aliases for package consumers.
|
|
130
156
|
New callers should use the `registerContracts...` names.
|
|
@@ -138,17 +164,29 @@ helpers.
|
|
|
138
164
|
`loadProgramNext()` returns a loaded program with source items, source texts and
|
|
139
165
|
source line comments. `analyzeProgramNext()` runs semantic checks and returns
|
|
140
166
|
symbols. `analyzeRegisterContractsForTools()` returns register contract
|
|
141
|
-
diagnostics and code actions in a form
|
|
167
|
+
diagnostics, typed findings, output candidates and code actions in a form
|
|
168
|
+
suitable for editors.
|
|
142
169
|
|
|
143
170
|
The tooling loader now recognises both `.include` and `.import`. Both directives
|
|
144
171
|
flatten source into one parse stream. `.import` also marks parsed spans with a
|
|
145
172
|
new source ownership unit, while `.include` keeps the surrounding owner's unit.
|
|
146
|
-
Editor features can use `item.span.sourceUnit
|
|
147
|
-
|
|
173
|
+
Editor features can use `item.span.sourceUnit`, `item.span.sourceRelation` and
|
|
174
|
+
`item.span.sourceUnitRelation` together: `sourceRelation` tracks the physical
|
|
175
|
+
file edge that produced the parsed item, while `sourceUnitRelation` tracks
|
|
176
|
+
whether the owning unit entered as the entry source or through `.import`.
|
|
148
177
|
Diagnostics, symbols and source segments continue to use physical source file
|
|
149
178
|
paths, so imported files appear as their own files in editor and Debug80 map
|
|
150
179
|
metadata.
|
|
151
180
|
|
|
181
|
+
`analyzeProgramNext()` now also enforces the completed import-visibility pass.
|
|
182
|
+
Visibility checks walk instruction operands, data expressions, equates,
|
|
183
|
+
alignment and bin-range expressions and bare `.ds` size expressions. Imported
|
|
184
|
+
private labels remain visible inside their own source unit, including op
|
|
185
|
+
generated references and text included into that same unit. When a name already
|
|
186
|
+
collides with an equate, enum member or case-insensitive type or enum
|
|
187
|
+
declaration, assembly keeps the duplicate-symbol or duplicate-type diagnostic
|
|
188
|
+
instead of replacing it with a visibility error.
|
|
189
|
+
|
|
152
190
|
An editor integration usually starts with:
|
|
153
191
|
|
|
154
192
|
```ts
|
|
@@ -179,6 +217,7 @@ The output layer uses structured artifact objects from `src/outputs/types.ts`:
|
|
|
179
217
|
- `Asm80Artifact`
|
|
180
218
|
- `RegisterContractsReportArtifact`
|
|
181
219
|
- `RegisterContractsInterfaceArtifact`
|
|
220
|
+
- `RegisterContractsInferenceArtifact`
|
|
182
221
|
- `RegisterContractsAnnotationsArtifact`
|
|
183
222
|
|
|
184
223
|
Each artifact has a `kind` field. Callers can switch on `kind` to find the
|
|
@@ -241,11 +280,22 @@ supported.
|
|
|
241
280
|
|
|
242
281
|
Register contract report, interface and annotation artifacts are created through
|
|
243
282
|
`runRegisterContracts()` in `src/api-register-contracts.ts` and flow through
|
|
244
|
-
the same compile result and CLI write path.
|
|
245
|
-
interface is metadata that can be loaded by later compile runs through
|
|
283
|
+
the same compile result and CLI write path. Reports can be human-readable text
|
|
284
|
+
or JSON. The `.asmi` interface is metadata that can be loaded by later compile runs through
|
|
246
285
|
`--interface`. Annotation artifacts write source files when `--contracts` or
|
|
247
286
|
`--fix` is used.
|
|
248
287
|
|
|
288
|
+
The register-contract report artifact now carries optional structured payloads:
|
|
289
|
+
`format`, `json` and the active `findings` list. JSON reports use the stable
|
|
290
|
+
`azm-register-contracts-report` envelope with summaries, findings, suppressed
|
|
291
|
+
findings, unknown calls and optional ratchet results.
|
|
292
|
+
|
|
293
|
+
Inference artifacts carry a routine-oriented `azm-register-contracts-inference`
|
|
294
|
+
model. Each routine records inferred `in`, `out`, `clobbers` and `preserves`
|
|
295
|
+
carriers, an inference confidence and caller-impact counts for output
|
|
296
|
+
candidates. Markdown rendering is intended for review, while JSON is suitable
|
|
297
|
+
for automation and regression tooling.
|
|
298
|
+
|
|
249
299
|
## Public API Compatibility
|
|
250
300
|
|
|
251
301
|
The public API is defined by package exports and exported TypeScript types.
|
|
@@ -55,8 +55,9 @@ between modules rather than inside one helper.
|
|
|
55
55
|
|
|
56
56
|
Source-loading and tooling provenance changes belong here as well. The
|
|
57
57
|
`stage-11-tooling-api.test.ts` integration suite covers include and import
|
|
58
|
-
resolution, recursive load failures
|
|
59
|
-
|
|
58
|
+
resolution, recursive load failures, span ownership metadata and import
|
|
59
|
+
visibility analysis across direct calls, jump fixups, data expressions, bare
|
|
60
|
+
`.ds` sizes, duplicate-symbol precedence and include-only wrappers.
|
|
60
61
|
|
|
61
62
|
## CLI, ASM80 and Differential Tests
|
|
62
63
|
|
|
@@ -65,6 +66,10 @@ failure modes, determinism, case-style linting and register contract switches.
|
|
|
65
66
|
Users experience the command-line behaviour through argument parsing,
|
|
66
67
|
diagnostics, output paths and exit status.
|
|
67
68
|
|
|
69
|
+
The register-contract CLI suite now also covers JSON report output, inference
|
|
70
|
+
artifact output, baseline loading and ratchet failures so option parsing and
|
|
71
|
+
artifact suffix rules stay stable.
|
|
72
|
+
|
|
68
73
|
CLI tests also protect deterministic output. `compareDiagnosticsForCli()` sorts
|
|
69
74
|
diagnostics by file, line, column, severity, code and message. A CLI test can
|
|
70
75
|
catch changes that leave the compiler correct but make terminal output unstable.
|
|
@@ -153,6 +158,8 @@ Ask what kind of fact the change affects:
|
|
|
153
158
|
- Instruction-chain splitting belongs in `source/`, while inline source
|
|
154
159
|
generation and op template expansion belong in `expansion/`.
|
|
155
160
|
- Routine contracts and liveness belong in `register-contracts/`.
|
|
161
|
+
- Register-contract policy matching, suppression parsing and ratchets also
|
|
162
|
+
belong in `register-contracts/`.
|
|
156
163
|
- Artifact shape belongs in `outputs/`.
|
|
157
164
|
- User commands belong in `cli/`.
|
|
158
165
|
- Package consumers belong in `api-compile.ts`, `api-tooling.ts` and
|
|
@@ -187,6 +194,7 @@ This book should change when:
|
|
|
187
194
|
- public package exports change
|
|
188
195
|
- CLI option groups change
|
|
189
196
|
- output artifact shapes change
|
|
197
|
+
- register-contract finding kinds, policy rules or report schemas change
|
|
190
198
|
- a major subsystem gains a new responsibility
|
|
191
199
|
- tests or guardrails are reorganised
|
|
192
200
|
|
|
@@ -139,11 +139,13 @@ you need to find the owner of a behaviour quickly.
|
|
|
139
139
|
| `carriers.ts` | Normalizes register contract carrier names and expands register pairs. |
|
|
140
140
|
| `controlFlow.ts` | Successor logic for routine instruction flow. |
|
|
141
141
|
| `profiles.ts` | Built-in external routine profiles such as MON-3. |
|
|
142
|
-
| `report.ts` | Renders
|
|
142
|
+
| `report.ts` | Renders text and JSON register-contract reports, inference exports, `.asmi` output and compact source contract blocks. |
|
|
143
143
|
| `annotate.ts` | Inserts or replaces generated contract blocks near routine labels. |
|
|
144
144
|
| `annotations.ts` | Builds source annotation artifact data. |
|
|
145
145
|
| `fix.ts` | Finds and applies conservative expected-output fixes. |
|
|
146
146
|
| `accept-output.ts` | Parses user-accepted output candidate options. |
|
|
147
|
+
| `policy.ts` | Resolves per-file strict, audit and off register-contract policy matches. |
|
|
148
|
+
| `ratchet.ts` | Compares current JSON findings against a baseline report. |
|
|
147
149
|
| `tooling.ts` | Editor-friendly register contract diagnostics and code actions. |
|
|
148
150
|
| `types.ts` | Register contract unit, routine, effect, summary, contract and report types. |
|
|
149
151
|
| `sourceText.ts` | Source line splitting and joining helpers for text edits. |
|
|
@@ -23,7 +23,7 @@ compile(entryFile, options, deps)
|
|
|
23
23
|
expand textual .include and tooling .import
|
|
24
24
|
collect source texts
|
|
25
25
|
collect source line comments
|
|
26
|
-
attach source ownership metadata
|
|
26
|
+
attach source ownership metadata and unit ancestry
|
|
27
27
|
scan logical lines
|
|
28
28
|
read directive alias profiles
|
|
29
29
|
build directive alias policy
|
|
@@ -43,7 +43,9 @@ compile(entryFile, options, deps)
|
|
|
43
43
|
read AZMDoc and .asmi contracts
|
|
44
44
|
infer summaries
|
|
45
45
|
run liveness
|
|
46
|
-
|
|
46
|
+
apply suppressions and scoped policy
|
|
47
|
+
compare JSON findings against optional baseline
|
|
48
|
+
build report, interface, inference and annotation artifacts
|
|
47
49
|
assembleProgram()
|
|
48
50
|
buildAddressState()
|
|
49
51
|
emitProgramImage()
|
|
@@ -85,7 +87,7 @@ analyzeProgramNext(loaded)
|
|
|
85
87
|
|
|
86
88
|
analyzeRegisterContractsForTools(loaded)
|
|
87
89
|
run register contract analysis in audit-oriented tooling mode
|
|
88
|
-
return candidate diagnostics and code actions
|
|
90
|
+
return findings, candidate diagnostics and code actions
|
|
89
91
|
```
|
|
90
92
|
|
|
91
93
|
`analyzeRegisterCareForTools()` remains as a deprecated compatibility export for
|
|
@@ -97,8 +99,8 @@ tooling integrations that still use the older name.
|
|
|
97
99
|
| ------------------ | -------------------- | ------------------------------------- |
|
|
98
100
|
| Source loading | entry path | logical lines with ownership metadata, source texts, comments |
|
|
99
101
|
| Parsing | logical lines | source items |
|
|
100
|
-
| Analysis | source items | diagnostics, symbols
|
|
101
|
-
| Register contracts | loaded program | summaries,
|
|
102
|
+
| Analysis | source items | diagnostics, symbols, import-visibility checks |
|
|
103
|
+
| Register contracts | loaded program | summaries, findings, reports and inference artifacts |
|
|
102
104
|
| Assembly | source items | byte map, symbols, source segments with per-item columns |
|
|
103
105
|
| Outputs | byte map and symbols | artifacts |
|
|
104
106
|
| CLI | artifacts | files on disk |
|
|
@@ -44,6 +44,16 @@ want one import path.
|
|
|
44
44
|
Use this path for build tools, Debug80 integration and scripts that need bytes
|
|
45
45
|
or artifacts.
|
|
46
46
|
|
|
47
|
+
Compile consumers should treat these register-contract options as public when
|
|
48
|
+
they use that subsystem:
|
|
49
|
+
|
|
50
|
+
- `registerContractsPolicy`
|
|
51
|
+
- `registerContractsReportFormat`
|
|
52
|
+
- `registerContractsBaseline`
|
|
53
|
+
- `registerContractsRatchet`
|
|
54
|
+
- `emitRegisterInference`
|
|
55
|
+
- `registerContractsInferenceFormat`
|
|
56
|
+
|
|
47
57
|
## Tooling Exports
|
|
48
58
|
|
|
49
59
|
`@jhlagado/azm/tooling` exposes:
|
|
@@ -62,9 +72,10 @@ Use this path for editors, linters and language tooling.
|
|
|
62
72
|
`analyzeRegisterCareForTools` remains as a deprecated compatibility export.
|
|
63
73
|
|
|
64
74
|
Tooling consumers should treat parsed item spans as provenance-bearing data.
|
|
65
|
-
When present, `sourceUnit` names the owning source unit
|
|
66
|
-
records whether
|
|
67
|
-
`
|
|
75
|
+
When present, `sourceUnit` names the owning source unit, `sourceRelation`
|
|
76
|
+
records whether the physical file edge was `entry`, `include` or `import`, and
|
|
77
|
+
`sourceUnitRelation` records whether the owning unit entered the load through
|
|
78
|
+
`entry` or `import`.
|
|
68
79
|
|
|
69
80
|
## CLI Export
|
|
70
81
|
|
|
@@ -95,12 +106,15 @@ Treat these as public contracts:
|
|
|
95
106
|
- `D8mSymbol`
|
|
96
107
|
- `LoadedProgramNext`
|
|
97
108
|
- `AnalyzeProgramNextResult`
|
|
109
|
+
- `RegisterContractsFinding`
|
|
110
|
+
- `RegisterContractsFindingKind`
|
|
111
|
+
- `RegisterContractsInferenceModel`
|
|
98
112
|
- `RegisterContractsCandidateDiagnostic`
|
|
99
113
|
- `RegisterContractsCodeAction`
|
|
100
114
|
|
|
101
115
|
For tooling consumers, this contract also includes the optional
|
|
102
|
-
`SourceSpan.sourceUnit
|
|
103
|
-
items.
|
|
116
|
+
`SourceSpan.sourceUnit`, `SourceSpan.sourceRelation` and
|
|
117
|
+
`SourceSpan.sourceUnitRelation` fields carried on parsed items.
|
|
104
118
|
|
|
105
119
|
When these shapes change, update package tests, TypeScript type tests, README
|
|
106
120
|
examples, repo-local reference docs and this manual.
|