@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
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { stripLineComment } from '../source/strip-line-comment.js';
|
|
2
|
+
import { parseTypeExpr } from './parse-expression.js';
|
|
3
|
+
export function parseLayoutDeclarationAt(lines, index) {
|
|
4
|
+
const line = lines[index];
|
|
5
|
+
if (line === undefined)
|
|
6
|
+
return undefined;
|
|
7
|
+
const text = stripLineComment(line.text).trim();
|
|
8
|
+
const typeAlias = parseTypeAlias(line, text);
|
|
9
|
+
if (typeAlias !== undefined) {
|
|
10
|
+
return { consumedUntilIndex: index, ...typeAlias };
|
|
11
|
+
}
|
|
12
|
+
const prefixLayoutHeader = /^\.(type|union)\s+([A-Za-z_][A-Za-z0-9_]*)\s*$/.exec(text);
|
|
13
|
+
if (prefixLayoutHeader) {
|
|
14
|
+
const directive = prefixLayoutHeader[1] ?? 'type';
|
|
15
|
+
return {
|
|
16
|
+
consumedUntilIndex: skipToLayoutEnd(lines, index, directive),
|
|
17
|
+
diagnostics: [
|
|
18
|
+
parseDiagnostic(line, `Use "${prefixLayoutHeader[2] ?? ''} .${directive}" for layouts.`),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const layoutHeader = parseNameLeftLayoutHeader(text);
|
|
23
|
+
if (layoutHeader === undefined) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
return parseLayoutBlock(lines, index, layoutHeader);
|
|
27
|
+
}
|
|
28
|
+
function parseTypeAlias(line, text) {
|
|
29
|
+
const nameLeftTypeAlias = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.typealias\s+(.+)$/.exec(text);
|
|
30
|
+
if (nameLeftTypeAlias) {
|
|
31
|
+
const typeExprText = nameLeftTypeAlias[2] ?? '';
|
|
32
|
+
const typeExpr = parseTypeExpr(typeExprText);
|
|
33
|
+
if (!typeExpr) {
|
|
34
|
+
return { diagnostics: [parseDiagnostic(line, `invalid .typealias target: ${typeExprText}`)] };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
item: {
|
|
38
|
+
kind: 'type-alias',
|
|
39
|
+
name: nameLeftTypeAlias[1] ?? '',
|
|
40
|
+
typeExpr,
|
|
41
|
+
span: spanForLine(line),
|
|
42
|
+
},
|
|
43
|
+
diagnostics: [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const oldTypeAlias = /^\.type\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$/.exec(text);
|
|
47
|
+
if (oldTypeAlias) {
|
|
48
|
+
return {
|
|
49
|
+
diagnostics: [
|
|
50
|
+
parseDiagnostic(line, `Use "${oldTypeAlias[1] ?? ''} .typealias ..." for type aliases.`),
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function parseNameLeftLayoutHeader(text) {
|
|
57
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.(type|union)\s*$/.exec(text);
|
|
58
|
+
return match
|
|
59
|
+
? {
|
|
60
|
+
directive: match[2] ?? '',
|
|
61
|
+
name: match[1] ?? '',
|
|
62
|
+
}
|
|
63
|
+
: undefined;
|
|
64
|
+
}
|
|
65
|
+
function parseLayoutBlock(lines, index, header) {
|
|
66
|
+
const line = lines[index];
|
|
67
|
+
const layoutKind = header.directive === 'union' ? 'union' : 'record';
|
|
68
|
+
const endDirective = layoutKind === 'union' ? '.endunion' : '.endtype';
|
|
69
|
+
const fields = [];
|
|
70
|
+
const diagnostics = [];
|
|
71
|
+
let consumedUntilIndex = index;
|
|
72
|
+
let terminated = false;
|
|
73
|
+
for (let fieldIndex = index + 1; fieldIndex < lines.length; fieldIndex += 1) {
|
|
74
|
+
consumedUntilIndex = fieldIndex;
|
|
75
|
+
const fieldLine = lines[fieldIndex];
|
|
76
|
+
const fieldText = stripLineComment(fieldLine.text).trim();
|
|
77
|
+
if (fieldText.length === 0) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (fieldText === endDirective) {
|
|
81
|
+
terminated = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
const field = parseLayoutField(fieldText);
|
|
85
|
+
if (!field) {
|
|
86
|
+
diagnostics.push(parseDiagnostic(fieldLine, `invalid .${header.directive} field declaration`));
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
fields.push(field);
|
|
90
|
+
}
|
|
91
|
+
if (!terminated) {
|
|
92
|
+
diagnostics.push(parseDiagnostic(line, `.${header.directive} ${header.name} missing ${endDirective}`));
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
consumedUntilIndex,
|
|
96
|
+
diagnostics,
|
|
97
|
+
item: {
|
|
98
|
+
kind: 'type',
|
|
99
|
+
name: header.name,
|
|
100
|
+
layoutKind,
|
|
101
|
+
fields,
|
|
102
|
+
span: spanForLine(line),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function spanForLine(line) {
|
|
107
|
+
return {
|
|
108
|
+
sourceName: line.sourceName,
|
|
109
|
+
line: line.line,
|
|
110
|
+
column: firstColumn(line.text),
|
|
111
|
+
...(line.sourceUnit !== undefined ? { sourceUnit: line.sourceUnit } : {}),
|
|
112
|
+
...(line.sourceRelation !== undefined ? { sourceRelation: line.sourceRelation } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function skipToLayoutEnd(lines, index, directive) {
|
|
116
|
+
const endDirective = directive === 'union' ? '.endunion' : '.endtype';
|
|
117
|
+
for (let next = index + 1; next < lines.length; next += 1) {
|
|
118
|
+
if (stripLineComment(lines[next].text).trim() === endDirective) {
|
|
119
|
+
return next;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return index;
|
|
123
|
+
}
|
|
124
|
+
function parseLayoutField(text) {
|
|
125
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)\s+(\.(?:field|byte|word|addr))(?:\s+(.+))?$/.exec(text);
|
|
126
|
+
if (!match) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
const name = match[1] ?? '';
|
|
130
|
+
const directive = (match[2] ?? '').toLowerCase();
|
|
131
|
+
const operand = match[3]?.trim();
|
|
132
|
+
return directive === '.field'
|
|
133
|
+
? parseNamedField(name, operand)
|
|
134
|
+
: parseScalarDirectiveField(name, directive, operand);
|
|
135
|
+
}
|
|
136
|
+
function parseNamedField(name, operand) {
|
|
137
|
+
return operand === undefined ? undefined : parseFieldOperand(name, operand);
|
|
138
|
+
}
|
|
139
|
+
function parseScalarDirectiveField(name, directive, operand) {
|
|
140
|
+
if (operand !== undefined) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
const size = scalarDirectiveSize(directive);
|
|
144
|
+
return size === undefined ? undefined : { name, size };
|
|
145
|
+
}
|
|
146
|
+
function scalarDirectiveSize(directive) {
|
|
147
|
+
if (directive === '.byte')
|
|
148
|
+
return 1;
|
|
149
|
+
if (directive === '.word' || directive === '.addr')
|
|
150
|
+
return 2;
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
function parseFieldOperand(name, operand) {
|
|
154
|
+
const size = /^[0-9]+$/.test(operand) ? Number.parseInt(operand, 10) : undefined;
|
|
155
|
+
if (size !== undefined) {
|
|
156
|
+
return size > 0 ? { name, size } : undefined;
|
|
157
|
+
}
|
|
158
|
+
const scalar = scalarFieldSize(operand);
|
|
159
|
+
if (scalar !== undefined) {
|
|
160
|
+
return { name, size: scalar };
|
|
161
|
+
}
|
|
162
|
+
const typeExpr = parseTypeExpr(operand);
|
|
163
|
+
return typeExpr ? { name, size: 0, typeExpr } : undefined;
|
|
164
|
+
}
|
|
165
|
+
function scalarFieldSize(typeName) {
|
|
166
|
+
switch (typeName.toLowerCase()) {
|
|
167
|
+
case 'byte':
|
|
168
|
+
return 1;
|
|
169
|
+
case 'word':
|
|
170
|
+
case 'addr':
|
|
171
|
+
return 2;
|
|
172
|
+
default:
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function parseDiagnostic(line, message) {
|
|
177
|
+
return {
|
|
178
|
+
severity: 'error',
|
|
179
|
+
code: 'AZMN_PARSE',
|
|
180
|
+
message,
|
|
181
|
+
sourceName: line.sourceName,
|
|
182
|
+
line: line.line,
|
|
183
|
+
column: firstColumn(line.text),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function firstColumn(text) {
|
|
187
|
+
const match = /\S/.exec(text);
|
|
188
|
+
return match ? match.index + 1 : 1;
|
|
189
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Expression, TypeExpr } from '../model/expression.js';
|
|
2
|
+
export type ParseNestedExpression = (text: string) => Expression | undefined;
|
|
3
|
+
export declare function parseTypeExpr(text: string): TypeExpr | undefined;
|
|
4
|
+
export declare function parseLayoutExpression(text: string, parseNestedExpression: ParseNestedExpression): Expression | undefined;
|
|
5
|
+
export declare function findMatchingBracket(text: string): number | undefined;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
export function parseTypeExpr(text) {
|
|
2
|
+
const trimmed = text.trim();
|
|
3
|
+
const match = /^([A-Za-z_][A-Za-z0-9_]*)(?:\[\s*([0-9]+)\s*\])?$/.exec(trimmed);
|
|
4
|
+
if (!match) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const name = match[1] ?? '';
|
|
8
|
+
const lengthText = match[2];
|
|
9
|
+
if (lengthText === undefined) {
|
|
10
|
+
return { name };
|
|
11
|
+
}
|
|
12
|
+
const length = Number.parseInt(lengthText, 10);
|
|
13
|
+
return length >= 0 ? { name, length } : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function parseLayoutExpression(text, parseNestedExpression) {
|
|
16
|
+
const trimmed = text.trim();
|
|
17
|
+
const layoutCast = parseLayoutCast(trimmed, parseNestedExpression);
|
|
18
|
+
if (layoutCast) {
|
|
19
|
+
return layoutCast;
|
|
20
|
+
}
|
|
21
|
+
const sizeof = /^sizeof\s*\((.*)\)$/.exec(trimmed);
|
|
22
|
+
if (sizeof) {
|
|
23
|
+
const typeExpr = parseTypeExpr(sizeof[1] ?? '');
|
|
24
|
+
return typeExpr ? { kind: 'sizeof', typeExpr } : undefined;
|
|
25
|
+
}
|
|
26
|
+
const offset = /^offset\s*\((.*),(.*)\)$/.exec(trimmed);
|
|
27
|
+
if (offset) {
|
|
28
|
+
const typeExpr = parseTypeExpr(offset[1] ?? '');
|
|
29
|
+
const path = parseOffsetPath(offset[2] ?? '');
|
|
30
|
+
return typeExpr && path ? { kind: 'offset', typeExpr, path } : undefined;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
export function findMatchingBracket(text) {
|
|
35
|
+
let state = { depth: 0, quote: undefined, escaped: false };
|
|
36
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
37
|
+
const char = text[index] ?? '';
|
|
38
|
+
if (state.quote !== undefined) {
|
|
39
|
+
state = scanQuotedBracketChar(char, state);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const quotedState = startBracketQuote(char, state);
|
|
43
|
+
if (quotedState) {
|
|
44
|
+
state = quotedState;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
state = scanBracketDepth(char, state);
|
|
48
|
+
if (char === ']') {
|
|
49
|
+
if (state.depth === 0) {
|
|
50
|
+
return index;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function scanQuotedBracketChar(char, state) {
|
|
57
|
+
if (state.escaped)
|
|
58
|
+
return { ...state, escaped: false };
|
|
59
|
+
if (char === '\\')
|
|
60
|
+
return { ...state, escaped: true };
|
|
61
|
+
if (char === state.quote)
|
|
62
|
+
return { ...state, quote: undefined };
|
|
63
|
+
return state;
|
|
64
|
+
}
|
|
65
|
+
function startBracketQuote(char, state) {
|
|
66
|
+
return char === '"' || char === "'" ? { ...state, quote: char } : undefined;
|
|
67
|
+
}
|
|
68
|
+
function scanBracketDepth(char, state) {
|
|
69
|
+
if (char === '[')
|
|
70
|
+
return { ...state, depth: state.depth + 1 };
|
|
71
|
+
if (char === ']')
|
|
72
|
+
return { ...state, depth: state.depth - 1 };
|
|
73
|
+
return state;
|
|
74
|
+
}
|
|
75
|
+
function parseLayoutCast(text, parseNestedExpression) {
|
|
76
|
+
if (!text.startsWith('<')) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
const close = text.indexOf('>');
|
|
80
|
+
if (close <= 1) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const typeExpr = parseTypeExpr(text.slice(1, close));
|
|
84
|
+
if (!typeExpr) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const rest = text.slice(close + 1);
|
|
88
|
+
const base = /^(?:[A-Za-z_$][A-Za-z0-9_$?]*|\?[A-Za-z0-9_$?]+)/.exec(rest);
|
|
89
|
+
if (!base) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
const path = parseLayoutCastPath(rest.slice(base[0].length), parseNestedExpression);
|
|
93
|
+
if (!path) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
kind: 'layout-cast',
|
|
98
|
+
typeExpr,
|
|
99
|
+
base: { kind: 'symbol', name: base[0] },
|
|
100
|
+
path,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function parseLayoutCastPath(text, parseNestedExpression) {
|
|
104
|
+
const parts = [];
|
|
105
|
+
let rest = text.trim();
|
|
106
|
+
while (rest.length > 0) {
|
|
107
|
+
const parsed = parseLayoutCastPathPart(rest, parseNestedExpression);
|
|
108
|
+
if (!parsed)
|
|
109
|
+
return undefined;
|
|
110
|
+
parts.push(parsed.part);
|
|
111
|
+
rest = parsed.rest.trim();
|
|
112
|
+
}
|
|
113
|
+
return parts.length > 0 ? parts : undefined;
|
|
114
|
+
}
|
|
115
|
+
function parseLayoutCastPathPart(text, parseNestedExpression) {
|
|
116
|
+
return text.startsWith('.')
|
|
117
|
+
? parseLayoutCastField(text)
|
|
118
|
+
: parseLayoutCastIndex(text, parseNestedExpression);
|
|
119
|
+
}
|
|
120
|
+
function parseLayoutCastField(text) {
|
|
121
|
+
const field = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(text);
|
|
122
|
+
return field ? { part: { kind: 'field', name: field[1] ?? '' }, rest: text.slice(field[0].length) } : undefined;
|
|
123
|
+
}
|
|
124
|
+
function parseLayoutCastIndex(text, parseNestedExpression) {
|
|
125
|
+
if (!text.startsWith('['))
|
|
126
|
+
return undefined;
|
|
127
|
+
const close = findMatchingBracket(text);
|
|
128
|
+
if (close === undefined)
|
|
129
|
+
return undefined;
|
|
130
|
+
const expression = parseNestedExpression(text.slice(1, close));
|
|
131
|
+
return expression
|
|
132
|
+
? { part: { kind: 'index', expression }, rest: text.slice(close + 1) }
|
|
133
|
+
: undefined;
|
|
134
|
+
}
|
|
135
|
+
function parseOffsetPath(text) {
|
|
136
|
+
const trimmed = text.trim();
|
|
137
|
+
if (trimmed.length === 0) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
const parts = [];
|
|
141
|
+
let rest = trimmed;
|
|
142
|
+
while (rest.length > 0) {
|
|
143
|
+
const parsed = parseOffsetPathPart(rest);
|
|
144
|
+
if (!parsed)
|
|
145
|
+
return undefined;
|
|
146
|
+
parts.push(parsed.part);
|
|
147
|
+
rest = parsed.rest;
|
|
148
|
+
if (rest.length === 0) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (!rest.startsWith('.')) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
rest = rest.slice(1);
|
|
155
|
+
}
|
|
156
|
+
return parts.length > 0 ? parts : undefined;
|
|
157
|
+
}
|
|
158
|
+
function parseOffsetPathPart(text) {
|
|
159
|
+
return text.startsWith('[') ? parseOffsetIndex(text) : parseOffsetField(text);
|
|
160
|
+
}
|
|
161
|
+
function parseOffsetIndex(text) {
|
|
162
|
+
const index = /^\[\s*([0-9]+)\s*\]/.exec(text);
|
|
163
|
+
return index
|
|
164
|
+
? {
|
|
165
|
+
part: { kind: 'index', index: Number.parseInt(index[1] ?? '', 10) },
|
|
166
|
+
rest: text.slice(index[0].length),
|
|
167
|
+
}
|
|
168
|
+
: undefined;
|
|
169
|
+
}
|
|
170
|
+
function parseOffsetField(text) {
|
|
171
|
+
const field = /^[A-Za-z_][A-Za-z0-9_]*/.exec(text);
|
|
172
|
+
return field
|
|
173
|
+
? { part: { kind: 'field', name: field[0] }, rest: text.slice(field[0].length) }
|
|
174
|
+
: undefined;
|
|
175
|
+
}
|