@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
package/dist/src/core/compile.js
CHANGED
|
@@ -4,10 +4,9 @@ import { createSourceFile } from '../source/source-file.js';
|
|
|
4
4
|
import { scanLogicalLines } from '../source/logical-lines.js';
|
|
5
5
|
import { stripLineComment } from '../source/strip-line-comment.js';
|
|
6
6
|
import { parseLogicalLine } from '../syntax/parse-line.js';
|
|
7
|
-
import {
|
|
8
|
-
import { collectOps, expandOpInvocation, parseOpInvocation } from '../expansion/op-expansion.js';
|
|
9
|
-
import {
|
|
10
|
-
import { evaluateExpression, lookupEquateRecord, } from '../semantics/expression-evaluation.js';
|
|
7
|
+
import { parseLayoutDeclarationAt } from '../syntax/parse-layout-declarations.js';
|
|
8
|
+
import { collectOps, expandOpInvocation, parseOpInvocation, } from '../expansion/op-expansion.js';
|
|
9
|
+
import { applyConditionalAssembly } from './conditional-assembly.js';
|
|
11
10
|
export function parseNextSourceItems(lines, options = {}) {
|
|
12
11
|
const diagnostics = [];
|
|
13
12
|
const items = [];
|
|
@@ -17,233 +16,67 @@ export function parseNextSourceItems(lines, options = {}) {
|
|
|
17
16
|
const conditional = applyConditionalAssembly(lines, diagnostics, parseOptions.directiveAliasPolicy);
|
|
18
17
|
const pendingLines = [...conditional.lines];
|
|
19
18
|
const { ops, opLineIndexes } = collectOps(pendingLines, diagnostics, parseOptions);
|
|
19
|
+
const context = {
|
|
20
|
+
diagnostics,
|
|
21
|
+
items,
|
|
22
|
+
lines: pendingLines,
|
|
23
|
+
ops,
|
|
24
|
+
opLineIndexes,
|
|
25
|
+
parseOptions,
|
|
26
|
+
};
|
|
20
27
|
let afterTopLevelEnd = false;
|
|
21
28
|
for (let index = 0; index < pendingLines.length; index += 1) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const line = pendingLines[index];
|
|
26
|
-
if (afterTopLevelEnd && !isPostEndParseAllowed(line.text)) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
const nameLeftTypeAlias = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.typealias\s+(.+)$/.exec(stripLineComment(line.text).trim());
|
|
30
|
-
if (nameLeftTypeAlias) {
|
|
31
|
-
const typeExprText = nameLeftTypeAlias[2] ?? '';
|
|
32
|
-
const typeExpr = parseTypeExpr(typeExprText);
|
|
33
|
-
if (!typeExpr) {
|
|
34
|
-
diagnostics.push(parseDiagnostic(line, `invalid .typealias target: ${typeExprText}`));
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
items.push({
|
|
38
|
-
kind: 'type-alias',
|
|
39
|
-
name: nameLeftTypeAlias[1] ?? '',
|
|
40
|
-
typeExpr,
|
|
41
|
-
span: { sourceName: line.sourceName, line: line.line, column: firstColumn(line.text) },
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const typeAlias = /^\.type\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$/.exec(stripLineComment(line.text).trim());
|
|
47
|
-
if (typeAlias) {
|
|
48
|
-
diagnostics.push(parseDiagnostic(line, `Use "${typeAlias[1] ?? ''} .typealias ..." for type aliases.`));
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
const nameLeftLayoutHeader = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.(type|union)\s*$/.exec(stripLineComment(line.text).trim());
|
|
52
|
-
const prefixLayoutHeader = /^\.(type|union)\s+([A-Za-z_][A-Za-z0-9_]*)\s*$/.exec(stripLineComment(line.text).trim());
|
|
53
|
-
if (prefixLayoutHeader) {
|
|
54
|
-
const directive = prefixLayoutHeader[1] ?? 'type';
|
|
55
|
-
diagnostics.push(parseDiagnostic(line, `Use "${prefixLayoutHeader[2] ?? ''} .${directive}" for layouts.`));
|
|
56
|
-
const endDirective = directive === 'union' ? '.endunion' : '.endtype';
|
|
57
|
-
for (index += 1; index < pendingLines.length; index += 1) {
|
|
58
|
-
if (stripLineComment(pendingLines[index].text).trim() === endDirective) {
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
const layoutHeader = nameLeftLayoutHeader
|
|
65
|
-
? {
|
|
66
|
-
directive: nameLeftLayoutHeader[2] ?? '',
|
|
67
|
-
name: nameLeftLayoutHeader[1] ?? '',
|
|
68
|
-
}
|
|
69
|
-
: undefined;
|
|
70
|
-
if (layoutHeader) {
|
|
71
|
-
const layoutKind = layoutHeader.directive === 'union' ? 'union' : 'record';
|
|
72
|
-
const endDirective = layoutKind === 'union' ? '.endunion' : '.endtype';
|
|
73
|
-
const fields = [];
|
|
74
|
-
let terminated = false;
|
|
75
|
-
for (index += 1; index < pendingLines.length; index += 1) {
|
|
76
|
-
const fieldLine = pendingLines[index];
|
|
77
|
-
const fieldText = stripLineComment(fieldLine.text).trim();
|
|
78
|
-
if (fieldText.length === 0) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (fieldText === endDirective) {
|
|
82
|
-
terminated = true;
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
const field = parseLayoutField(fieldText);
|
|
86
|
-
if (!field) {
|
|
87
|
-
diagnostics.push(parseDiagnostic(fieldLine, `invalid .${layoutHeader.directive} field declaration`));
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
fields.push(field);
|
|
91
|
-
}
|
|
92
|
-
if (!terminated) {
|
|
93
|
-
diagnostics.push(parseDiagnostic(line, `.${layoutHeader.directive} ${layoutHeader.name} missing ${endDirective}`));
|
|
94
|
-
}
|
|
95
|
-
items.push({
|
|
96
|
-
kind: 'type',
|
|
97
|
-
name: layoutHeader.name,
|
|
98
|
-
layoutKind,
|
|
99
|
-
fields,
|
|
100
|
-
span: { sourceName: line.sourceName, line: line.line, column: firstColumn(line.text) },
|
|
101
|
-
});
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
const opCall = parseOpInvocation(line);
|
|
105
|
-
if (opCall && !isTopLevelEnd(line.text)) {
|
|
106
|
-
const overloads = ops.get(opCall.name);
|
|
107
|
-
if (overloads) {
|
|
108
|
-
const expanded = expandOpInvocation(ops, overloads, opCall.operands, line, diagnostics);
|
|
109
|
-
if (expanded) {
|
|
110
|
-
items.push(...expanded);
|
|
111
|
-
}
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
const result = parseLogicalLine(line, parseOptions);
|
|
116
|
-
diagnostics.push(...result.diagnostics);
|
|
117
|
-
items.push(...result.items);
|
|
118
|
-
if (result.items.some((item) => item.kind === 'end')) {
|
|
119
|
-
afterTopLevelEnd = true;
|
|
120
|
-
}
|
|
29
|
+
const step = parsePendingLine(context, index, afterTopLevelEnd);
|
|
30
|
+
index = step.consumedUntilIndex;
|
|
31
|
+
afterTopLevelEnd = step.afterTopLevelEnd;
|
|
121
32
|
}
|
|
122
33
|
return { diagnostics, items };
|
|
123
34
|
}
|
|
124
|
-
function
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const stack = [];
|
|
129
|
-
for (const line of lines) {
|
|
130
|
-
const text = stripLineComment(line.text).trim();
|
|
131
|
-
const ifDirective = /^\.if\s+(.+)$/.exec(text);
|
|
132
|
-
if (ifDirective) {
|
|
133
|
-
const parentActive = conditionalActive(stack);
|
|
134
|
-
const expressionText = ifDirective[1] ?? '';
|
|
135
|
-
const value = parentActive
|
|
136
|
-
? evaluateConditionalExpression(line, expressionText, equates, locationDependentEquates, diagnostics)
|
|
137
|
-
: undefined;
|
|
138
|
-
const conditionActive = parentActive && value !== undefined && value !== 0;
|
|
139
|
-
stack.push({ line, parentActive, conditionActive, elseSeen: false });
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (/^\.else\s*$/.test(text)) {
|
|
143
|
-
const frame = stack.pop();
|
|
144
|
-
if (!frame) {
|
|
145
|
-
diagnostics.push(parseDiagnostic(line, 'unmatched .else'));
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
if (frame.elseSeen) {
|
|
149
|
-
diagnostics.push(parseDiagnostic(line, 'duplicate .else'));
|
|
150
|
-
}
|
|
151
|
-
stack.push({
|
|
152
|
-
line: frame.line,
|
|
153
|
-
parentActive: frame.parentActive,
|
|
154
|
-
conditionActive: frame.parentActive && !frame.conditionActive,
|
|
155
|
-
elseSeen: true,
|
|
156
|
-
});
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (/^\.endif\s*$/.test(text)) {
|
|
160
|
-
if (!stack.pop()) {
|
|
161
|
-
diagnostics.push(parseDiagnostic(line, 'unmatched .endif'));
|
|
162
|
-
}
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
if (!conditionalActive(stack)) {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
out.push(line);
|
|
169
|
-
recordConditionalEquate(line, equates, locationDependentEquates, directiveAliasPolicy);
|
|
35
|
+
function parsePendingLine(context, index, afterTopLevelEnd) {
|
|
36
|
+
const line = context.lines[index];
|
|
37
|
+
if (shouldSkipPendingLine(context, index, line, afterTopLevelEnd)) {
|
|
38
|
+
return { consumedUntilIndex: index, afterTopLevelEnd };
|
|
170
39
|
}
|
|
171
|
-
|
|
172
|
-
|
|
40
|
+
const layoutStep = parseLayoutLine(context, index);
|
|
41
|
+
if (layoutStep)
|
|
42
|
+
return { ...layoutStep, afterTopLevelEnd };
|
|
43
|
+
if (parseExpandedOpLine(context, line)) {
|
|
44
|
+
return { consumedUntilIndex: index, afterTopLevelEnd };
|
|
173
45
|
}
|
|
174
|
-
return
|
|
46
|
+
return parseNormalLine(context, index, line, afterTopLevelEnd);
|
|
175
47
|
}
|
|
176
|
-
function
|
|
177
|
-
return
|
|
48
|
+
function shouldSkipPendingLine(context, index, line, afterTopLevelEnd) {
|
|
49
|
+
return context.opLineIndexes.has(index) || (afterTopLevelEnd && !isPostEndParseAllowed(line.text));
|
|
178
50
|
}
|
|
179
|
-
function
|
|
180
|
-
const
|
|
181
|
-
if (
|
|
182
|
-
diagnostics.push(parseDiagnostic(line, `invalid .if expression: ${expressionText}`));
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
if (expressionReferencesCurrentLocation(expression, equates, locationDependentEquates)) {
|
|
186
|
-
diagnostics.push(parseDiagnostic(line, 'invalid .if expression: current location is not available during conditional assembly'));
|
|
51
|
+
function parseLayoutLine(context, index) {
|
|
52
|
+
const layoutDeclaration = parseLayoutDeclarationAt(context.lines, index);
|
|
53
|
+
if (layoutDeclaration === undefined)
|
|
187
54
|
return undefined;
|
|
55
|
+
context.diagnostics.push(...layoutDeclaration.diagnostics);
|
|
56
|
+
if (layoutDeclaration.item !== undefined) {
|
|
57
|
+
context.items.push(layoutDeclaration.item);
|
|
188
58
|
}
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
function recordConditionalEquate(line, equates, locationDependentEquates, directiveAliasPolicy) {
|
|
192
|
-
const text = normalizeDirectiveAlias(stripLineComment(line.text), directiveAliasPolicy).trim();
|
|
193
|
-
const equ = /^([A-Za-z_.$?][A-Za-z0-9_.$?]*)(?::\s*|\s+)\.equ\s+(.+)$/.exec(text);
|
|
194
|
-
if (!equ) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const name = equ[1] ?? '';
|
|
198
|
-
const expressionText = equ[2] ?? '';
|
|
199
|
-
const expression = parseExpression(expressionText);
|
|
200
|
-
if (!expression) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (expressionReferencesCurrentLocation(expression, equates, locationDependentEquates)) {
|
|
204
|
-
locationDependentEquates.add(canonicalConditionalSymbolKey(name));
|
|
205
|
-
}
|
|
206
|
-
equates.set(name, {
|
|
207
|
-
expression,
|
|
208
|
-
span: { sourceName: line.sourceName, line: line.line, column: firstColumn(line.text) },
|
|
209
|
-
currentLocation: 0,
|
|
210
|
-
});
|
|
59
|
+
return { consumedUntilIndex: layoutDeclaration.consumedUntilIndex };
|
|
211
60
|
}
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
const nextVisiting = new Set(visiting);
|
|
225
|
-
nextVisiting.add(canonicalConditionalSymbolKey(lookup.key));
|
|
226
|
-
return expressionReferencesCurrentLocation(lookup.record.expression, equates, locationDependentEquates, nextVisiting);
|
|
227
|
-
}
|
|
228
|
-
case 'byte-function':
|
|
229
|
-
case 'unary':
|
|
230
|
-
return expressionReferencesCurrentLocation(expression.expression, equates, locationDependentEquates, visiting);
|
|
231
|
-
case 'binary':
|
|
232
|
-
return (expressionReferencesCurrentLocation(expression.left, equates, locationDependentEquates, visiting) ||
|
|
233
|
-
expressionReferencesCurrentLocation(expression.right, equates, locationDependentEquates, visiting));
|
|
234
|
-
case 'layout-cast':
|
|
235
|
-
return (expressionReferencesCurrentLocation(expression.base, equates, locationDependentEquates, visiting) ||
|
|
236
|
-
expression.path.some((part) => part.kind === 'index' &&
|
|
237
|
-
expressionReferencesCurrentLocation(part.expression, equates, locationDependentEquates, visiting)));
|
|
238
|
-
case 'number':
|
|
239
|
-
case 'type-size':
|
|
240
|
-
case 'sizeof':
|
|
241
|
-
case 'offset':
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
61
|
+
function parseExpandedOpLine(context, line) {
|
|
62
|
+
const opCall = parseOpInvocation(line);
|
|
63
|
+
if (!opCall || isTopLevelEnd(line.text))
|
|
64
|
+
return false;
|
|
65
|
+
const overloads = context.ops.get(opCall.name);
|
|
66
|
+
if (!overloads)
|
|
67
|
+
return false;
|
|
68
|
+
const expanded = expandOpInvocation(context.ops, overloads, opCall.operands, line, context.diagnostics);
|
|
69
|
+
context.items.push(...expanded);
|
|
70
|
+
return true;
|
|
244
71
|
}
|
|
245
|
-
function
|
|
246
|
-
|
|
72
|
+
function parseNormalLine(context, index, line, afterTopLevelEnd) {
|
|
73
|
+
const result = parseLogicalLine(line, context.parseOptions);
|
|
74
|
+
context.diagnostics.push(...result.diagnostics);
|
|
75
|
+
context.items.push(...result.items);
|
|
76
|
+
return {
|
|
77
|
+
consumedUntilIndex: index,
|
|
78
|
+
afterTopLevelEnd: afterTopLevelEnd || result.items.some((item) => item.kind === 'end'),
|
|
79
|
+
};
|
|
247
80
|
}
|
|
248
81
|
export function compileSource(sourceText, options = {}) {
|
|
249
82
|
const source = createSourceFile(options.entryName ?? '<memory>', sourceText);
|
|
@@ -273,59 +106,3 @@ function isTopLevelEnd(text) {
|
|
|
273
106
|
function isPostEndParseAllowed(text) {
|
|
274
107
|
return /^(?:\.binfrom|\.binto|binfrom|binto)\b/i.test(stripLineComment(text).trim());
|
|
275
108
|
}
|
|
276
|
-
function parseLayoutField(text) {
|
|
277
|
-
const match = /^([A-Za-z_][A-Za-z0-9_]*)\s+(\.(?:field|byte|word|addr))(?:\s+(.+))?$/.exec(text);
|
|
278
|
-
if (!match) {
|
|
279
|
-
return undefined;
|
|
280
|
-
}
|
|
281
|
-
const name = match[1] ?? '';
|
|
282
|
-
const directive = (match[2] ?? '').toLowerCase();
|
|
283
|
-
const operand = match[3]?.trim();
|
|
284
|
-
switch (directive) {
|
|
285
|
-
case '.byte':
|
|
286
|
-
return operand === undefined ? { name, size: 1 } : undefined;
|
|
287
|
-
case '.word':
|
|
288
|
-
case '.addr':
|
|
289
|
-
return operand === undefined ? { name, size: 2 } : undefined;
|
|
290
|
-
case '.field': {
|
|
291
|
-
if (operand === undefined) {
|
|
292
|
-
return undefined;
|
|
293
|
-
}
|
|
294
|
-
const size = /^[0-9]+$/.test(operand) ? Number.parseInt(operand, 10) : undefined;
|
|
295
|
-
if (size !== undefined) {
|
|
296
|
-
return size > 0 ? { name, size } : undefined;
|
|
297
|
-
}
|
|
298
|
-
const scalar = scalarFieldSize(operand);
|
|
299
|
-
if (scalar !== undefined) {
|
|
300
|
-
return { name, size: scalar };
|
|
301
|
-
}
|
|
302
|
-
const typeExpr = parseTypeExpr(operand);
|
|
303
|
-
return typeExpr ? { name, size: 0, typeExpr } : undefined;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function scalarFieldSize(typeName) {
|
|
308
|
-
switch (typeName.toLowerCase()) {
|
|
309
|
-
case 'byte':
|
|
310
|
-
return 1;
|
|
311
|
-
case 'word':
|
|
312
|
-
case 'addr':
|
|
313
|
-
return 2;
|
|
314
|
-
default:
|
|
315
|
-
return undefined;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
function parseDiagnostic(line, message) {
|
|
319
|
-
return {
|
|
320
|
-
severity: 'error',
|
|
321
|
-
code: 'AZMN_PARSE',
|
|
322
|
-
message,
|
|
323
|
-
sourceName: line.sourceName,
|
|
324
|
-
line: line.line,
|
|
325
|
-
column: firstColumn(line.text),
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
function firstColumn(text) {
|
|
329
|
-
const match = /\S/.exec(text);
|
|
330
|
-
return match ? match.index + 1 : 1;
|
|
331
|
-
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
+
import type { LogicalLine } from '../source/logical-lines.js';
|
|
3
|
+
import { type DirectiveAliasPolicy } from '../syntax/directive-aliases.js';
|
|
4
|
+
export declare function applyConditionalAssembly(lines: readonly LogicalLine[], diagnostics: Diagnostic[], directiveAliasPolicy: DirectiveAliasPolicy | undefined): {
|
|
5
|
+
readonly lines: readonly LogicalLine[];
|
|
6
|
+
};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { stripLineComment } from '../source/strip-line-comment.js';
|
|
2
|
+
import { normalizeDirectiveAlias } from '../syntax/directive-aliases.js';
|
|
3
|
+
import { parseExpression } from '../syntax/parse-expression.js';
|
|
4
|
+
import { evaluateExpression, lookupEquateRecord, } from '../semantics/expression-evaluation.js';
|
|
5
|
+
export function applyConditionalAssembly(lines, diagnostics, directiveAliasPolicy) {
|
|
6
|
+
const out = [];
|
|
7
|
+
const equates = new Map();
|
|
8
|
+
const locationDependentEquates = new Set();
|
|
9
|
+
const stack = [];
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
const directive = parseConditionalDirective(line);
|
|
12
|
+
if (applyConditionalDirective(directive, line, stack, equates, locationDependentEquates, diagnostics)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (!conditionalActive(stack)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
out.push(line);
|
|
19
|
+
recordConditionalEquate(line, equates, locationDependentEquates, directiveAliasPolicy);
|
|
20
|
+
}
|
|
21
|
+
for (const frame of stack) {
|
|
22
|
+
diagnostics.push(parseDiagnostic(frame.line, 'unterminated .if'));
|
|
23
|
+
}
|
|
24
|
+
return { lines: out };
|
|
25
|
+
}
|
|
26
|
+
function parseConditionalDirective(line) {
|
|
27
|
+
const text = stripLineComment(line.text).trim();
|
|
28
|
+
const ifDirective = /^\.if\s+(.+)$/.exec(text);
|
|
29
|
+
if (ifDirective)
|
|
30
|
+
return { kind: 'if', expressionText: ifDirective[1] ?? '' };
|
|
31
|
+
if (/^\.else\s*$/.test(text))
|
|
32
|
+
return { kind: 'else' };
|
|
33
|
+
if (/^\.endif\s*$/.test(text))
|
|
34
|
+
return { kind: 'endif' };
|
|
35
|
+
return { kind: 'none' };
|
|
36
|
+
}
|
|
37
|
+
function applyConditionalDirective(directive, line, stack, equates, locationDependentEquates, diagnostics) {
|
|
38
|
+
switch (directive.kind) {
|
|
39
|
+
case 'if':
|
|
40
|
+
pushConditionalFrame(line, directive.expressionText, stack, equates, locationDependentEquates, diagnostics);
|
|
41
|
+
return true;
|
|
42
|
+
case 'else':
|
|
43
|
+
flipConditionalFrame(line, stack, diagnostics);
|
|
44
|
+
return true;
|
|
45
|
+
case 'endif':
|
|
46
|
+
popConditionalFrame(line, stack, diagnostics);
|
|
47
|
+
return true;
|
|
48
|
+
case 'none':
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function pushConditionalFrame(line, expressionText, stack, equates, locationDependentEquates, diagnostics) {
|
|
53
|
+
const parentActive = conditionalActive(stack);
|
|
54
|
+
const value = parentActive
|
|
55
|
+
? evaluateConditionalExpression(line, expressionText, equates, locationDependentEquates, diagnostics)
|
|
56
|
+
: undefined;
|
|
57
|
+
stack.push({
|
|
58
|
+
line,
|
|
59
|
+
parentActive,
|
|
60
|
+
conditionActive: parentActive && value !== undefined && value !== 0,
|
|
61
|
+
elseSeen: false,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function flipConditionalFrame(line, stack, diagnostics) {
|
|
65
|
+
const frame = stack.pop();
|
|
66
|
+
if (!frame) {
|
|
67
|
+
diagnostics.push(parseDiagnostic(line, 'unmatched .else'));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (frame.elseSeen) {
|
|
71
|
+
diagnostics.push(parseDiagnostic(line, 'duplicate .else'));
|
|
72
|
+
}
|
|
73
|
+
stack.push({
|
|
74
|
+
line: frame.line,
|
|
75
|
+
parentActive: frame.parentActive,
|
|
76
|
+
conditionActive: frame.parentActive && !frame.conditionActive,
|
|
77
|
+
elseSeen: true,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function popConditionalFrame(line, stack, diagnostics) {
|
|
81
|
+
if (!stack.pop()) {
|
|
82
|
+
diagnostics.push(parseDiagnostic(line, 'unmatched .endif'));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function conditionalActive(stack) {
|
|
86
|
+
return stack.every((frame) => frame.parentActive && frame.conditionActive);
|
|
87
|
+
}
|
|
88
|
+
function evaluateConditionalExpression(line, expressionText, equates, locationDependentEquates, diagnostics) {
|
|
89
|
+
const expression = parseExpression(expressionText);
|
|
90
|
+
if (!expression) {
|
|
91
|
+
diagnostics.push(parseDiagnostic(line, `invalid .if expression: ${expressionText}`));
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
if (expressionReferencesCurrentLocation(expression, equates, locationDependentEquates)) {
|
|
95
|
+
diagnostics.push(parseDiagnostic(line, 'invalid .if expression: current location is not available during conditional assembly'));
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return evaluateExpression(expression, {}, equates, { sourceName: line.sourceName, line: line.line, column: firstColumn(line.text) }, diagnostics, { currentLocation: 0 });
|
|
99
|
+
}
|
|
100
|
+
function recordConditionalEquate(line, equates, locationDependentEquates, directiveAliasPolicy) {
|
|
101
|
+
const text = normalizeDirectiveAlias(stripLineComment(line.text), directiveAliasPolicy).trim();
|
|
102
|
+
const equ = /^([A-Za-z_.$?][A-Za-z0-9_.$?]*)(?::\s*|\s+)\.equ\s+(.+)$/.exec(text);
|
|
103
|
+
if (!equ) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const name = equ[1] ?? '';
|
|
107
|
+
const expressionText = equ[2] ?? '';
|
|
108
|
+
const expression = parseExpression(expressionText);
|
|
109
|
+
if (!expression) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (expressionReferencesCurrentLocation(expression, equates, locationDependentEquates)) {
|
|
113
|
+
locationDependentEquates.add(canonicalConditionalSymbolKey(name));
|
|
114
|
+
}
|
|
115
|
+
equates.set(name, {
|
|
116
|
+
expression,
|
|
117
|
+
span: { sourceName: line.sourceName, line: line.line, column: firstColumn(line.text) },
|
|
118
|
+
currentLocation: 0,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function expressionReferencesCurrentLocation(expression, equates, locationDependentEquates, visiting = new Set()) {
|
|
122
|
+
if (expression.kind === 'current-location')
|
|
123
|
+
return true;
|
|
124
|
+
if (expression.kind === 'symbol') {
|
|
125
|
+
return symbolReferencesCurrentLocation(expression.name, equates, locationDependentEquates, visiting);
|
|
126
|
+
}
|
|
127
|
+
return expressionChildExpressions(expression).some((child) => expressionReferencesCurrentLocation(child, equates, locationDependentEquates, visiting));
|
|
128
|
+
}
|
|
129
|
+
function expressionChildExpressions(expression) {
|
|
130
|
+
switch (expression.kind) {
|
|
131
|
+
case 'byte-function':
|
|
132
|
+
case 'unary':
|
|
133
|
+
return [expression.expression];
|
|
134
|
+
case 'binary':
|
|
135
|
+
return [expression.left, expression.right];
|
|
136
|
+
case 'layout-cast':
|
|
137
|
+
return layoutCastChildExpressions(expression);
|
|
138
|
+
default:
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function layoutCastChildExpressions(expression) {
|
|
143
|
+
return [
|
|
144
|
+
expression.base,
|
|
145
|
+
...expression.path.flatMap((part) => (part.kind === 'index' ? [part.expression] : [])),
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
function symbolReferencesCurrentLocation(name, equates, locationDependentEquates, visiting) {
|
|
149
|
+
if (locationDependentEquates.has(canonicalConditionalSymbolKey(name))) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
const lookup = lookupEquateRecord(equates, name);
|
|
153
|
+
if (!lookup)
|
|
154
|
+
return false;
|
|
155
|
+
return equateReferencesCurrentLocation(lookup, equates, locationDependentEquates, visiting);
|
|
156
|
+
}
|
|
157
|
+
function equateReferencesCurrentLocation(lookup, equates, locationDependentEquates, visiting) {
|
|
158
|
+
const key = canonicalConditionalSymbolKey(lookup.key);
|
|
159
|
+
if (visiting.has(key))
|
|
160
|
+
return false;
|
|
161
|
+
const nextVisiting = new Set(visiting);
|
|
162
|
+
nextVisiting.add(key);
|
|
163
|
+
return expressionReferencesCurrentLocation(lookup.record.expression, equates, locationDependentEquates, nextVisiting);
|
|
164
|
+
}
|
|
165
|
+
function canonicalConditionalSymbolKey(name) {
|
|
166
|
+
return name.toLowerCase();
|
|
167
|
+
}
|
|
168
|
+
function parseDiagnostic(line, message) {
|
|
169
|
+
return {
|
|
170
|
+
severity: 'error',
|
|
171
|
+
code: 'AZMN_PARSE',
|
|
172
|
+
message,
|
|
173
|
+
sourceName: line.sourceName,
|
|
174
|
+
line: line.line,
|
|
175
|
+
column: firstColumn(line.text),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function firstColumn(text) {
|
|
179
|
+
const match = /\S/.exec(text);
|
|
180
|
+
return match ? match.index + 1 : 1;
|
|
181
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const BINARY_CONSTANT_OPERATORS = new Map([
|
|
2
|
+
['+', (left, right) => left + right],
|
|
3
|
+
['-', (left, right) => left - right],
|
|
4
|
+
['*', (left, right) => left * right],
|
|
5
|
+
['/', (left, right) => (right === 0 ? undefined : Math.trunc(left / right))],
|
|
6
|
+
['%', (left, right) => (right === 0 ? undefined : left % right)],
|
|
7
|
+
['&', (left, right) => left & right],
|
|
8
|
+
['^', (left, right) => left ^ right],
|
|
9
|
+
['|', (left, right) => left | right],
|
|
10
|
+
['<<', (left, right) => left << right],
|
|
11
|
+
['>>', (left, right) => left >> right],
|
|
12
|
+
]);
|
|
13
|
+
export function expressionFitsKnownImm8(expression) {
|
|
14
|
+
const value = expressionConstantValue(expression);
|
|
15
|
+
return value === undefined || (value >= -0x80 && value <= 0xff);
|
|
16
|
+
}
|
|
17
|
+
export function expressionFitsKnownImm16(expression) {
|
|
18
|
+
const value = expressionConstantValue(expression);
|
|
19
|
+
return value === undefined || (value >= -0x8000 && value <= 0xffff);
|
|
20
|
+
}
|
|
21
|
+
function expressionConstantValue(expression) {
|
|
22
|
+
switch (expression.kind) {
|
|
23
|
+
case 'number':
|
|
24
|
+
return expression.value;
|
|
25
|
+
case 'unary':
|
|
26
|
+
return unaryConstantValue(expression);
|
|
27
|
+
case 'binary':
|
|
28
|
+
return binaryConstantValue(expression);
|
|
29
|
+
default:
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function unaryConstantValue(expression) {
|
|
34
|
+
const value = expressionConstantValue(expression.expression);
|
|
35
|
+
if (value === undefined)
|
|
36
|
+
return undefined;
|
|
37
|
+
switch (expression.operator) {
|
|
38
|
+
case '+':
|
|
39
|
+
return value;
|
|
40
|
+
case '-':
|
|
41
|
+
return -value;
|
|
42
|
+
case '~':
|
|
43
|
+
return ~value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function binaryConstantValue(expression) {
|
|
47
|
+
const left = expressionConstantValue(expression.left);
|
|
48
|
+
const right = expressionConstantValue(expression.right);
|
|
49
|
+
if (left === undefined || right === undefined)
|
|
50
|
+
return undefined;
|
|
51
|
+
return BINARY_CONSTANT_OPERATORS.get(expression.operator)?.(left, right);
|
|
52
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
+
import type { SourceItem } from '../model/source-item.js';
|
|
3
|
+
import type { LogicalLineLike, OpDecl } from './op-expansion.js';
|
|
4
|
+
import { type OpOperand } from './op-operands.js';
|
|
5
|
+
export declare function expandSelectedOp(ops: ReadonlyMap<string, readonly OpDecl[]>, overloads: readonly OpDecl[], operands: readonly OpOperand[], line: LogicalLineLike, diagnostics: Diagnostic[], stack: readonly OpDecl[]): readonly SourceItem[];
|