@jhlagado/azm 0.2.8 → 0.2.9
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 +68 -6
- package/dist/src/api-compile.js +27 -0
- package/dist/src/assembly/assemble-program.js +5 -0
- package/dist/src/assembly/import-visibility.d.ts +3 -0
- package/dist/src/assembly/import-visibility.js +204 -0
- package/dist/src/node/source-host.js +40 -13
- package/dist/src/outputs/write-asm80.js +4 -0
- package/dist/src/register-contracts/programModel-routines.js +33 -17
- package/dist/src/source/logical-lines.d.ts +3 -0
- package/dist/src/source/source-span.d.ts +2 -0
- package/dist/src/syntax/parse-directive-statement.d.ts +1 -6
- package/dist/src/syntax/parse-directive-statement.js +3 -1
- package/dist/src/syntax/parse-layout-declarations.js +11 -2
- package/dist/src/syntax/parse-line.js +18 -2
- package/dist/src/tooling/api.js +1 -1
- package/docs/codebase/01-orientation-and-repository-layout.md +192 -0
- package/docs/codebase/02-source-loading-and-parsing.md +263 -0
- package/docs/codebase/03-assembly-and-z80-emission.md +251 -0
- package/docs/codebase/04-ops-and-register-contracts.md +237 -0
- package/docs/codebase/05-interfaces-and-output-artifacts.md +253 -0
- package/docs/codebase/06-verification-and-maintenance.md +202 -0
- package/docs/codebase/appendices/a-directory-file-reference.md +253 -0
- package/docs/codebase/appendices/b-compile-flow-reference.md +103 -0
- package/docs/codebase/appendices/c-public-surface-reference.md +106 -0
- package/docs/codebase/appendices/index.md +16 -0
- package/docs/codebase/index.md +46 -0
- package/package.json +2 -3
- package/docs/reference/cli.md +0 -158
- package/docs/reference/tooling-api.md +0 -320
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: 'Chapter 5 - Interfaces and Output Artifacts'
|
|
4
|
+
parent: 'AZM Engineering Manual'
|
|
5
|
+
nav_order: 5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
[<- Ops and Register Contracts](04-ops-and-register-contracts.md) | [Verification and Maintenance ->](06-verification-and-maintenance.md)
|
|
9
|
+
|
|
10
|
+
# Chapter 5 - Interfaces and Output Artifacts
|
|
11
|
+
|
|
12
|
+
AZM has three public entry surfaces: the command-line binary, the compile API
|
|
13
|
+
and the tooling API. They all use the same compiler pipeline. Output writers
|
|
14
|
+
then serialize assembled facts for users, Debug80 and package consumers.
|
|
15
|
+
|
|
16
|
+
This chapter covers the boundary between the compiler and its callers: package
|
|
17
|
+
exports, CLI flow, public TypeScript APIs and artifact shapes.
|
|
18
|
+
|
|
19
|
+
## Package Exports
|
|
20
|
+
|
|
21
|
+
`package.json` exposes:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
@jhlagado/azm
|
|
25
|
+
@jhlagado/azm/compile
|
|
26
|
+
@jhlagado/azm/tooling
|
|
27
|
+
@jhlagado/azm/cli
|
|
28
|
+
@jhlagado/azm/package.json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`src/index.ts` re-exports the stable public surface. `src/api-compile.ts` backs
|
|
32
|
+
`@jhlagado/azm/compile`. `src/api-artifacts.ts` isolates assembly artifact
|
|
33
|
+
creation for the compile API. `src/api-register-contracts.ts` isolates register contract
|
|
34
|
+
analysis, interface loading and register contract artifact creation.
|
|
35
|
+
`src/api-tooling.ts` backs `@jhlagado/azm/tooling`. `src/cli.ts` is the
|
|
36
|
+
executable entry.
|
|
37
|
+
|
|
38
|
+
The root export gives consumers a broad import. The `/compile` path is the
|
|
39
|
+
build-system path. The `/tooling` path is the editor and analysis path. The
|
|
40
|
+
`/cli` path backs the executable entry. The `/package.json` path exposes package
|
|
41
|
+
metadata for tools that need the installed version.
|
|
42
|
+
|
|
43
|
+
## CLI Flow
|
|
44
|
+
|
|
45
|
+
The executable path in `package.json` points to `dist/src/cli.js`, compiled from
|
|
46
|
+
`src/cli.ts`. That file calls `runCli(process.argv.slice(2))` and sets the
|
|
47
|
+
process exit code.
|
|
48
|
+
|
|
49
|
+
`src/cli/run.ts` owns the CLI control flow:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
runCli(argv)
|
|
53
|
+
parseCliArgs(argv)
|
|
54
|
+
artifactBase(entryFile, outputType, outputPath)
|
|
55
|
+
compile(entryFile, buildCompileOptions(parsed, base))
|
|
56
|
+
sort and print diagnostics
|
|
57
|
+
writeArtifacts(base, artifacts, outputType)
|
|
58
|
+
return exit code
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The CLI returns `0` for a successful assembly, `1` when diagnostics include an
|
|
62
|
+
error and `2` for argument or unexpected runtime failures. Diagnostics are
|
|
63
|
+
printed to standard error. The primary output path is printed to standard output
|
|
64
|
+
when artifact writing succeeds.
|
|
65
|
+
|
|
66
|
+
`src/cli/parse-args.ts` parses switches and validates the command shape.
|
|
67
|
+
`src/cli/usage.ts` owns help text. The parser recognises output selection,
|
|
68
|
+
artifact suppression, include paths, source-root, case-style linting, directive
|
|
69
|
+
aliases and register contract options.
|
|
70
|
+
|
|
71
|
+
`src/cli/write-artifacts.ts` maps parsed options into
|
|
72
|
+
`CompileNextFunctionOptions` and calculates the output stem.
|
|
73
|
+
`src/cli/artifact-files.ts` writes in-memory artifacts to disk. If the user
|
|
74
|
+
supplies `--output build/program.bin`, the primary artifact is written to that
|
|
75
|
+
path and side artifacts use the same base. If the user supplies only
|
|
76
|
+
`program.asm`, AZM writes outputs next to the entry source using the source
|
|
77
|
+
stem.
|
|
78
|
+
|
|
79
|
+
## Compile API
|
|
80
|
+
|
|
81
|
+
`src/api-compile.ts` exports:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
export async function compile(
|
|
85
|
+
entryFile: string,
|
|
86
|
+
options: CompileNextFunctionOptions = {},
|
|
87
|
+
deps: CompileNextDependencies = { formats: defaultFormatWriters },
|
|
88
|
+
): Promise<CompileNextResult>;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The compile API is file-backed. It reads source from disk, expands includes,
|
|
92
|
+
analyses the program, assembles it and returns artifacts in memory.
|
|
93
|
+
|
|
94
|
+
Important options include:
|
|
95
|
+
|
|
96
|
+
| Option | Meaning |
|
|
97
|
+
| -------------------------------------------- | --------------------------------------- |
|
|
98
|
+
| `includeDirs` | Include search paths. |
|
|
99
|
+
| `directiveAliasFiles` | Project alias profile files. |
|
|
100
|
+
| `caseStyle` | Case-style lint mode. |
|
|
101
|
+
| `outputType` | Primary output type, `hex` or `bin`. |
|
|
102
|
+
| `sourceRoot` | Root used for portable D8 map paths. |
|
|
103
|
+
| `d8mInputs` | Artifact paths recorded in D8 metadata. |
|
|
104
|
+
| `emitBin`, `emitHex`, `emitD8m`, `emitAsm80` | Artifact selection. |
|
|
105
|
+
| `registerContracts` | Register contract mode. |
|
|
106
|
+
| `emitRegisterReport` | Emit `.regcontracts.txt` artifact. |
|
|
107
|
+
| `emitRegisterInterface` | Emit `.asmi` artifact. |
|
|
108
|
+
| `emitRegisterAnnotations` | Emit source annotation artifact. |
|
|
109
|
+
| `fixRegisterContracts` | Apply conservative source fixes. |
|
|
110
|
+
| `acceptRegisterOutputCandidates` | Promote selected output candidates. |
|
|
111
|
+
| `registerContractsProfile` | Built-in external contract profile. |
|
|
112
|
+
| `registerContractsInterfaces` | External `.asmi` contract files. |
|
|
113
|
+
| `skipAssembly` | Run loading and analysis only. |
|
|
114
|
+
|
|
115
|
+
`compile()` returns:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
export interface CompileNextResult {
|
|
119
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
120
|
+
readonly artifacts: readonly Artifact[];
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Diagnostics describe every warning or error observed during loading, analysis,
|
|
125
|
+
register contract analysis, assembly or artifact creation. Artifacts contain the
|
|
126
|
+
in-memory outputs requested by options.
|
|
127
|
+
|
|
128
|
+
The older option names `registerCare`, `registerCareProfile` and
|
|
129
|
+
`registerCareInterfaces` remain as deprecated aliases for package consumers.
|
|
130
|
+
New callers should use the `registerContracts...` names.
|
|
131
|
+
|
|
132
|
+
## Tooling API
|
|
133
|
+
|
|
134
|
+
`src/tooling/api.ts` exports `loadProgramNext()` and `analyzeProgramNext()`.
|
|
135
|
+
`src/api-tooling.ts` re-exports those functions with register contract tooling
|
|
136
|
+
helpers.
|
|
137
|
+
|
|
138
|
+
`loadProgramNext()` returns a loaded program with source items, source texts and
|
|
139
|
+
source line comments. `analyzeProgramNext()` runs semantic checks and returns
|
|
140
|
+
symbols. `analyzeRegisterContractsForTools()` returns register contract
|
|
141
|
+
diagnostics and code actions in a form suitable for editors.
|
|
142
|
+
|
|
143
|
+
The tooling loader now recognises both `.include` and `.import`. Both directives
|
|
144
|
+
flatten source into one parse stream. `.import` also marks parsed spans with a
|
|
145
|
+
new source ownership unit, while `.include` keeps the surrounding owner's unit.
|
|
146
|
+
Editor features can use `item.span.sourceUnit` and `item.span.sourceRelation`
|
|
147
|
+
to distinguish module-owned declarations from text included into another unit.
|
|
148
|
+
Diagnostics, symbols and source segments continue to use physical source file
|
|
149
|
+
paths, so imported files appear as their own files in editor and Debug80 map
|
|
150
|
+
metadata.
|
|
151
|
+
|
|
152
|
+
An editor integration usually starts with:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const loaded = await loadProgramNext({
|
|
156
|
+
entryFile: '/project/src/main.asm',
|
|
157
|
+
includeDirs: ['/project/include'],
|
|
158
|
+
preloadedText: editorText,
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
When `loaded.loadedProgram` is present, the editor can call
|
|
163
|
+
`analyzeProgramNext()` for symbols and case-style diagnostics. It can also call
|
|
164
|
+
`analyzeRegisterContractsForTools()` for register contract candidate diagnostics
|
|
165
|
+
and code actions.
|
|
166
|
+
|
|
167
|
+
## Artifact Types
|
|
168
|
+
|
|
169
|
+
The output layer uses structured artifact objects from `src/outputs/types.ts`:
|
|
170
|
+
|
|
171
|
+
- `BinArtifact`
|
|
172
|
+
- `HexArtifact`
|
|
173
|
+
- `D8mArtifact`
|
|
174
|
+
- `Asm80Artifact`
|
|
175
|
+
- `RegisterContractsReportArtifact`
|
|
176
|
+
- `RegisterContractsInterfaceArtifact`
|
|
177
|
+
- `RegisterContractsAnnotationsArtifact`
|
|
178
|
+
|
|
179
|
+
Each artifact has a `kind` field. Callers can switch on `kind` to find the
|
|
180
|
+
artifact they need:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const d8m = result.artifacts.find((artifact) => artifact.kind === 'd8m');
|
|
184
|
+
const bin = result.artifacts.find((artifact) => artifact.kind === 'bin');
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
This shape keeps the compile API independent from output paths. A caller can
|
|
188
|
+
write artifacts to disk, keep them in memory, send them to another process or
|
|
189
|
+
compare them in a test.
|
|
190
|
+
|
|
191
|
+
## Byte Maps, BIN and HEX
|
|
192
|
+
|
|
193
|
+
Assembly produces an `EmittedByteMap`. It represents sparse output: addresses
|
|
194
|
+
map to byte values and source segments describe where those bytes came from.
|
|
195
|
+
|
|
196
|
+
`src/outputs/range.ts` provides range helpers. `getWrittenSegments()` identifies
|
|
197
|
+
contiguous written address ranges. `getWrittenRange()` returns the overall
|
|
198
|
+
written span.
|
|
199
|
+
|
|
200
|
+
`src/outputs/write-bin.ts` writes flat binary. It chooses the written range,
|
|
201
|
+
fills gaps as needed and returns a `Uint8Array` artifact.
|
|
202
|
+
`src/outputs/write-hex.ts` wraps `src/outputs/hex.ts`, which writes Intel HEX
|
|
203
|
+
records and checksums.
|
|
204
|
+
|
|
205
|
+
## D8 Debug Maps
|
|
206
|
+
|
|
207
|
+
`src/outputs/write-d8.ts` writes Debug80 metadata. It records generator details,
|
|
208
|
+
input artifact paths, source files, source segments, addressable symbols and
|
|
209
|
+
value-only constants.
|
|
210
|
+
|
|
211
|
+
The writer normalizes source paths through `sourceRoot` when provided. It also
|
|
212
|
+
coalesces source segments and clips them to written ranges so Debug80 receives a
|
|
213
|
+
clean map of source lines to emitted bytes.
|
|
214
|
+
|
|
215
|
+
The D8 map distinguishes addressable symbols from constants. Labels and
|
|
216
|
+
addressable data carry addresses. Constants carry values. Debug80 can then use
|
|
217
|
+
addressable symbols for breakpoints and display constants as metadata.
|
|
218
|
+
|
|
219
|
+
## Lowered ASM80 and Register Contract Artifacts
|
|
220
|
+
|
|
221
|
+
`src/outputs/write-asm80.ts` serializes accepted AZM source items as
|
|
222
|
+
ASM80-compatible `.z80` text. It lowers supported AZM constructs into forms that
|
|
223
|
+
can be compared against ASM80 output. The writer is larger than the other
|
|
224
|
+
writers because it turns structured items back into source text.
|
|
225
|
+
|
|
226
|
+
Lowered ASM80 output currently rejects programs that use `.import`. Imported
|
|
227
|
+
source units carry visibility semantics that would be misleading if silently
|
|
228
|
+
flattened into compatibility text. The compile API reports `AZMN_ASM80` for
|
|
229
|
+
this output combination while native BIN, HEX and D8 artifacts remain
|
|
230
|
+
supported.
|
|
231
|
+
|
|
232
|
+
Register contract report, interface and annotation artifacts are created through
|
|
233
|
+
`runRegisterContracts()` in `src/api-register-contracts.ts` and flow through
|
|
234
|
+
the same compile result and CLI write path. The report is human-readable. The `.asmi`
|
|
235
|
+
interface is metadata that can be loaded by later compile runs through
|
|
236
|
+
`--interface`. Annotation artifacts write source files when `--contracts` or
|
|
237
|
+
`--fix` is used.
|
|
238
|
+
|
|
239
|
+
## Public API Compatibility
|
|
240
|
+
|
|
241
|
+
The public API is defined by package exports and exported TypeScript types.
|
|
242
|
+
Major-version planning is the point where these shapes can change:
|
|
243
|
+
|
|
244
|
+
- exported function names
|
|
245
|
+
- option object property names
|
|
246
|
+
- result object shapes
|
|
247
|
+
- artifact kinds
|
|
248
|
+
- diagnostic object shape
|
|
249
|
+
- D8 map type exports
|
|
250
|
+
- register contract tooling result shapes
|
|
251
|
+
|
|
252
|
+
The type tests are the safety net for this boundary. When a public type changes,
|
|
253
|
+
the change should be intentional and reflected in package documentation.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: 'Chapter 6 - Verification and Maintenance'
|
|
4
|
+
parent: 'AZM Engineering Manual'
|
|
5
|
+
nav_order: 6
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
[<- Interfaces and Output Artifacts](05-interfaces-and-output-artifacts.md) | [Appendices ->](appendices/)
|
|
9
|
+
|
|
10
|
+
# Chapter 6 - Verification and Maintenance
|
|
11
|
+
|
|
12
|
+
AZM's verification suite is organised by compiler boundary. A parser change has
|
|
13
|
+
a parser test. A byte-emission change has an encoder or integration test. A
|
|
14
|
+
public API change has a type-surface test. Reading the tests beside the
|
|
15
|
+
implementation is often the fastest way to understand a subsystem.
|
|
16
|
+
|
|
17
|
+
## Test Directory Map
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
test/
|
|
21
|
+
unit/
|
|
22
|
+
integration/
|
|
23
|
+
cli/
|
|
24
|
+
asm80/
|
|
25
|
+
differential/
|
|
26
|
+
fixtures/
|
|
27
|
+
helpers/
|
|
28
|
+
types/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Start with the narrowest useful test, then add the integration or CLI coverage
|
|
32
|
+
that proves the user-facing behaviour.
|
|
33
|
+
|
|
34
|
+
## Unit and Integration Tests
|
|
35
|
+
|
|
36
|
+
Unit tests live under `test/unit/` and mirror implementation directories:
|
|
37
|
+
|
|
38
|
+
| Directory | Boundary |
|
|
39
|
+
| -------------------------- | ------------------------------------------------------------------- |
|
|
40
|
+
| `unit/syntax/` | Line parsing, expression parsing and directive aliases. |
|
|
41
|
+
| `unit/source/` | Logical line and comment handling. |
|
|
42
|
+
| `unit/z80/` | Instruction parsing, diagnostics and encoding. |
|
|
43
|
+
| `unit/outputs/` | Artifact writer behaviour. |
|
|
44
|
+
| `unit/expansion/` | Op collection and expansion. |
|
|
45
|
+
| `unit/register-contracts/` | Register contract carriers, summaries, liveness, reports and fixes. |
|
|
46
|
+
|
|
47
|
+
Unit tests are small and direct. A new indexed operand form belongs in
|
|
48
|
+
`test/unit/z80/` before it appears in a full source fixture. The unit test proves
|
|
49
|
+
the instruction parser and encoder agree on that one form.
|
|
50
|
+
|
|
51
|
+
Integration tests under `test/integration/` assemble real source snippets
|
|
52
|
+
through multiple compiler stages. Layout features, ops and register contracts
|
|
53
|
+
interactions usually need this level of test because the behaviour exists
|
|
54
|
+
between modules rather than inside one helper.
|
|
55
|
+
|
|
56
|
+
Source-loading and tooling provenance changes belong here as well. The
|
|
57
|
+
`stage-11-tooling-api.test.ts` integration suite covers include and import
|
|
58
|
+
resolution, recursive load failures and the span ownership metadata that tools
|
|
59
|
+
read from parsed items.
|
|
60
|
+
|
|
61
|
+
## CLI, ASM80 and Differential Tests
|
|
62
|
+
|
|
63
|
+
`test/cli/` verifies the command-line contract: options, artifact writing,
|
|
64
|
+
failure modes, determinism, case-style linting and register contract switches.
|
|
65
|
+
Users experience the command-line behaviour through argument parsing,
|
|
66
|
+
diagnostics, output paths and exit status.
|
|
67
|
+
|
|
68
|
+
CLI tests also protect deterministic output. `compareDiagnosticsForCli()` sorts
|
|
69
|
+
diagnostics by file, line, column, severity, code and message. A CLI test can
|
|
70
|
+
catch changes that leave the compiler correct but make terminal output unstable.
|
|
71
|
+
|
|
72
|
+
`test/asm80/` and `test/differential/` protect compatibility and byte parity.
|
|
73
|
+
These tests compare AZM behaviour against ASM80 expectations, lowered output and
|
|
74
|
+
real-program fixtures. For an assembler, a one-byte difference is a behavioural
|
|
75
|
+
change.
|
|
76
|
+
|
|
77
|
+
## Fixtures and Helpers
|
|
78
|
+
|
|
79
|
+
`test/fixtures/` contains small source programs named after the issue or
|
|
80
|
+
behaviour they cover. A good fixture shows the source shape that matters. It
|
|
81
|
+
includes enough context to assemble and diagnose the behaviour, then stops.
|
|
82
|
+
|
|
83
|
+
`test/helpers/` contains shared helpers for CLI runs, diagnostics, temporary
|
|
84
|
+
source files and acceptance tests. Use helpers for repetitive setup. Keep test
|
|
85
|
+
expectations close to the test itself so failures stay easy to read.
|
|
86
|
+
|
|
87
|
+
`test/types/` and `test/public_api_surface.test.ts` protect the package export
|
|
88
|
+
surface. Run them whenever changing `src/index.ts`, `src/api-compile.ts`,
|
|
89
|
+
`src/api-tooling.ts`, `src/outputs/types.ts` or `package.json` exports.
|
|
90
|
+
|
|
91
|
+
## Guardrails
|
|
92
|
+
|
|
93
|
+
The main package scripts are:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
npm run build
|
|
97
|
+
npm run typecheck
|
|
98
|
+
npm run lint
|
|
99
|
+
npm run test:azm:alpha
|
|
100
|
+
npm run test:azm:corpus
|
|
101
|
+
npm run next:guardrails:core
|
|
102
|
+
npm run next:guardrails:package
|
|
103
|
+
npm run next:guardrails:quality
|
|
104
|
+
npm run next:guardrails
|
|
105
|
+
npm test
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Additional guardrails live under `scripts/ci/` and `scripts/dev/`. They answer
|
|
109
|
+
larger questions: does the alpha lane still pass, does ASM80 parity still hold,
|
|
110
|
+
does the package work after build output is generated, does lowered ASM80 still
|
|
111
|
+
cover the intended source set, do source files remain within the size budget and
|
|
112
|
+
does the corpus still match the accepted compatibility baseline.
|
|
113
|
+
|
|
114
|
+
Use this map when choosing a verification lane:
|
|
115
|
+
|
|
116
|
+
| Change | Tests |
|
|
117
|
+
| --------------------------- | -------------------------------------------------------------------- |
|
|
118
|
+
| Parser or expression syntax | `test/unit/syntax/**`, relevant integration tests. |
|
|
119
|
+
| Source loading or tooling provenance | `test/integration/stage-11-tooling-api.test.ts`, relevant unit tests in `test/unit/source/**`. |
|
|
120
|
+
| Z80 instruction support | `test/unit/z80/**`, diagnostic matrices, ASM80 parity when relevant. |
|
|
121
|
+
| Layout semantics | layout integration tests and output tests. |
|
|
122
|
+
| Ops | `test/unit/expansion/**`, op integration tests. |
|
|
123
|
+
| Register contracts | register contract unit, integration and CLI tests. |
|
|
124
|
+
| CLI options | `test/cli/**`. |
|
|
125
|
+
| Output artifacts | `test/unit/outputs/**`, CLI artifact tests. |
|
|
126
|
+
| Public API | type tests, public API surface tests and tooling API tests. |
|
|
127
|
+
| ASM80 lowering or parity | `check:asm80-coverage`, `test:ci:asm80-parity`, corpus guardrails. |
|
|
128
|
+
| Package export surface | `test:package`, public API surface tests. |
|
|
129
|
+
|
|
130
|
+
For subtle compiler changes, use a narrow test that names the broken layer and
|
|
131
|
+
a broader test that proves the public behaviour. That combination makes failures
|
|
132
|
+
easy to diagnose.
|
|
133
|
+
|
|
134
|
+
## Maintenance Boundaries
|
|
135
|
+
|
|
136
|
+
AZM is stable enough that changes should preserve the existing boundaries. A
|
|
137
|
+
maintainer can usually decide where a change belongs before editing code:
|
|
138
|
+
source loading, parsing, expression evaluation, address planning, Z80 encoding,
|
|
139
|
+
op expansion, register contracts, artifact writing, CLI or public API.
|
|
140
|
+
|
|
141
|
+
Ask what kind of fact the change affects:
|
|
142
|
+
|
|
143
|
+
- Text and files belong in `node/` and `source/`.
|
|
144
|
+
- Syntax belongs in `syntax/` or the structural parsing section of
|
|
145
|
+
`core/compile.ts`.
|
|
146
|
+
- Assembler-time facts belong in `assembly/` and `semantics/`.
|
|
147
|
+
- Instruction forms belong in `z80/`.
|
|
148
|
+
- Inline source generation belongs in `expansion/`.
|
|
149
|
+
- Routine contracts and liveness belong in `register-contracts/`.
|
|
150
|
+
- Artifact shape belongs in `outputs/`.
|
|
151
|
+
- User commands belong in `cli/`.
|
|
152
|
+
- Package consumers belong in `api-compile.ts`, `api-tooling.ts` and
|
|
153
|
+
`index.ts`.
|
|
154
|
+
|
|
155
|
+
This boundary choice determines the files to read, the tests to write and the
|
|
156
|
+
documentation to update.
|
|
157
|
+
|
|
158
|
+
## Structured Data and Compatibility
|
|
159
|
+
|
|
160
|
+
AZM passes structured data between stages. When a later stage needs more
|
|
161
|
+
information, add it to the earlier structured model and carry it forward.
|
|
162
|
+
Source provenance belongs on logical lines and source items. Syntax shape
|
|
163
|
+
belongs in `SourceItem`. Instruction shape belongs in `Z80Instruction`. Layout
|
|
164
|
+
facts belong in layout records and type expressions. Artifact metadata belongs
|
|
165
|
+
in output types.
|
|
166
|
+
|
|
167
|
+
Directive aliases and ASM80 lowering serve compatibility. Native AZM syntax
|
|
168
|
+
stays clean inside the compiler model when compatibility forms are converted to
|
|
169
|
+
canonical source items early and compatibility output is serialized late.
|
|
170
|
+
|
|
171
|
+
## Diagnostics and Manual Updates
|
|
172
|
+
|
|
173
|
+
Diagnostics should name the source location, the failing construct and the
|
|
174
|
+
reason. Parser diagnostics should recover where possible. Assembly diagnostics
|
|
175
|
+
should be deterministic. CLI output should sort diagnostics consistently.
|
|
176
|
+
|
|
177
|
+
This book should change when:
|
|
178
|
+
|
|
179
|
+
- a source directory is added, removed or repurposed
|
|
180
|
+
- the compile flow changes
|
|
181
|
+
- public package exports change
|
|
182
|
+
- CLI option groups change
|
|
183
|
+
- output artifact shapes change
|
|
184
|
+
- a major subsystem gains a new responsibility
|
|
185
|
+
- tests or guardrails are reorganised
|
|
186
|
+
|
|
187
|
+
Small implementation changes usually need test updates. Structural changes need
|
|
188
|
+
tests and manual updates.
|
|
189
|
+
|
|
190
|
+
## Suggested Change Workflow
|
|
191
|
+
|
|
192
|
+
1. Identify the boundary.
|
|
193
|
+
2. Read the relevant chapter and appendix entry.
|
|
194
|
+
3. Add or revise the closest test for the behaviour.
|
|
195
|
+
4. Change the implementation.
|
|
196
|
+
5. Run the focused test.
|
|
197
|
+
6. Run the broader guardrail that matches the public behaviour.
|
|
198
|
+
7. Update docs when the contract or architecture changed.
|
|
199
|
+
|
|
200
|
+
This workflow leaves evidence at the level where future maintainers will look:
|
|
201
|
+
the affected boundary, the public behaviour and the engineering manual when the
|
|
202
|
+
structure changes.
|