@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,7 +1,9 @@
|
|
|
1
1
|
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
-
import type { Expression
|
|
3
|
-
import type { LayoutField } from '../model/source-item.js';
|
|
2
|
+
import type { Expression } from '../model/expression.js';
|
|
4
3
|
import type { SourceSpan } from '../source/source-span.js';
|
|
4
|
+
import { type LayoutRecord } from './layout-evaluation.js';
|
|
5
|
+
export { diagnostic } from './diagnostics.js';
|
|
6
|
+
export { validateLayouts, type LayoutRecord } from './layout-evaluation.js';
|
|
5
7
|
export interface EquateRecord {
|
|
6
8
|
readonly expression: Expression;
|
|
7
9
|
readonly span: SourceSpan;
|
|
@@ -9,25 +11,15 @@ export interface EquateRecord {
|
|
|
9
11
|
readonly enumMember?: boolean;
|
|
10
12
|
readonly stringValue?: string;
|
|
11
13
|
}
|
|
12
|
-
export
|
|
13
|
-
readonly
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
readonly typeExpr: TypeExpr;
|
|
19
|
-
readonly span: SourceSpan;
|
|
20
|
-
};
|
|
14
|
+
export interface EvaluateExpressionOptions {
|
|
15
|
+
readonly currentLocation: number;
|
|
16
|
+
readonly layouts?: ReadonlyMap<string, LayoutRecord> | undefined;
|
|
17
|
+
readonly visiting?: ReadonlySet<string>;
|
|
18
|
+
readonly reportUnknown?: boolean;
|
|
19
|
+
}
|
|
21
20
|
export declare function lookupEquateRecord(equates: ReadonlyMap<string, EquateRecord>, name: string): {
|
|
22
21
|
readonly key: string;
|
|
23
22
|
readonly record: EquateRecord;
|
|
24
23
|
} | undefined;
|
|
25
24
|
export declare function lookupSymbolValue(symbols: Readonly<Record<string, number>>, name: string): number | undefined;
|
|
26
|
-
export declare function evaluateExpression(expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options:
|
|
27
|
-
readonly currentLocation: number;
|
|
28
|
-
readonly layouts?: ReadonlyMap<string, LayoutRecord> | undefined;
|
|
29
|
-
readonly visiting?: ReadonlySet<string>;
|
|
30
|
-
readonly reportUnknown?: boolean;
|
|
31
|
-
}): number | undefined;
|
|
32
|
-
export declare function diagnostic(span: SourceSpan, message: string): Diagnostic;
|
|
33
|
-
export declare function validateLayouts(layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): void;
|
|
25
|
+
export declare function evaluateExpression(expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions): number | undefined;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { applyBinaryOperator, applyByteFunction, applyUnaryOperator, } from './constant-operators.js';
|
|
2
|
+
import { diagnostic } from './diagnostics.js';
|
|
3
|
+
import { evaluateLayoutCast, evaluateOffset, evaluateSizeof, typeExprSize, } from './layout-evaluation.js';
|
|
4
|
+
import { formatTypeExpr, scalarSize } from './layout-format.js';
|
|
5
|
+
export { diagnostic } from './diagnostics.js';
|
|
6
|
+
export { validateLayouts } from './layout-evaluation.js';
|
|
1
7
|
function canonicalSymbolKey(name) {
|
|
2
8
|
return name.toLowerCase();
|
|
3
9
|
}
|
|
@@ -44,7 +50,7 @@ export function evaluateExpression(expression, labels, equates, span, diagnostic
|
|
|
44
50
|
case 'offset':
|
|
45
51
|
return evaluateOffset(expression.typeExpr, expression.path, options.layouts, span, diagnostics);
|
|
46
52
|
case 'layout-cast':
|
|
47
|
-
return evaluateLayoutCast(expression, labels, equates, span, diagnostics, options);
|
|
53
|
+
return evaluateLayoutCast(expression, labels, equates, span, diagnostics, options, evaluateExpression);
|
|
48
54
|
case 'symbol':
|
|
49
55
|
return evaluateSymbol(expression.name, labels, equates, span, diagnostics, options);
|
|
50
56
|
case 'unary':
|
|
@@ -58,7 +64,7 @@ function evaluateByteFunction(expression, labels, equates, span, diagnostics, op
|
|
|
58
64
|
if (value === undefined) {
|
|
59
65
|
return undefined;
|
|
60
66
|
}
|
|
61
|
-
return expression.function
|
|
67
|
+
return applyByteFunction(expression.function, value);
|
|
62
68
|
}
|
|
63
69
|
function evaluateTypeSize(typeExpr, labels, equates, span, diagnostics, options) {
|
|
64
70
|
if (options.layouts) {
|
|
@@ -78,33 +84,6 @@ function evaluateTypeSize(typeExpr, labels, equates, span, diagnostics, options)
|
|
|
78
84
|
}
|
|
79
85
|
return evaluateSymbol(typeExpr.name, labels, equates, span, diagnostics, options);
|
|
80
86
|
}
|
|
81
|
-
function evaluateLayoutCast(expression, labels, equates, span, diagnostics, options) {
|
|
82
|
-
const base = evaluateExpression(expression.base, labels, equates, span, diagnostics, options);
|
|
83
|
-
if (base === undefined) {
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
if (!options.layouts) {
|
|
87
|
-
diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(expression.typeExpr)}`));
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
const offset = layoutCastOffset(expression.typeExpr, expression.path, labels, equates, options.layouts, span, diagnostics, options);
|
|
91
|
-
return offset === undefined ? undefined : base + offset;
|
|
92
|
-
}
|
|
93
|
-
export function diagnostic(span, message) {
|
|
94
|
-
return {
|
|
95
|
-
severity: 'error',
|
|
96
|
-
code: 'AZMN_SYMBOL',
|
|
97
|
-
message,
|
|
98
|
-
sourceName: span.sourceName,
|
|
99
|
-
line: span.line,
|
|
100
|
-
column: span.column,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function validateLayouts(layouts, diagnostics) {
|
|
104
|
-
for (const [name, layout] of layouts) {
|
|
105
|
-
layoutSize(name, layout, layouts, layout.span, diagnostics, new Set([name]));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
87
|
function evaluateSymbol(name, labels, equates, span, diagnostics, options) {
|
|
109
88
|
const label = lookupLabelValue(labels, name);
|
|
110
89
|
if (label !== undefined) {
|
|
@@ -132,275 +111,6 @@ function evaluateSymbol(name, labels, equates, span, diagnostics, options) {
|
|
|
132
111
|
}
|
|
133
112
|
return undefined;
|
|
134
113
|
}
|
|
135
|
-
function evaluateSizeof(typeExpr, layouts, span, diagnostics) {
|
|
136
|
-
if (!layouts) {
|
|
137
|
-
diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(typeExpr)}`));
|
|
138
|
-
return undefined;
|
|
139
|
-
}
|
|
140
|
-
return typeExprSize(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
141
|
-
}
|
|
142
|
-
function evaluateOffset(typeExpr, path, layouts, span, diagnostics) {
|
|
143
|
-
if (!layouts) {
|
|
144
|
-
diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(typeExpr)}`));
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
|
-
const diagnosticCount = diagnostics.length;
|
|
148
|
-
const offset = offsetPath(typeExpr, path, layouts, span, diagnostics);
|
|
149
|
-
if (offset !== undefined) {
|
|
150
|
-
return offset;
|
|
151
|
-
}
|
|
152
|
-
if (diagnostics.length === diagnosticCount) {
|
|
153
|
-
diagnostics.push(diagnostic(span, `unknown field "${formatOffsetPath(path)}" in type ${formatTypeExpr(typeExpr)}`));
|
|
154
|
-
}
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
function typeExprSize(typeExpr, layouts, span, diagnostics, visiting) {
|
|
158
|
-
const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, visiting);
|
|
159
|
-
if (!resolvedTypeExpr) {
|
|
160
|
-
return undefined;
|
|
161
|
-
}
|
|
162
|
-
if (resolvedTypeExpr !== typeExpr) {
|
|
163
|
-
return typeExprSize(resolvedTypeExpr, layouts, span, diagnostics, visiting);
|
|
164
|
-
}
|
|
165
|
-
const scalar = scalarSize(typeExpr.name);
|
|
166
|
-
const baseSize = scalar ??
|
|
167
|
-
(() => {
|
|
168
|
-
const layout = layouts.get(typeExpr.name);
|
|
169
|
-
if (!layout) {
|
|
170
|
-
diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
|
|
171
|
-
return undefined;
|
|
172
|
-
}
|
|
173
|
-
return layoutSize(typeExpr.name, layout, layouts, span, diagnostics, visiting);
|
|
174
|
-
})();
|
|
175
|
-
if (baseSize === undefined) {
|
|
176
|
-
return undefined;
|
|
177
|
-
}
|
|
178
|
-
return typeExpr.length === undefined ? baseSize : baseSize * typeExpr.length;
|
|
179
|
-
}
|
|
180
|
-
function layoutSize(typeName, layout, layouts, span, diagnostics, visiting) {
|
|
181
|
-
if (layout.kind === 'alias') {
|
|
182
|
-
return typeExprSize(layout.typeExpr, layouts, span, diagnostics, visiting);
|
|
183
|
-
}
|
|
184
|
-
const fieldSizes = [];
|
|
185
|
-
for (const field of layout.fields) {
|
|
186
|
-
const size = fieldSize(field, layouts, span, diagnostics, visiting);
|
|
187
|
-
if (size === undefined) {
|
|
188
|
-
return undefined;
|
|
189
|
-
}
|
|
190
|
-
fieldSizes.push(size);
|
|
191
|
-
}
|
|
192
|
-
return layout.kind === 'union'
|
|
193
|
-
? fieldSizes.reduce((largest, size) => Math.max(largest, size), 0)
|
|
194
|
-
: fieldSizes.reduce((sum, size) => sum + size, 0);
|
|
195
|
-
}
|
|
196
|
-
function fieldSize(field, layouts, span, diagnostics, visiting) {
|
|
197
|
-
if (field.typeExpr === undefined) {
|
|
198
|
-
return field.size;
|
|
199
|
-
}
|
|
200
|
-
if (visiting.has(field.typeExpr.name)) {
|
|
201
|
-
diagnostics.push(diagnostic(span, visiting.size === 1
|
|
202
|
-
? `Self-referential field type "${field.typeExpr.name}" has no finite size; use .addr for a pointer field.`
|
|
203
|
-
: `recursive type: ${field.typeExpr.name}`));
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
206
|
-
return typeExprSize(field.typeExpr, layouts, span, diagnostics, new Set([...visiting, field.typeExpr.name]));
|
|
207
|
-
}
|
|
208
|
-
function offsetPath(typeExpr, parts, layouts, span, diagnostics) {
|
|
209
|
-
const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
210
|
-
if (!resolvedTypeExpr) {
|
|
211
|
-
return undefined;
|
|
212
|
-
}
|
|
213
|
-
if (resolvedTypeExpr !== typeExpr) {
|
|
214
|
-
return offsetPath(resolvedTypeExpr, parts, layouts, span, diagnostics);
|
|
215
|
-
}
|
|
216
|
-
const [head, ...tail] = parts;
|
|
217
|
-
if (head === undefined) {
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
if (head.kind === 'index') {
|
|
221
|
-
if (typeExpr.length === undefined) {
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
if (head.index >= typeExpr.length) {
|
|
225
|
-
diagnostics.push(diagnostic(span, `array index ${head.index} out of range for ${formatTypeExpr(typeExpr)}`));
|
|
226
|
-
return undefined;
|
|
227
|
-
}
|
|
228
|
-
const elementTypeExpr = { name: typeExpr.name };
|
|
229
|
-
const stride = typeExprSize(elementTypeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
230
|
-
if (stride === undefined) {
|
|
231
|
-
return undefined;
|
|
232
|
-
}
|
|
233
|
-
if (tail.length === 0) {
|
|
234
|
-
return head.index * stride;
|
|
235
|
-
}
|
|
236
|
-
const nestedOffset = offsetPath(elementTypeExpr, tail, layouts, span, diagnostics);
|
|
237
|
-
return nestedOffset === undefined ? undefined : head.index * stride + nestedOffset;
|
|
238
|
-
}
|
|
239
|
-
if (typeExpr.length !== undefined) {
|
|
240
|
-
return undefined;
|
|
241
|
-
}
|
|
242
|
-
const layout = layouts.get(typeExpr.name);
|
|
243
|
-
if (!layout) {
|
|
244
|
-
diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
|
|
245
|
-
return undefined;
|
|
246
|
-
}
|
|
247
|
-
if (layout.kind === 'alias') {
|
|
248
|
-
return offsetPath(layout.typeExpr, parts, layouts, span, diagnostics);
|
|
249
|
-
}
|
|
250
|
-
let currentOffset = 0;
|
|
251
|
-
for (const field of layout.fields) {
|
|
252
|
-
const fieldOffset = layout.kind === 'union' ? 0 : currentOffset;
|
|
253
|
-
if (field.name === head.name) {
|
|
254
|
-
if (field.typeExpr !== undefined) {
|
|
255
|
-
const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
256
|
-
if (size === undefined) {
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
if (tail.length === 0) {
|
|
261
|
-
return fieldOffset;
|
|
262
|
-
}
|
|
263
|
-
if (field.typeExpr === undefined) {
|
|
264
|
-
return undefined;
|
|
265
|
-
}
|
|
266
|
-
const nestedOffset = offsetPath(field.typeExpr, tail, layouts, span, diagnostics);
|
|
267
|
-
return nestedOffset === undefined ? undefined : fieldOffset + nestedOffset;
|
|
268
|
-
}
|
|
269
|
-
const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
270
|
-
if (size === undefined) {
|
|
271
|
-
return undefined;
|
|
272
|
-
}
|
|
273
|
-
currentOffset += size;
|
|
274
|
-
}
|
|
275
|
-
return undefined;
|
|
276
|
-
}
|
|
277
|
-
function layoutCastOffset(typeExpr, parts, labels, equates, layouts, span, diagnostics, options) {
|
|
278
|
-
const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
279
|
-
if (!resolvedTypeExpr) {
|
|
280
|
-
return undefined;
|
|
281
|
-
}
|
|
282
|
-
if (resolvedTypeExpr !== typeExpr) {
|
|
283
|
-
return layoutCastOffset(resolvedTypeExpr, parts, labels, equates, layouts, span, diagnostics, options);
|
|
284
|
-
}
|
|
285
|
-
const [head, ...tail] = parts;
|
|
286
|
-
if (head === undefined) {
|
|
287
|
-
return 0;
|
|
288
|
-
}
|
|
289
|
-
if (head.kind === 'index') {
|
|
290
|
-
if (typeExpr.length === undefined) {
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
const registerName = registerIndexName(head.expression);
|
|
294
|
-
if (registerName) {
|
|
295
|
-
diagnostics.push(diagnostic(span, `runtime register index "${registerName}" is not supported in layout casts`));
|
|
296
|
-
return undefined;
|
|
297
|
-
}
|
|
298
|
-
const index = evaluateExpression(head.expression, labels, equates, span, diagnostics, {
|
|
299
|
-
...options,
|
|
300
|
-
layouts,
|
|
301
|
-
});
|
|
302
|
-
if (index === undefined) {
|
|
303
|
-
return undefined;
|
|
304
|
-
}
|
|
305
|
-
if (index < 0 || index >= typeExpr.length) {
|
|
306
|
-
diagnostics.push(diagnostic(span, `array index ${index} out of range for ${formatTypeExpr(typeExpr)}`));
|
|
307
|
-
return undefined;
|
|
308
|
-
}
|
|
309
|
-
const elementTypeExpr = { name: typeExpr.name };
|
|
310
|
-
const stride = typeExprSize(elementTypeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
311
|
-
if (stride === undefined) {
|
|
312
|
-
return undefined;
|
|
313
|
-
}
|
|
314
|
-
const nestedOffset = layoutCastOffset(elementTypeExpr, tail, labels, equates, layouts, span, diagnostics, options);
|
|
315
|
-
return nestedOffset === undefined ? undefined : index * stride + nestedOffset;
|
|
316
|
-
}
|
|
317
|
-
if (typeExpr.length !== undefined) {
|
|
318
|
-
return undefined;
|
|
319
|
-
}
|
|
320
|
-
const layout = layouts.get(typeExpr.name);
|
|
321
|
-
if (!layout) {
|
|
322
|
-
diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
|
|
323
|
-
return undefined;
|
|
324
|
-
}
|
|
325
|
-
if (layout.kind === 'alias') {
|
|
326
|
-
return layoutCastOffset(layout.typeExpr, parts, labels, equates, layouts, span, diagnostics, options);
|
|
327
|
-
}
|
|
328
|
-
let currentOffset = 0;
|
|
329
|
-
for (const field of layout.fields) {
|
|
330
|
-
const fieldOffset = layout.kind === 'union' ? 0 : currentOffset;
|
|
331
|
-
if (field.name === head.name) {
|
|
332
|
-
if (field.typeExpr !== undefined) {
|
|
333
|
-
const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
334
|
-
if (size === undefined) {
|
|
335
|
-
return undefined;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
if (tail.length === 0) {
|
|
339
|
-
return fieldOffset;
|
|
340
|
-
}
|
|
341
|
-
if (field.typeExpr === undefined) {
|
|
342
|
-
return undefined;
|
|
343
|
-
}
|
|
344
|
-
const nestedOffset = layoutCastOffset(field.typeExpr, tail, labels, equates, layouts, span, diagnostics, options);
|
|
345
|
-
return nestedOffset === undefined ? undefined : fieldOffset + nestedOffset;
|
|
346
|
-
}
|
|
347
|
-
const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
|
|
348
|
-
if (size === undefined) {
|
|
349
|
-
return undefined;
|
|
350
|
-
}
|
|
351
|
-
currentOffset += size;
|
|
352
|
-
}
|
|
353
|
-
return undefined;
|
|
354
|
-
}
|
|
355
|
-
function registerIndexName(expression) {
|
|
356
|
-
switch (expression.kind) {
|
|
357
|
-
case 'symbol':
|
|
358
|
-
return /^(a|b|c|d|e|h|l|af|bc|de|hl|ix|iy|sp|i|r|ixh|ixl|iyh|iyl)$/i.test(expression.name)
|
|
359
|
-
? expression.name.toUpperCase()
|
|
360
|
-
: undefined;
|
|
361
|
-
case 'unary':
|
|
362
|
-
return registerIndexName(expression.expression);
|
|
363
|
-
case 'binary':
|
|
364
|
-
return registerIndexName(expression.left) ?? registerIndexName(expression.right);
|
|
365
|
-
default:
|
|
366
|
-
return undefined;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
function formatTypeExpr(typeExpr) {
|
|
370
|
-
return typeExpr.length === undefined ? typeExpr.name : `${typeExpr.name}[${typeExpr.length}]`;
|
|
371
|
-
}
|
|
372
|
-
function resolveLayoutAlias(typeExpr, layouts, span, diagnostics, visiting) {
|
|
373
|
-
const layout = layouts.get(typeExpr.name);
|
|
374
|
-
if (!layout || layout.kind !== 'alias') {
|
|
375
|
-
return typeExpr;
|
|
376
|
-
}
|
|
377
|
-
if (visiting.has(layout.typeExpr.name)) {
|
|
378
|
-
diagnostics.push(diagnostic(span, `recursive type: ${typeExpr.name}`));
|
|
379
|
-
return undefined;
|
|
380
|
-
}
|
|
381
|
-
const target = resolveLayoutAlias(layout.typeExpr, layouts, span, diagnostics, new Set([...visiting, layout.typeExpr.name]));
|
|
382
|
-
if (!target) {
|
|
383
|
-
return undefined;
|
|
384
|
-
}
|
|
385
|
-
const length = typeExpr.length === undefined
|
|
386
|
-
? target.length
|
|
387
|
-
: (target.length ?? 1) * typeExpr.length;
|
|
388
|
-
return length === undefined ? { name: target.name } : { name: target.name, length };
|
|
389
|
-
}
|
|
390
|
-
function formatOffsetPath(path) {
|
|
391
|
-
return path.map((part) => (part.kind === 'field' ? part.name : `[${part.index}]`)).join('.');
|
|
392
|
-
}
|
|
393
|
-
function scalarSize(typeName) {
|
|
394
|
-
switch (typeName.toLowerCase()) {
|
|
395
|
-
case 'byte':
|
|
396
|
-
return 1;
|
|
397
|
-
case 'word':
|
|
398
|
-
case 'addr':
|
|
399
|
-
return 2;
|
|
400
|
-
default:
|
|
401
|
-
return undefined;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
114
|
function hasUnqualifiedEnumMember(name, equates) {
|
|
405
115
|
if (name.includes('.')) {
|
|
406
116
|
return false;
|
|
@@ -418,14 +128,18 @@ function evaluateUnary(expression, labels, equates, span, diagnostics, options)
|
|
|
418
128
|
if (value === undefined) {
|
|
419
129
|
return undefined;
|
|
420
130
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return ~value;
|
|
131
|
+
return applyUnaryOperator(expression.operator, value);
|
|
132
|
+
}
|
|
133
|
+
function reportInvalidBinaryExpression(operator, right, span, diagnostics) {
|
|
134
|
+
if (operator === '/' && right === 0) {
|
|
135
|
+
diagnostics.push(diagnostic(span, 'Divide by zero in imm expression.'));
|
|
136
|
+
return true;
|
|
428
137
|
}
|
|
138
|
+
if (operator === '%' && right === 0) {
|
|
139
|
+
diagnostics.push(diagnostic(span, 'modulo by zero in expression'));
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
429
143
|
}
|
|
430
144
|
function evaluateBinary(expression, labels, equates, span, diagnostics, options) {
|
|
431
145
|
const left = evaluateExpression(expression.left, labels, equates, span, diagnostics, options);
|
|
@@ -433,34 +147,8 @@ function evaluateBinary(expression, labels, equates, span, diagnostics, options)
|
|
|
433
147
|
if (left === undefined || right === undefined) {
|
|
434
148
|
return undefined;
|
|
435
149
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return left * right;
|
|
439
|
-
case '/':
|
|
440
|
-
if (right === 0) {
|
|
441
|
-
diagnostics.push(diagnostic(span, 'Divide by zero in imm expression.'));
|
|
442
|
-
return undefined;
|
|
443
|
-
}
|
|
444
|
-
return Math.trunc(left / right);
|
|
445
|
-
case '%':
|
|
446
|
-
if (right === 0) {
|
|
447
|
-
diagnostics.push(diagnostic(span, 'modulo by zero in expression'));
|
|
448
|
-
return undefined;
|
|
449
|
-
}
|
|
450
|
-
return left % right;
|
|
451
|
-
case '+':
|
|
452
|
-
return left + right;
|
|
453
|
-
case '-':
|
|
454
|
-
return left - right;
|
|
455
|
-
case '&':
|
|
456
|
-
return left & right;
|
|
457
|
-
case '^':
|
|
458
|
-
return left ^ right;
|
|
459
|
-
case '|':
|
|
460
|
-
return left | right;
|
|
461
|
-
case '<<':
|
|
462
|
-
return left << right;
|
|
463
|
-
case '>>':
|
|
464
|
-
return left >> right;
|
|
150
|
+
if (reportInvalidBinaryExpression(expression.operator, right, span, diagnostics)) {
|
|
151
|
+
return undefined;
|
|
465
152
|
}
|
|
153
|
+
return applyBinaryOperator(expression.operator, left, right);
|
|
466
154
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
+
import type { Expression, OffsetPathPart, TypeExpr } from '../model/expression.js';
|
|
3
|
+
import type { LayoutField } from '../model/source-item.js';
|
|
4
|
+
import type { SourceSpan } from '../source/source-span.js';
|
|
5
|
+
import type { EquateRecord, EvaluateExpressionOptions } from './expression-evaluation.js';
|
|
6
|
+
export type LayoutRecord = {
|
|
7
|
+
readonly kind: 'record' | 'union';
|
|
8
|
+
readonly fields: readonly LayoutField[];
|
|
9
|
+
readonly span: SourceSpan;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'alias';
|
|
12
|
+
readonly typeExpr: TypeExpr;
|
|
13
|
+
readonly span: SourceSpan;
|
|
14
|
+
};
|
|
15
|
+
type EvaluateNestedExpression = (expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions) => number | undefined;
|
|
16
|
+
export declare function evaluateSizeof(typeExpr: TypeExpr, layouts: ReadonlyMap<string, LayoutRecord> | undefined, span: SourceSpan, diagnostics: Diagnostic[]): number | undefined;
|
|
17
|
+
export declare function evaluateOffset(typeExpr: TypeExpr, path: readonly OffsetPathPart[], layouts: ReadonlyMap<string, LayoutRecord> | undefined, span: SourceSpan, diagnostics: Diagnostic[]): number | undefined;
|
|
18
|
+
export declare function evaluateLayoutCast(expression: Extract<Expression, {
|
|
19
|
+
readonly kind: 'layout-cast';
|
|
20
|
+
}>, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions, evaluateExpression: EvaluateNestedExpression): number | undefined;
|
|
21
|
+
export declare function validateLayouts(layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): void;
|
|
22
|
+
export declare function typeExprSize(typeExpr: TypeExpr, layouts: ReadonlyMap<string, LayoutRecord>, span: SourceSpan, diagnostics: Diagnostic[], visiting: Set<string>): number | undefined;
|
|
23
|
+
export {};
|