@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.
Files changed (29) hide show
  1. package/README.md +68 -6
  2. package/dist/src/api-compile.js +27 -0
  3. package/dist/src/assembly/assemble-program.js +5 -0
  4. package/dist/src/assembly/import-visibility.d.ts +3 -0
  5. package/dist/src/assembly/import-visibility.js +204 -0
  6. package/dist/src/node/source-host.js +40 -13
  7. package/dist/src/outputs/write-asm80.js +4 -0
  8. package/dist/src/register-contracts/programModel-routines.js +33 -17
  9. package/dist/src/source/logical-lines.d.ts +3 -0
  10. package/dist/src/source/source-span.d.ts +2 -0
  11. package/dist/src/syntax/parse-directive-statement.d.ts +1 -6
  12. package/dist/src/syntax/parse-directive-statement.js +3 -1
  13. package/dist/src/syntax/parse-layout-declarations.js +11 -2
  14. package/dist/src/syntax/parse-line.js +18 -2
  15. package/dist/src/tooling/api.js +1 -1
  16. package/docs/codebase/01-orientation-and-repository-layout.md +192 -0
  17. package/docs/codebase/02-source-loading-and-parsing.md +263 -0
  18. package/docs/codebase/03-assembly-and-z80-emission.md +251 -0
  19. package/docs/codebase/04-ops-and-register-contracts.md +237 -0
  20. package/docs/codebase/05-interfaces-and-output-artifacts.md +253 -0
  21. package/docs/codebase/06-verification-and-maintenance.md +202 -0
  22. package/docs/codebase/appendices/a-directory-file-reference.md +253 -0
  23. package/docs/codebase/appendices/b-compile-flow-reference.md +103 -0
  24. package/docs/codebase/appendices/c-public-surface-reference.md +106 -0
  25. package/docs/codebase/appendices/index.md +16 -0
  26. package/docs/codebase/index.md +46 -0
  27. package/package.json +2 -3
  28. package/docs/reference/cli.md +0 -158
  29. 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.