@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
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
function isGlobalLabel(name) {
|
|
2
|
-
return !name.startsWith('.');
|
|
3
|
-
}
|
|
4
|
-
function routineNameFromExpression(expression) {
|
|
5
|
-
return expression.kind === 'symbol' ? expression.name : undefined;
|
|
6
|
-
}
|
|
7
|
-
function evaluateConstantExpression(expression, constants) {
|
|
8
|
-
switch (expression.kind) {
|
|
9
|
-
case 'number':
|
|
10
|
-
return expression.value;
|
|
11
|
-
case 'symbol':
|
|
12
|
-
return constants.get(expression.name);
|
|
13
|
-
case 'unary': {
|
|
14
|
-
const value = evaluateConstantExpression(expression.expression, constants);
|
|
15
|
-
if (value === undefined)
|
|
16
|
-
return undefined;
|
|
17
|
-
switch (expression.operator) {
|
|
18
|
-
case '+':
|
|
19
|
-
return value;
|
|
20
|
-
case '-':
|
|
21
|
-
return -value;
|
|
22
|
-
case '~':
|
|
23
|
-
return ~value;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
case 'binary': {
|
|
27
|
-
const left = evaluateConstantExpression(expression.left, constants);
|
|
28
|
-
const right = evaluateConstantExpression(expression.right, constants);
|
|
29
|
-
if (left === undefined || right === undefined)
|
|
30
|
-
return undefined;
|
|
31
|
-
switch (expression.operator) {
|
|
32
|
-
case '+':
|
|
33
|
-
return left + right;
|
|
34
|
-
case '-':
|
|
35
|
-
return left - right;
|
|
36
|
-
case '*':
|
|
37
|
-
return left * right;
|
|
38
|
-
case '/':
|
|
39
|
-
return right === 0 ? undefined : Math.trunc(left / right);
|
|
40
|
-
case '%':
|
|
41
|
-
return right === 0 ? undefined : left % right;
|
|
42
|
-
case '&':
|
|
43
|
-
return left & right;
|
|
44
|
-
case '^':
|
|
45
|
-
return left ^ right;
|
|
46
|
-
case '|':
|
|
47
|
-
return left | right;
|
|
48
|
-
case '<<':
|
|
49
|
-
return left << right;
|
|
50
|
-
case '>>':
|
|
51
|
-
return left >> right;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
case 'byte-function': {
|
|
55
|
-
const value = evaluateConstantExpression(expression.expression, constants);
|
|
56
|
-
if (value === undefined)
|
|
57
|
-
return undefined;
|
|
58
|
-
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
59
|
-
}
|
|
60
|
-
default:
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function collectConstants(items) {
|
|
65
|
-
const constants = new Map();
|
|
66
|
-
let changed = true;
|
|
67
|
-
while (changed) {
|
|
68
|
-
changed = false;
|
|
69
|
-
for (const item of items) {
|
|
70
|
-
if (item.kind !== 'equ' || constants.has(item.name))
|
|
71
|
-
continue;
|
|
72
|
-
const value = evaluateConstantExpression(item.expression, constants);
|
|
73
|
-
if (value === undefined)
|
|
74
|
-
continue;
|
|
75
|
-
constants.set(item.name, value);
|
|
76
|
-
changed = true;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return constants;
|
|
80
|
-
}
|
|
81
|
-
function instructionCallTarget(item) {
|
|
82
|
-
if (item.kind !== 'instruction')
|
|
83
|
-
return undefined;
|
|
84
|
-
const mnemonic = item.instruction.mnemonic;
|
|
85
|
-
if (mnemonic === 'call' || mnemonic === 'call-cc') {
|
|
86
|
-
return routineNameFromExpression(item.instruction.expression);
|
|
87
|
-
}
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
function instructionTailJumpTarget(item, entryNames) {
|
|
91
|
-
if (item.kind !== 'instruction')
|
|
92
|
-
return undefined;
|
|
93
|
-
const mnemonic = item.instruction.mnemonic;
|
|
94
|
-
if (mnemonic === 'jp-cc' && entryNames === undefined)
|
|
95
|
-
return undefined;
|
|
96
|
-
if (mnemonic !== 'jp' && mnemonic !== 'jp-cc')
|
|
97
|
-
return undefined;
|
|
98
|
-
const target = routineNameFromExpression(item.instruction.expression);
|
|
99
|
-
if (target === undefined || target.startsWith('.'))
|
|
100
|
-
return undefined;
|
|
101
|
-
if (entryNames !== undefined && !entryNames.has(target))
|
|
102
|
-
return undefined;
|
|
103
|
-
return target;
|
|
104
|
-
}
|
|
105
|
-
function toInstruction(item, labels, constants) {
|
|
106
|
-
return {
|
|
107
|
-
instruction: item.instruction,
|
|
108
|
-
file: item.span.sourceName,
|
|
109
|
-
line: item.span.line,
|
|
110
|
-
column: item.span.column,
|
|
111
|
-
labels: [...labels],
|
|
112
|
-
constants,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function pushDirectBoundary(boundaries, target, subject, file, line, column) {
|
|
116
|
-
boundaries.push({ target, subject, file, line, column });
|
|
117
|
-
}
|
|
118
|
-
export function buildRegisterCareProgramModel(items) {
|
|
119
|
-
const routines = [];
|
|
120
|
-
const directCalls = [];
|
|
121
|
-
const constants = collectConstants(items);
|
|
122
|
-
const filesWithEntryLabels = new Set(items
|
|
123
|
-
.filter((item) => item.kind === 'label')
|
|
124
|
-
.filter((item) => item.isEntry === true)
|
|
125
|
-
.map((item) => item.span.sourceName));
|
|
126
|
-
let routineName;
|
|
127
|
-
let entryLabels = [];
|
|
128
|
-
let labels = [];
|
|
129
|
-
let sourceName;
|
|
130
|
-
let routineStartLine;
|
|
131
|
-
let routineStartColumn;
|
|
132
|
-
let instructions = [];
|
|
133
|
-
const startRoutine = (item) => {
|
|
134
|
-
sourceName = item.span.sourceName;
|
|
135
|
-
routineName = item.name;
|
|
136
|
-
entryLabels = item.isEntry === true ? [item.name] : [];
|
|
137
|
-
labels = [item.name];
|
|
138
|
-
routineStartLine = item.span.line;
|
|
139
|
-
routineStartColumn = item.span.column;
|
|
140
|
-
instructions = [];
|
|
141
|
-
};
|
|
142
|
-
const flushRoutine = () => {
|
|
143
|
-
if (routineName === undefined || routineStartLine === undefined) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
if (instructions.length === 0) {
|
|
147
|
-
routines.push({
|
|
148
|
-
name: routineName,
|
|
149
|
-
labels: [...labels],
|
|
150
|
-
entryLabels: [...entryLabels],
|
|
151
|
-
instructions: [],
|
|
152
|
-
constants,
|
|
153
|
-
span: {
|
|
154
|
-
file: sourceName ?? '',
|
|
155
|
-
start: { line: routineStartLine, column: routineStartColumn ?? 1 },
|
|
156
|
-
end: { line: routineStartLine, column: routineStartColumn ?? 1 },
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const end = instructions[instructions.length - 1];
|
|
162
|
-
if (end === undefined)
|
|
163
|
-
return;
|
|
164
|
-
routines.push({
|
|
165
|
-
name: routineName,
|
|
166
|
-
labels: [...labels],
|
|
167
|
-
entryLabels: [...entryLabels],
|
|
168
|
-
instructions: [...instructions],
|
|
169
|
-
constants,
|
|
170
|
-
span: {
|
|
171
|
-
file: sourceName ?? '',
|
|
172
|
-
start: { line: routineStartLine, column: routineStartColumn ?? 1 },
|
|
173
|
-
end: { line: end.line, column: end.column },
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
};
|
|
177
|
-
const resetRoutine = () => {
|
|
178
|
-
routineName = undefined;
|
|
179
|
-
entryLabels = [];
|
|
180
|
-
labels = [];
|
|
181
|
-
sourceName = undefined;
|
|
182
|
-
routineStartLine = undefined;
|
|
183
|
-
routineStartColumn = undefined;
|
|
184
|
-
instructions = [];
|
|
185
|
-
};
|
|
186
|
-
const finalizeAndRestart = (item) => {
|
|
187
|
-
flushRoutine();
|
|
188
|
-
resetRoutine();
|
|
189
|
-
startRoutine(item);
|
|
190
|
-
};
|
|
191
|
-
for (const item of items) {
|
|
192
|
-
if (item.kind !== 'label') {
|
|
193
|
-
if (item.kind !== 'instruction') {
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
if (routineName === undefined || sourceName === undefined) {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
if (item.span.sourceName !== sourceName) {
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
instructions.push(toInstruction(item, labels, constants));
|
|
203
|
-
const directTarget = instructionCallTarget(item);
|
|
204
|
-
if (directTarget !== undefined) {
|
|
205
|
-
pushDirectBoundary(directCalls, directTarget, `CALL ${directTarget}`, item.span.sourceName, item.span.line, item.span.column);
|
|
206
|
-
}
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (!isGlobalLabel(item.name)) {
|
|
210
|
-
if (routineName !== undefined) {
|
|
211
|
-
labels.push(item.name);
|
|
212
|
-
}
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
if (routineName === undefined) {
|
|
216
|
-
if (filesWithEntryLabels.has(item.span.sourceName) && item.isEntry !== true) {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
startRoutine(item);
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
if (sourceName === undefined || sourceName !== item.span.sourceName) {
|
|
223
|
-
finalizeAndRestart(item);
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
if (instructions.length > 0) {
|
|
227
|
-
if (filesWithEntryLabels.has(item.span.sourceName) && item.isEntry !== true) {
|
|
228
|
-
labels.push(item.name);
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
finalizeAndRestart(item);
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
// Multiple global labels before body on same routine are coalesced as entry labels.
|
|
235
|
-
labels.push(item.name);
|
|
236
|
-
if (item.isEntry === true) {
|
|
237
|
-
entryLabels.push(item.name);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
flushRoutine();
|
|
241
|
-
const entryNamesByFile = new Map();
|
|
242
|
-
for (const item of items) {
|
|
243
|
-
if (item.kind !== 'label' || item.isEntry !== true)
|
|
244
|
-
continue;
|
|
245
|
-
const names = entryNamesByFile.get(item.span.sourceName) ?? new Set();
|
|
246
|
-
names.add(item.name);
|
|
247
|
-
entryNamesByFile.set(item.span.sourceName, names);
|
|
248
|
-
}
|
|
249
|
-
const directTailJumps = [];
|
|
250
|
-
for (const item of items) {
|
|
251
|
-
if (item.kind !== 'instruction')
|
|
252
|
-
continue;
|
|
253
|
-
const entryNames = filesWithEntryLabels.has(item.span.sourceName)
|
|
254
|
-
? entryNamesByFile.get(item.span.sourceName)
|
|
255
|
-
: undefined;
|
|
256
|
-
const target = instructionTailJumpTarget(item, entryNames);
|
|
257
|
-
if (target === undefined)
|
|
258
|
-
continue;
|
|
259
|
-
pushDirectBoundary(directTailJumps, target, `JP ${target}`, item.span.sourceName, item.span.line, item.span.column);
|
|
260
|
-
}
|
|
261
|
-
return {
|
|
262
|
-
routines,
|
|
263
|
-
directCalls,
|
|
264
|
-
directBoundaries: [...directCalls, ...directTailJumps],
|
|
265
|
-
};
|
|
266
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareReportModel, RegisterCareUnit, RoutineSummary } from './types.js';
|
|
2
|
-
export declare function contractCarrierList(units: RegisterCareUnit[]): string;
|
|
3
|
-
export declare function renderRegisterCareReport(model: RegisterCareReportModel): string;
|
|
4
|
-
export declare function renderRegisterCareInterface(summaries: RoutineSummary[]): string;
|
|
5
|
-
export declare function renderRegisterCareSourceBlock(summary: RoutineSummary): string[];
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareRoutine, RoutineContract, RoutineSummary } from './types.js';
|
|
2
|
-
export declare function summariesWithExternalContracts(summaries: RoutineSummary[], contracts: Map<string, RoutineContract>, routineNameSet: Set<string>): RoutineSummary[];
|
|
3
|
-
export declare function inferRoutineSummariesToFixedPoint(routines: RegisterCareRoutine[], contracts: Map<string, RoutineContract>, routineNameSet: Set<string>, profileSummaries: RoutineSummary[]): Array<{
|
|
4
|
-
routine: RegisterCareRoutine;
|
|
5
|
-
summary: RoutineSummary;
|
|
6
|
-
}>;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { LocatedSmartComment, RegisterCareRoutine, RoutineContract, SmartComment } from './types.js';
|
|
2
|
-
export declare function parseSmartCommentLine(line: string): SmartComment | undefined;
|
|
3
|
-
export declare function parseSmartComments(sourceLineComments: ReadonlyMap<string, ReadonlyMap<number, string>>): LocatedSmartComment[];
|
|
4
|
-
export declare function buildRoutineContracts(comments: LocatedSmartComment[], routines?: RegisterCareRoutine[], sourceTexts?: ReadonlyMap<string, string>): Map<string, RoutineContract>;
|
|
5
|
-
export declare function parseInterfaceContracts(text: string, file?: string): Map<string, RoutineContract>;
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { expandCarrierList } from './carriers.js';
|
|
2
|
-
const COMPACT_SOURCE_TAG_RE = /^;?\s*!\s*(in|out|clobbers|preserves)(?:\s+(.+))?$/i;
|
|
3
|
-
const COMPACT_SOURCE_LINE_RE = /^\s*;\s*!\s*(?:in|out|maybe-out|clobbers|preserves)(?:\s|$)/i;
|
|
4
|
-
const INTERFACE_TAG_RE = /^\s*(in|out|clobbers|preserves)(?:\s+(.+))?$/i;
|
|
5
|
-
const CARRIER_RE = /^\{([^}]+)\}(?:\s+(.+))?$/;
|
|
6
|
-
function parseCarrierPayload(rest) {
|
|
7
|
-
if (!rest)
|
|
8
|
-
return undefined;
|
|
9
|
-
const match = CARRIER_RE.exec(rest.trim());
|
|
10
|
-
if (match) {
|
|
11
|
-
const carriers = match[1].split(',').map((value) => value.trim()).filter(Boolean);
|
|
12
|
-
const name = match[2]?.trim();
|
|
13
|
-
return { carriers, ...(name ? { name } : {}) };
|
|
14
|
-
}
|
|
15
|
-
const tokens = rest.trim().split(/\s+/u);
|
|
16
|
-
const carriers = [];
|
|
17
|
-
let consumed = 0;
|
|
18
|
-
for (const token of tokens) {
|
|
19
|
-
const cleaned = token.replace(/[.:;]+$/u, '');
|
|
20
|
-
const parts = cleaned
|
|
21
|
-
.split(',')
|
|
22
|
-
.map((value) => value.trim())
|
|
23
|
-
.filter(Boolean);
|
|
24
|
-
if (parts.length === 0 || !expandCarrierList(parts))
|
|
25
|
-
break;
|
|
26
|
-
carriers.push(...parts);
|
|
27
|
-
consumed += 1;
|
|
28
|
-
}
|
|
29
|
-
if (carriers.length === 0)
|
|
30
|
-
return undefined;
|
|
31
|
-
const name = tokens.slice(consumed).join(' ').trim();
|
|
32
|
-
return { carriers, ...(name ? { name } : {}) };
|
|
33
|
-
}
|
|
34
|
-
export function parseSmartCommentLine(line) {
|
|
35
|
-
const trimmed = line.trim();
|
|
36
|
-
const expectOut = /^;?\s*expects\s+out\s+(.+)$/i.exec(trimmed);
|
|
37
|
-
if (expectOut !== null) {
|
|
38
|
-
const payload = parseCarrierPayload(expectOut[1]?.trim());
|
|
39
|
-
if (!payload)
|
|
40
|
-
return undefined;
|
|
41
|
-
const carriers = expandCarrierList(payload.carriers);
|
|
42
|
-
if (!carriers || carriers.length === 0)
|
|
43
|
-
return undefined;
|
|
44
|
-
return { kind: 'expectOut', carriers, ...(payload.name ? { name: payload.name } : {}) };
|
|
45
|
-
}
|
|
46
|
-
const match = COMPACT_SOURCE_TAG_RE.exec(trimmed);
|
|
47
|
-
if (!match)
|
|
48
|
-
return undefined;
|
|
49
|
-
const tag = match[1].toLowerCase();
|
|
50
|
-
const rest = match[2]?.trim();
|
|
51
|
-
const payload = parseCarrierPayload(rest);
|
|
52
|
-
if (!payload)
|
|
53
|
-
return undefined;
|
|
54
|
-
const carriers = expandCarrierList(payload.carriers);
|
|
55
|
-
if (!carriers || carriers.length === 0)
|
|
56
|
-
return undefined;
|
|
57
|
-
if (tag === 'in')
|
|
58
|
-
return { kind: 'in', carriers, ...(payload.name ? { name: payload.name } : {}) };
|
|
59
|
-
if (tag === 'out')
|
|
60
|
-
return { kind: 'out', carriers, ...(payload.name ? { name: payload.name } : {}) };
|
|
61
|
-
if (tag === 'clobbers')
|
|
62
|
-
return { kind: 'clobbers', carriers };
|
|
63
|
-
if (tag === 'preserves')
|
|
64
|
-
return { kind: 'preserves', carriers };
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
function parseInterfaceContractLine(line) {
|
|
68
|
-
const trimmed = line.trim();
|
|
69
|
-
if (trimmed.length === 0 || trimmed.startsWith(';'))
|
|
70
|
-
return undefined;
|
|
71
|
-
const extern = /^extern\s+(\S+)\s*$/i.exec(trimmed);
|
|
72
|
-
if (extern !== null)
|
|
73
|
-
return { kind: 'extern', name: extern[1] };
|
|
74
|
-
if (/^end\s*$/i.test(trimmed))
|
|
75
|
-
return { kind: 'end' };
|
|
76
|
-
const match = INTERFACE_TAG_RE.exec(trimmed);
|
|
77
|
-
if (!match)
|
|
78
|
-
return undefined;
|
|
79
|
-
const tag = match[1].toLowerCase();
|
|
80
|
-
const rest = match[2]?.trim();
|
|
81
|
-
if (!rest)
|
|
82
|
-
return undefined;
|
|
83
|
-
const rawCarriers = rest.split(',').map((part) => part.trim());
|
|
84
|
-
if (rawCarriers.length === 0 || rawCarriers.some((part) => part.length === 0))
|
|
85
|
-
return undefined;
|
|
86
|
-
const carriers = expandCarrierList(rawCarriers);
|
|
87
|
-
if (!carriers || carriers.length === 0)
|
|
88
|
-
return undefined;
|
|
89
|
-
if (tag === 'in')
|
|
90
|
-
return { kind: 'in', carriers };
|
|
91
|
-
if (tag === 'out')
|
|
92
|
-
return { kind: 'out', carriers };
|
|
93
|
-
if (tag === 'clobbers')
|
|
94
|
-
return { kind: 'clobbers', carriers };
|
|
95
|
-
if (tag === 'preserves')
|
|
96
|
-
return { kind: 'preserves', carriers };
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
function isCompactSourceCommentLine(line) {
|
|
100
|
-
return COMPACT_SOURCE_LINE_RE.test(line);
|
|
101
|
-
}
|
|
102
|
-
export function parseSmartComments(sourceLineComments) {
|
|
103
|
-
const out = [];
|
|
104
|
-
for (const [file, comments] of sourceLineComments) {
|
|
105
|
-
for (const [line, text] of comments) {
|
|
106
|
-
const parsed = parseSmartCommentLine(`;${text}`);
|
|
107
|
-
if (parsed) {
|
|
108
|
-
out.push({ file, line, comment: parsed });
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return out.sort((a, b) => (a.file === b.file ? a.line - b.line : a.file.localeCompare(b.file)));
|
|
113
|
-
}
|
|
114
|
-
function appendUnique(items, values) {
|
|
115
|
-
for (const value of values) {
|
|
116
|
-
if (!items.includes(value)) {
|
|
117
|
-
items.push(value);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function isCommentOnlyLine(line) {
|
|
122
|
-
return /^\s*;/.test(line);
|
|
123
|
-
}
|
|
124
|
-
function applyContractComment(contract, comment) {
|
|
125
|
-
if (comment.kind === 'in')
|
|
126
|
-
appendUnique(contract.in, comment.carriers);
|
|
127
|
-
if (comment.kind === 'out')
|
|
128
|
-
appendUnique(contract.out, comment.carriers);
|
|
129
|
-
if (comment.kind === 'clobbers')
|
|
130
|
-
appendUnique(contract.clobbers, comment.carriers);
|
|
131
|
-
if (comment.kind === 'preserves')
|
|
132
|
-
appendUnique(contract.preserves, comment.carriers);
|
|
133
|
-
}
|
|
134
|
-
function hasContractContent(contract) {
|
|
135
|
-
return (contract.in.length > 0 ||
|
|
136
|
-
contract.out.length > 0 ||
|
|
137
|
-
contract.clobbers.length > 0 ||
|
|
138
|
-
contract.preserves.length > 0);
|
|
139
|
-
}
|
|
140
|
-
function collectPrecedingCommentBlock(routine, sourceTexts) {
|
|
141
|
-
const source = sourceTexts.get(routine.span.file);
|
|
142
|
-
if (source === undefined)
|
|
143
|
-
return { comments: [], complete: false };
|
|
144
|
-
const lines = source.split(/\r?\n/);
|
|
145
|
-
const rawBlock = [];
|
|
146
|
-
for (let index = routine.span.start.line - 2; index >= 0; index -= 1) {
|
|
147
|
-
const text = lines[index] ?? '';
|
|
148
|
-
if (!isCommentOnlyLine(text))
|
|
149
|
-
break;
|
|
150
|
-
rawBlock.push({ line: index + 1, text });
|
|
151
|
-
}
|
|
152
|
-
rawBlock.reverse();
|
|
153
|
-
let compactStart = rawBlock.length;
|
|
154
|
-
while (compactStart > 0 &&
|
|
155
|
-
isCompactSourceCommentLine(rawBlock[compactStart - 1]?.text ?? '')) {
|
|
156
|
-
compactStart -= 1;
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
complete: compactStart < rawBlock.length,
|
|
160
|
-
comments: (compactStart < rawBlock.length ? rawBlock.slice(compactStart) : rawBlock).flatMap((item) => {
|
|
161
|
-
const parsed = parseSmartCommentLine(item.text);
|
|
162
|
-
return parsed ? [{ file: routine.span.file, line: item.line, comment: parsed }] : [];
|
|
163
|
-
}),
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function buildImplicitRoutineContracts(routines, sourceTexts) {
|
|
167
|
-
const contracts = new Map();
|
|
168
|
-
for (const routine of routines) {
|
|
169
|
-
const docBlock = collectPrecedingCommentBlock(routine, sourceTexts);
|
|
170
|
-
if (docBlock.comments.some((item) => item.comment.kind === 'extern' || item.comment.kind === 'end')) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
const contract = {
|
|
174
|
-
name: routine.name,
|
|
175
|
-
in: [],
|
|
176
|
-
out: [],
|
|
177
|
-
clobbers: [],
|
|
178
|
-
preserves: [],
|
|
179
|
-
...(docBlock.complete ? { complete: true } : {}),
|
|
180
|
-
};
|
|
181
|
-
for (const item of docBlock.comments) {
|
|
182
|
-
applyContractComment(contract, item.comment);
|
|
183
|
-
}
|
|
184
|
-
if (hasContractContent(contract)) {
|
|
185
|
-
contracts.set(routine.name, contract);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return contracts;
|
|
189
|
-
}
|
|
190
|
-
export function buildRoutineContracts(comments, routines = [], sourceTexts = new Map()) {
|
|
191
|
-
const contracts = new Map();
|
|
192
|
-
let current;
|
|
193
|
-
for (const item of comments) {
|
|
194
|
-
if (item.comment.kind === 'extern') {
|
|
195
|
-
current = {
|
|
196
|
-
name: item.comment.name,
|
|
197
|
-
in: [],
|
|
198
|
-
out: [],
|
|
199
|
-
clobbers: [],
|
|
200
|
-
preserves: [],
|
|
201
|
-
};
|
|
202
|
-
contracts.set(item.comment.name, current);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (item.comment.kind === 'end') {
|
|
206
|
-
current = undefined;
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
if (current !== undefined) {
|
|
210
|
-
applyContractComment(current, item.comment);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
for (const [name, contract] of buildImplicitRoutineContracts(routines, sourceTexts)) {
|
|
214
|
-
if (!contracts.has(name)) {
|
|
215
|
-
contracts.set(name, contract);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return contracts;
|
|
219
|
-
}
|
|
220
|
-
export function parseInterfaceContracts(text, file = '<register-care-interface>') {
|
|
221
|
-
const comments = [];
|
|
222
|
-
const lines = text.split(/\r?\n/u);
|
|
223
|
-
for (const [index, line] of lines.entries()) {
|
|
224
|
-
const trimmed = line.trim();
|
|
225
|
-
if (trimmed.length === 0)
|
|
226
|
-
continue;
|
|
227
|
-
if (trimmed.startsWith(';')) {
|
|
228
|
-
throw new Error(`${file}:${index + 1}: .asmi files do not permit comments`);
|
|
229
|
-
}
|
|
230
|
-
const comment = parseInterfaceContractLine(line);
|
|
231
|
-
if (comment === undefined) {
|
|
232
|
-
throw new Error(`${file}:${index + 1}: invalid register-care interface line \"${trimmed}\"`);
|
|
233
|
-
}
|
|
234
|
-
comments.push({ file, line: index + 1, comment });
|
|
235
|
-
}
|
|
236
|
-
const routines = buildRoutineContracts(comments);
|
|
237
|
-
const out = new Map();
|
|
238
|
-
for (const [name, contract] of routines) {
|
|
239
|
-
if (hasContractContent(contract))
|
|
240
|
-
out.set(name, contract);
|
|
241
|
-
}
|
|
242
|
-
return out;
|
|
243
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
-
import type { AnalyzeRegisterCareOptions, RegisterCareDirectCall, RegisterCareRoutine, RoutineContract, RoutineSummary, RegisterCareUnit, RegisterCareOutputCandidate } from './types.js';
|
|
3
|
-
export declare function buildProfileSummaries(profileName: AnalyzeRegisterCareOptions['registerCareProfile']): RoutineSummary[];
|
|
4
|
-
export declare function buildProfileSummaryLookup(profileName: AnalyzeRegisterCareOptions['registerCareProfile']): Map<string, RoutineSummary>;
|
|
5
|
-
export declare function routineNames(routines: readonly RegisterCareRoutine[]): string[];
|
|
6
|
-
export declare function buildSummaries(routines: readonly RegisterCareRoutine[], contractMap: Map<string, RoutineContract>, profileSummaries?: readonly RoutineSummary[]): RoutineSummary[];
|
|
7
|
-
export declare function buildSummaryByName(routines: readonly RegisterCareRoutine[], summaries: readonly RoutineSummary[], profileSummaries?: readonly RoutineSummary[]): Map<string, RoutineSummary>;
|
|
8
|
-
export declare function withAcceptedOutputs(summaries: readonly RoutineSummary[], acceptedOutputCandidates: ReadonlyMap<string, RegisterCareUnit[]> | undefined): RoutineSummary[];
|
|
9
|
-
export declare function unknownBoundaryDiagnostics(directBoundaries: readonly RegisterCareDirectCall[], knownRoutines: ReadonlySet<string>): Diagnostic[];
|
|
10
|
-
export declare function unknownCallList(directBoundaries: readonly RegisterCareDirectCall[], knownRoutines: ReadonlySet<string>): string[];
|
|
11
|
-
export declare function buildOutputCandidateFixability(routines: readonly RegisterCareRoutine[], outputCandidates: readonly RegisterCareOutputCandidate[], autoFixableCandidateKeys: (routines: RegisterCareRoutine[], outputCandidates: RegisterCareOutputCandidate[]) => ReadonlySet<string>): ReadonlyMap<string, boolean>;
|
|
12
|
-
export declare function outputCandidateKey(file: string, line: number, column: number): string;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareRoutine, RoutineContract, RoutineSummary } from './types.js';
|
|
2
|
-
export declare function inferRoutineSummary(routine: RegisterCareRoutine, boundarySummaries?: ReadonlyMap<string, RoutineSummary>): RoutineSummary;
|
|
3
|
-
export declare function applyRoutineContract(summary: RoutineSummary, contract: RoutineContract): RoutineSummary;
|