@jhlagado/azm 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -69
- package/dist/src/api-artifacts.d.ts +20 -0
- package/dist/src/api-artifacts.js +165 -0
- package/dist/src/api-compile.d.ts +8 -2
- package/dist/src/api-compile.js +31 -230
- package/dist/src/api-register-contracts.d.ts +9 -0
- package/dist/src/api-register-contracts.js +77 -0
- package/dist/src/api-tooling.d.ts +2 -2
- package/dist/src/api-tooling.js +1 -1
- package/dist/src/assembly/address-planning.d.ts +1 -2
- package/dist/src/assembly/address-planning.js +119 -218
- package/dist/src/assembly/address-symbols.d.ts +12 -0
- package/dist/src/assembly/address-symbols.js +118 -0
- package/dist/src/assembly/fixup-emission.js +30 -48
- package/dist/src/assembly/program-emission.js +163 -164
- package/dist/src/cli/artifact-files.d.ts +15 -0
- package/dist/src/cli/artifact-files.js +86 -0
- package/dist/src/cli/parse-args.d.ts +6 -5
- package/dist/src/cli/parse-args.js +162 -136
- package/dist/src/cli/run.js +4 -1
- package/dist/src/cli/usage.d.ts +1 -0
- package/dist/src/cli/usage.js +33 -0
- package/dist/src/cli/write-artifacts.js +18 -91
- package/dist/src/core/compile.js +51 -274
- package/dist/src/core/conditional-assembly.d.ts +6 -0
- package/dist/src/core/conditional-assembly.js +181 -0
- package/dist/src/expansion/op-constant-expression.d.ts +3 -0
- package/dist/src/expansion/op-constant-expression.js +52 -0
- package/dist/src/expansion/op-expand-selected.d.ts +5 -0
- package/dist/src/expansion/op-expand-selected.js +143 -0
- package/dist/src/expansion/op-expansion.d.ts +5 -53
- package/dist/src/expansion/op-expansion.js +85 -815
- package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
- package/dist/src/expansion/op-instruction-instantiation.js +194 -0
- package/dist/src/expansion/op-local-labels.d.ts +8 -0
- package/dist/src/expansion/op-local-labels.js +166 -0
- package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
- package/dist/src/expansion/op-operand-splitting.js +44 -0
- package/dist/src/expansion/op-operands.d.ts +53 -0
- package/dist/src/expansion/op-operands.js +66 -0
- package/dist/src/expansion/op-selection.d.ts +18 -0
- package/dist/src/expansion/op-selection.js +172 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/model/diagnostic.d.ts +4 -0
- package/dist/src/model/diagnostic.js +4 -0
- package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
- package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
- package/dist/src/outputs/asm80-expressions.d.ts +5 -0
- package/dist/src/outputs/asm80-expressions.js +47 -0
- package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
- package/dist/src/outputs/asm80-instruction-operands.js +38 -0
- package/dist/src/outputs/asm80-instructions.d.ts +5 -0
- package/dist/src/outputs/asm80-instructions.js +272 -0
- package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
- package/dist/src/outputs/asm80-ld-operands.js +157 -0
- package/dist/src/outputs/asm80-strings.d.ts +4 -0
- package/dist/src/outputs/asm80-strings.js +14 -0
- package/dist/src/outputs/d8-files.d.ts +10 -0
- package/dist/src/outputs/d8-files.js +103 -0
- package/dist/src/outputs/d8-helpers.d.ts +21 -0
- package/dist/src/outputs/d8-helpers.js +136 -0
- package/dist/src/outputs/hex.js +26 -18
- package/dist/src/outputs/types.d.ts +16 -10
- package/dist/src/outputs/write-asm80.js +68 -597
- package/dist/src/outputs/write-d8.js +6 -216
- package/dist/src/register-contracts/accept-output.d.ts +2 -0
- package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
- package/dist/src/register-contracts/analyze-helpers.js +162 -0
- package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
- package/dist/src/register-contracts/analyze.js +73 -0
- package/dist/src/register-contracts/annotate.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
- package/dist/src/register-contracts/annotations.d.ts +8 -0
- package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
- package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
- package/dist/src/register-contracts/boundaryHints.js +24 -0
- package/dist/src/register-contracts/carriers.d.ts +2 -0
- package/dist/src/register-contracts/constants.d.ts +4 -0
- package/dist/src/register-contracts/constants.js +51 -0
- package/dist/src/register-contracts/controlFlow.d.ts +5 -0
- package/dist/src/register-contracts/controlFlow.js +55 -0
- package/dist/src/register-contracts/fix.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/fix.js +47 -30
- package/dist/src/register-contracts/instruction-head.d.ts +2 -0
- package/dist/src/register-contracts/instruction-head.js +3 -0
- package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
- package/dist/src/register-contracts/instruction-operands.js +101 -0
- package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
- package/dist/src/register-contracts/instruction-predicates.js +44 -0
- package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
- package/dist/src/register-contracts/interfaceContracts.js +68 -0
- package/dist/src/register-contracts/liveness.d.ts +3 -0
- package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
- package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
- package/dist/src/register-contracts/operand-register-name.js +13 -0
- package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
- package/dist/src/{register-care → register-contracts}/profiles.js +13 -2
- package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
- package/dist/src/register-contracts/programModel-boundaries.js +64 -0
- package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
- package/dist/src/register-contracts/programModel-routines.js +128 -0
- package/dist/src/register-contracts/programModel.d.ts +3 -0
- package/dist/src/register-contracts/programModel.js +14 -0
- package/dist/src/register-contracts/report.d.ts +5 -0
- package/dist/src/{register-care → register-contracts}/report.js +34 -17
- package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
- package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
- package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
- package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
- package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
- package/dist/src/register-contracts/smartCommentParsing.js +80 -0
- package/dist/src/register-contracts/smartComments.d.ts +5 -0
- package/dist/src/register-contracts/smartComments.js +92 -0
- package/dist/src/register-contracts/summaries.d.ts +12 -0
- package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
- package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
- package/dist/src/register-contracts/summary-boundary.js +40 -0
- package/dist/src/register-contracts/summary-contract.d.ts +2 -0
- package/dist/src/register-contracts/summary-contract.js +45 -0
- package/dist/src/register-contracts/summary-result.d.ts +7 -0
- package/dist/src/register-contracts/summary-result.js +122 -0
- package/dist/src/register-contracts/summary-state.d.ts +23 -0
- package/dist/src/register-contracts/summary-state.js +88 -0
- package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
- package/dist/src/register-contracts/summary-token-transfer.js +67 -0
- package/dist/src/register-contracts/summary.d.ts +3 -0
- package/dist/src/register-contracts/summary.js +266 -0
- package/dist/src/register-contracts/tooling.d.ts +57 -0
- package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
- package/dist/src/register-contracts/types.d.ts +188 -0
- package/dist/src/semantics/binary-operators.d.ts +2 -0
- package/dist/src/semantics/binary-operators.js +15 -0
- package/dist/src/semantics/byte-functions.d.ts +2 -0
- package/dist/src/semantics/byte-functions.js +7 -0
- package/dist/src/semantics/constant-operator-types.d.ts +10 -0
- package/dist/src/semantics/constant-operator-types.js +1 -0
- package/dist/src/semantics/constant-operators.d.ts +3 -0
- package/dist/src/semantics/constant-operators.js +3 -0
- package/dist/src/semantics/diagnostics.d.ts +3 -0
- package/dist/src/semantics/diagnostics.js +10 -0
- package/dist/src/semantics/expression-evaluation.d.ts +11 -19
- package/dist/src/semantics/expression-evaluation.js +22 -334
- package/dist/src/semantics/layout-evaluation.d.ts +23 -0
- package/dist/src/semantics/layout-evaluation.js +202 -0
- package/dist/src/semantics/layout-format.d.ts +5 -0
- package/dist/src/semantics/layout-format.js +31 -0
- package/dist/src/semantics/layout-path.d.ts +24 -0
- package/dist/src/semantics/layout-path.js +58 -0
- package/dist/src/semantics/unary-operators.d.ts +2 -0
- package/dist/src/semantics/unary-operators.js +8 -0
- package/dist/src/source/line-comment-scanner.d.ts +1 -0
- package/dist/src/source/line-comment-scanner.js +51 -0
- package/dist/src/source/strip-line-comment.js +8 -44
- package/dist/src/syntax/directive-aliases.js +36 -22
- package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
- package/dist/src/syntax/expression-tokenizer.js +310 -0
- package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
- package/dist/src/syntax/parse-directive-statement.js +307 -0
- package/dist/src/syntax/parse-expression.d.ts +2 -2
- package/dist/src/syntax/parse-expression.js +7 -568
- package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
- package/dist/src/syntax/parse-layout-declarations.js +180 -0
- package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
- package/dist/src/syntax/parse-layout-expression.js +175 -0
- package/dist/src/syntax/parse-line.js +4 -272
- package/dist/src/syntax/parse-token-expression.d.ts +3 -0
- package/dist/src/syntax/parse-token-expression.js +133 -0
- package/dist/src/tooling/case-style.js +47 -30
- package/dist/src/z80/effect-groups.d.ts +38 -0
- package/dist/src/z80/effect-groups.js +265 -0
- package/dist/src/z80/effect-units.d.ts +18 -0
- package/dist/src/z80/effect-units.js +165 -0
- package/dist/src/z80/effects.d.ts +1 -1
- package/dist/src/z80/effects.js +94 -557
- package/dist/src/z80/encode-core.d.ts +2 -0
- package/dist/src/z80/encode-core.js +42 -0
- package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
- package/dist/src/z80/encode-ld-helpers.js +172 -0
- package/dist/src/z80/encode-ld.d.ts +2 -0
- package/dist/src/z80/encode-ld.js +285 -0
- package/dist/src/z80/encode.js +190 -542
- package/dist/src/z80/ld-support.d.ts +3 -0
- package/dist/src/z80/ld-support.js +146 -0
- package/dist/src/z80/operand-split-state.d.ts +8 -0
- package/dist/src/z80/operand-split-state.js +46 -0
- package/dist/src/z80/operand-split.d.ts +1 -0
- package/dist/src/z80/operand-split.js +13 -0
- package/dist/src/z80/parse-basic.d.ts +4 -0
- package/dist/src/z80/parse-basic.js +39 -0
- package/dist/src/z80/parse-branch.d.ts +4 -0
- package/dist/src/z80/parse-branch.js +218 -0
- package/dist/src/z80/parse-conditions.d.ts +6 -0
- package/dist/src/z80/parse-conditions.js +10 -0
- package/dist/src/z80/parse-exchange.d.ts +2 -0
- package/dist/src/z80/parse-exchange.js +30 -0
- package/dist/src/z80/parse-instruction.js +224 -1010
- package/dist/src/z80/parse-io-control.d.ts +5 -0
- package/dist/src/z80/parse-io-control.js +108 -0
- package/dist/src/z80/parse-ld.d.ts +2 -0
- package/dist/src/z80/parse-ld.js +83 -0
- package/dist/src/z80/parse-operands.d.ts +41 -0
- package/dist/src/z80/parse-operands.js +259 -0
- package/docs/reference/cli.md +42 -35
- package/docs/reference/tooling-api.md +20 -16
- package/package.json +1 -1
- package/dist/src/register-care/accept-output.d.ts +0 -2
- package/dist/src/register-care/analyze.js +0 -166
- package/dist/src/register-care/annotate.d.ts +0 -11
- package/dist/src/register-care/annotations.d.ts +0 -8
- package/dist/src/register-care/boundaryHints.d.ts +0 -3
- package/dist/src/register-care/boundaryHints.js +0 -80
- package/dist/src/register-care/carriers.d.ts +0 -2
- package/dist/src/register-care/controlFlow.d.ts +0 -5
- package/dist/src/register-care/controlFlow.js +0 -38
- package/dist/src/register-care/fix.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.js +0 -129
- package/dist/src/register-care/liveness.d.ts +0 -3
- package/dist/src/register-care/programModel.d.ts +0 -3
- package/dist/src/register-care/programModel.js +0 -266
- package/dist/src/register-care/report.d.ts +0 -5
- package/dist/src/register-care/routine-summaries.d.ts +0 -6
- package/dist/src/register-care/smartComments.d.ts +0 -5
- package/dist/src/register-care/smartComments.js +0 -243
- package/dist/src/register-care/summaries.d.ts +0 -12
- package/dist/src/register-care/summary.d.ts +0 -3
- package/dist/src/register-care/summary.js +0 -474
- package/dist/src/register-care/tooling.d.ts +0 -43
- package/dist/src/register-care/types.d.ts +0 -172
- /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
- /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
- /package/dist/src/{register-care → register-contracts}/types.js +0 -0
|
@@ -1,576 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
['<<', 4],
|
|
6
|
-
['>>', 4],
|
|
7
|
-
['+', 5],
|
|
8
|
-
['-', 5],
|
|
9
|
-
['*', 6],
|
|
10
|
-
['/', 6],
|
|
11
|
-
['%', 6],
|
|
12
|
-
]);
|
|
1
|
+
import { parseLayoutExpression } from './parse-layout-expression.js';
|
|
2
|
+
import { tokenizeExpression } from './expression-tokenizer.js';
|
|
3
|
+
import { parseTokenExpression } from './parse-token-expression.js';
|
|
4
|
+
export { parseTypeExpr } from './parse-layout-expression.js';
|
|
13
5
|
export function parseExpression(text) {
|
|
14
|
-
const layoutExpression = parseLayoutExpression(text);
|
|
6
|
+
const layoutExpression = parseLayoutExpression(text, parseExpression);
|
|
15
7
|
if (layoutExpression) {
|
|
16
8
|
return layoutExpression;
|
|
17
9
|
}
|
|
18
|
-
const tokens = tokenizeExpression(text);
|
|
10
|
+
const tokens = tokenizeExpression(text, parseExpression);
|
|
19
11
|
if (!tokens) {
|
|
20
12
|
return undefined;
|
|
21
13
|
}
|
|
22
|
-
|
|
23
|
-
let index = 0;
|
|
24
|
-
function parsePrimary() {
|
|
25
|
-
const token = tokenList[index];
|
|
26
|
-
if (!token) {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
if (token.kind === 'number') {
|
|
30
|
-
index += 1;
|
|
31
|
-
return { kind: 'number', value: token.value };
|
|
32
|
-
}
|
|
33
|
-
if (token.kind === 'expression') {
|
|
34
|
-
index += 1;
|
|
35
|
-
return token.expression;
|
|
36
|
-
}
|
|
37
|
-
if (token.kind === 'symbol') {
|
|
38
|
-
const next = tokenList[index + 1];
|
|
39
|
-
if (token.text === 'sizeof' && next?.kind === 'left-paren') {
|
|
40
|
-
index += 2;
|
|
41
|
-
const typeName = tokenList[index];
|
|
42
|
-
if (typeName?.kind !== 'symbol' || tokenList[index + 1]?.kind !== 'right-paren') {
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
index += 2;
|
|
46
|
-
return { kind: 'sizeof', typeExpr: { name: typeName.text } };
|
|
47
|
-
}
|
|
48
|
-
if (token.text === 'offset' && next?.kind === 'left-paren') {
|
|
49
|
-
index += 2;
|
|
50
|
-
const typeName = tokenList[index];
|
|
51
|
-
const comma = tokenList[index + 1];
|
|
52
|
-
const fieldName = tokenList[index + 2];
|
|
53
|
-
const rightParen = tokenList[index + 3];
|
|
54
|
-
if (typeName?.kind !== 'symbol' ||
|
|
55
|
-
comma?.kind !== 'comma' ||
|
|
56
|
-
fieldName?.kind !== 'symbol' ||
|
|
57
|
-
rightParen?.kind !== 'right-paren') {
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
index += 4;
|
|
61
|
-
return {
|
|
62
|
-
kind: 'offset',
|
|
63
|
-
typeExpr: { name: typeName.text },
|
|
64
|
-
path: [{ kind: 'field', name: fieldName.text }],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
index += 1;
|
|
68
|
-
return { kind: 'symbol', name: token.text };
|
|
69
|
-
}
|
|
70
|
-
if (token.kind === 'current-location') {
|
|
71
|
-
index += 1;
|
|
72
|
-
return { kind: 'current-location' };
|
|
73
|
-
}
|
|
74
|
-
if (token.kind === 'operator' && isUnaryOperator(token.text)) {
|
|
75
|
-
index += 1;
|
|
76
|
-
const expression = parsePrimary();
|
|
77
|
-
return expression ? { kind: 'unary', operator: token.text, expression } : undefined;
|
|
78
|
-
}
|
|
79
|
-
if (token.kind === 'left-paren') {
|
|
80
|
-
index += 1;
|
|
81
|
-
const expression = parseBinary(1);
|
|
82
|
-
if (!expression || tokenList[index]?.kind !== 'right-paren') {
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
85
|
-
index += 1;
|
|
86
|
-
return expression;
|
|
87
|
-
}
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
function parseBinary(minPrecedence) {
|
|
91
|
-
let left = parsePrimary();
|
|
92
|
-
if (!left) {
|
|
93
|
-
return undefined;
|
|
94
|
-
}
|
|
95
|
-
while (true) {
|
|
96
|
-
const token = tokenList[index];
|
|
97
|
-
if (!token || token.kind !== 'operator' || !isBinaryOperator(token.text)) {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
const precedence = PRECEDENCE.get(token.text) ?? 0;
|
|
101
|
-
if (precedence < minPrecedence) {
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
index += 1;
|
|
105
|
-
const right = parseBinary(precedence + 1);
|
|
106
|
-
if (!right) {
|
|
107
|
-
return undefined;
|
|
108
|
-
}
|
|
109
|
-
left = { kind: 'binary', operator: token.text, left, right };
|
|
110
|
-
}
|
|
111
|
-
return left;
|
|
112
|
-
}
|
|
113
|
-
const expression = parseBinary(1);
|
|
114
|
-
return expression && index === tokenList.length ? expression : undefined;
|
|
115
|
-
}
|
|
116
|
-
export function parseTypeExpr(text) {
|
|
117
|
-
const trimmed = text.trim();
|
|
118
|
-
const match = /^([A-Za-z_][A-Za-z0-9_]*)(?:\[\s*([0-9]+)\s*\])?$/.exec(trimmed);
|
|
119
|
-
if (!match) {
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
const name = match[1] ?? '';
|
|
123
|
-
const lengthText = match[2];
|
|
124
|
-
if (lengthText === undefined) {
|
|
125
|
-
return { name };
|
|
126
|
-
}
|
|
127
|
-
const length = Number.parseInt(lengthText, 10);
|
|
128
|
-
return length >= 0 ? { name, length } : undefined;
|
|
129
|
-
}
|
|
130
|
-
function parseLayoutExpression(text) {
|
|
131
|
-
const trimmed = text.trim();
|
|
132
|
-
const layoutCast = parseLayoutCast(trimmed);
|
|
133
|
-
if (layoutCast) {
|
|
134
|
-
return layoutCast;
|
|
135
|
-
}
|
|
136
|
-
const sizeof = /^sizeof\s*\((.*)\)$/.exec(trimmed);
|
|
137
|
-
if (sizeof) {
|
|
138
|
-
const typeExpr = parseTypeExpr(sizeof[1] ?? '');
|
|
139
|
-
return typeExpr ? { kind: 'sizeof', typeExpr } : undefined;
|
|
140
|
-
}
|
|
141
|
-
const offset = /^offset\s*\((.*),(.*)\)$/.exec(trimmed);
|
|
142
|
-
if (offset) {
|
|
143
|
-
const typeExpr = parseTypeExpr(offset[1] ?? '');
|
|
144
|
-
const path = parseOffsetPath(offset[2] ?? '');
|
|
145
|
-
return typeExpr && path ? { kind: 'offset', typeExpr, path } : undefined;
|
|
146
|
-
}
|
|
147
|
-
return undefined;
|
|
148
|
-
}
|
|
149
|
-
function parseLayoutCast(text) {
|
|
150
|
-
if (!text.startsWith('<')) {
|
|
151
|
-
return undefined;
|
|
152
|
-
}
|
|
153
|
-
const close = text.indexOf('>');
|
|
154
|
-
if (close <= 1) {
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
const typeExpr = parseTypeExpr(text.slice(1, close));
|
|
158
|
-
if (!typeExpr) {
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
const rest = text.slice(close + 1);
|
|
162
|
-
const base = /^(?:[A-Za-z_$][A-Za-z0-9_$?]*|\?[A-Za-z0-9_$?]+)/.exec(rest);
|
|
163
|
-
if (!base) {
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
const path = parseLayoutCastPath(rest.slice(base[0].length));
|
|
167
|
-
if (!path) {
|
|
168
|
-
return undefined;
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
kind: 'layout-cast',
|
|
172
|
-
typeExpr,
|
|
173
|
-
base: { kind: 'symbol', name: base[0] },
|
|
174
|
-
path,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function parseLayoutCastPath(text) {
|
|
178
|
-
const parts = [];
|
|
179
|
-
let rest = text.trim();
|
|
180
|
-
while (rest.length > 0) {
|
|
181
|
-
if (rest.startsWith('.')) {
|
|
182
|
-
const field = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(rest);
|
|
183
|
-
if (!field) {
|
|
184
|
-
return undefined;
|
|
185
|
-
}
|
|
186
|
-
parts.push({ kind: 'field', name: field[1] ?? '' });
|
|
187
|
-
rest = rest.slice(field[0].length).trim();
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
if (rest.startsWith('[')) {
|
|
191
|
-
const close = findMatchingBracket(rest);
|
|
192
|
-
if (close === undefined) {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
195
|
-
const expression = parseExpression(rest.slice(1, close));
|
|
196
|
-
if (!expression) {
|
|
197
|
-
return undefined;
|
|
198
|
-
}
|
|
199
|
-
parts.push({ kind: 'index', expression });
|
|
200
|
-
rest = rest.slice(close + 1).trim();
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
return undefined;
|
|
204
|
-
}
|
|
205
|
-
return parts.length > 0 ? parts : undefined;
|
|
206
|
-
}
|
|
207
|
-
function findMatchingBracket(text) {
|
|
208
|
-
let depth = 0;
|
|
209
|
-
let quote;
|
|
210
|
-
let escaped = false;
|
|
211
|
-
for (let index = 0; index < text.length; index += 1) {
|
|
212
|
-
const char = text[index];
|
|
213
|
-
if (quote) {
|
|
214
|
-
if (escaped) {
|
|
215
|
-
escaped = false;
|
|
216
|
-
}
|
|
217
|
-
else if (char === '\\') {
|
|
218
|
-
escaped = true;
|
|
219
|
-
}
|
|
220
|
-
else if (char === quote) {
|
|
221
|
-
quote = undefined;
|
|
222
|
-
}
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
if (char === '"' || char === "'") {
|
|
226
|
-
quote = char;
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
if (char === '[') {
|
|
230
|
-
depth += 1;
|
|
231
|
-
}
|
|
232
|
-
else if (char === ']') {
|
|
233
|
-
depth -= 1;
|
|
234
|
-
if (depth === 0) {
|
|
235
|
-
return index;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return undefined;
|
|
240
|
-
}
|
|
241
|
-
function parseOffsetPath(text) {
|
|
242
|
-
const trimmed = text.trim();
|
|
243
|
-
if (trimmed.length === 0) {
|
|
244
|
-
return undefined;
|
|
245
|
-
}
|
|
246
|
-
const parts = [];
|
|
247
|
-
let rest = trimmed;
|
|
248
|
-
while (rest.length > 0) {
|
|
249
|
-
if (rest.startsWith('[')) {
|
|
250
|
-
const index = /^\[\s*([0-9]+)\s*\]/.exec(rest);
|
|
251
|
-
if (!index) {
|
|
252
|
-
return undefined;
|
|
253
|
-
}
|
|
254
|
-
parts.push({ kind: 'index', index: Number.parseInt(index[1] ?? '', 10) });
|
|
255
|
-
rest = rest.slice(index[0].length);
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
const field = /^[A-Za-z_][A-Za-z0-9_]*/.exec(rest);
|
|
259
|
-
if (!field) {
|
|
260
|
-
return undefined;
|
|
261
|
-
}
|
|
262
|
-
parts.push({ kind: 'field', name: field[0] });
|
|
263
|
-
rest = rest.slice(field[0].length);
|
|
264
|
-
}
|
|
265
|
-
if (rest.length === 0) {
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
if (!rest.startsWith('.')) {
|
|
269
|
-
return undefined;
|
|
270
|
-
}
|
|
271
|
-
rest = rest.slice(1);
|
|
272
|
-
}
|
|
273
|
-
return parts.length > 0 ? parts : undefined;
|
|
274
|
-
}
|
|
275
|
-
function tokenizeExpression(text) {
|
|
276
|
-
const tokens = [];
|
|
277
|
-
const input = text.trim();
|
|
278
|
-
let index = 0;
|
|
279
|
-
while (index < input.length) {
|
|
280
|
-
const char = input[index] ?? '';
|
|
281
|
-
if (/\s/.test(char)) {
|
|
282
|
-
index += 1;
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
if (char === '(') {
|
|
286
|
-
tokens.push({ kind: 'left-paren' });
|
|
287
|
-
index += 1;
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
if (char === ')') {
|
|
291
|
-
tokens.push({ kind: 'right-paren' });
|
|
292
|
-
index += 1;
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
if (char === ',') {
|
|
296
|
-
tokens.push({ kind: 'comma' });
|
|
297
|
-
index += 1;
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
const two = input.slice(index, index + 2);
|
|
301
|
-
if (two === '<<' || two === '>>') {
|
|
302
|
-
tokens.push({ kind: 'operator', text: two });
|
|
303
|
-
index += 2;
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
if (char === '$') {
|
|
307
|
-
const prefixedHex = /^\$[0-9A-Fa-f]+/.exec(input.slice(index));
|
|
308
|
-
if (prefixedHex) {
|
|
309
|
-
tokens.push({ kind: 'number', value: Number.parseInt(prefixedHex[0].slice(1), 16) });
|
|
310
|
-
index += prefixedHex[0].length;
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
if (/^[A-Za-z_]/.test(input[index + 1] ?? '')) {
|
|
314
|
-
return undefined;
|
|
315
|
-
}
|
|
316
|
-
tokens.push({ kind: 'current-location' });
|
|
317
|
-
index += 1;
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
if (char === '"' || char === "'") {
|
|
321
|
-
const quoted = scanQuotedByte(input, index, char);
|
|
322
|
-
if (!quoted) {
|
|
323
|
-
return undefined;
|
|
324
|
-
}
|
|
325
|
-
tokens.push({ kind: 'number', value: quoted.value });
|
|
326
|
-
index = quoted.end;
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
const layoutTerm = scanSpecialTerm(input, index);
|
|
330
|
-
if (layoutTerm) {
|
|
331
|
-
tokens.push({ kind: 'expression', expression: layoutTerm.expression });
|
|
332
|
-
index = layoutTerm.end;
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
const number = scanNumber(input.slice(index));
|
|
336
|
-
if (number) {
|
|
337
|
-
tokens.push({ kind: 'number', value: number.value });
|
|
338
|
-
index += number.length;
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
if (isOperatorChar(char)) {
|
|
342
|
-
tokens.push({ kind: 'operator', text: char });
|
|
343
|
-
index += 1;
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
const symbol = /^(?:[A-Za-z_.][A-Za-z0-9_.?]*|\?[A-Za-z0-9_.?]+)/.exec(input.slice(index));
|
|
347
|
-
if (symbol) {
|
|
348
|
-
tokens.push({ kind: 'symbol', text: symbol[0] });
|
|
349
|
-
index += symbol[0].length;
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
return undefined;
|
|
353
|
-
}
|
|
354
|
-
return tokens.length > 0 ? tokens : undefined;
|
|
355
|
-
}
|
|
356
|
-
function scanSpecialTerm(input, start) {
|
|
357
|
-
const byteFunction = scanByteFunction(input, start);
|
|
358
|
-
if (byteFunction) {
|
|
359
|
-
return byteFunction;
|
|
360
|
-
}
|
|
361
|
-
return scanLayoutTerm(input, start);
|
|
362
|
-
}
|
|
363
|
-
function scanByteFunction(input, start) {
|
|
364
|
-
const head = /^(LSB|MSB)\s*\(/.exec(input.slice(start));
|
|
365
|
-
if (!head) {
|
|
366
|
-
return undefined;
|
|
367
|
-
}
|
|
368
|
-
const name = head[1];
|
|
369
|
-
const open = input.indexOf('(', start + name.length);
|
|
370
|
-
if (open === -1 || input.slice(start + name.length, open).trim().length > 0) {
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
|
-
const close = findMatchingParen(input, open);
|
|
374
|
-
if (close === undefined) {
|
|
375
|
-
return undefined;
|
|
376
|
-
}
|
|
377
|
-
const expression = parseExpression(input.slice(open + 1, close));
|
|
378
|
-
return expression
|
|
379
|
-
? { expression: { kind: 'byte-function', function: name, expression }, end: close + 1 }
|
|
380
|
-
: undefined;
|
|
381
|
-
}
|
|
382
|
-
function scanLayoutTerm(input, start) {
|
|
383
|
-
if (input.slice(start).startsWith('sizeof')) {
|
|
384
|
-
const open = input.indexOf('(', start + 'sizeof'.length);
|
|
385
|
-
if (open === -1 || input.slice(start + 'sizeof'.length, open).trim().length > 0) {
|
|
386
|
-
return undefined;
|
|
387
|
-
}
|
|
388
|
-
const close = findMatchingParen(input, open);
|
|
389
|
-
if (close === undefined) {
|
|
390
|
-
return undefined;
|
|
391
|
-
}
|
|
392
|
-
const expression = parseLayoutExpression(input.slice(start, close + 1));
|
|
393
|
-
return expression ? { expression, end: close + 1 } : undefined;
|
|
394
|
-
}
|
|
395
|
-
if (input.slice(start).startsWith('offset')) {
|
|
396
|
-
const open = input.indexOf('(', start + 'offset'.length);
|
|
397
|
-
if (open === -1 || input.slice(start + 'offset'.length, open).trim().length > 0) {
|
|
398
|
-
return undefined;
|
|
399
|
-
}
|
|
400
|
-
const close = findMatchingParen(input, open);
|
|
401
|
-
if (close === undefined) {
|
|
402
|
-
return undefined;
|
|
403
|
-
}
|
|
404
|
-
const expression = parseLayoutExpression(input.slice(start, close + 1));
|
|
405
|
-
return expression ? { expression, end: close + 1 } : undefined;
|
|
406
|
-
}
|
|
407
|
-
if ((input[start] ?? '') !== '<') {
|
|
408
|
-
return undefined;
|
|
409
|
-
}
|
|
410
|
-
const end = scanLayoutCastEnd(input, start);
|
|
411
|
-
if (end === undefined) {
|
|
412
|
-
return undefined;
|
|
413
|
-
}
|
|
414
|
-
const expression = parseLayoutExpression(input.slice(start, end));
|
|
415
|
-
return expression ? { expression, end } : undefined;
|
|
416
|
-
}
|
|
417
|
-
function findMatchingParen(text, open) {
|
|
418
|
-
let depth = 0;
|
|
419
|
-
let quote;
|
|
420
|
-
for (let index = open; index < text.length; index += 1) {
|
|
421
|
-
const char = text[index];
|
|
422
|
-
if (quote) {
|
|
423
|
-
if (char === quote) {
|
|
424
|
-
quote = undefined;
|
|
425
|
-
}
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
if (char === '"' || char === "'") {
|
|
429
|
-
quote = char;
|
|
430
|
-
continue;
|
|
431
|
-
}
|
|
432
|
-
if (char === '(') {
|
|
433
|
-
depth += 1;
|
|
434
|
-
}
|
|
435
|
-
else if (char === ')') {
|
|
436
|
-
depth -= 1;
|
|
437
|
-
if (depth === 0) {
|
|
438
|
-
return index;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return undefined;
|
|
443
|
-
}
|
|
444
|
-
function scanLayoutCastEnd(input, start) {
|
|
445
|
-
const closeType = input.indexOf('>', start + 1);
|
|
446
|
-
if (closeType === -1) {
|
|
447
|
-
return undefined;
|
|
448
|
-
}
|
|
449
|
-
let index = closeType + 1;
|
|
450
|
-
const base = /^(?:[A-Za-z_$][A-Za-z0-9_$?]*|\?[A-Za-z0-9_$?]+)/.exec(input.slice(index));
|
|
451
|
-
if (!base) {
|
|
452
|
-
return undefined;
|
|
453
|
-
}
|
|
454
|
-
index += base[0].length;
|
|
455
|
-
let sawPath = false;
|
|
456
|
-
while (index < input.length) {
|
|
457
|
-
const char = input[index];
|
|
458
|
-
if (char === '.') {
|
|
459
|
-
const field = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(input.slice(index));
|
|
460
|
-
if (!field) {
|
|
461
|
-
return undefined;
|
|
462
|
-
}
|
|
463
|
-
sawPath = true;
|
|
464
|
-
index += field[0].length;
|
|
465
|
-
continue;
|
|
466
|
-
}
|
|
467
|
-
if (char === '[') {
|
|
468
|
-
const close = findMatchingBracket(input.slice(index));
|
|
469
|
-
if (close === undefined) {
|
|
470
|
-
return undefined;
|
|
471
|
-
}
|
|
472
|
-
sawPath = true;
|
|
473
|
-
index += close + 1;
|
|
474
|
-
continue;
|
|
475
|
-
}
|
|
476
|
-
break;
|
|
477
|
-
}
|
|
478
|
-
return sawPath ? index : undefined;
|
|
479
|
-
}
|
|
480
|
-
function scanNumber(text) {
|
|
481
|
-
const trailingHex = /^[0-9][0-9A-Fa-f]*[Hh]\b/.exec(text);
|
|
482
|
-
if (trailingHex) {
|
|
483
|
-
return {
|
|
484
|
-
value: Number.parseInt(trailingHex[0].slice(0, -1), 16),
|
|
485
|
-
length: trailingHex[0].length,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
const trailingBinary = /^[01]+[Bb]\b/.exec(text);
|
|
489
|
-
if (trailingBinary) {
|
|
490
|
-
return {
|
|
491
|
-
value: Number.parseInt(trailingBinary[0].slice(0, -1), 2),
|
|
492
|
-
length: trailingBinary[0].length,
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
const percentBinary = /^%[01]+/.exec(text);
|
|
496
|
-
if (percentBinary) {
|
|
497
|
-
return {
|
|
498
|
-
value: Number.parseInt(percentBinary[0].slice(1), 2),
|
|
499
|
-
length: percentBinary[0].length,
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
const prefixedBinary = /^0b[01]+/i.exec(text);
|
|
503
|
-
if (prefixedBinary) {
|
|
504
|
-
return {
|
|
505
|
-
value: Number.parseInt(prefixedBinary[0].slice(2), 2),
|
|
506
|
-
length: prefixedBinary[0].length,
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
const prefixedHex = /^0x[0-9A-Fa-f]+/i.exec(text);
|
|
510
|
-
if (prefixedHex) {
|
|
511
|
-
return { value: Number.parseInt(prefixedHex[0].slice(2), 16), length: prefixedHex[0].length };
|
|
512
|
-
}
|
|
513
|
-
const decimal = /^[0-9]+/.exec(text);
|
|
514
|
-
if (decimal) {
|
|
515
|
-
return { value: Number.parseInt(decimal[0], 10), length: decimal[0].length };
|
|
516
|
-
}
|
|
517
|
-
return undefined;
|
|
518
|
-
}
|
|
519
|
-
function scanQuotedByte(text, start, quote) {
|
|
520
|
-
const valueIndex = start + 1;
|
|
521
|
-
const value = text[valueIndex];
|
|
522
|
-
if (value === undefined || value === quote || value === '\n' || value === '\r') {
|
|
523
|
-
return undefined;
|
|
524
|
-
}
|
|
525
|
-
let byte;
|
|
526
|
-
let end;
|
|
527
|
-
if (value === '\\') {
|
|
528
|
-
const escaped = text[valueIndex + 1];
|
|
529
|
-
if (escaped === undefined) {
|
|
530
|
-
return undefined;
|
|
531
|
-
}
|
|
532
|
-
const escapeValue = escapeByteValue(escaped);
|
|
533
|
-
if (escapeValue === undefined) {
|
|
534
|
-
return undefined;
|
|
535
|
-
}
|
|
536
|
-
byte = escapeValue;
|
|
537
|
-
end = valueIndex + 2;
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
byte = value.codePointAt(0) ?? 0;
|
|
541
|
-
end = valueIndex + (byte > 0xffff ? 2 : 1);
|
|
542
|
-
}
|
|
543
|
-
if (text[end] !== quote) {
|
|
544
|
-
return undefined;
|
|
545
|
-
}
|
|
546
|
-
return { value: byte, end: end + 1 };
|
|
547
|
-
}
|
|
548
|
-
function escapeByteValue(char) {
|
|
549
|
-
switch (char) {
|
|
550
|
-
case '0':
|
|
551
|
-
return 0;
|
|
552
|
-
case 'n':
|
|
553
|
-
return 10;
|
|
554
|
-
case 'r':
|
|
555
|
-
return 13;
|
|
556
|
-
case 't':
|
|
557
|
-
return 9;
|
|
558
|
-
case "'":
|
|
559
|
-
return 39;
|
|
560
|
-
case '"':
|
|
561
|
-
return 34;
|
|
562
|
-
case '\\':
|
|
563
|
-
return 92;
|
|
564
|
-
default:
|
|
565
|
-
return undefined;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
function isOperatorChar(char) {
|
|
569
|
-
return ['*', '/', '%', '+', '-', '&', '^', '|', '~'].includes(char);
|
|
570
|
-
}
|
|
571
|
-
function isUnaryOperator(operator) {
|
|
572
|
-
return operator === '+' || operator === '-' || operator === '~';
|
|
573
|
-
}
|
|
574
|
-
function isBinaryOperator(operator) {
|
|
575
|
-
return PRECEDENCE.has(operator);
|
|
14
|
+
return parseTokenExpression(tokens);
|
|
576
15
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
+
import type { SourceItem } from '../model/source-item.js';
|
|
3
|
+
import type { LogicalLine } from '../source/logical-lines.js';
|
|
4
|
+
export interface LayoutDeclarationParseResult {
|
|
5
|
+
readonly consumedUntilIndex: number;
|
|
6
|
+
readonly item?: SourceItem;
|
|
7
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
8
|
+
}
|
|
9
|
+
export declare function parseLayoutDeclarationAt(lines: readonly LogicalLine[], index: number): LayoutDeclarationParseResult | undefined;
|