@jhlagado/azm 0.2.10 → 0.2.12
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 +14 -0
- package/dist/src/assembly/import-visibility.js +108 -33
- package/dist/src/core/compile.js +98 -1
- package/dist/src/expansion/op-expand-selected.js +8 -1
- package/dist/src/expansion/op-expansion.d.ts +3 -0
- package/dist/src/expansion/op-expansion.js +47 -9
- package/dist/src/node/source-host.js +5 -2
- package/dist/src/outputs/d8-files.js +1 -0
- package/dist/src/outputs/types.d.ts +1 -0
- package/dist/src/source/instruction-chain.d.ts +5 -0
- package/dist/src/source/instruction-chain.js +75 -0
- package/dist/src/source/logical-lines.d.ts +1 -0
- package/dist/src/source/source-span.d.ts +1 -0
- package/dist/src/syntax/names.d.ts +18 -0
- package/dist/src/syntax/names.js +44 -0
- package/dist/src/syntax/parse-data-directives.d.ts +17 -0
- package/dist/src/syntax/parse-data-directives.js +147 -0
- package/dist/src/syntax/parse-declaration-directives.d.ts +18 -0
- package/dist/src/syntax/parse-declaration-directives.js +90 -0
- package/dist/src/syntax/parse-diagnostics.d.ts +8 -0
- package/dist/src/syntax/parse-diagnostics.js +15 -0
- package/dist/src/syntax/parse-directive-statement.d.ts +1 -5
- package/dist/src/syntax/parse-directive-statement.js +19 -259
- package/dist/src/syntax/parse-instruction-chain.d.ts +22 -0
- package/dist/src/syntax/parse-instruction-chain.js +62 -0
- package/dist/src/syntax/parse-layout-declarations.js +10 -18
- package/dist/src/syntax/parse-layout-expression.js +4 -3
- package/dist/src/syntax/parse-line.js +21 -31
- package/dist/src/syntax/parse-location-directives.d.ts +7 -0
- package/dist/src/syntax/parse-location-directives.js +15 -0
- package/dist/src/syntax/statement-classification.d.ts +2 -0
- package/dist/src/syntax/statement-classification.js +24 -0
- package/dist/src/tooling/case-style.js +42 -26
- package/docs/codebase/02-source-loading-and-parsing.md +28 -8
- package/docs/codebase/04-ops-and-register-contracts.md +24 -3
- package/docs/codebase/05-interfaces-and-output-artifacts.md +10 -0
- package/docs/codebase/06-verification-and-maintenance.md +9 -3
- package/docs/codebase/appendices/a-directory-file-reference.md +17 -10
- package/docs/codebase/appendices/b-compile-flow-reference.md +3 -2
- package/docs/codebase/index.md +4 -0
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { splitInstructionChain } from '../source/instruction-chain.js';
|
|
1
2
|
import { stripLineComment } from '../source/strip-line-comment.js';
|
|
3
|
+
import { IDENTIFIER_PATTERN } from '../syntax/names.js';
|
|
4
|
+
import { isPotentialOpInvocationStatement } from '../syntax/statement-classification.js';
|
|
2
5
|
const REGISTER_RE = /(?<![A-Za-z0-9_$])(AF'|AF|BC|DE|HL|SP|IXH|IXL|IYH|IYL|IX|IY|A|B|C|D|E|H|L|I|R)(?![A-Za-z0-9_])/gi;
|
|
3
6
|
export function lintCaseStyleNext(options) {
|
|
4
7
|
if (options.mode === 'off')
|
|
@@ -23,19 +26,32 @@ function buildSourceLineMap(sourceTexts) {
|
|
|
23
26
|
return result;
|
|
24
27
|
}
|
|
25
28
|
function lintInstructionLine(rawLine, sourceName, line, mode, state, diagnostics) {
|
|
26
|
-
const
|
|
29
|
+
const segments = splitInstructionChain(rawLine);
|
|
30
|
+
if (segments !== undefined) {
|
|
31
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
32
|
+
const stripped = index === 0
|
|
33
|
+
? stripLeadingLabelsWithOffset(segments[index].text)
|
|
34
|
+
: { text: segments[index].text, offset: 0 };
|
|
35
|
+
lintInstructionSegment(stripped.text.trim(), segments[index].column + stripped.offset + firstColumn(stripped.text) - 1, sourceName, line, mode, state, diagnostics);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const stripped = stripLeadingLabelsWithOffset(stripLineComment(rawLine));
|
|
40
|
+
lintInstructionSegment(stripped.text.trim(), stripped.offset + firstColumn(stripped.text), sourceName, line, mode, state, diagnostics);
|
|
41
|
+
}
|
|
42
|
+
function lintInstructionSegment(text, baseColumn, sourceName, line, mode, state, diagnostics) {
|
|
27
43
|
if (text.length === 0)
|
|
28
44
|
return;
|
|
29
45
|
const mnemonic = text.split(/\s+/, 1)[0] ?? '';
|
|
30
46
|
if (mnemonic.length > 0) {
|
|
31
|
-
lintToken(mode, state, mnemonic, 'mnemonic', sourceName, line, diagnostics);
|
|
47
|
+
lintToken(mode, state, mnemonic, 'mnemonic', sourceName, line, baseColumn, diagnostics);
|
|
32
48
|
}
|
|
33
49
|
const scrubbed = scrubCharLiterals(text);
|
|
34
50
|
for (const match of scrubbed.matchAll(REGISTER_RE)) {
|
|
35
51
|
const raw = match[1];
|
|
36
52
|
if (!raw)
|
|
37
53
|
continue;
|
|
38
|
-
lintToken(mode, state, raw, 'register', sourceName, line, diagnostics);
|
|
54
|
+
lintToken(mode, state, raw, 'register', sourceName, line, baseColumn + match.index, diagnostics);
|
|
39
55
|
}
|
|
40
56
|
}
|
|
41
57
|
function lintSourceLines(sourceLines, instructionLines, mode, state, diagnostics) {
|
|
@@ -67,42 +83,30 @@ function shouldLintCaseStyleLine(rawLine, sourceName, line, instructionLines, st
|
|
|
67
83
|
isPotentialOpInvocationLine(text));
|
|
68
84
|
}
|
|
69
85
|
function isOpHeaderLine(text) {
|
|
70
|
-
return
|
|
86
|
+
return new RegExp(`^op\\s+${IDENTIFIER_PATTERN}\\s*\\(`, 'i').test(text);
|
|
71
87
|
}
|
|
72
88
|
function isOpEndLine(text) {
|
|
73
89
|
return /^end\s*$/i.test(text);
|
|
74
90
|
}
|
|
75
91
|
function isPotentialOpInvocationLine(text) {
|
|
76
|
-
|
|
77
|
-
return false;
|
|
78
|
-
if (/^[A-Za-z_][A-Za-z0-9_]*\s+\.?equ\b/i.test(text))
|
|
79
|
-
return false;
|
|
80
|
-
if (/^[A-Za-z_][A-Za-z0-9_]*\s+\.(?:enum|type|union|typealias|field|byte|word|addr)\b/.test(text)) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
if (/^(?:op|end|enum|type|union|field|byte|word|addr)\b/i.test(text))
|
|
84
|
-
return false;
|
|
85
|
-
if (/^(?:org|equ|db|dw|ds|align|include|binfrom|binto|cstr|pstr|istr)\b/i.test(text)) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
return true;
|
|
92
|
+
return isPotentialOpInvocationStatement(text);
|
|
89
93
|
}
|
|
90
94
|
function lineKey(sourceName, line) {
|
|
91
95
|
return `${sourceName}:${line}`;
|
|
92
96
|
}
|
|
93
|
-
function lintToken(mode, state, token, category, sourceName, line, diagnostics) {
|
|
97
|
+
function lintToken(mode, state, token, category, sourceName, line, column, diagnostics) {
|
|
94
98
|
const style = classifyTokenStyle(token);
|
|
95
99
|
if (!style)
|
|
96
100
|
return;
|
|
97
101
|
if (mode === 'consistent') {
|
|
98
|
-
lintConsistentToken(state, style, token, category, sourceName, line, diagnostics);
|
|
102
|
+
lintConsistentToken(state, style, token, category, sourceName, line, column, diagnostics);
|
|
99
103
|
return;
|
|
100
104
|
}
|
|
101
105
|
if (mode === 'off')
|
|
102
106
|
return;
|
|
103
|
-
lintFixedStyleToken(mode, style, token, category, sourceName, line, diagnostics);
|
|
107
|
+
lintFixedStyleToken(mode, style, token, category, sourceName, line, column, diagnostics);
|
|
104
108
|
}
|
|
105
|
-
function lintConsistentToken(state, style, token, category, sourceName, line, diagnostics) {
|
|
109
|
+
function lintConsistentToken(state, style, token, category, sourceName, line, column, diagnostics) {
|
|
106
110
|
if (!state.consistentStyle && (style === 'upper' || style === 'lower')) {
|
|
107
111
|
state.consistentStyle = style;
|
|
108
112
|
return;
|
|
@@ -116,10 +120,10 @@ function lintConsistentToken(state, style, token, category, sourceName, line, di
|
|
|
116
120
|
message: `Case-style lint: ${category} "${token}" does not match established ${expected}case style under --case-style=consistent.`,
|
|
117
121
|
sourceName,
|
|
118
122
|
line,
|
|
119
|
-
column
|
|
123
|
+
column,
|
|
120
124
|
});
|
|
121
125
|
}
|
|
122
|
-
function lintFixedStyleToken(mode, style, token, category, sourceName, line, diagnostics) {
|
|
126
|
+
function lintFixedStyleToken(mode, style, token, category, sourceName, line, column, diagnostics) {
|
|
123
127
|
if (style === mode)
|
|
124
128
|
return;
|
|
125
129
|
const expectedText = mode === 'upper' ? 'uppercase' : 'lowercase';
|
|
@@ -129,7 +133,7 @@ function lintFixedStyleToken(mode, style, token, category, sourceName, line, dia
|
|
|
129
133
|
message: `Case-style lint: ${category} "${token}" should be ${expectedText} under --case-style=${mode}.`,
|
|
130
134
|
sourceName,
|
|
131
135
|
line,
|
|
132
|
-
column
|
|
136
|
+
column,
|
|
133
137
|
});
|
|
134
138
|
}
|
|
135
139
|
function classifyTokenStyle(token) {
|
|
@@ -143,14 +147,26 @@ function classifyTokenStyle(token) {
|
|
|
143
147
|
return 'mixed';
|
|
144
148
|
}
|
|
145
149
|
function stripLeadingLabels(text) {
|
|
150
|
+
return stripLeadingLabelsWithOffset(text).text;
|
|
151
|
+
}
|
|
152
|
+
function stripLeadingLabelsWithOffset(text) {
|
|
146
153
|
let remaining = text;
|
|
154
|
+
let offset = 0;
|
|
147
155
|
while (true) {
|
|
148
|
-
const
|
|
156
|
+
const match = /^\s*[A-Za-z_.$?][A-Za-z0-9_.$?]*\s*:\s*/.exec(remaining);
|
|
157
|
+
if (!match)
|
|
158
|
+
return { text: remaining, offset };
|
|
159
|
+
const stripped = remaining.slice(match[0].length);
|
|
149
160
|
if (stripped === remaining)
|
|
150
|
-
return remaining;
|
|
161
|
+
return { text: remaining, offset };
|
|
151
162
|
remaining = stripped;
|
|
163
|
+
offset += match[0].length;
|
|
152
164
|
}
|
|
153
165
|
}
|
|
166
|
+
function firstColumn(text) {
|
|
167
|
+
const match = /\S/.exec(text);
|
|
168
|
+
return match ? match.index + 1 : 1;
|
|
169
|
+
}
|
|
154
170
|
function scrubCharLiterals(text) {
|
|
155
171
|
let output = '';
|
|
156
172
|
let inChar = false;
|
|
@@ -15,9 +15,9 @@ tooling and register contracts consume.
|
|
|
15
15
|
|
|
16
16
|
The loading boundary lives in `src/node/source-host.ts`. The parser is
|
|
17
17
|
orchestrated by `parseNextSourceItems()` in `src/core/compile.ts`, with
|
|
18
|
-
single-line parsing in `src/syntax/parse-line.ts`. Expression
|
|
19
|
-
parsing is split across
|
|
20
|
-
|
|
18
|
+
single-line parsing in `src/syntax/parse-line.ts`. Expression, name,
|
|
19
|
+
instruction-chain and directive parsing is split across small syntax helpers in
|
|
20
|
+
`src/syntax/`.
|
|
21
21
|
|
|
22
22
|
## Entry Files and Source Text
|
|
23
23
|
|
|
@@ -123,6 +123,7 @@ The source helpers are small and important:
|
|
|
123
123
|
| `logical-lines.ts` | Splits text into line records. |
|
|
124
124
|
| `source-span.ts` | Defines the common span shape. |
|
|
125
125
|
| `line-comment-scanner.ts` | Finds line comments while respecting quoted text. |
|
|
126
|
+
| `instruction-chain.ts` | Finds spaced-backslash separators and segment columns. |
|
|
126
127
|
| `strip-line-comment.ts` | Removes semicolon comments through the shared scanner. |
|
|
127
128
|
|
|
128
129
|
`strip-line-comment.ts` is used by source-loading directive recognition, layout parsing,
|
|
@@ -130,6 +131,15 @@ conditional assembly and single-line parsing. Shared comment handling prevents
|
|
|
130
131
|
each stage from inventing a slightly different rule for semicolons inside
|
|
131
132
|
strings and character literals.
|
|
132
133
|
|
|
134
|
+
`src/source/instruction-chain.ts` uses the same quoted-text rules to find
|
|
135
|
+
readable ` \ ` separators without splitting byte and string operands. It
|
|
136
|
+
reports trimmed segment text plus the original 1-based column for each segment,
|
|
137
|
+
so later stages can keep diagnostics and source maps aligned to the exact
|
|
138
|
+
instruction inside a physical line. `src/syntax/parse-instruction-chain.ts`
|
|
139
|
+
then applies the syntax rules: labels are allowed only before the first segment,
|
|
140
|
+
directives and declarations are rejected, and each segment is parsed as an
|
|
141
|
+
instruction or op invocation.
|
|
142
|
+
|
|
133
143
|
## Directive Aliases
|
|
134
144
|
|
|
135
145
|
Directive aliases are loaded during `loadProgramNext()`:
|
|
@@ -182,13 +192,16 @@ spans to connect emitted bytes back to files and lines.
|
|
|
182
192
|
4. Record and union headers collect `.field` declarations until `.endtype` or
|
|
183
193
|
`.endunion`.
|
|
184
194
|
5. Visible op invocations expand into ordinary source items.
|
|
185
|
-
6.
|
|
186
|
-
|
|
195
|
+
6. Chained instruction lines are split on spaced backslashes and each segment is
|
|
196
|
+
parsed as an instruction or op invocation.
|
|
197
|
+
7. `parseLogicalLine()` handles remaining single-line labels, directives, data
|
|
198
|
+
and instructions.
|
|
187
199
|
|
|
188
200
|
This order matters. Ops must be collected before invocation expansion. Layout
|
|
189
201
|
declarations must collect their body lines as one source item. Ordinary
|
|
190
202
|
instruction parsing should see the lines that remain after those structural
|
|
191
|
-
forms have been handled.
|
|
203
|
+
forms have been handled. Chained instruction parsing also needs the op registry
|
|
204
|
+
up front so later segments can expand ops and keep segment-level columns.
|
|
192
205
|
|
|
193
206
|
## Layout and Declaration Parsing
|
|
194
207
|
|
|
@@ -237,10 +250,17 @@ assembler-time value based on expression evaluation.
|
|
|
237
250
|
`src/syntax/expression-tokenizer.ts` tokenizes expression text.
|
|
238
251
|
`parse-token-expression.ts` builds expression trees from tokens.
|
|
239
252
|
`parse-expression.ts` is the public syntax wrapper used by line parsing.
|
|
253
|
+
`names.ts` centralises identifier, label and `@` entry-label parsing so line
|
|
254
|
+
parsing, chained-line parsing, op expansion and tooling share the same name
|
|
255
|
+
rules.
|
|
256
|
+
`statement-classification.ts` distinguishes potential op invocations from
|
|
257
|
+
declarations and rejects directives inside chained instruction segments.
|
|
240
258
|
`parse-layout-expression.ts` parses layout type expressions used by `.ds`,
|
|
241
259
|
`.field`, `.typealias`, `sizeof(...)`, `offset(...)` and layout casts.
|
|
242
|
-
`parse-directive-statement.ts`
|
|
243
|
-
|
|
260
|
+
`parse-directive-statement.ts` dispatches directive statements into focused
|
|
261
|
+
parsers: declaration directives in `parse-declaration-directives.ts`, data and
|
|
262
|
+
string directives in `parse-data-directives.ts` and expression-bearing location
|
|
263
|
+
directives in `parse-location-directives.ts`.
|
|
244
264
|
|
|
245
265
|
The parser produces expression trees from `src/model/expression.ts`.
|
|
246
266
|
`src/semantics/expression-evaluation.ts` evaluates those trees when the
|
|
@@ -67,6 +67,12 @@ The parser handles op invocations before `parseLogicalLine()`. An op head can
|
|
|
67
67
|
look like an instruction head at the source level. The expansion stage resolves
|
|
68
68
|
it before ordinary line parsing.
|
|
69
69
|
|
|
70
|
+
Top-level parsing also recognises chained instruction lines separated by a
|
|
71
|
+
spaced backslash. Each segment is parsed independently, with labels only
|
|
72
|
+
allowed before the first segment and directives still restricted to their own
|
|
73
|
+
physical lines. That lets short instruction runs compact onto one source line
|
|
74
|
+
without changing directive or declaration shape.
|
|
75
|
+
|
|
70
76
|
## Overloads and Templates
|
|
71
77
|
|
|
72
78
|
Ops support overloads. `op-selection.ts` compares invocation operands against
|
|
@@ -84,6 +90,12 @@ from the call site are substituted into the template by
|
|
|
84
90
|
`op-instruction-instantiation.ts`. The result is formatted as ordinary source
|
|
85
91
|
text and parsed through the same line parser used for top-level source.
|
|
86
92
|
|
|
93
|
+
Op bodies now accept the same chained-instruction form as top-level source.
|
|
94
|
+
`collectOps()` splits a spaced-backslash body line into template segments before
|
|
95
|
+
it decides whether each segment is a parameterised instruction template, an
|
|
96
|
+
ordinary source-item fragment or a nested op invocation. A first label may lead
|
|
97
|
+
the chain and becomes an ordinary label item in the expanded body.
|
|
98
|
+
|
|
87
99
|
Local label rewriting lives in `op-local-labels.ts`. A local label in an op
|
|
88
100
|
expansion becomes unique at the use site so each expansion receives its own
|
|
89
101
|
generated label. Once the rewritten labels become source items, address planning
|
|
@@ -148,7 +160,10 @@ items. Routine-specific extraction is split into
|
|
|
148
160
|
`programModel-boundaries.ts` and `programModel-routines.ts`. Together they find
|
|
149
161
|
routine boundaries, direct calls, labels and instructions. Routine entry labels
|
|
150
162
|
use `@` in source and become callable public routine names after the marker is
|
|
151
|
-
removed.
|
|
163
|
+
removed. When an imported public routine calls private labels inside the same
|
|
164
|
+
import unit, the routine builder keeps those direct call targets in the
|
|
165
|
+
internal routine set so strict analysis can follow imported helper routines
|
|
166
|
+
without exposing them outside the module.
|
|
152
167
|
|
|
153
168
|
`src/register-contracts/smartComments.ts` reads AZMDoc comments from the comment maps
|
|
154
169
|
captured during loading. Comment-block splitting and token parsing live in
|
|
@@ -166,6 +181,8 @@ Contracts can describe:
|
|
|
166
181
|
Source comments and external interfaces describe the same kind of fact: a
|
|
167
182
|
routine contract. Source comments attach to routines in the current program.
|
|
168
183
|
`.asmi` entries attach to routines whose source is assembled elsewhere.
|
|
184
|
+
The compact source form can place several clauses on one `;!` line, for
|
|
185
|
+
example `;! in A; out A; clobbers F`.
|
|
169
186
|
|
|
170
187
|
## Effects, Summaries and Liveness
|
|
171
188
|
|
|
@@ -198,8 +215,12 @@ boundary may leave the stack in an unknown state.
|
|
|
198
215
|
## Reports, Interfaces and Tooling
|
|
199
216
|
|
|
200
217
|
`report.ts` renders human-readable `.regcontracts.txt` reports and `.asmi` interface
|
|
201
|
-
metadata.
|
|
202
|
-
|
|
218
|
+
metadata. It also renders generated source contracts as one compact `;!` line,
|
|
219
|
+
joining `in`, `out`, `maybe-out` and `clobbers` clauses with semicolons.
|
|
220
|
+
When a routine may clobber the full flag set, the source form uses `F` as the
|
|
221
|
+
compact carrier name. `annotate.ts`, `annotations.ts`, `fix.ts` and
|
|
222
|
+
`sourceText.ts` support source updates for generated AZMDoc comments and
|
|
223
|
+
conservative fixes.
|
|
203
224
|
|
|
204
225
|
The CLI can request these behaviours through:
|
|
205
226
|
|
|
@@ -164,6 +164,11 @@ When `loaded.loadedProgram` is present, the editor can call
|
|
|
164
164
|
`analyzeRegisterContractsForTools()` for register contract candidate diagnostics
|
|
165
165
|
and code actions.
|
|
166
166
|
|
|
167
|
+
Case-style linting now understands chained instruction lines. A physical line
|
|
168
|
+
such as `LD A,B \ inc c \ RET` is linted per segment, and warnings report the
|
|
169
|
+
column of the specific mnemonic or register inside the chain rather than the
|
|
170
|
+
start of the line.
|
|
171
|
+
|
|
167
172
|
## Artifact Types
|
|
168
173
|
|
|
169
174
|
The output layer uses structured artifact objects from `src/outputs/types.ts`:
|
|
@@ -212,6 +217,11 @@ The writer normalizes source paths through `sourceRoot` when provided. It also
|
|
|
212
217
|
coalesces source segments and clips them to written ranges so Debug80 receives a
|
|
213
218
|
clean map of source lines to emitted bytes.
|
|
214
219
|
|
|
220
|
+
When one physical line emits multiple chained instructions, each emitted segment
|
|
221
|
+
keeps its own source column in the D8 map. Debug80 can therefore point at the
|
|
222
|
+
exact chained instruction that produced each byte range instead of collapsing
|
|
223
|
+
the whole line to one column.
|
|
224
|
+
|
|
215
225
|
The D8 map distinguishes addressable symbols from constants. Labels and
|
|
216
226
|
addressable data carry addresses. Constants carry values. Debug80 can then use
|
|
217
227
|
addressable symbols for breakpoints and display constants as metadata.
|
|
@@ -74,6 +74,11 @@ These tests compare AZM behaviour against ASM80 expectations, lowered output and
|
|
|
74
74
|
real-program fixtures. For an assembler, a one-byte difference is a behavioural
|
|
75
75
|
change.
|
|
76
76
|
|
|
77
|
+
The chained-instruction feature currently lives in `test/asm80/` because it
|
|
78
|
+
crosses parser, op expansion, D8 map output and case-style linting in one user
|
|
79
|
+
visible source shape. `multi_instruction_lines.test.ts` is the focused
|
|
80
|
+
acceptance suite for that contract.
|
|
81
|
+
|
|
77
82
|
## Fixtures and Helpers
|
|
78
83
|
|
|
79
84
|
`test/fixtures/` contains small source programs named after the issue or
|
|
@@ -115,11 +120,11 @@ Use this map when choosing a verification lane:
|
|
|
115
120
|
|
|
116
121
|
| Change | Tests |
|
|
117
122
|
| --------------------------- | -------------------------------------------------------------------- |
|
|
118
|
-
| Parser or expression syntax | `test/unit/syntax/**`, relevant integration tests.
|
|
123
|
+
| Parser or expression syntax | `test/unit/syntax/**`, relevant integration tests and `test/asm80/multi_instruction_lines.test.ts` when the change affects chained physical lines. |
|
|
119
124
|
| Source loading or tooling provenance | `test/integration/stage-11-tooling-api.test.ts`, relevant unit tests in `test/unit/source/**`. |
|
|
120
125
|
| Z80 instruction support | `test/unit/z80/**`, diagnostic matrices, ASM80 parity when relevant. |
|
|
121
126
|
| Layout semantics | layout integration tests and output tests. |
|
|
122
|
-
| Ops | `test/unit/expansion/**`, op integration tests.
|
|
127
|
+
| Ops | `test/unit/expansion/**`, op integration tests and `test/asm80/multi_instruction_lines.test.ts` for chained bodies and invocation segments. |
|
|
123
128
|
| Register contracts | register contract unit, integration and CLI tests. |
|
|
124
129
|
| CLI options | `test/cli/**`. |
|
|
125
130
|
| Output artifacts | `test/unit/outputs/**`, CLI artifact tests. |
|
|
@@ -145,7 +150,8 @@ Ask what kind of fact the change affects:
|
|
|
145
150
|
`core/compile.ts`.
|
|
146
151
|
- Assembler-time facts belong in `assembly/` and `semantics/`.
|
|
147
152
|
- Instruction forms belong in `z80/`.
|
|
148
|
-
-
|
|
153
|
+
- Instruction-chain splitting belongs in `source/`, while inline source
|
|
154
|
+
generation and op template expansion belong in `expansion/`.
|
|
149
155
|
- Routine contracts and liveness belong in `register-contracts/`.
|
|
150
156
|
- Artifact shape belongs in `outputs/`.
|
|
151
157
|
- User commands belong in `cli/`.
|
|
@@ -172,21 +172,28 @@ you need to find the owner of a behaviour quickly.
|
|
|
172
172
|
| `logical-lines.ts` | Splits source text into logical line records. |
|
|
173
173
|
| `source-span.ts` | Defines source span shape. |
|
|
174
174
|
| `line-comment-scanner.ts` | Finds semicolon comments while respecting quoted text. |
|
|
175
|
+
| `instruction-chain.ts` | Splits spaced-backslash instruction lines into segments. |
|
|
175
176
|
| `strip-line-comment.ts` | Removes semicolon comments while respecting quoted text. |
|
|
176
177
|
|
|
177
178
|
## `src/syntax/`
|
|
178
179
|
|
|
179
180
|
| File | Role |
|
|
180
181
|
| ------------------------------ | ----------------------------------------------------- |
|
|
181
|
-
| `parse-line.ts`
|
|
182
|
-
| `expression-tokenizer.ts`
|
|
183
|
-
| `parse-token-expression.ts`
|
|
184
|
-
| `parse-expression.ts`
|
|
185
|
-
| `
|
|
186
|
-
| `parse-
|
|
187
|
-
| `
|
|
188
|
-
| `parse-
|
|
189
|
-
| `
|
|
182
|
+
| `parse-line.ts` | Parses single logical lines into source items. |
|
|
183
|
+
| `expression-tokenizer.ts` | Tokenizes expression text. |
|
|
184
|
+
| `parse-token-expression.ts` | Parses tokenized expressions into ASTs. |
|
|
185
|
+
| `parse-expression.ts` | Public expression parse wrapper. |
|
|
186
|
+
| `names.ts` | Shared identifier, label and entry-label parsing primitives. |
|
|
187
|
+
| `parse-instruction-chain.ts` | Parses spaced-backslash chained instruction segments. |
|
|
188
|
+
| `statement-classification.ts` | Shared chained-line and op-invocation classification helpers. |
|
|
189
|
+
| `parse-directive-statement.ts` | Dispatches directive statements to focused directive parsers. |
|
|
190
|
+
| `parse-data-directives.ts` | Parses `.db`, `.dw`, `.ds`, `.cstr`, `.pstr` and `.istr`. |
|
|
191
|
+
| `parse-declaration-directives.ts` | Parses `.equ`, `.enum` and quoted declaration payloads. |
|
|
192
|
+
| `parse-location-directives.ts` | Parses `.org`, `.align`, `.binfrom` and `.binto`. |
|
|
193
|
+
| `parse-layout-declarations.ts` | Parses layout declaration forms. |
|
|
194
|
+
| `parse-layout-expression.ts` | Parses layout type expressions. |
|
|
195
|
+
| `parse-diagnostics.ts` | Shared parse diagnostic helpers. |
|
|
196
|
+
| `directive-aliases.ts` | Built-in and project directive alias policy. |
|
|
190
197
|
|
|
191
198
|
## `src/tooling/`
|
|
192
199
|
|
|
@@ -232,7 +239,7 @@ you need to find the owner of a behaviour quickly.
|
|
|
232
239
|
| `test/integration/` | Cross-stage compiler tests. |
|
|
233
240
|
| `test/integration/register-contracts/` | End-to-end register contract tests. |
|
|
234
241
|
| `test/cli/` | CLI option, artifact and exit-code contracts. |
|
|
235
|
-
| `test/asm80/` | ASM80 compatibility
|
|
242
|
+
| `test/asm80/` | ASM80 compatibility, real-program acceptance and chained-line behaviour. |
|
|
236
243
|
| `test/differential/` | Differential comparison fixtures and runners. |
|
|
237
244
|
| `test/fixtures/` | Source fixture programs. |
|
|
238
245
|
| `test/helpers/` | Shared test setup and helpers. |
|
|
@@ -30,9 +30,10 @@ compile(entryFile, options, deps)
|
|
|
30
30
|
parseNextSourceItems()
|
|
31
31
|
applyConditionalAssembly()
|
|
32
32
|
collect op definitions
|
|
33
|
+
expand op invocations
|
|
34
|
+
split chained instruction lines
|
|
33
35
|
tokenize and parse expressions
|
|
34
36
|
parse layouts, aliases, enums, directives and instructions
|
|
35
|
-
expand op invocations
|
|
36
37
|
analyzeProgramNext()
|
|
37
38
|
assembleProgram() for symbols
|
|
38
39
|
lintCaseStyleNext()
|
|
@@ -98,6 +99,6 @@ tooling integrations that still use the older name.
|
|
|
98
99
|
| Parsing | logical lines | source items |
|
|
99
100
|
| Analysis | source items | diagnostics, symbols |
|
|
100
101
|
| Register contracts | loaded program | summaries, conflicts, reports |
|
|
101
|
-
| Assembly | source items | byte map, symbols, source segments
|
|
102
|
+
| Assembly | source items | byte map, symbols, source segments with per-item columns |
|
|
102
103
|
| Outputs | byte map and symbols | artifacts |
|
|
103
104
|
| CLI | artifacts | files on disk |
|
package/docs/codebase/index.md
CHANGED
|
@@ -44,3 +44,7 @@ modules. The directory appendix is the current file map for those modules.
|
|
|
44
44
|
- [Appendix A - Directory and File Reference](appendices/a-directory-file-reference.md)
|
|
45
45
|
- [Appendix B - Compile Flow Reference](appendices/b-compile-flow-reference.md)
|
|
46
46
|
- [Appendix C - Public Surface Reference](appendices/c-public-surface-reference.md)
|
|
47
|
+
|
|
48
|
+
## Related References
|
|
49
|
+
|
|
50
|
+
- [AZM Grammar Reference](../reference/azm-grammar.md)
|