@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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const PRECEDENCE = new Map([
|
|
2
|
+
['|', 1],
|
|
3
|
+
['^', 2],
|
|
4
|
+
['&', 3],
|
|
5
|
+
['<<', 4],
|
|
6
|
+
['>>', 4],
|
|
7
|
+
['+', 5],
|
|
8
|
+
['-', 5],
|
|
9
|
+
['*', 6],
|
|
10
|
+
['/', 6],
|
|
11
|
+
['%', 6],
|
|
12
|
+
]);
|
|
13
|
+
export function parseTokenExpression(tokenList) {
|
|
14
|
+
let index = 0;
|
|
15
|
+
function consume() {
|
|
16
|
+
const token = tokenList[index];
|
|
17
|
+
if (!token) {
|
|
18
|
+
throw new Error('parseExpression consumed past end of token list');
|
|
19
|
+
}
|
|
20
|
+
index += 1;
|
|
21
|
+
return token;
|
|
22
|
+
}
|
|
23
|
+
function parsePrimary() {
|
|
24
|
+
const token = tokenList[index];
|
|
25
|
+
if (!token)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (token.kind === 'number')
|
|
28
|
+
return parseNumberToken(consume());
|
|
29
|
+
if (token.kind === 'expression')
|
|
30
|
+
return parseNestedExpressionToken(consume());
|
|
31
|
+
if (token.kind === 'symbol')
|
|
32
|
+
return parseSymbolPrimary();
|
|
33
|
+
if (token.kind === 'current-location')
|
|
34
|
+
return parseCurrentLocationPrimary();
|
|
35
|
+
if (token.kind === 'operator' && isUnaryOperator(token.text)) {
|
|
36
|
+
return parseUnaryPrimary(token.text);
|
|
37
|
+
}
|
|
38
|
+
if (token.kind === 'left-paren')
|
|
39
|
+
return parseParenthesizedPrimary();
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
function parseNumberToken(token) {
|
|
43
|
+
return token.kind === 'number' ? { kind: 'number', value: token.value } : undefined;
|
|
44
|
+
}
|
|
45
|
+
function parseNestedExpressionToken(token) {
|
|
46
|
+
return token.kind === 'expression' ? token.expression : undefined;
|
|
47
|
+
}
|
|
48
|
+
function parseCurrentLocationPrimary() {
|
|
49
|
+
consume();
|
|
50
|
+
return { kind: 'current-location' };
|
|
51
|
+
}
|
|
52
|
+
function parseSymbolPrimary() {
|
|
53
|
+
const token = tokenList[index];
|
|
54
|
+
if (token?.kind !== 'symbol')
|
|
55
|
+
return undefined;
|
|
56
|
+
if (token.text === 'sizeof' && tokenList[index + 1]?.kind === 'left-paren') {
|
|
57
|
+
return parseSizeofPrimary();
|
|
58
|
+
}
|
|
59
|
+
if (token.text === 'offset' && tokenList[index + 1]?.kind === 'left-paren') {
|
|
60
|
+
return parseOffsetPrimary();
|
|
61
|
+
}
|
|
62
|
+
index += 1;
|
|
63
|
+
return { kind: 'symbol', name: token.text };
|
|
64
|
+
}
|
|
65
|
+
function parseSizeofPrimary() {
|
|
66
|
+
index += 2;
|
|
67
|
+
const typeName = tokenList[index];
|
|
68
|
+
if (typeName?.kind !== 'symbol' || tokenList[index + 1]?.kind !== 'right-paren') {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
index += 2;
|
|
72
|
+
return { kind: 'sizeof', typeExpr: { name: typeName.text } };
|
|
73
|
+
}
|
|
74
|
+
function parseOffsetPrimary() {
|
|
75
|
+
index += 2;
|
|
76
|
+
const typeName = tokenList[index];
|
|
77
|
+
const comma = tokenList[index + 1];
|
|
78
|
+
const fieldName = tokenList[index + 2];
|
|
79
|
+
const rightParen = tokenList[index + 3];
|
|
80
|
+
if (typeName?.kind !== 'symbol' ||
|
|
81
|
+
comma?.kind !== 'comma' ||
|
|
82
|
+
fieldName?.kind !== 'symbol' ||
|
|
83
|
+
rightParen?.kind !== 'right-paren') {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
index += 4;
|
|
87
|
+
return {
|
|
88
|
+
kind: 'offset',
|
|
89
|
+
typeExpr: { name: typeName.text },
|
|
90
|
+
path: [{ kind: 'field', name: fieldName.text }],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function parseUnaryPrimary(operator) {
|
|
94
|
+
index += 1;
|
|
95
|
+
const expression = parsePrimary();
|
|
96
|
+
return expression ? { kind: 'unary', operator, expression } : undefined;
|
|
97
|
+
}
|
|
98
|
+
function parseParenthesizedPrimary() {
|
|
99
|
+
index += 1;
|
|
100
|
+
const expression = parseBinary(1);
|
|
101
|
+
if (!expression || tokenList[index]?.kind !== 'right-paren')
|
|
102
|
+
return undefined;
|
|
103
|
+
index += 1;
|
|
104
|
+
return expression;
|
|
105
|
+
}
|
|
106
|
+
function parseBinary(minPrecedence) {
|
|
107
|
+
let left = parsePrimary();
|
|
108
|
+
if (!left)
|
|
109
|
+
return undefined;
|
|
110
|
+
while (true) {
|
|
111
|
+
const token = tokenList[index];
|
|
112
|
+
if (!token || token.kind !== 'operator' || !isBinaryOperator(token.text))
|
|
113
|
+
break;
|
|
114
|
+
const precedence = PRECEDENCE.get(token.text) ?? 0;
|
|
115
|
+
if (precedence < minPrecedence)
|
|
116
|
+
break;
|
|
117
|
+
index += 1;
|
|
118
|
+
const right = parseBinary(precedence + 1);
|
|
119
|
+
if (!right)
|
|
120
|
+
return undefined;
|
|
121
|
+
left = { kind: 'binary', operator: token.text, left, right };
|
|
122
|
+
}
|
|
123
|
+
return left;
|
|
124
|
+
}
|
|
125
|
+
const expression = parseBinary(1);
|
|
126
|
+
return expression && index === tokenList.length ? expression : undefined;
|
|
127
|
+
}
|
|
128
|
+
function isUnaryOperator(operator) {
|
|
129
|
+
return operator === '+' || operator === '-' || operator === '~';
|
|
130
|
+
}
|
|
131
|
+
function isBinaryOperator(operator) {
|
|
132
|
+
return PRECEDENCE.has(operator);
|
|
133
|
+
}
|
|
@@ -40,29 +40,38 @@ function lintInstructionLine(rawLine, sourceName, line, mode, state, diagnostics
|
|
|
40
40
|
}
|
|
41
41
|
function lintSourceLines(sourceLines, instructionLines, mode, state, diagnostics) {
|
|
42
42
|
for (const [sourceName, lines] of sourceLines) {
|
|
43
|
-
|
|
43
|
+
const lineState = { inOpBody: false };
|
|
44
44
|
for (let index = 0; index < lines.length; index += 1) {
|
|
45
45
|
const line = index + 1;
|
|
46
46
|
const rawLine = lines[index] ?? '';
|
|
47
|
-
|
|
48
|
-
if (text.length === 0)
|
|
49
|
-
continue;
|
|
50
|
-
if (/^op\s+[A-Za-z_][A-Za-z0-9_]*\s*\(/i.test(text)) {
|
|
51
|
-
inOpBody = true;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
if (inOpBody && /^end\s*$/i.test(text)) {
|
|
55
|
-
inOpBody = false;
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (inOpBody ||
|
|
59
|
-
instructionLines.has(lineKey(sourceName, line)) ||
|
|
60
|
-
isPotentialOpInvocationLine(text)) {
|
|
47
|
+
if (shouldLintCaseStyleLine(rawLine, sourceName, line, instructionLines, lineState)) {
|
|
61
48
|
lintInstructionLine(rawLine, sourceName, line, mode, state, diagnostics);
|
|
62
49
|
}
|
|
63
50
|
}
|
|
64
51
|
}
|
|
65
52
|
}
|
|
53
|
+
function shouldLintCaseStyleLine(rawLine, sourceName, line, instructionLines, state) {
|
|
54
|
+
const text = stripLeadingLabels(stripLineComment(rawLine)).trim();
|
|
55
|
+
if (text.length === 0)
|
|
56
|
+
return false;
|
|
57
|
+
if (isOpHeaderLine(text)) {
|
|
58
|
+
state.inOpBody = true;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (state.inOpBody && isOpEndLine(text)) {
|
|
62
|
+
state.inOpBody = false;
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return (state.inOpBody ||
|
|
66
|
+
instructionLines.has(lineKey(sourceName, line)) ||
|
|
67
|
+
isPotentialOpInvocationLine(text));
|
|
68
|
+
}
|
|
69
|
+
function isOpHeaderLine(text) {
|
|
70
|
+
return /^op\s+[A-Za-z_][A-Za-z0-9_]*\s*\(/i.test(text);
|
|
71
|
+
}
|
|
72
|
+
function isOpEndLine(text) {
|
|
73
|
+
return /^end\s*$/i.test(text);
|
|
74
|
+
}
|
|
66
75
|
function isPotentialOpInvocationLine(text) {
|
|
67
76
|
if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\s+.*)?$/.test(text))
|
|
68
77
|
return false;
|
|
@@ -86,23 +95,31 @@ function lintToken(mode, state, token, category, sourceName, line, diagnostics)
|
|
|
86
95
|
if (!style)
|
|
87
96
|
return;
|
|
88
97
|
if (mode === 'consistent') {
|
|
89
|
-
|
|
90
|
-
state.consistentStyle = style;
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const expected = state.consistentStyle;
|
|
94
|
-
if (!expected || style === expected)
|
|
95
|
-
return;
|
|
96
|
-
diagnostics.push({
|
|
97
|
-
severity: 'warning',
|
|
98
|
-
code: 'AZMN_CASE_STYLE',
|
|
99
|
-
message: `Case-style lint: ${category} "${token}" does not match established ${expected}case style under --case-style=consistent.`,
|
|
100
|
-
sourceName,
|
|
101
|
-
line,
|
|
102
|
-
column: 1,
|
|
103
|
-
});
|
|
98
|
+
lintConsistentToken(state, style, token, category, sourceName, line, diagnostics);
|
|
104
99
|
return;
|
|
105
100
|
}
|
|
101
|
+
if (mode === 'off')
|
|
102
|
+
return;
|
|
103
|
+
lintFixedStyleToken(mode, style, token, category, sourceName, line, diagnostics);
|
|
104
|
+
}
|
|
105
|
+
function lintConsistentToken(state, style, token, category, sourceName, line, diagnostics) {
|
|
106
|
+
if (!state.consistentStyle && (style === 'upper' || style === 'lower')) {
|
|
107
|
+
state.consistentStyle = style;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const expected = state.consistentStyle;
|
|
111
|
+
if (!expected || style === expected)
|
|
112
|
+
return;
|
|
113
|
+
diagnostics.push({
|
|
114
|
+
severity: 'warning',
|
|
115
|
+
code: 'AZMN_CASE_STYLE',
|
|
116
|
+
message: `Case-style lint: ${category} "${token}" does not match established ${expected}case style under --case-style=consistent.`,
|
|
117
|
+
sourceName,
|
|
118
|
+
line,
|
|
119
|
+
column: 1,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function lintFixedStyleToken(mode, style, token, category, sourceName, line, diagnostics) {
|
|
106
123
|
if (style === mode)
|
|
107
124
|
return;
|
|
108
125
|
const expectedText = mode === 'upper' ? 'uppercase' : 'lowercase';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ControlEffect, InstructionEffect, RegisterContractsUnit } from '../register-contracts/types.js';
|
|
2
|
+
import type { Z80Instruction, Z80StackRegister16 } from './instruction.js';
|
|
3
|
+
export declare function callControl(target: string | undefined, conditional: boolean): ControlEffect;
|
|
4
|
+
export declare function rstControl(vector: number | undefined): ControlEffect;
|
|
5
|
+
export declare function jumpControl(target: string | undefined, conditional: boolean): ControlEffect;
|
|
6
|
+
export declare function controlEffect(control: ControlEffect, reads?: RegisterContractsUnit[]): InstructionEffect;
|
|
7
|
+
export declare function stackControlEffect(control: ControlEffect, reads?: RegisterContractsUnit[]): InstructionEffect;
|
|
8
|
+
export declare function ldEffect(instruction: Extract<Z80Instruction, {
|
|
9
|
+
mnemonic: 'ld';
|
|
10
|
+
}>): InstructionEffect;
|
|
11
|
+
export declare function incDecEffect(instruction: Extract<Z80Instruction, {
|
|
12
|
+
mnemonic: 'inc' | 'dec';
|
|
13
|
+
}>): InstructionEffect;
|
|
14
|
+
export declare function aluEffect(instruction: Extract<Z80Instruction, {
|
|
15
|
+
mnemonic: 'add' | 'adc' | 'sbc';
|
|
16
|
+
}>): InstructionEffect;
|
|
17
|
+
export declare function aluEffect(instruction: Extract<Z80Instruction, {
|
|
18
|
+
mnemonic: 'sub' | 'and' | 'or' | 'xor' | 'cp' | 'add' | 'adc' | 'sbc';
|
|
19
|
+
}>): InstructionEffect;
|
|
20
|
+
export declare function pushEffect(register: Z80StackRegister16): InstructionEffect;
|
|
21
|
+
export declare function popEffect(register: Z80StackRegister16): InstructionEffect;
|
|
22
|
+
export declare function rotateShiftEffect(instruction: Extract<Z80Instruction, {
|
|
23
|
+
mnemonic: 'rlc' | 'rrc' | 'rl' | 'rr' | 'sla' | 'sra' | 'sll' | 'sls' | 'srl';
|
|
24
|
+
}>): InstructionEffect;
|
|
25
|
+
export declare function bitEffect(instruction: Extract<Z80Instruction, {
|
|
26
|
+
mnemonic: 'bit' | 'res' | 'set';
|
|
27
|
+
}>): InstructionEffect;
|
|
28
|
+
export declare function inEffect(instruction: Extract<Z80Instruction, {
|
|
29
|
+
mnemonic: 'in';
|
|
30
|
+
}>): InstructionEffect;
|
|
31
|
+
export declare function outEffect(instruction: Extract<Z80Instruction, {
|
|
32
|
+
mnemonic: 'out';
|
|
33
|
+
}>): InstructionEffect;
|
|
34
|
+
export declare function blockTransferEffect(): InstructionEffect;
|
|
35
|
+
export declare function exEffect(instruction: Extract<Z80Instruction, {
|
|
36
|
+
mnemonic: 'ex';
|
|
37
|
+
}>): InstructionEffect;
|
|
38
|
+
export declare function accumulatorRotateEffect(mnemonic: 'rlca' | 'rrca' | 'rla' | 'rra'): InstructionEffect;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { BIT_FLAG_WRITES, FLAG_WRITES, INC_DEC_FLAG_WRITES, ROTATE_SHIFT_FLAG_WRITES, STACK_POINTER_UNITS, baseEffect, concatUnique, operandReads, operandWrites, reg16Units, reg8Units, regHalfUnits, unknownEffect, } from './effect-units.js';
|
|
2
|
+
export function callControl(target, conditional) {
|
|
3
|
+
return target === undefined
|
|
4
|
+
? { kind: 'call', conditional }
|
|
5
|
+
: { kind: 'call', target, conditional };
|
|
6
|
+
}
|
|
7
|
+
export function rstControl(vector) {
|
|
8
|
+
return vector === undefined ? { kind: 'rst' } : { kind: 'rst', vector };
|
|
9
|
+
}
|
|
10
|
+
export function jumpControl(target, conditional) {
|
|
11
|
+
return target === undefined
|
|
12
|
+
? { kind: 'jump', conditional }
|
|
13
|
+
: { kind: 'jump', target, conditional };
|
|
14
|
+
}
|
|
15
|
+
export function controlEffect(control, reads = []) {
|
|
16
|
+
return {
|
|
17
|
+
...baseEffect(),
|
|
18
|
+
reads,
|
|
19
|
+
control,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function stackControlEffect(control, reads = []) {
|
|
23
|
+
return {
|
|
24
|
+
...controlEffect(control, reads),
|
|
25
|
+
writes: STACK_POINTER_UNITS,
|
|
26
|
+
stack: { kind: 'unknown' },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function ldEffect(instruction) {
|
|
30
|
+
const srcReads = operandReads(instruction.source);
|
|
31
|
+
if (srcReads === undefined)
|
|
32
|
+
return unknownEffect();
|
|
33
|
+
const dstWrites = operandWrites(instruction.target);
|
|
34
|
+
if (instruction.target.kind === 'reg8' || instruction.target.kind === 'reg16') {
|
|
35
|
+
if (dstWrites === undefined)
|
|
36
|
+
return unknownEffect();
|
|
37
|
+
return {
|
|
38
|
+
...baseEffect(),
|
|
39
|
+
reads: srcReads,
|
|
40
|
+
writes: dstWrites,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (instruction.target.kind === 'reg-index16' ||
|
|
44
|
+
instruction.target.kind === 'reg-half-index') {
|
|
45
|
+
if (dstWrites === undefined)
|
|
46
|
+
return unknownEffect();
|
|
47
|
+
return {
|
|
48
|
+
...baseEffect(),
|
|
49
|
+
reads: srcReads,
|
|
50
|
+
writes: dstWrites,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (instruction.target.kind === 'reg-indirect' || instruction.target.kind === 'indexed') {
|
|
54
|
+
const dstReads = operandReads(instruction.target);
|
|
55
|
+
if (dstReads === undefined)
|
|
56
|
+
return unknownEffect();
|
|
57
|
+
return {
|
|
58
|
+
...baseEffect(),
|
|
59
|
+
reads: concatUnique(dstReads, srcReads),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (instruction.target.kind === 'mem-abs') {
|
|
63
|
+
return {
|
|
64
|
+
...baseEffect(),
|
|
65
|
+
reads: srcReads,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return unknownEffect();
|
|
69
|
+
}
|
|
70
|
+
export function incDecEffect(instruction) {
|
|
71
|
+
const operand = instruction.operand;
|
|
72
|
+
if (operand.kind === 'reg8') {
|
|
73
|
+
const units = reg8Units(operand.register);
|
|
74
|
+
return {
|
|
75
|
+
...baseEffect(),
|
|
76
|
+
reads: units,
|
|
77
|
+
writes: concatUnique(units, INC_DEC_FLAG_WRITES),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (operand.kind === 'reg16') {
|
|
81
|
+
const units = reg16Units(operand.register);
|
|
82
|
+
return {
|
|
83
|
+
...baseEffect(),
|
|
84
|
+
reads: units,
|
|
85
|
+
writes: units,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (operand.kind === 'reg-half-index') {
|
|
89
|
+
const units = regHalfUnits(operand.register);
|
|
90
|
+
return {
|
|
91
|
+
...baseEffect(),
|
|
92
|
+
reads: units,
|
|
93
|
+
writes: concatUnique(units, INC_DEC_FLAG_WRITES),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const reads = operandReads(operand);
|
|
97
|
+
if (reads === undefined)
|
|
98
|
+
return unknownEffect();
|
|
99
|
+
return {
|
|
100
|
+
...baseEffect(),
|
|
101
|
+
reads,
|
|
102
|
+
writes: INC_DEC_FLAG_WRITES,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export function aluEffect(instruction) {
|
|
106
|
+
if (instruction.mnemonic === 'add' &&
|
|
107
|
+
'target' in instruction &&
|
|
108
|
+
(instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
|
|
109
|
+
return wideAluEffect(instruction, []);
|
|
110
|
+
}
|
|
111
|
+
if (instruction.mnemonic === 'adc' &&
|
|
112
|
+
'target' in instruction &&
|
|
113
|
+
(instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
|
|
114
|
+
return wideAluEffect(instruction, ['carry']);
|
|
115
|
+
}
|
|
116
|
+
if (instruction.mnemonic === 'sbc' &&
|
|
117
|
+
'target' in instruction &&
|
|
118
|
+
(instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
|
|
119
|
+
return wideAluEffect(instruction, ['carry']);
|
|
120
|
+
}
|
|
121
|
+
if (!('source' in instruction))
|
|
122
|
+
return unknownEffect();
|
|
123
|
+
const source = instruction.source;
|
|
124
|
+
const sourceReads = aluSourceReads(source);
|
|
125
|
+
const xorSelfZero = instruction.mnemonic === 'xor' &&
|
|
126
|
+
source.kind === 'reg8' &&
|
|
127
|
+
source.register === 'a';
|
|
128
|
+
const reads = xorSelfZero ? [] : concatUnique(['A'], sourceReads);
|
|
129
|
+
const carryReads = instruction.mnemonic === 'adc' || instruction.mnemonic === 'sbc' ? ['carry'] : [];
|
|
130
|
+
if (instruction.mnemonic === 'cp') {
|
|
131
|
+
return {
|
|
132
|
+
...baseEffect(),
|
|
133
|
+
reads: concatUnique(reads, carryReads),
|
|
134
|
+
writes: FLAG_WRITES,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
...baseEffect(),
|
|
139
|
+
reads: concatUnique(reads, carryReads),
|
|
140
|
+
writes: concatUnique(['A'], FLAG_WRITES),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export function pushEffect(register) {
|
|
144
|
+
const units = reg16Units(register);
|
|
145
|
+
return {
|
|
146
|
+
...baseEffect(),
|
|
147
|
+
reads: units,
|
|
148
|
+
writes: STACK_POINTER_UNITS,
|
|
149
|
+
stack: { kind: 'push', units },
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export function popEffect(register) {
|
|
153
|
+
const units = reg16Units(register);
|
|
154
|
+
return {
|
|
155
|
+
...baseEffect(),
|
|
156
|
+
writes: concatUnique(units, STACK_POINTER_UNITS),
|
|
157
|
+
stack: { kind: 'pop', units },
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export function rotateShiftEffect(instruction) {
|
|
161
|
+
const reads = operandReads(instruction.operand);
|
|
162
|
+
const writes = operandWrites(instruction.operand);
|
|
163
|
+
if (reads === undefined || writes === undefined)
|
|
164
|
+
return unknownEffect();
|
|
165
|
+
return {
|
|
166
|
+
...baseEffect(),
|
|
167
|
+
reads,
|
|
168
|
+
writes: concatUnique(writes, ROTATE_SHIFT_FLAG_WRITES),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export function bitEffect(instruction) {
|
|
172
|
+
const reads = operandReads(instruction.operand);
|
|
173
|
+
if (reads === undefined)
|
|
174
|
+
return unknownEffect();
|
|
175
|
+
if (instruction.mnemonic === 'bit') {
|
|
176
|
+
return {
|
|
177
|
+
...baseEffect(),
|
|
178
|
+
reads,
|
|
179
|
+
writes: BIT_FLAG_WRITES,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const writes = operandWrites(instruction.operand);
|
|
183
|
+
if (writes === undefined)
|
|
184
|
+
return unknownEffect();
|
|
185
|
+
return {
|
|
186
|
+
...baseEffect(),
|
|
187
|
+
reads,
|
|
188
|
+
writes,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
export function inEffect(instruction) {
|
|
192
|
+
const targetWrites = instruction.target?.kind === 'reg8' ? reg8Units(instruction.target.register) : undefined;
|
|
193
|
+
if (instruction.port.kind === 'imm') {
|
|
194
|
+
return {
|
|
195
|
+
...baseEffect(),
|
|
196
|
+
reads: ['A'],
|
|
197
|
+
writes: targetWrites ?? [],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
...baseEffect(),
|
|
202
|
+
reads: ['C'],
|
|
203
|
+
writes: concatUnique(targetWrites ?? [], BIT_FLAG_WRITES),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export function outEffect(instruction) {
|
|
207
|
+
const valueReads = instruction.source.kind === 'reg8' ? reg8Units(instruction.source.register) : [];
|
|
208
|
+
if (instruction.port.kind === 'c') {
|
|
209
|
+
return {
|
|
210
|
+
...baseEffect(),
|
|
211
|
+
reads: concatUnique(['C'], valueReads),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
...baseEffect(),
|
|
216
|
+
reads: valueReads,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
export function blockTransferEffect() {
|
|
220
|
+
return {
|
|
221
|
+
...baseEffect(),
|
|
222
|
+
reads: ['H', 'L', 'D', 'E', 'B', 'C'],
|
|
223
|
+
writes: ['H', 'L', 'D', 'E', 'B', 'C', 'halfCarry', 'parity'],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
export function exEffect(instruction) {
|
|
227
|
+
if (instruction.form === 'de-hl') {
|
|
228
|
+
return {
|
|
229
|
+
...baseEffect(),
|
|
230
|
+
reads: ['D', 'E', 'H', 'L'],
|
|
231
|
+
writes: ['D', 'E', 'H', 'L'],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return unknownEffect();
|
|
235
|
+
}
|
|
236
|
+
export function accumulatorRotateEffect(mnemonic) {
|
|
237
|
+
const reads = mnemonic === 'rla' || mnemonic === 'rra' ? ['A', 'carry'] : ['A'];
|
|
238
|
+
return {
|
|
239
|
+
...baseEffect(),
|
|
240
|
+
reads,
|
|
241
|
+
writes: ['A', 'carry', 'halfCarry'],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function wideAluEffect(instruction, extraReads) {
|
|
245
|
+
const targetReads = operandReads(instruction.target);
|
|
246
|
+
const sourceReads = operandReads(instruction.source);
|
|
247
|
+
if (targetReads === undefined || sourceReads === undefined)
|
|
248
|
+
return unknownEffect();
|
|
249
|
+
return {
|
|
250
|
+
...baseEffect(),
|
|
251
|
+
reads: concatUnique(targetReads, sourceReads, extraReads),
|
|
252
|
+
writes: concatUnique(operandWrites(instruction.target) ?? [], FLAG_WRITES),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function aluSourceReads(source) {
|
|
256
|
+
if (source.kind === 'reg8')
|
|
257
|
+
return reg8Units(source.register);
|
|
258
|
+
if (source.kind === 'reg16' || source.kind === 'reg-index16')
|
|
259
|
+
return reg16Units(source.register);
|
|
260
|
+
if (source.kind === 'reg-half-index')
|
|
261
|
+
return regHalfUnits(source.register);
|
|
262
|
+
if (source.kind === 'reg-indirect' || source.kind === 'indexed')
|
|
263
|
+
return operandReads(source) ?? [];
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Expression } from '../model/expression.js';
|
|
2
|
+
import type { InstructionEffect, RegisterContractsUnit } from '../register-contracts/types.js';
|
|
3
|
+
import type { Z80Condition, Z80Operand, Z80RelativeCondition } from './instruction.js';
|
|
4
|
+
export declare const FLAG_WRITES: RegisterContractsUnit[];
|
|
5
|
+
export declare const INC_DEC_FLAG_WRITES: RegisterContractsUnit[];
|
|
6
|
+
export declare const ROTATE_SHIFT_FLAG_WRITES: RegisterContractsUnit[];
|
|
7
|
+
export declare const BIT_FLAG_WRITES: RegisterContractsUnit[];
|
|
8
|
+
export declare const STACK_POINTER_UNITS: RegisterContractsUnit[];
|
|
9
|
+
export declare function baseEffect(): InstructionEffect;
|
|
10
|
+
export declare function unknownEffect(): InstructionEffect;
|
|
11
|
+
export declare function concatUnique(...groups: RegisterContractsUnit[][]): RegisterContractsUnit[];
|
|
12
|
+
export declare function reg8Units(raw: string): RegisterContractsUnit[];
|
|
13
|
+
export declare function reg16Units(raw: string): RegisterContractsUnit[];
|
|
14
|
+
export declare function regHalfUnits(raw: string): RegisterContractsUnit[];
|
|
15
|
+
export declare function expressionSymbol(expression: Expression): string | undefined;
|
|
16
|
+
export declare function operandReads(op: Z80Operand): RegisterContractsUnit[] | undefined;
|
|
17
|
+
export declare function operandWrites(op: Z80Operand): RegisterContractsUnit[] | undefined;
|
|
18
|
+
export declare function conditionFlagRead(condition: Z80Condition | Z80RelativeCondition): RegisterContractsUnit[];
|