@jhlagado/azm 0.2.6 → 0.2.8
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 +170 -69
- package/dist/src/api-artifacts.d.ts +20 -0
- package/dist/src/api-artifacts.js +165 -0
- package/dist/src/api-compile.d.ts +8 -2
- package/dist/src/api-compile.js +31 -230
- package/dist/src/api-register-contracts.d.ts +9 -0
- package/dist/src/api-register-contracts.js +77 -0
- package/dist/src/api-tooling.d.ts +2 -2
- package/dist/src/api-tooling.js +1 -1
- package/dist/src/assembly/address-planning.d.ts +1 -2
- package/dist/src/assembly/address-planning.js +119 -218
- package/dist/src/assembly/address-symbols.d.ts +12 -0
- package/dist/src/assembly/address-symbols.js +118 -0
- package/dist/src/assembly/fixup-emission.js +30 -48
- package/dist/src/assembly/program-emission.js +163 -164
- package/dist/src/cli/artifact-files.d.ts +15 -0
- package/dist/src/cli/artifact-files.js +86 -0
- package/dist/src/cli/parse-args.d.ts +6 -5
- package/dist/src/cli/parse-args.js +162 -136
- package/dist/src/cli/run.js +4 -1
- package/dist/src/cli/usage.d.ts +1 -0
- package/dist/src/cli/usage.js +33 -0
- package/dist/src/cli/write-artifacts.js +18 -91
- package/dist/src/core/compile.js +51 -274
- package/dist/src/core/conditional-assembly.d.ts +6 -0
- package/dist/src/core/conditional-assembly.js +181 -0
- package/dist/src/expansion/op-constant-expression.d.ts +3 -0
- package/dist/src/expansion/op-constant-expression.js +52 -0
- package/dist/src/expansion/op-expand-selected.d.ts +5 -0
- package/dist/src/expansion/op-expand-selected.js +143 -0
- package/dist/src/expansion/op-expansion.d.ts +5 -53
- package/dist/src/expansion/op-expansion.js +85 -815
- package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
- package/dist/src/expansion/op-instruction-instantiation.js +194 -0
- package/dist/src/expansion/op-local-labels.d.ts +8 -0
- package/dist/src/expansion/op-local-labels.js +166 -0
- package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
- package/dist/src/expansion/op-operand-splitting.js +44 -0
- package/dist/src/expansion/op-operands.d.ts +53 -0
- package/dist/src/expansion/op-operands.js +66 -0
- package/dist/src/expansion/op-selection.d.ts +18 -0
- package/dist/src/expansion/op-selection.js +172 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/model/diagnostic.d.ts +4 -0
- package/dist/src/model/diagnostic.js +4 -0
- package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
- package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
- package/dist/src/outputs/asm80-expressions.d.ts +5 -0
- package/dist/src/outputs/asm80-expressions.js +47 -0
- package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
- package/dist/src/outputs/asm80-instruction-operands.js +38 -0
- package/dist/src/outputs/asm80-instructions.d.ts +5 -0
- package/dist/src/outputs/asm80-instructions.js +272 -0
- package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
- package/dist/src/outputs/asm80-ld-operands.js +157 -0
- package/dist/src/outputs/asm80-strings.d.ts +4 -0
- package/dist/src/outputs/asm80-strings.js +14 -0
- package/dist/src/outputs/d8-files.d.ts +10 -0
- package/dist/src/outputs/d8-files.js +103 -0
- package/dist/src/outputs/d8-helpers.d.ts +21 -0
- package/dist/src/outputs/d8-helpers.js +136 -0
- package/dist/src/outputs/hex.js +26 -18
- package/dist/src/outputs/types.d.ts +16 -10
- package/dist/src/outputs/write-asm80.js +68 -597
- package/dist/src/outputs/write-d8.js +6 -216
- package/dist/src/register-contracts/accept-output.d.ts +2 -0
- package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
- package/dist/src/register-contracts/analyze-helpers.js +162 -0
- package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
- package/dist/src/register-contracts/analyze.js +73 -0
- package/dist/src/register-contracts/annotate.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
- package/dist/src/register-contracts/annotations.d.ts +8 -0
- package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
- package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
- package/dist/src/register-contracts/boundaryHints.js +24 -0
- package/dist/src/register-contracts/carriers.d.ts +2 -0
- package/dist/src/register-contracts/constants.d.ts +4 -0
- package/dist/src/register-contracts/constants.js +51 -0
- package/dist/src/register-contracts/controlFlow.d.ts +5 -0
- package/dist/src/register-contracts/controlFlow.js +55 -0
- package/dist/src/register-contracts/fix.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/fix.js +47 -30
- package/dist/src/register-contracts/instruction-head.d.ts +2 -0
- package/dist/src/register-contracts/instruction-head.js +3 -0
- package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
- package/dist/src/register-contracts/instruction-operands.js +101 -0
- package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
- package/dist/src/register-contracts/instruction-predicates.js +44 -0
- package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
- package/dist/src/register-contracts/interfaceContracts.js +68 -0
- package/dist/src/register-contracts/liveness.d.ts +3 -0
- package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
- package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
- package/dist/src/register-contracts/operand-register-name.js +13 -0
- package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
- package/dist/src/{register-care → register-contracts}/profiles.js +13 -2
- package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
- package/dist/src/register-contracts/programModel-boundaries.js +64 -0
- package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
- package/dist/src/register-contracts/programModel-routines.js +128 -0
- package/dist/src/register-contracts/programModel.d.ts +3 -0
- package/dist/src/register-contracts/programModel.js +14 -0
- package/dist/src/register-contracts/report.d.ts +5 -0
- package/dist/src/{register-care → register-contracts}/report.js +34 -17
- package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
- package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
- package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
- package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
- package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
- package/dist/src/register-contracts/smartCommentParsing.js +80 -0
- package/dist/src/register-contracts/smartComments.d.ts +5 -0
- package/dist/src/register-contracts/smartComments.js +92 -0
- package/dist/src/register-contracts/summaries.d.ts +12 -0
- package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
- package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
- package/dist/src/register-contracts/summary-boundary.js +40 -0
- package/dist/src/register-contracts/summary-contract.d.ts +2 -0
- package/dist/src/register-contracts/summary-contract.js +45 -0
- package/dist/src/register-contracts/summary-result.d.ts +7 -0
- package/dist/src/register-contracts/summary-result.js +122 -0
- package/dist/src/register-contracts/summary-state.d.ts +23 -0
- package/dist/src/register-contracts/summary-state.js +88 -0
- package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
- package/dist/src/register-contracts/summary-token-transfer.js +67 -0
- package/dist/src/register-contracts/summary.d.ts +3 -0
- package/dist/src/register-contracts/summary.js +266 -0
- package/dist/src/register-contracts/tooling.d.ts +57 -0
- package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
- package/dist/src/register-contracts/types.d.ts +188 -0
- package/dist/src/semantics/binary-operators.d.ts +2 -0
- package/dist/src/semantics/binary-operators.js +15 -0
- package/dist/src/semantics/byte-functions.d.ts +2 -0
- package/dist/src/semantics/byte-functions.js +7 -0
- package/dist/src/semantics/constant-operator-types.d.ts +10 -0
- package/dist/src/semantics/constant-operator-types.js +1 -0
- package/dist/src/semantics/constant-operators.d.ts +3 -0
- package/dist/src/semantics/constant-operators.js +3 -0
- package/dist/src/semantics/diagnostics.d.ts +3 -0
- package/dist/src/semantics/diagnostics.js +10 -0
- package/dist/src/semantics/expression-evaluation.d.ts +11 -19
- package/dist/src/semantics/expression-evaluation.js +22 -334
- package/dist/src/semantics/layout-evaluation.d.ts +23 -0
- package/dist/src/semantics/layout-evaluation.js +202 -0
- package/dist/src/semantics/layout-format.d.ts +5 -0
- package/dist/src/semantics/layout-format.js +31 -0
- package/dist/src/semantics/layout-path.d.ts +24 -0
- package/dist/src/semantics/layout-path.js +58 -0
- package/dist/src/semantics/unary-operators.d.ts +2 -0
- package/dist/src/semantics/unary-operators.js +8 -0
- package/dist/src/source/line-comment-scanner.d.ts +1 -0
- package/dist/src/source/line-comment-scanner.js +51 -0
- package/dist/src/source/strip-line-comment.js +8 -44
- package/dist/src/syntax/directive-aliases.js +36 -22
- package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
- package/dist/src/syntax/expression-tokenizer.js +310 -0
- package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
- package/dist/src/syntax/parse-directive-statement.js +307 -0
- package/dist/src/syntax/parse-expression.d.ts +2 -2
- package/dist/src/syntax/parse-expression.js +7 -568
- package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
- package/dist/src/syntax/parse-layout-declarations.js +180 -0
- package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
- package/dist/src/syntax/parse-layout-expression.js +175 -0
- package/dist/src/syntax/parse-line.js +4 -272
- package/dist/src/syntax/parse-token-expression.d.ts +3 -0
- package/dist/src/syntax/parse-token-expression.js +133 -0
- package/dist/src/tooling/case-style.js +47 -30
- package/dist/src/z80/effect-groups.d.ts +38 -0
- package/dist/src/z80/effect-groups.js +265 -0
- package/dist/src/z80/effect-units.d.ts +18 -0
- package/dist/src/z80/effect-units.js +165 -0
- package/dist/src/z80/effects.d.ts +1 -1
- package/dist/src/z80/effects.js +94 -557
- package/dist/src/z80/encode-core.d.ts +2 -0
- package/dist/src/z80/encode-core.js +42 -0
- package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
- package/dist/src/z80/encode-ld-helpers.js +172 -0
- package/dist/src/z80/encode-ld.d.ts +2 -0
- package/dist/src/z80/encode-ld.js +285 -0
- package/dist/src/z80/encode.js +190 -542
- package/dist/src/z80/ld-support.d.ts +3 -0
- package/dist/src/z80/ld-support.js +146 -0
- package/dist/src/z80/operand-split-state.d.ts +8 -0
- package/dist/src/z80/operand-split-state.js +46 -0
- package/dist/src/z80/operand-split.d.ts +1 -0
- package/dist/src/z80/operand-split.js +13 -0
- package/dist/src/z80/parse-basic.d.ts +4 -0
- package/dist/src/z80/parse-basic.js +39 -0
- package/dist/src/z80/parse-branch.d.ts +4 -0
- package/dist/src/z80/parse-branch.js +218 -0
- package/dist/src/z80/parse-conditions.d.ts +6 -0
- package/dist/src/z80/parse-conditions.js +10 -0
- package/dist/src/z80/parse-exchange.d.ts +2 -0
- package/dist/src/z80/parse-exchange.js +30 -0
- package/dist/src/z80/parse-instruction.js +224 -1010
- package/dist/src/z80/parse-io-control.d.ts +5 -0
- package/dist/src/z80/parse-io-control.js +108 -0
- package/dist/src/z80/parse-ld.d.ts +2 -0
- package/dist/src/z80/parse-ld.js +83 -0
- package/dist/src/z80/parse-operands.d.ts +41 -0
- package/dist/src/z80/parse-operands.js +259 -0
- package/docs/reference/cli.md +42 -35
- package/docs/reference/tooling-api.md +20 -16
- package/package.json +1 -1
- package/dist/src/register-care/accept-output.d.ts +0 -2
- package/dist/src/register-care/analyze.js +0 -166
- package/dist/src/register-care/annotate.d.ts +0 -11
- package/dist/src/register-care/annotations.d.ts +0 -8
- package/dist/src/register-care/boundaryHints.d.ts +0 -3
- package/dist/src/register-care/boundaryHints.js +0 -80
- package/dist/src/register-care/carriers.d.ts +0 -2
- package/dist/src/register-care/controlFlow.d.ts +0 -5
- package/dist/src/register-care/controlFlow.js +0 -38
- package/dist/src/register-care/fix.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.js +0 -129
- package/dist/src/register-care/liveness.d.ts +0 -3
- package/dist/src/register-care/programModel.d.ts +0 -3
- package/dist/src/register-care/programModel.js +0 -266
- package/dist/src/register-care/report.d.ts +0 -5
- package/dist/src/register-care/routine-summaries.d.ts +0 -6
- package/dist/src/register-care/smartComments.d.ts +0 -5
- package/dist/src/register-care/smartComments.js +0 -243
- package/dist/src/register-care/summaries.d.ts +0 -12
- package/dist/src/register-care/summary.d.ts +0 -3
- package/dist/src/register-care/summary.js +0 -474
- package/dist/src/register-care/tooling.d.ts +0 -43
- package/dist/src/register-care/types.d.ts +0 -172
- /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
- /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
- /package/dist/src/{register-care → register-contracts}/types.js +0 -0
|
@@ -1,38 +1,58 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { extname } from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
'',
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
3
|
+
import { cliUsage } from './usage.js';
|
|
4
|
+
const BOOLEAN_FLAG_ACTIONS = [
|
|
5
|
+
{
|
|
6
|
+
flags: ['--nobin'],
|
|
7
|
+
apply: (state) => {
|
|
8
|
+
state.emitBin = false;
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
flags: ['--nohex'],
|
|
13
|
+
apply: (state) => {
|
|
14
|
+
state.emitHex = false;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
flags: ['--nod8m'],
|
|
19
|
+
apply: (state) => {
|
|
20
|
+
state.emitD8m = false;
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
flags: ['--asm80'],
|
|
25
|
+
apply: (state) => {
|
|
26
|
+
state.emitAsm80 = true;
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
flags: ['--emit-register-report', '--reg-report'],
|
|
31
|
+
apply: (state) => {
|
|
32
|
+
state.emitRegisterReport = true;
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
flags: ['--emit-register-interface', '--reg-interface'],
|
|
37
|
+
apply: (state) => {
|
|
38
|
+
state.emitRegisterInterface = true;
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
flags: ['--fix'],
|
|
43
|
+
apply: (state) => {
|
|
44
|
+
state.fixRegisterContracts = true;
|
|
45
|
+
state.emitRegisterAnnotations = true;
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
flags: ['--contracts', '--annotate-register-contracts'],
|
|
50
|
+
apply: (state) => {
|
|
51
|
+
state.emitRegisterAnnotations = true;
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
export { cliUsage };
|
|
36
56
|
function fail(message) {
|
|
37
57
|
throw new Error(message);
|
|
38
58
|
}
|
|
@@ -45,13 +65,13 @@ function createDefaultCliState() {
|
|
|
45
65
|
emitD8m: true,
|
|
46
66
|
emitAsm80: false,
|
|
47
67
|
caseStyle: 'off',
|
|
48
|
-
|
|
68
|
+
registerContracts: 'off',
|
|
49
69
|
emitRegisterReport: false,
|
|
50
70
|
emitRegisterInterface: false,
|
|
51
71
|
emitRegisterAnnotations: false,
|
|
52
72
|
fixRegisterContracts: false,
|
|
53
73
|
acceptRegisterOutputCandidates: [],
|
|
54
|
-
|
|
74
|
+
registerContractsInterfaces: [],
|
|
55
75
|
sourceRoot: undefined,
|
|
56
76
|
includeDirs: [],
|
|
57
77
|
directiveAliasFiles: [],
|
|
@@ -89,7 +109,9 @@ function parseOutputPathArg(arg, argv, indexRef, state) {
|
|
|
89
109
|
function parseOutputTypeArg(arg, argv, indexRef, state) {
|
|
90
110
|
if (arg !== '-t' && arg !== '--type' && !arg.startsWith('--type='))
|
|
91
111
|
return false;
|
|
92
|
-
const value = arg.startsWith('--type=')
|
|
112
|
+
const value = arg.startsWith('--type=')
|
|
113
|
+
? arg.slice('--type='.length)
|
|
114
|
+
: readValue(argv, indexRef, '--type');
|
|
93
115
|
if (!value) {
|
|
94
116
|
fail('--type expects a value');
|
|
95
117
|
}
|
|
@@ -148,8 +170,12 @@ function readMatchedFlagValue(arg, argv, indexRef, flags) {
|
|
|
148
170
|
}
|
|
149
171
|
return { flag, value };
|
|
150
172
|
}
|
|
151
|
-
function
|
|
152
|
-
const parsed = readMatchedFlagValue(arg, argv, indexRef, [
|
|
173
|
+
function parseRegisterContractsArg(arg, argv, indexRef, state) {
|
|
174
|
+
const parsed = readMatchedFlagValue(arg, argv, indexRef, [
|
|
175
|
+
'--register-contracts',
|
|
176
|
+
'--register-care',
|
|
177
|
+
'--rc',
|
|
178
|
+
]);
|
|
153
179
|
if (!parsed)
|
|
154
180
|
return false;
|
|
155
181
|
const { value, flag } = parsed;
|
|
@@ -160,7 +186,7 @@ function parseRegisterCareArg(arg, argv, indexRef, state) {
|
|
|
160
186
|
value !== 'strict') {
|
|
161
187
|
fail(`Unsupported ${flag} "${value}" (expected off|audit|warn|error|strict)`);
|
|
162
188
|
}
|
|
163
|
-
state.
|
|
189
|
+
state.registerContracts = value;
|
|
164
190
|
return true;
|
|
165
191
|
}
|
|
166
192
|
function parseRegisterProfileArg(arg, argv, indexRef, state) {
|
|
@@ -170,7 +196,7 @@ function parseRegisterProfileArg(arg, argv, indexRef, state) {
|
|
|
170
196
|
if (parsed.value !== 'mon3') {
|
|
171
197
|
fail(`Unsupported ${parsed.flag} "${parsed.value}" (expected mon3)`);
|
|
172
198
|
}
|
|
173
|
-
state.
|
|
199
|
+
state.registerContractsProfile = parsed.value;
|
|
174
200
|
return true;
|
|
175
201
|
}
|
|
176
202
|
function parseRegisterInterfaceArg(arg, argv, indexRef, state) {
|
|
@@ -181,7 +207,7 @@ function parseRegisterInterfaceArg(arg, argv, indexRef, state) {
|
|
|
181
207
|
: readValue(argv, indexRef, '--interface');
|
|
182
208
|
if (!value)
|
|
183
209
|
fail('--interface expects a value');
|
|
184
|
-
state.
|
|
210
|
+
state.registerContractsInterfaces.push(value);
|
|
185
211
|
return true;
|
|
186
212
|
}
|
|
187
213
|
function parseAcceptOutputArg(arg, argv, indexRef, state) {
|
|
@@ -211,58 +237,116 @@ function handleFastPath(arg) {
|
|
|
211
237
|
}
|
|
212
238
|
return undefined;
|
|
213
239
|
}
|
|
240
|
+
function cliOptionOutputPath(state) {
|
|
241
|
+
return state.outputPath ? { outputPath: state.outputPath } : {};
|
|
242
|
+
}
|
|
243
|
+
function cliOptionSourceRoot(state) {
|
|
244
|
+
return state.sourceRoot !== undefined ? { sourceRoot: state.sourceRoot } : {};
|
|
245
|
+
}
|
|
246
|
+
function cliOptionRegisterContractsProfile(state) {
|
|
247
|
+
return state.registerContractsProfile !== undefined
|
|
248
|
+
? { registerContractsProfile: state.registerContractsProfile }
|
|
249
|
+
: {};
|
|
250
|
+
}
|
|
214
251
|
function finalizeCliOptions(state) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const ext = extname(state.entryFile).toLowerCase();
|
|
219
|
-
if (ext !== '.asm' && ext !== '.z80') {
|
|
220
|
-
fail(`Unsupported entry extension "${ext || '<none>'}" (expected .asm, .z80)`);
|
|
221
|
-
}
|
|
222
|
-
if (state.outputPath !== undefined) {
|
|
223
|
-
const wantExt = state.outputType === 'hex' ? '.hex' : '.bin';
|
|
224
|
-
const providedExt = extname(state.outputPath).toLowerCase();
|
|
225
|
-
if (providedExt !== wantExt) {
|
|
226
|
-
fail(`--output must end with "${wantExt}" when --type is "${state.outputType}"`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
const emitsRegisterCare = state.registerCare !== 'off' ||
|
|
230
|
-
state.emitRegisterReport ||
|
|
231
|
-
state.emitRegisterInterface ||
|
|
232
|
-
state.emitRegisterAnnotations ||
|
|
233
|
-
state.fixRegisterContracts ||
|
|
234
|
-
state.acceptRegisterOutputCandidates.length > 0 ||
|
|
235
|
-
state.registerCareInterfaces.length > 0;
|
|
236
|
-
if (state.outputType === 'hex' && !state.emitHex && !emitsRegisterCare) {
|
|
237
|
-
fail(`--type hex requires HEX output to be enabled`);
|
|
238
|
-
}
|
|
239
|
-
if (state.outputType === 'bin' && !state.emitBin && !emitsRegisterCare) {
|
|
240
|
-
fail(`--type bin requires BIN output to be enabled`);
|
|
241
|
-
}
|
|
252
|
+
validateEntryFile(state.entryFile);
|
|
253
|
+
validateOutputPath(state);
|
|
254
|
+
validateEnabledPrimaryOutput(state);
|
|
242
255
|
return {
|
|
243
256
|
entryFile: state.entryFile,
|
|
244
|
-
...(state
|
|
257
|
+
...cliOptionOutputPath(state),
|
|
245
258
|
outputType: state.outputType,
|
|
246
|
-
...(state
|
|
259
|
+
...cliOptionSourceRoot(state),
|
|
247
260
|
emitBin: state.emitBin,
|
|
248
261
|
emitHex: state.emitHex,
|
|
249
262
|
emitD8m: state.emitD8m,
|
|
250
263
|
emitAsm80: state.emitAsm80,
|
|
251
264
|
caseStyle: state.caseStyle,
|
|
252
|
-
|
|
265
|
+
registerContracts: state.registerContracts,
|
|
253
266
|
emitRegisterReport: state.emitRegisterReport,
|
|
254
267
|
emitRegisterInterface: state.emitRegisterInterface,
|
|
255
268
|
emitRegisterAnnotations: state.emitRegisterAnnotations,
|
|
256
269
|
fixRegisterContracts: state.fixRegisterContracts,
|
|
257
270
|
acceptRegisterOutputCandidates: state.acceptRegisterOutputCandidates,
|
|
258
|
-
...(state
|
|
259
|
-
|
|
260
|
-
: {}),
|
|
261
|
-
registerCareInterfaces: state.registerCareInterfaces,
|
|
271
|
+
...cliOptionRegisterContractsProfile(state),
|
|
272
|
+
registerContractsInterfaces: state.registerContractsInterfaces,
|
|
262
273
|
includeDirs: state.includeDirs,
|
|
263
274
|
directiveAliasFiles: state.directiveAliasFiles,
|
|
264
275
|
};
|
|
265
276
|
}
|
|
277
|
+
function validateEntryFile(entryFile) {
|
|
278
|
+
if (!entryFile) {
|
|
279
|
+
fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function validateOutputPath(state) {
|
|
283
|
+
if (!state.entryFile)
|
|
284
|
+
return;
|
|
285
|
+
const ext = extname(state.entryFile).toLowerCase();
|
|
286
|
+
if (ext !== '.asm' && ext !== '.z80') {
|
|
287
|
+
fail(`Unsupported entry extension "${ext || '<none>'}" (expected .asm, .z80)`);
|
|
288
|
+
}
|
|
289
|
+
if (state.outputPath !== undefined) {
|
|
290
|
+
const wantExt = state.outputType === 'hex' ? '.hex' : '.bin';
|
|
291
|
+
const providedExt = extname(state.outputPath).toLowerCase();
|
|
292
|
+
if (providedExt !== wantExt) {
|
|
293
|
+
fail(`--output must end with "${wantExt}" when --type is "${state.outputType}"`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function emitsRegisterContractsArtifact(state) {
|
|
298
|
+
return [
|
|
299
|
+
state.registerContracts !== 'off',
|
|
300
|
+
state.emitRegisterReport,
|
|
301
|
+
state.emitRegisterInterface,
|
|
302
|
+
state.emitRegisterAnnotations,
|
|
303
|
+
state.fixRegisterContracts,
|
|
304
|
+
state.acceptRegisterOutputCandidates.length > 0,
|
|
305
|
+
state.registerContractsInterfaces.length > 0,
|
|
306
|
+
].some(Boolean);
|
|
307
|
+
}
|
|
308
|
+
function primaryOutputDisabled(state) {
|
|
309
|
+
return state.outputType === 'hex' ? !state.emitHex : !state.emitBin;
|
|
310
|
+
}
|
|
311
|
+
function primaryOutputName(state) {
|
|
312
|
+
return state.outputType === 'hex' ? 'HEX' : 'BIN';
|
|
313
|
+
}
|
|
314
|
+
function validateEnabledPrimaryOutput(state) {
|
|
315
|
+
if (primaryOutputDisabled(state) && !emitsRegisterContractsArtifact(state)) {
|
|
316
|
+
fail(`--type ${state.outputType} requires ${primaryOutputName(state)} output to be enabled`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const VALUE_ARG_PARSERS = [
|
|
320
|
+
(arg, { argv, indexRef, state }) => parseOutputPathArg(arg, argv, indexRef, state),
|
|
321
|
+
(arg, { argv, indexRef, state }) => parseOutputTypeArg(arg, argv, indexRef, state),
|
|
322
|
+
(arg, { argv, indexRef, state }) => parseSourceRootArg(arg, argv, indexRef, state),
|
|
323
|
+
(arg, { argv, indexRef, state }) => parseCaseStyleArg(arg, argv, indexRef, state),
|
|
324
|
+
(arg, { argv, indexRef, state }) => parseDirectiveAliasFileArg(arg, argv, indexRef, state),
|
|
325
|
+
(arg, { argv, indexRef, state }) => parseRegisterContractsArg(arg, argv, indexRef, state),
|
|
326
|
+
(arg, { argv, indexRef, state }) => parseRegisterProfileArg(arg, argv, indexRef, state),
|
|
327
|
+
(arg, { argv, indexRef, state }) => parseAcceptOutputArg(arg, argv, indexRef, state),
|
|
328
|
+
(arg, { argv, indexRef, state }) => parseRegisterInterfaceArg(arg, argv, indexRef, state),
|
|
329
|
+
(arg, { argv, indexRef, state }) => parseIncludeArg(arg, argv, indexRef, state),
|
|
330
|
+
];
|
|
331
|
+
function parseBooleanFlag(arg, state) {
|
|
332
|
+
const action = BOOLEAN_FLAG_ACTIONS.find(({ flags }) => flags.includes(arg));
|
|
333
|
+
if (!action)
|
|
334
|
+
return false;
|
|
335
|
+
action.apply(state);
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
function parseValueArg(arg, context) {
|
|
339
|
+
return VALUE_ARG_PARSERS.some((parser) => parser(arg, context));
|
|
340
|
+
}
|
|
341
|
+
function parseEntryArg(arg, argv, indexRef, state) {
|
|
342
|
+
if (arg.startsWith('-')) {
|
|
343
|
+
fail(`Unknown option "${arg}"`);
|
|
344
|
+
}
|
|
345
|
+
if (state.entryFile !== undefined || indexRef.current !== argv.length - 1) {
|
|
346
|
+
fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
|
|
347
|
+
}
|
|
348
|
+
state.entryFile = arg;
|
|
349
|
+
}
|
|
266
350
|
export function parseCliArgs(argv) {
|
|
267
351
|
const state = createDefaultCliState();
|
|
268
352
|
const indexRef = { current: 0 };
|
|
@@ -271,69 +355,11 @@ export function parseCliArgs(argv) {
|
|
|
271
355
|
const fastPath = handleFastPath(arg);
|
|
272
356
|
if (fastPath)
|
|
273
357
|
return fastPath;
|
|
274
|
-
if (
|
|
275
|
-
continue;
|
|
276
|
-
if (parseOutputTypeArg(arg, argv, indexRef, state))
|
|
277
|
-
continue;
|
|
278
|
-
if (arg === '--nobin') {
|
|
279
|
-
state.emitBin = false;
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
if (arg === '--nohex') {
|
|
283
|
-
state.emitHex = false;
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
if (arg === '--nod8m') {
|
|
287
|
-
state.emitD8m = false;
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
if (arg === '--asm80') {
|
|
291
|
-
state.emitAsm80 = true;
|
|
358
|
+
if (parseBooleanFlag(arg, state))
|
|
292
359
|
continue;
|
|
293
|
-
}
|
|
294
|
-
if (arg === '--emit-register-report' || arg === '--reg-report') {
|
|
295
|
-
state.emitRegisterReport = true;
|
|
296
|
-
continue;
|
|
297
|
-
}
|
|
298
|
-
if (arg === '--emit-register-interface' || arg === '--reg-interface') {
|
|
299
|
-
state.emitRegisterInterface = true;
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
if (arg === '--fix') {
|
|
303
|
-
state.fixRegisterContracts = true;
|
|
304
|
-
state.emitRegisterAnnotations = true;
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
if (arg === '--contracts' || arg === '--annotate-register-contracts') {
|
|
308
|
-
state.emitRegisterAnnotations = true;
|
|
360
|
+
if (parseValueArg(arg, { argv, indexRef, state }))
|
|
309
361
|
continue;
|
|
310
|
-
|
|
311
|
-
if (parseSourceRootArg(arg, argv, indexRef, state))
|
|
312
|
-
continue;
|
|
313
|
-
if (parseCaseStyleArg(arg, argv, indexRef, state))
|
|
314
|
-
continue;
|
|
315
|
-
if (parseDirectiveAliasFileArg(arg, argv, indexRef, state))
|
|
316
|
-
continue;
|
|
317
|
-
if (parseRegisterCareArg(arg, argv, indexRef, state))
|
|
318
|
-
continue;
|
|
319
|
-
if (parseRegisterProfileArg(arg, argv, indexRef, state))
|
|
320
|
-
continue;
|
|
321
|
-
if (parseAcceptOutputArg(arg, argv, indexRef, state))
|
|
322
|
-
continue;
|
|
323
|
-
if (parseRegisterInterfaceArg(arg, argv, indexRef, state))
|
|
324
|
-
continue;
|
|
325
|
-
if (parseIncludeArg(arg, argv, indexRef, state))
|
|
326
|
-
continue;
|
|
327
|
-
if (arg.startsWith('-')) {
|
|
328
|
-
fail(`Unknown option "${arg}"`);
|
|
329
|
-
}
|
|
330
|
-
if (state.entryFile !== undefined) {
|
|
331
|
-
fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
|
|
332
|
-
}
|
|
333
|
-
if (indexRef.current !== argv.length - 1) {
|
|
334
|
-
fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
|
|
335
|
-
}
|
|
336
|
-
state.entryFile = arg;
|
|
362
|
+
parseEntryArg(arg, argv, indexRef, state);
|
|
337
363
|
}
|
|
338
364
|
return finalizeCliOptions(state);
|
|
339
365
|
}
|
package/dist/src/cli/run.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { compile } from '../api-compile.js';
|
|
2
2
|
import { formatDiagnostic } from '../diagnostics/format.js';
|
|
3
3
|
import { cliUsage, parseCliArgs } from './parse-args.js';
|
|
4
|
-
import { artifactBase, buildCompileOptions, compareDiagnosticsForCli, writeArtifacts } from './write-artifacts.js';
|
|
4
|
+
import { artifactBase, buildCompileOptions, compareDiagnosticsForCli, writeArtifacts, } from './write-artifacts.js';
|
|
5
5
|
export { parseCliArgs } from './parse-args.js';
|
|
6
6
|
export async function runCli(argv) {
|
|
7
7
|
try {
|
|
@@ -18,6 +18,9 @@ export async function runCli(argv) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
if (sortedDiagnostics.some((diagnostic) => diagnostic.severity === 'error')) {
|
|
21
|
+
if (compileResult.artifacts.length > 0) {
|
|
22
|
+
await writeArtifacts(base, compileResult.artifacts, parsed.outputType);
|
|
23
|
+
}
|
|
21
24
|
return 1;
|
|
22
25
|
}
|
|
23
26
|
const primaryPath = await writeArtifacts(base, compileResult.artifacts, parsed.outputType);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cliUsage(): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function cliUsage() {
|
|
2
|
+
return [
|
|
3
|
+
'azm [options] <entry.asm|entry.z80>',
|
|
4
|
+
'',
|
|
5
|
+
'Options:',
|
|
6
|
+
' -o, --output <file> Primary output path (must match --type extension)',
|
|
7
|
+
' -t, --type <type> Primary output type: hex|bin (default: hex)',
|
|
8
|
+
' --nobin Suppress .bin',
|
|
9
|
+
' --nohex Suppress .hex',
|
|
10
|
+
' --nod8m Suppress .d8.json',
|
|
11
|
+
' --asm80 Emit lowered source (.z80)',
|
|
12
|
+
' --register-contracts <m> Register contracts mode: off|audit|warn|error|strict',
|
|
13
|
+
' --rc <m> Register contracts mode alias for --register-contracts',
|
|
14
|
+
' --reg-report Emit register contracts report artifact',
|
|
15
|
+
' --reg-interface Emit inferred register contracts interface (.asmi)',
|
|
16
|
+
' --contracts Rewrite source with inferred register contracts',
|
|
17
|
+
' --fix Enable contract rewrite and conservative fixes',
|
|
18
|
+
' --accept-out <x> Accept register contracts output candidates',
|
|
19
|
+
' --interface <file> Load .asmi contract file',
|
|
20
|
+
' --reg-profile <p> Register contracts profile (currently mon3)',
|
|
21
|
+
' --source-root <d> Normalize D8 source paths relative to this directory',
|
|
22
|
+
' --case-style <m> Case-style lint mode: off|upper|lower|consistent',
|
|
23
|
+
' --aliases <file> Load project directive alias JSON (repeatable)',
|
|
24
|
+
' -I, --include <dir> Add include search path (repeatable)',
|
|
25
|
+
' -V, --version Print version',
|
|
26
|
+
' -h, --help Show help',
|
|
27
|
+
'',
|
|
28
|
+
'Notes:',
|
|
29
|
+
' - <entry.asm|entry.z80> must be the last argument (assembler-style).',
|
|
30
|
+
' - Output artifacts are written using the primary output stem with standard suffixes.',
|
|
31
|
+
'',
|
|
32
|
+
].join('\n');
|
|
33
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { extname, resolve } from 'node:path';
|
|
2
|
+
import { writeArtifactFiles } from './artifact-files.js';
|
|
3
3
|
function normalizeDiagnosticPath(file) {
|
|
4
4
|
const normalized = file.replace(/\\/g, '/');
|
|
5
5
|
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
@@ -38,97 +38,24 @@ export function artifactBase(entryFile, outputType, outputPath) {
|
|
|
38
38
|
if (outputPath !== undefined) {
|
|
39
39
|
const resolvedOutputPath = resolve(outputPath);
|
|
40
40
|
const providedExt = extname(resolvedOutputPath);
|
|
41
|
-
return providedExt.length > 0
|
|
41
|
+
return providedExt.length > 0
|
|
42
|
+
? resolvedOutputPath.slice(0, -providedExt.length)
|
|
43
|
+
: resolvedOutputPath;
|
|
42
44
|
}
|
|
43
45
|
const resolvedEntry = resolve(entryFile);
|
|
44
46
|
const entryExt = extname(resolvedEntry);
|
|
45
47
|
return entryExt.length > 0 ? resolvedEntry.slice(0, -entryExt.length) : resolvedEntry;
|
|
46
48
|
}
|
|
47
49
|
export async function writeArtifacts(base, artifacts, outputType) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const registerCareInterfacePath = `${base}.asmi`;
|
|
58
|
-
const writes = [];
|
|
59
|
-
const ensureDir = async (path) => {
|
|
60
|
-
await mkdir(dirname(path), { recursive: true });
|
|
61
|
-
};
|
|
62
|
-
let primaryPath;
|
|
63
|
-
let registerCarePath;
|
|
64
|
-
const bin = byKind.get('bin');
|
|
65
|
-
if (bin && bin.kind === 'bin') {
|
|
66
|
-
writes.push((async () => {
|
|
67
|
-
await ensureDir(binPath);
|
|
68
|
-
await writeFile(binPath, Buffer.from(bin.bytes));
|
|
69
|
-
})());
|
|
70
|
-
if (outputType === 'bin') {
|
|
71
|
-
primaryPath = binPath;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const hex = byKind.get('hex');
|
|
75
|
-
if (hex && hex.kind === 'hex') {
|
|
76
|
-
writes.push((async () => {
|
|
77
|
-
await ensureDir(hexPath);
|
|
78
|
-
await writeFile(hexPath, hex.text, 'utf8');
|
|
79
|
-
})());
|
|
80
|
-
if (outputType === 'hex') {
|
|
81
|
-
primaryPath = hexPath;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const d8m = byKind.get('d8m');
|
|
85
|
-
if (d8m && d8m.kind === 'd8m') {
|
|
86
|
-
writes.push((async () => {
|
|
87
|
-
await ensureDir(d8mPath);
|
|
88
|
-
const text = JSON.stringify(d8m.json, null, 2);
|
|
89
|
-
await writeFile(d8mPath, `${text}\n`, 'utf8');
|
|
90
|
-
})());
|
|
91
|
-
}
|
|
92
|
-
const asm80 = byKind.get('asm80');
|
|
93
|
-
if (asm80 && asm80.kind === 'asm80') {
|
|
94
|
-
writes.push((async () => {
|
|
95
|
-
await ensureDir(asm80Path);
|
|
96
|
-
await writeFile(asm80Path, asm80.text, 'utf8');
|
|
97
|
-
})());
|
|
98
|
-
}
|
|
99
|
-
const registerCareReport = byKind.get('register-care-report');
|
|
100
|
-
if (registerCareReport && registerCareReport.kind === 'register-care-report') {
|
|
101
|
-
writes.push((async () => {
|
|
102
|
-
await ensureDir(registerCareReportPath);
|
|
103
|
-
await writeFile(registerCareReportPath, registerCareReport.text, 'utf8');
|
|
104
|
-
})());
|
|
105
|
-
registerCarePath = registerCareReportPath;
|
|
106
|
-
}
|
|
107
|
-
const registerCareInterface = byKind.get('register-care-interface');
|
|
108
|
-
if (registerCareInterface && registerCareInterface.kind === 'register-care-interface') {
|
|
109
|
-
writes.push((async () => {
|
|
110
|
-
await ensureDir(registerCareInterfacePath);
|
|
111
|
-
await writeFile(registerCareInterfacePath, registerCareInterface.text, 'utf8');
|
|
112
|
-
})());
|
|
113
|
-
registerCarePath ??= registerCareInterfacePath;
|
|
114
|
-
}
|
|
115
|
-
const registerCareAnnotations = byKind.get('register-care-annotations');
|
|
116
|
-
if (registerCareAnnotations && registerCareAnnotations.kind === 'register-care-annotations') {
|
|
117
|
-
for (const item of registerCareAnnotations.files) {
|
|
118
|
-
writes.push((async () => {
|
|
119
|
-
await ensureDir(item.path);
|
|
120
|
-
await writeFile(item.path, item.text, 'utf8');
|
|
121
|
-
})());
|
|
122
|
-
if (primaryPath === undefined) {
|
|
123
|
-
primaryPath = item.path;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
await Promise.all(writes);
|
|
128
|
-
if (primaryPath !== undefined) {
|
|
129
|
-
return primaryPath;
|
|
130
|
-
}
|
|
131
|
-
return registerCarePath;
|
|
50
|
+
const result = await writeArtifactFiles(artifacts, {
|
|
51
|
+
hex: `${base}.hex`,
|
|
52
|
+
bin: `${base}.bin`,
|
|
53
|
+
d8m: `${base}.d8.json`,
|
|
54
|
+
asm80: `${base}.z80`,
|
|
55
|
+
registerContractsReport: `${base}.regcontracts.txt`,
|
|
56
|
+
registerContractsInterface: `${base}.asmi`,
|
|
57
|
+
}, outputType);
|
|
58
|
+
return result.primaryPath ?? result.registerContractsPath;
|
|
132
59
|
}
|
|
133
60
|
export function buildCompileOptions(parsed, base) {
|
|
134
61
|
const hexPath = `${base}.hex`;
|
|
@@ -141,16 +68,16 @@ export function buildCompileOptions(parsed, base) {
|
|
|
141
68
|
emitD8m: parsed.emitD8m,
|
|
142
69
|
emitAsm80: parsed.emitAsm80,
|
|
143
70
|
caseStyle: parsed.caseStyle,
|
|
144
|
-
|
|
71
|
+
registerContracts: parsed.registerContracts,
|
|
145
72
|
emitRegisterReport: parsed.emitRegisterReport,
|
|
146
73
|
emitRegisterInterface: parsed.emitRegisterInterface,
|
|
147
74
|
emitRegisterAnnotations: parsed.emitRegisterAnnotations,
|
|
148
75
|
fixRegisterContracts: parsed.fixRegisterContracts,
|
|
149
76
|
acceptRegisterOutputCandidates: parsed.acceptRegisterOutputCandidates,
|
|
150
|
-
...(parsed.
|
|
151
|
-
? {
|
|
77
|
+
...(parsed.registerContractsProfile !== undefined
|
|
78
|
+
? { registerContractsProfile: parsed.registerContractsProfile }
|
|
152
79
|
: {}),
|
|
153
|
-
|
|
80
|
+
registerContractsInterfaces: parsed.registerContractsInterfaces,
|
|
154
81
|
...(parsed.sourceRoot !== undefined ? { sourceRoot: parsed.sourceRoot } : {}),
|
|
155
82
|
...(parsed.sourceRoot !== undefined
|
|
156
83
|
? {
|