@jhlagado/azm 0.2.7 → 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 +239 -76
- 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 +55 -227
- 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/assemble-program.js +5 -0
- package/dist/src/assembly/fixup-emission.js +30 -48
- package/dist/src/assembly/import-visibility.d.ts +3 -0
- package/dist/src/assembly/import-visibility.js +204 -0
- 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/node/source-host.js +40 -13
- 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 +72 -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 +2 -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 +144 -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/logical-lines.d.ts +3 -0
- package/dist/src/source/source-span.d.ts +2 -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 +9 -0
- package/dist/src/syntax/parse-directive-statement.js +309 -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 +189 -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 +21 -273
- 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/api.js +1 -1
- 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/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/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/docs/reference/cli.md +0 -151
- package/docs/reference/tooling-api.md +0 -316
- /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
package/dist/src/api-compile.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, normalize } from 'node:path';
|
|
1
|
+
import { normalize } from 'node:path';
|
|
3
2
|
import { assembleProgram } from './assembly/assemble-program.js';
|
|
3
|
+
import { emitAssemblyArtifacts } from './api-artifacts.js';
|
|
4
|
+
import { runRegisterContracts, shouldAnalyzeRegisterContracts } from './api-register-contracts.js';
|
|
4
5
|
import { analyzeProgramNext, loadProgramNext } from './tooling/api.js';
|
|
5
6
|
import { defaultFormatWriters } from './outputs/index.js';
|
|
6
|
-
import { UnsupportedAsm80LoweringError } from './outputs/write-asm80.js';
|
|
7
7
|
import { writeHex } from './outputs/write-hex.js';
|
|
8
|
-
import {
|
|
9
|
-
import { buildRegisterCareProgramModel } from './register-care/programModel.js';
|
|
10
|
-
import { parseAcceptedOutputCandidates } from './register-care/accept-output.js';
|
|
11
|
-
import { parseInterfaceContracts } from './register-care/smartComments.js';
|
|
8
|
+
import { buildRegisterContractsProgramModel } from './register-contracts/programModel.js';
|
|
12
9
|
function parseUnresolvedSymbolName(message) {
|
|
13
10
|
const match = /^Unresolved symbol "([^"]+)"/.exec(message);
|
|
14
11
|
return match?.[1];
|
|
15
12
|
}
|
|
16
|
-
function
|
|
13
|
+
function isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls) {
|
|
17
14
|
if (directCalls === undefined || directCalls.length === 0) {
|
|
18
15
|
return false;
|
|
19
16
|
}
|
|
@@ -33,7 +30,6 @@ function isSuppressedUnknownSymbolInRegisterCareMode(diagnostic, directCalls) {
|
|
|
33
30
|
call.column === diagnostic.column);
|
|
34
31
|
}
|
|
35
32
|
export { writeHex, defaultFormatWriters };
|
|
36
|
-
let cachedPackageVersion;
|
|
37
33
|
/**
|
|
38
34
|
* Compile an AZM/ASM80-style program into in-memory artifacts.
|
|
39
35
|
*/
|
|
@@ -54,223 +50,58 @@ export async function compile(entryFile, options = {}, deps = { formats: default
|
|
|
54
50
|
const analysis = analyzeProgramNext(loaded.loadedProgram, {
|
|
55
51
|
...(options.caseStyle !== undefined ? { caseStyle: options.caseStyle } : {}),
|
|
56
52
|
});
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
options.emitRegisterAnnotations === true ||
|
|
62
|
-
options.fixRegisterContracts === true ||
|
|
63
|
-
(options.acceptRegisterOutputCandidates?.length ?? 0) > 0 ||
|
|
64
|
-
(options.registerCareInterfaces?.length ?? 0) > 0;
|
|
65
|
-
const directCalls = shouldAnalyzeRegisterCare
|
|
66
|
-
? buildRegisterCareProgramModel(loaded.loadedProgram.program.files[0]?.items ?? []).directCalls
|
|
53
|
+
const analyzeRegisterContractsNow = shouldAnalyzeRegisterContracts(options);
|
|
54
|
+
const directCalls = analyzeRegisterContractsNow
|
|
55
|
+
? buildRegisterContractsProgramModel(loaded.loadedProgram.program.files[0]?.items ?? [])
|
|
56
|
+
.directCalls
|
|
67
57
|
: undefined;
|
|
68
|
-
diagnostics.push(...analysis.diagnostics.filter((diagnostic) =>
|
|
69
|
-
? !
|
|
58
|
+
diagnostics.push(...analysis.diagnostics.filter((diagnostic) => analyzeRegisterContractsNow
|
|
59
|
+
? !isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls)
|
|
70
60
|
: true));
|
|
71
61
|
const artifacts = [];
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
severity: 'error',
|
|
81
|
-
code: 'AZMN_REGISTER_CARE',
|
|
82
|
-
message: 'Register-care interface files must use the .asmi extension',
|
|
83
|
-
sourceName: contractPath,
|
|
84
|
-
});
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
const interfaceText = await readFile(contractPath, 'utf8');
|
|
88
|
-
for (const contract of parseInterfaceContracts(interfaceText, contractPath).values()) {
|
|
89
|
-
interfaceContracts.push(contract);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (hasErrors(diagnostics)) {
|
|
93
|
-
return { diagnostics, artifacts: [] };
|
|
94
|
-
}
|
|
95
|
-
const registerCare = analyzeRegisterCare(loaded.loadedProgram, {
|
|
96
|
-
mode: registerCareMode,
|
|
97
|
-
emitReport: options.emitRegisterReport === true,
|
|
98
|
-
emitInterface: options.emitRegisterInterface === true,
|
|
99
|
-
emitAnnotations: options.emitRegisterAnnotations === true || options.fixRegisterContracts === true,
|
|
100
|
-
fixRegisterContracts: options.fixRegisterContracts === true,
|
|
101
|
-
acceptedOutputCandidates,
|
|
102
|
-
...(options.registerCareProfile !== undefined
|
|
103
|
-
? { registerCareProfile: options.registerCareProfile }
|
|
104
|
-
: {}),
|
|
105
|
-
...(interfaceContracts.length > 0 ? { interfaceContracts } : {}),
|
|
106
|
-
});
|
|
107
|
-
if (registerCare.reportText !== undefined) {
|
|
108
|
-
artifacts.push({ kind: 'register-care-report', text: registerCare.reportText });
|
|
109
|
-
}
|
|
110
|
-
if (registerCare.interfaceText !== undefined) {
|
|
111
|
-
artifacts.push({ kind: 'register-care-interface', text: registerCare.interfaceText });
|
|
112
|
-
}
|
|
113
|
-
if (registerCare.annotations !== undefined && registerCare.annotations.length > 0) {
|
|
114
|
-
const files = registerCare.annotations.map((item) => ({
|
|
115
|
-
path: item.path,
|
|
116
|
-
text: item.text,
|
|
117
|
-
}));
|
|
118
|
-
artifacts.push({ kind: 'register-care-annotations', files });
|
|
119
|
-
}
|
|
120
|
-
diagnostics.push(...registerCare.diagnostics);
|
|
62
|
+
if (hasErrors(diagnostics)) {
|
|
63
|
+
sortDiagnosticsInPlace(diagnostics);
|
|
64
|
+
return { diagnostics, artifacts };
|
|
65
|
+
}
|
|
66
|
+
if (analyzeRegisterContractsNow) {
|
|
67
|
+
const registerContracts = await runRegisterContracts(loaded.loadedProgram, options);
|
|
68
|
+
artifacts.push(...registerContracts.artifacts);
|
|
69
|
+
diagnostics.push(...registerContracts.diagnostics);
|
|
121
70
|
if (hasErrors(diagnostics))
|
|
122
|
-
return { diagnostics, artifacts
|
|
71
|
+
return { diagnostics, artifacts };
|
|
123
72
|
}
|
|
124
73
|
if (options.skipAssembly === true) {
|
|
125
74
|
return { diagnostics, artifacts };
|
|
126
75
|
}
|
|
127
76
|
const program = loaded.loadedProgram.program.files[0]?.items ?? [];
|
|
128
77
|
const assembled = assembleProgram(program);
|
|
129
|
-
diagnostics.push(...assembled.diagnostics.filter((diagnostic) =>
|
|
130
|
-
? !
|
|
78
|
+
diagnostics.push(...assembled.diagnostics.filter((diagnostic) => analyzeRegisterContractsNow
|
|
79
|
+
? !isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls)
|
|
131
80
|
: true));
|
|
132
81
|
sortDiagnosticsInPlace(diagnostics);
|
|
133
82
|
if (hasErrors(diagnostics)) {
|
|
134
83
|
return { diagnostics, artifacts: [] };
|
|
135
84
|
}
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const main = symbols.find((symbol) => symbol.kind === 'label' && symbol.name.toLowerCase() === 'main');
|
|
150
|
-
const d8mOpts = {
|
|
151
|
-
rootDir: normalize(d8Root),
|
|
152
|
-
packageVersion: await readPackageVersion(),
|
|
153
|
-
inputs: {
|
|
154
|
-
entry: normalizedEntry,
|
|
155
|
-
...(options.d8mInputs?.hex !== undefined ? { hex: options.d8mInputs.hex } : {}),
|
|
156
|
-
...(options.d8mInputs?.bin !== undefined ? { bin: options.d8mInputs.bin } : {}),
|
|
157
|
-
},
|
|
158
|
-
...(main !== undefined ? { entrySymbol: main.name } : {}),
|
|
159
|
-
...(main !== undefined
|
|
160
|
-
? { entryAddress: main.kind === 'constant' ? main.value : main.address }
|
|
161
|
-
: {}),
|
|
162
|
-
};
|
|
163
|
-
artifacts.push(deps.formats.writeD8m(sidecarMap, symbols, d8mOpts));
|
|
164
|
-
}
|
|
165
|
-
if (emit.emitAsm80) {
|
|
166
|
-
if (deps.formats.writeAsm80 !== undefined) {
|
|
167
|
-
try {
|
|
168
|
-
artifacts.push(deps.formats.writeAsm80(program, symbols));
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
if (error instanceof UnsupportedAsm80LoweringError) {
|
|
172
|
-
diagnostics.push({
|
|
173
|
-
severity: 'error',
|
|
174
|
-
code: 'AZMN_ASM80',
|
|
175
|
-
message: error.message,
|
|
176
|
-
sourceName: error.item.span.sourceName,
|
|
177
|
-
line: error.item.span.line,
|
|
178
|
-
column: error.item.span.column,
|
|
179
|
-
});
|
|
180
|
-
return { diagnostics, artifacts };
|
|
181
|
-
}
|
|
182
|
-
throw error;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
85
|
+
const emittedArtifacts = await emitAssemblyArtifacts({
|
|
86
|
+
entryFile: normalizedEntry,
|
|
87
|
+
options,
|
|
88
|
+
formats: deps.formats,
|
|
89
|
+
program,
|
|
90
|
+
bytes: assembled.bytes,
|
|
91
|
+
origin: assembled.origin,
|
|
92
|
+
sourceSegments: assembled.sourceSegments,
|
|
93
|
+
initializedAddresses: assembled.initializedAddresses,
|
|
94
|
+
symbols: assembled.symbols,
|
|
95
|
+
});
|
|
96
|
+
artifacts.push(...emittedArtifacts.artifacts);
|
|
97
|
+
diagnostics.push(...emittedArtifacts.diagnostics);
|
|
186
98
|
return { diagnostics, artifacts };
|
|
187
99
|
}
|
|
188
|
-
function compileArtifactDefaults(options) {
|
|
189
|
-
const anyPrimary = [options.emitBin, options.emitHex, options.emitD8m].some((value) => value !== undefined);
|
|
190
|
-
const emitBin = anyPrimary ? (options.emitBin ?? false) : true;
|
|
191
|
-
const emitHex = anyPrimary ? (options.emitHex ?? false) : true;
|
|
192
|
-
const emitD8m = anyPrimary ? (options.emitD8m ?? false) : true;
|
|
193
|
-
const emitAsm80 = options.emitAsm80 ?? false;
|
|
194
|
-
return { emitBin, emitHex, emitD8m, emitAsm80 };
|
|
195
|
-
}
|
|
196
|
-
function assembledImageToMap(bytes, origin, sourceSegments = []) {
|
|
197
|
-
const map = new Map();
|
|
198
|
-
for (let offset = 0; offset < bytes.length; offset += 1) {
|
|
199
|
-
map.set(origin + offset, bytes[offset] ?? 0);
|
|
200
|
-
}
|
|
201
|
-
const writtenRange = {
|
|
202
|
-
start: origin,
|
|
203
|
-
end: origin + bytes.length,
|
|
204
|
-
};
|
|
205
|
-
return { bytes: map, writtenRange, sourceSegments };
|
|
206
|
-
}
|
|
207
|
-
function assembledInitializedImageToMap(bytes, origin, initializedAddresses, sourceSegments = []) {
|
|
208
|
-
const map = new Map();
|
|
209
|
-
for (const address of initializedAddresses) {
|
|
210
|
-
const offset = address - origin;
|
|
211
|
-
if (offset >= 0 && offset < bytes.length) {
|
|
212
|
-
map.set(address, bytes[offset] ?? 0);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return { bytes: map, sourceSegments };
|
|
216
|
-
}
|
|
217
|
-
function collectSymbolEntries(items, resolvedSymbols) {
|
|
218
|
-
const map = new Map();
|
|
219
|
-
for (const item of items) {
|
|
220
|
-
switch (item.kind) {
|
|
221
|
-
case 'equ': {
|
|
222
|
-
const value = resolvedSymbols[item.name];
|
|
223
|
-
if (value !== undefined) {
|
|
224
|
-
map.set(item.name, {
|
|
225
|
-
kind: 'constant',
|
|
226
|
-
name: item.name,
|
|
227
|
-
value,
|
|
228
|
-
file: item.span.sourceName,
|
|
229
|
-
line: item.span.line,
|
|
230
|
-
scope: 'global',
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
case 'label': {
|
|
236
|
-
const address = resolvedSymbols[item.name];
|
|
237
|
-
if (address !== undefined) {
|
|
238
|
-
map.set(item.name, {
|
|
239
|
-
kind: 'label',
|
|
240
|
-
name: item.name,
|
|
241
|
-
address,
|
|
242
|
-
file: item.span.sourceName,
|
|
243
|
-
line: item.span.line,
|
|
244
|
-
scope: 'global',
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
case 'enum': {
|
|
250
|
-
for (const member of item.members) {
|
|
251
|
-
const fullName = `${item.name}.${member}`;
|
|
252
|
-
const value = resolvedSymbols[fullName];
|
|
253
|
-
if (value !== undefined) {
|
|
254
|
-
map.set(fullName, {
|
|
255
|
-
kind: 'constant',
|
|
256
|
-
name: fullName,
|
|
257
|
-
value,
|
|
258
|
-
file: item.span.sourceName,
|
|
259
|
-
line: item.span.line,
|
|
260
|
-
scope: 'global',
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return [...map.values()];
|
|
269
|
-
}
|
|
270
100
|
function hasErrors(diagnostics) {
|
|
271
101
|
return diagnostics.some((diagnostic) => diagnostic.severity === 'error');
|
|
272
102
|
}
|
|
273
103
|
function sortDiagnosticsInPlace(diagnostics) {
|
|
104
|
+
dedupeDiagnosticsInPlace(diagnostics);
|
|
274
105
|
diagnostics.sort((left, right) => {
|
|
275
106
|
const lineDelta = (left.line ?? 0) - (right.line ?? 0);
|
|
276
107
|
if (lineDelta !== 0) {
|
|
@@ -279,28 +110,25 @@ function sortDiagnosticsInPlace(diagnostics) {
|
|
|
279
110
|
return (left.column ?? 0) - (right.column ?? 0);
|
|
280
111
|
});
|
|
281
112
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
];
|
|
291
|
-
for (const candidate of packageJsonCandidates) {
|
|
292
|
-
try {
|
|
293
|
-
const raw = await readFile(candidate, 'utf8');
|
|
294
|
-
const json = JSON.parse(raw);
|
|
295
|
-
if (json.version !== undefined) {
|
|
296
|
-
cachedPackageVersion = json.version;
|
|
297
|
-
return cachedPackageVersion;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
catch {
|
|
301
|
-
// Continue searching candidates.
|
|
113
|
+
function dedupeDiagnosticsInPlace(diagnostics) {
|
|
114
|
+
const seen = new Set();
|
|
115
|
+
for (let index = diagnostics.length - 1; index >= 0; index -= 1) {
|
|
116
|
+
const diagnostic = diagnostics[index];
|
|
117
|
+
const key = diagnosticKey(diagnostic);
|
|
118
|
+
if (seen.has(key)) {
|
|
119
|
+
diagnostics.splice(index, 1);
|
|
120
|
+
continue;
|
|
302
121
|
}
|
|
122
|
+
seen.add(key);
|
|
303
123
|
}
|
|
304
|
-
|
|
305
|
-
|
|
124
|
+
}
|
|
125
|
+
function diagnosticKey(diagnostic) {
|
|
126
|
+
return [
|
|
127
|
+
diagnostic.severity,
|
|
128
|
+
diagnostic.code,
|
|
129
|
+
diagnostic.message,
|
|
130
|
+
diagnostic.sourceName ?? '',
|
|
131
|
+
diagnostic.line ?? '',
|
|
132
|
+
diagnostic.column ?? '',
|
|
133
|
+
].join('\0');
|
|
306
134
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Diagnostic } from './model/diagnostic.js';
|
|
2
|
+
import type { Artifact } from './outputs/types.js';
|
|
3
|
+
import type { LoadedProgramNext } from './tooling/api.js';
|
|
4
|
+
import type { CompileNextFunctionOptions } from './api-compile.js';
|
|
5
|
+
export declare function shouldAnalyzeRegisterContracts(options: CompileNextFunctionOptions): boolean;
|
|
6
|
+
export declare function runRegisterContracts(loadedProgram: LoadedProgramNext, options: CompileNextFunctionOptions): Promise<{
|
|
7
|
+
readonly artifacts: readonly Artifact[];
|
|
8
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { normalize } from 'node:path';
|
|
3
|
+
import { analyzeRegisterContracts } from './register-contracts/analyze.js';
|
|
4
|
+
import { parseAcceptedOutputCandidates } from './register-contracts/accept-output.js';
|
|
5
|
+
import { parseInterfaceContracts } from './register-contracts/interfaceContracts.js';
|
|
6
|
+
export function shouldAnalyzeRegisterContracts(options) {
|
|
7
|
+
const registerContractsMode = options.registerContracts ?? options.registerCare ?? 'off';
|
|
8
|
+
return (registerContractsMode !== 'off' ||
|
|
9
|
+
options.emitRegisterReport === true ||
|
|
10
|
+
options.emitRegisterInterface === true ||
|
|
11
|
+
options.emitRegisterAnnotations === true ||
|
|
12
|
+
options.fixRegisterContracts === true ||
|
|
13
|
+
(options.acceptRegisterOutputCandidates?.length ?? 0) > 0 ||
|
|
14
|
+
(options.registerContractsInterfaces?.length ?? options.registerCareInterfaces?.length ?? 0) > 0);
|
|
15
|
+
}
|
|
16
|
+
export async function runRegisterContracts(loadedProgram, options) {
|
|
17
|
+
const diagnostics = [];
|
|
18
|
+
const artifacts = [];
|
|
19
|
+
const interfaceContracts = await loadInterfaceContracts(options.registerContractsInterfaces ?? options.registerCareInterfaces ?? [], diagnostics);
|
|
20
|
+
if (hasErrors(diagnostics)) {
|
|
21
|
+
return { diagnostics, artifacts };
|
|
22
|
+
}
|
|
23
|
+
const registerContracts = analyzeRegisterContracts(loadedProgram, {
|
|
24
|
+
mode: options.registerContracts ?? options.registerCare ?? 'off',
|
|
25
|
+
emitReport: options.emitRegisterReport === true,
|
|
26
|
+
emitInterface: options.emitRegisterInterface === true,
|
|
27
|
+
emitAnnotations: options.emitRegisterAnnotations === true || options.fixRegisterContracts === true,
|
|
28
|
+
fixRegisterContracts: options.fixRegisterContracts === true,
|
|
29
|
+
acceptedOutputCandidates: parseAcceptedOutputCandidates(options.acceptRegisterOutputCandidates ?? []),
|
|
30
|
+
...(options.registerContractsProfile !== undefined || options.registerCareProfile !== undefined
|
|
31
|
+
? {
|
|
32
|
+
registerContractsProfile: options.registerContractsProfile ?? options.registerCareProfile,
|
|
33
|
+
}
|
|
34
|
+
: {}),
|
|
35
|
+
...(interfaceContracts.length > 0 ? { interfaceContracts } : {}),
|
|
36
|
+
});
|
|
37
|
+
if (registerContracts.reportText !== undefined) {
|
|
38
|
+
artifacts.push({ kind: 'register-contracts-report', text: registerContracts.reportText });
|
|
39
|
+
}
|
|
40
|
+
if (registerContracts.interfaceText !== undefined) {
|
|
41
|
+
artifacts.push({ kind: 'register-contracts-interface', text: registerContracts.interfaceText });
|
|
42
|
+
}
|
|
43
|
+
if (registerContracts.annotations !== undefined && registerContracts.annotations.length > 0) {
|
|
44
|
+
artifacts.push({
|
|
45
|
+
kind: 'register-contracts-annotations',
|
|
46
|
+
files: registerContracts.annotations.map((item) => ({
|
|
47
|
+
path: item.path,
|
|
48
|
+
text: item.text,
|
|
49
|
+
})),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
diagnostics.push(...registerContracts.diagnostics);
|
|
53
|
+
return { artifacts, diagnostics };
|
|
54
|
+
}
|
|
55
|
+
async function loadInterfaceContracts(interfaces, diagnostics) {
|
|
56
|
+
const interfaceContracts = [];
|
|
57
|
+
for (const rawInterface of interfaces) {
|
|
58
|
+
const contractPath = normalize(rawInterface);
|
|
59
|
+
if (contractPath.slice(-5).toLowerCase() !== '.asmi') {
|
|
60
|
+
diagnostics.push({
|
|
61
|
+
severity: 'error',
|
|
62
|
+
code: 'AZMN_REGISTER_CONTRACTS',
|
|
63
|
+
message: 'Register contracts interface files must use the .asmi extension',
|
|
64
|
+
sourceName: contractPath,
|
|
65
|
+
});
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const interfaceText = await readFile(contractPath, 'utf8');
|
|
69
|
+
for (const contract of parseInterfaceContracts(interfaceText, contractPath).values()) {
|
|
70
|
+
interfaceContracts.push(contract);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return interfaceContracts;
|
|
74
|
+
}
|
|
75
|
+
function hasErrors(diagnostics) {
|
|
76
|
+
return diagnostics.some((diagnostic) => diagnostic.severity === 'error');
|
|
77
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { analyzeProgram, analyzeProgramNext, loadProgram, loadProgramNext } from './tooling/api.js';
|
|
2
|
-
export { analyzeRegisterCareForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, type RegisterCareTextEdit, } from './register-
|
|
2
|
+
export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type AnalyzeRegisterContractsForToolsOptions, type AnalyzeRegisterContractsForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, type RegisterCareTextEdit, type RegisterContractsCandidateDiagnostic, type RegisterContractsCodeAction, type RegisterContractsTextEdit, } from './register-contracts/tooling.js';
|
|
3
3
|
export { DiagnosticIds } from './model/diagnostic.js';
|
|
4
4
|
export type { AnalyzeProgramOptions, AnalyzeProgramResult, LoadedProgram, LoadProgramOptions, LoadProgramResult, AnalyzeProgramNextOptions, AnalyzeProgramNextResult, LoadedProgramNext, LoadProgramNextOptions, LoadProgramNextResult, } from './tooling/api.js';
|
|
5
5
|
export type { CaseStyleMode } from './tooling/case-style.js';
|
|
6
6
|
export type { Diagnostic, DiagnosticId, DiagnosticSeverity } from './model/diagnostic.js';
|
|
7
|
-
export type { RegisterCareMode, RegisterCareOutputCandidate, RegisterCareUnit, } from './register-
|
|
7
|
+
export type { RegisterCareMode, RegisterCareOutputCandidate, RegisterCareUnit, RegisterContractsMode, RegisterContractsOutputCandidate, RegisterContractsUnit, } from './register-contracts/types.js';
|
package/dist/src/api-tooling.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { analyzeProgram, analyzeProgramNext, loadProgram, loadProgramNext } from './tooling/api.js';
|
|
2
|
-
export { analyzeRegisterCareForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, } from './register-
|
|
2
|
+
export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, } from './register-contracts/tooling.js';
|
|
3
3
|
export { DiagnosticIds } from './model/diagnostic.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
2
|
import type { SourceItem } from '../model/source-item.js';
|
|
3
|
-
import type { SymbolTable } from '../model/symbol.js';
|
|
4
3
|
import { type EquateRecord, type LayoutRecord } from '../semantics/expression-evaluation.js';
|
|
4
|
+
export { resolveSymbols } from './address-symbols.js';
|
|
5
5
|
export interface AddressState {
|
|
6
6
|
readonly labels: Record<string, number>;
|
|
7
7
|
readonly equates: Map<string, EquateRecord>;
|
|
@@ -16,4 +16,3 @@ export declare function buildAddressState(items: readonly SourceItem[], diagnost
|
|
|
16
16
|
};
|
|
17
17
|
export declare function stringDirectiveBytes(directive: 'cstr' | 'pstr' | 'istr', value: string): readonly number[];
|
|
18
18
|
export declare function alignmentPadding(address: number, alignment: number): number;
|
|
19
|
-
export declare function resolveSymbols(labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): SymbolTable;
|