@jhlagado/azm 0.2.7 → 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 +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 +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,6 +1,29 @@
|
|
|
1
1
|
import { diagnostic, evaluateExpression, lookupEquateRecord, validateLayouts, } from '../semantics/expression-evaluation.js';
|
|
2
2
|
import { instructionSize } from './fixup-emission.js';
|
|
3
3
|
import { advanceCodePlacement, advancePlacement, applyOrg, createPlacementState, placementAddress, placementForOrg, } from './placement.js';
|
|
4
|
+
export { resolveSymbols } from './address-symbols.js';
|
|
5
|
+
import { defineEnumMembers, defineEquate, defineLabel, defineLayout, defineTypeAlias, } from './address-symbols.js';
|
|
6
|
+
const ADDRESS_ITEM_HANDLERS = {
|
|
7
|
+
org: (context, item, items, itemIndex) => applyAddressOrg(context, items, itemIndex, item),
|
|
8
|
+
type: (context, item) => defineAddressLayout(context, item),
|
|
9
|
+
'type-alias': (context, item) => defineAddressTypeAlias(context, item),
|
|
10
|
+
equ: (context, item) => defineAddressEquate(context, item),
|
|
11
|
+
enum: (context, item) => defineAddressEnum(context, item),
|
|
12
|
+
comment: () => undefined,
|
|
13
|
+
label: (context, item) => defineAddressLabel(context, item),
|
|
14
|
+
db: (context, item) => advancePlacement(context.placement, dbSize(item, context.lookupEquates)),
|
|
15
|
+
dw: (context, item) => advancePlacement(context.placement, item.values.length * 2),
|
|
16
|
+
ds: (context, item) => advanceStorage(context, item),
|
|
17
|
+
align: (context, item) => advanceAlignment(context, item),
|
|
18
|
+
end: () => true,
|
|
19
|
+
binfrom: () => undefined,
|
|
20
|
+
binto: () => undefined,
|
|
21
|
+
'string-data': (context, item) => {
|
|
22
|
+
const stringItem = item;
|
|
23
|
+
advancePlacement(context.placement, stringDirectiveBytes(stringItem.directive, stringItem.value).length);
|
|
24
|
+
},
|
|
25
|
+
instruction: (context, item) => advanceInstruction(context, item),
|
|
26
|
+
};
|
|
4
27
|
export function buildAddressState(items, diagnostics) {
|
|
5
28
|
let state = buildAddressStateOnce(items, [], undefined, false);
|
|
6
29
|
let previousSignature = '';
|
|
@@ -15,115 +38,110 @@ export function buildAddressState(items, diagnostics) {
|
|
|
15
38
|
return buildAddressStateOnce(items, diagnostics, state, true);
|
|
16
39
|
}
|
|
17
40
|
function buildAddressStateOnce(items, diagnostics, previous, reportUnknown) {
|
|
18
|
-
const
|
|
19
|
-
const equates = new Map();
|
|
20
|
-
const layouts = new Map();
|
|
21
|
-
const enumNames = new Set();
|
|
22
|
-
const enumNamesLower = new Set();
|
|
23
|
-
let origin = 0;
|
|
24
|
-
let originSet = false;
|
|
25
|
-
const placement = createPlacementState();
|
|
41
|
+
const context = createAddressBuildContext(previous, diagnostics, reportUnknown);
|
|
26
42
|
let ended = false;
|
|
27
|
-
const lookupLabels = previous?.labels ?? labels;
|
|
28
|
-
const lookupEquates = previous?.equates ?? equates;
|
|
29
|
-
const lookupLayouts = previous?.layouts ?? layouts;
|
|
30
43
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
|
|
31
44
|
const item = items[itemIndex];
|
|
32
|
-
if (ended
|
|
45
|
+
if (shouldSkipAfterEnd(ended, item)) {
|
|
33
46
|
continue;
|
|
34
47
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
advancePlacement(placement, stringDirectiveBytes(item.directive, item.value).length);
|
|
112
|
-
break;
|
|
113
|
-
case 'instruction': {
|
|
114
|
-
const instructionBytes = instructionSize(item.instruction);
|
|
115
|
-
advanceCodePlacement(placement, instructionBytes);
|
|
116
|
-
if (placement.activePlacement === 'data') {
|
|
117
|
-
advancePlacement(placement, instructionBytes);
|
|
118
|
-
}
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
48
|
+
ended = ADDRESS_ITEM_HANDLERS[item.kind](context, item, items, itemIndex) === true || ended;
|
|
49
|
+
}
|
|
50
|
+
if (context.reportUnknown) {
|
|
51
|
+
validateLayouts(context.layouts, diagnostics);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
labels: context.labels,
|
|
55
|
+
equates: context.equates,
|
|
56
|
+
layouts: context.layouts,
|
|
57
|
+
origin: context.origin,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function shouldSkipAfterEnd(ended, item) {
|
|
61
|
+
return ended && item.kind !== 'binfrom' && item.kind !== 'binto';
|
|
62
|
+
}
|
|
63
|
+
function createAddressBuildContext(previous, diagnostics, reportUnknown) {
|
|
64
|
+
const labels = {};
|
|
65
|
+
const equates = new Map();
|
|
66
|
+
const layouts = new Map();
|
|
67
|
+
return {
|
|
68
|
+
labels,
|
|
69
|
+
equates,
|
|
70
|
+
layouts,
|
|
71
|
+
enumNames: new Set(),
|
|
72
|
+
enumNamesLower: new Set(),
|
|
73
|
+
diagnostics,
|
|
74
|
+
lookupLabels: previous?.labels ?? labels,
|
|
75
|
+
lookupEquates: previous?.equates ?? equates,
|
|
76
|
+
lookupLayouts: previous?.layouts ?? layouts,
|
|
77
|
+
reportUnknown,
|
|
78
|
+
placement: createPlacementState(),
|
|
79
|
+
origin: 0,
|
|
80
|
+
originSet: false,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function applyAddressOrg(context, items, itemIndex, item) {
|
|
84
|
+
context.placement.activePlacement = placementForOrg(items, itemIndex);
|
|
85
|
+
const value = evaluateAddressExpression(context, item.expression, item.span);
|
|
86
|
+
if (value === undefined) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!context.originSet) {
|
|
90
|
+
context.origin = value;
|
|
91
|
+
context.originSet = true;
|
|
92
|
+
}
|
|
93
|
+
applyOrg(context.placement, value);
|
|
94
|
+
}
|
|
95
|
+
function defineAddressLayout(context, item) {
|
|
96
|
+
defineLayout(context.layouts, context.labels, context.equates, context.enumNamesLower, item.name, item.layoutKind, item.fields, item.span, context.diagnostics);
|
|
97
|
+
}
|
|
98
|
+
function defineAddressTypeAlias(context, item) {
|
|
99
|
+
defineTypeAlias(context.layouts, context.labels, context.equates, context.enumNamesLower, item.name, item.typeExpr, item.span, context.diagnostics);
|
|
100
|
+
}
|
|
101
|
+
function defineAddressEquate(context, item) {
|
|
102
|
+
defineEquate(context.equates, context.labels, context.layouts, context.enumNames, context.enumNamesLower, item.name, item.expression, item.span, placementAddress(context.placement), context.diagnostics, item.stringValue);
|
|
103
|
+
}
|
|
104
|
+
function defineAddressEnum(context, item) {
|
|
105
|
+
defineEnumMembers(context.equates, context.labels, context.layouts, context.enumNames, context.enumNamesLower, item.name, item.members, item.span, context.diagnostics);
|
|
106
|
+
}
|
|
107
|
+
function defineAddressLabel(context, item) {
|
|
108
|
+
defineLabel(context.labels, context.equates, context.layouts, context.enumNamesLower, item.name, placementAddress(context.placement), item.span, context.diagnostics);
|
|
109
|
+
}
|
|
110
|
+
function advanceStorage(context, item) {
|
|
111
|
+
const size = evaluateAddressExpression(context, item.size, item.span);
|
|
112
|
+
if (size !== undefined) {
|
|
113
|
+
advancePlacement(context.placement, size);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function advanceAlignment(context, item) {
|
|
117
|
+
const alignment = evaluateAddressExpression(context, item.alignment, item.span);
|
|
118
|
+
if (alignment === undefined) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (alignment <= 0) {
|
|
122
|
+
if (context.reportUnknown) {
|
|
123
|
+
context.diagnostics.push(diagnostic(item.span, `.align value must be positive: ${alignment}.`));
|
|
121
124
|
}
|
|
125
|
+
return;
|
|
122
126
|
}
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
advancePlacement(context.placement, alignmentPadding(placementAddress(context.placement), alignment));
|
|
128
|
+
}
|
|
129
|
+
function advanceInstruction(context, item) {
|
|
130
|
+
const instructionBytes = instructionSize(item.instruction);
|
|
131
|
+
advanceCodePlacement(context.placement, instructionBytes);
|
|
132
|
+
if (context.placement.activePlacement === 'data') {
|
|
133
|
+
advancePlacement(context.placement, instructionBytes);
|
|
125
134
|
}
|
|
126
|
-
|
|
135
|
+
}
|
|
136
|
+
function evaluateAddressExpression(context, expression, span) {
|
|
137
|
+
return evaluateExpression(expression, context.lookupLabels, context.lookupEquates, span, context.diagnostics, {
|
|
138
|
+
currentLocation: placementAddress(context.placement),
|
|
139
|
+
layouts: context.lookupLayouts,
|
|
140
|
+
reportUnknown: context.reportUnknown,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function dbSize(item, lookupEquates) {
|
|
144
|
+
return item.values.reduce((size, value) => size + dataValueSize(value, lookupEquates), 0);
|
|
127
145
|
}
|
|
128
146
|
export function stringDirectiveBytes(directive, value) {
|
|
129
147
|
const bytes = [...value].map((char) => char.codePointAt(0) ?? 0);
|
|
@@ -167,120 +185,3 @@ function addressStateSignature(state) {
|
|
|
167
185
|
origin: state.origin,
|
|
168
186
|
});
|
|
169
187
|
}
|
|
170
|
-
function defineLayout(layouts, labels, equates, enumNamesLower, name, layoutKind, fields, span, diagnostics) {
|
|
171
|
-
const lowerName = name.toLowerCase();
|
|
172
|
-
if (hasCaseInsensitiveMapKey(layouts, lowerName) ||
|
|
173
|
-
hasCaseInsensitiveKey(labels, lowerName) ||
|
|
174
|
-
hasCaseInsensitiveMapKey(equates, lowerName) ||
|
|
175
|
-
enumNamesLower.has(lowerName)) {
|
|
176
|
-
diagnostics.push(diagnostic(span, `duplicate type name: ${name}`));
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
const fieldNames = new Set();
|
|
180
|
-
for (const field of fields) {
|
|
181
|
-
const fieldLower = field.name.toLowerCase();
|
|
182
|
-
if (fieldNames.has(fieldLower)) {
|
|
183
|
-
diagnostics.push(diagnostic(span, `duplicate type field name: ${field.name}`));
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
fieldNames.add(fieldLower);
|
|
187
|
-
}
|
|
188
|
-
layouts.set(name, { kind: layoutKind, fields, span });
|
|
189
|
-
}
|
|
190
|
-
function defineTypeAlias(layouts, labels, equates, enumNamesLower, name, typeExpr, span, diagnostics) {
|
|
191
|
-
const lowerName = name.toLowerCase();
|
|
192
|
-
if (hasCaseInsensitiveMapKey(layouts, lowerName) ||
|
|
193
|
-
hasCaseInsensitiveKey(labels, lowerName) ||
|
|
194
|
-
hasCaseInsensitiveMapKey(equates, lowerName) ||
|
|
195
|
-
enumNamesLower.has(lowerName)) {
|
|
196
|
-
diagnostics.push(diagnostic(span, `duplicate type name: ${name}`));
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
layouts.set(name, { kind: 'alias', typeExpr, span });
|
|
200
|
-
}
|
|
201
|
-
function defineLabel(labels, equates, layouts, enumNamesLower, name, address, span, diagnostics) {
|
|
202
|
-
if (labels[name] !== undefined ||
|
|
203
|
-
equates.has(name) ||
|
|
204
|
-
hasCaseInsensitiveMapKey(layouts, name.toLowerCase()) ||
|
|
205
|
-
enumNamesLower.has(name.toLowerCase())) {
|
|
206
|
-
diagnostics.push(diagnostic(span, `duplicate symbol: ${name}`));
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
labels[name] = address;
|
|
210
|
-
}
|
|
211
|
-
function defineEquate(equates, labels, layouts, enumNames, enumNamesLower, name, expression, span, currentLocation, diagnostics, stringValue) {
|
|
212
|
-
if (labels[name] !== undefined ||
|
|
213
|
-
equates.has(name) ||
|
|
214
|
-
hasCaseInsensitiveMapKey(layouts, name.toLowerCase()) ||
|
|
215
|
-
enumNames.has(name) ||
|
|
216
|
-
enumNamesLower.has(name.toLowerCase())) {
|
|
217
|
-
diagnostics.push(diagnostic(span, `duplicate symbol: ${name}`));
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
equates.set(name, {
|
|
221
|
-
expression,
|
|
222
|
-
span,
|
|
223
|
-
currentLocation,
|
|
224
|
-
...(stringValue !== undefined ? { stringValue } : {}),
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
function defineEnumMembers(equates, labels, layouts, enumNames, enumNamesLower, enumName, members, span, diagnostics) {
|
|
228
|
-
const enumNameLower = enumName.toLowerCase();
|
|
229
|
-
if (hasCaseInsensitiveKey(labels, enumNameLower) ||
|
|
230
|
-
hasCaseInsensitiveMapKey(equates, enumNameLower) ||
|
|
231
|
-
hasCaseInsensitiveMapKey(layouts, enumNameLower) ||
|
|
232
|
-
enumNamesLower.has(enumNameLower)) {
|
|
233
|
-
diagnostics.push(diagnostic(span, `duplicate enum name: ${enumName}`));
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
enumNames.add(enumName);
|
|
237
|
-
enumNamesLower.add(enumNameLower);
|
|
238
|
-
const memberNames = new Set();
|
|
239
|
-
for (let index = 0; index < members.length; index += 1) {
|
|
240
|
-
const member = members[index] ?? '';
|
|
241
|
-
const memberLower = member.toLowerCase();
|
|
242
|
-
if (memberNames.has(memberLower)) {
|
|
243
|
-
diagnostics.push(diagnostic(span, `duplicate enum member name: ${member}`));
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
memberNames.add(memberLower);
|
|
247
|
-
const qualifiedName = `${enumName}.${member}`;
|
|
248
|
-
if (hasCaseInsensitiveKey(labels, qualifiedName.toLowerCase()) ||
|
|
249
|
-
hasCaseInsensitiveMapKey(equates, qualifiedName.toLowerCase())) {
|
|
250
|
-
diagnostics.push(diagnostic(span, `duplicate symbol: ${qualifiedName}`));
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
equates.set(qualifiedName, {
|
|
254
|
-
expression: { kind: 'number', value: index },
|
|
255
|
-
span,
|
|
256
|
-
currentLocation: 0,
|
|
257
|
-
enumMember: true,
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
function hasCaseInsensitiveKey(record, lowerName) {
|
|
262
|
-
return Object.keys(record).some((key) => key.toLowerCase() === lowerName);
|
|
263
|
-
}
|
|
264
|
-
function hasCaseInsensitiveMapKey(map, lowerName) {
|
|
265
|
-
for (const key of map.keys()) {
|
|
266
|
-
if (key.toLowerCase() === lowerName) {
|
|
267
|
-
return true;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
export function resolveSymbols(labels, equates, layouts, diagnostics) {
|
|
273
|
-
const symbols = { ...labels };
|
|
274
|
-
for (const [name, record] of equates) {
|
|
275
|
-
const value = evaluateExpression(record.expression, labels, equates, record.span, diagnostics, {
|
|
276
|
-
currentLocation: record.currentLocation,
|
|
277
|
-
visiting: new Set([name]),
|
|
278
|
-
layouts,
|
|
279
|
-
reportUnknown: false,
|
|
280
|
-
});
|
|
281
|
-
if (value !== undefined) {
|
|
282
|
-
symbols[name] = value;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return symbols;
|
|
286
|
-
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Diagnostic } from '../model/diagnostic.js';
|
|
2
|
+
import type { Expression, TypeExpr } from '../model/expression.js';
|
|
3
|
+
import type { LayoutField } from '../model/source-item.js';
|
|
4
|
+
import type { SymbolTable } from '../model/symbol.js';
|
|
5
|
+
import type { SourceSpan } from '../source/source-span.js';
|
|
6
|
+
import { type EquateRecord, type LayoutRecord } from '../semantics/expression-evaluation.js';
|
|
7
|
+
export declare function defineLayout(layouts: Map<string, LayoutRecord>, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, enumNamesLower: ReadonlySet<string>, name: string, layoutKind: 'record' | 'union', fields: readonly LayoutField[], span: SourceSpan, diagnostics: Diagnostic[]): void;
|
|
8
|
+
export declare function defineTypeAlias(layouts: Map<string, LayoutRecord>, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, enumNamesLower: ReadonlySet<string>, name: string, typeExpr: TypeExpr, span: SourceSpan, diagnostics: Diagnostic[]): void;
|
|
9
|
+
export declare function defineLabel(labels: Record<string, number>, equates: ReadonlyMap<string, EquateRecord>, layouts: ReadonlyMap<string, LayoutRecord>, enumNamesLower: ReadonlySet<string>, name: string, address: number, span: SourceSpan, diagnostics: Diagnostic[]): void;
|
|
10
|
+
export declare function defineEquate(equates: Map<string, EquateRecord>, labels: Readonly<Record<string, number>>, layouts: ReadonlyMap<string, LayoutRecord>, enumNames: ReadonlySet<string>, enumNamesLower: ReadonlySet<string>, name: string, expression: Expression, span: SourceSpan, currentLocation: number, diagnostics: Diagnostic[], stringValue?: string): void;
|
|
11
|
+
export declare function defineEnumMembers(equates: Map<string, EquateRecord>, labels: Readonly<Record<string, number>>, layouts: ReadonlyMap<string, LayoutRecord>, enumNames: Set<string>, enumNamesLower: Set<string>, enumName: string, members: readonly string[], span: SourceSpan, diagnostics: Diagnostic[]): void;
|
|
12
|
+
export declare function resolveSymbols(labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): SymbolTable;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { diagnostic, evaluateExpression, } from '../semantics/expression-evaluation.js';
|
|
2
|
+
export function defineLayout(layouts, labels, equates, enumNamesLower, name, layoutKind, fields, span, diagnostics) {
|
|
3
|
+
const lowerName = name.toLowerCase();
|
|
4
|
+
if (hasCaseInsensitiveMapKey(layouts, lowerName) ||
|
|
5
|
+
hasCaseInsensitiveKey(labels, lowerName) ||
|
|
6
|
+
hasCaseInsensitiveMapKey(equates, lowerName) ||
|
|
7
|
+
enumNamesLower.has(lowerName)) {
|
|
8
|
+
diagnostics.push(diagnostic(span, `duplicate type name: ${name}`));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const fieldNames = new Set();
|
|
12
|
+
for (const field of fields) {
|
|
13
|
+
const fieldLower = field.name.toLowerCase();
|
|
14
|
+
if (fieldNames.has(fieldLower)) {
|
|
15
|
+
diagnostics.push(diagnostic(span, `duplicate type field name: ${field.name}`));
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
fieldNames.add(fieldLower);
|
|
19
|
+
}
|
|
20
|
+
layouts.set(name, { kind: layoutKind, fields, span });
|
|
21
|
+
}
|
|
22
|
+
export function defineTypeAlias(layouts, labels, equates, enumNamesLower, name, typeExpr, span, diagnostics) {
|
|
23
|
+
const lowerName = name.toLowerCase();
|
|
24
|
+
if (hasCaseInsensitiveMapKey(layouts, lowerName) ||
|
|
25
|
+
hasCaseInsensitiveKey(labels, lowerName) ||
|
|
26
|
+
hasCaseInsensitiveMapKey(equates, lowerName) ||
|
|
27
|
+
enumNamesLower.has(lowerName)) {
|
|
28
|
+
diagnostics.push(diagnostic(span, `duplicate type name: ${name}`));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
layouts.set(name, { kind: 'alias', typeExpr, span });
|
|
32
|
+
}
|
|
33
|
+
export function defineLabel(labels, equates, layouts, enumNamesLower, name, address, span, diagnostics) {
|
|
34
|
+
if (labels[name] !== undefined ||
|
|
35
|
+
equates.has(name) ||
|
|
36
|
+
hasCaseInsensitiveMapKey(layouts, name.toLowerCase()) ||
|
|
37
|
+
enumNamesLower.has(name.toLowerCase())) {
|
|
38
|
+
diagnostics.push(diagnostic(span, `duplicate symbol: ${name}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
labels[name] = address;
|
|
42
|
+
}
|
|
43
|
+
export function defineEquate(equates, labels, layouts, enumNames, enumNamesLower, name, expression, span, currentLocation, diagnostics, stringValue) {
|
|
44
|
+
if (labels[name] !== undefined ||
|
|
45
|
+
equates.has(name) ||
|
|
46
|
+
hasCaseInsensitiveMapKey(layouts, name.toLowerCase()) ||
|
|
47
|
+
enumNames.has(name) ||
|
|
48
|
+
enumNamesLower.has(name.toLowerCase())) {
|
|
49
|
+
diagnostics.push(diagnostic(span, `duplicate symbol: ${name}`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
equates.set(name, {
|
|
53
|
+
expression,
|
|
54
|
+
span,
|
|
55
|
+
currentLocation,
|
|
56
|
+
...(stringValue !== undefined ? { stringValue } : {}),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
export function defineEnumMembers(equates, labels, layouts, enumNames, enumNamesLower, enumName, members, span, diagnostics) {
|
|
60
|
+
const enumNameLower = enumName.toLowerCase();
|
|
61
|
+
if (hasCaseInsensitiveKey(labels, enumNameLower) ||
|
|
62
|
+
hasCaseInsensitiveMapKey(equates, enumNameLower) ||
|
|
63
|
+
hasCaseInsensitiveMapKey(layouts, enumNameLower) ||
|
|
64
|
+
enumNamesLower.has(enumNameLower)) {
|
|
65
|
+
diagnostics.push(diagnostic(span, `duplicate enum name: ${enumName}`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
enumNames.add(enumName);
|
|
69
|
+
enumNamesLower.add(enumNameLower);
|
|
70
|
+
const memberNames = new Set();
|
|
71
|
+
for (let index = 0; index < members.length; index += 1) {
|
|
72
|
+
const member = members[index] ?? '';
|
|
73
|
+
const memberLower = member.toLowerCase();
|
|
74
|
+
if (memberNames.has(memberLower)) {
|
|
75
|
+
diagnostics.push(diagnostic(span, `duplicate enum member name: ${member}`));
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
memberNames.add(memberLower);
|
|
79
|
+
const qualifiedName = `${enumName}.${member}`;
|
|
80
|
+
if (hasCaseInsensitiveKey(labels, qualifiedName.toLowerCase()) ||
|
|
81
|
+
hasCaseInsensitiveMapKey(equates, qualifiedName.toLowerCase())) {
|
|
82
|
+
diagnostics.push(diagnostic(span, `duplicate symbol: ${qualifiedName}`));
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
equates.set(qualifiedName, {
|
|
86
|
+
expression: { kind: 'number', value: index },
|
|
87
|
+
span,
|
|
88
|
+
currentLocation: 0,
|
|
89
|
+
enumMember: true,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function resolveSymbols(labels, equates, layouts, diagnostics) {
|
|
94
|
+
const symbols = { ...labels };
|
|
95
|
+
for (const [name, record] of equates) {
|
|
96
|
+
const value = evaluateExpression(record.expression, labels, equates, record.span, diagnostics, {
|
|
97
|
+
currentLocation: record.currentLocation,
|
|
98
|
+
visiting: new Set([name]),
|
|
99
|
+
layouts,
|
|
100
|
+
reportUnknown: false,
|
|
101
|
+
});
|
|
102
|
+
if (value !== undefined) {
|
|
103
|
+
symbols[name] = value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return symbols;
|
|
107
|
+
}
|
|
108
|
+
function hasCaseInsensitiveKey(record, lowerName) {
|
|
109
|
+
return Object.keys(record).some((key) => key.toLowerCase() === lowerName);
|
|
110
|
+
}
|
|
111
|
+
function hasCaseInsensitiveMapKey(map, lowerName) {
|
|
112
|
+
for (const key of map.keys()) {
|
|
113
|
+
if (key.toLowerCase() === lowerName) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { diagnostic, evaluateExpression, lookupSymbolValue, } from '../semantics/expression-evaluation.js';
|
|
2
|
+
import { applyBinaryOperator, applyUnaryOperator, } from '../semantics/constant-operators.js';
|
|
2
3
|
import { encodeZ80Instruction } from '../z80/encode.js';
|
|
3
4
|
export function emitInstruction(instruction, span, currentAddress, labels, equates, diagnostics, bytes, fixups, layouts) {
|
|
4
5
|
const encoded = encodeZ80Instruction(instruction);
|
|
@@ -169,25 +170,34 @@ function fixupTargetFromExpression(expression) {
|
|
|
169
170
|
if (expression.kind === 'symbol') {
|
|
170
171
|
return { symbol: expression.name, addend: 0 };
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
+
return expression.kind === 'binary' ? binaryFixupTarget(expression) : undefined;
|
|
174
|
+
}
|
|
175
|
+
function binaryFixupTarget(expression) {
|
|
176
|
+
if (expression.operator !== '+' && expression.operator !== '-')
|
|
173
177
|
return undefined;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
return leftSymbolFixupTarget(expression) ?? rightSymbolFixupTarget(expression);
|
|
179
|
+
}
|
|
180
|
+
function expressionSymbol(expression) {
|
|
181
|
+
return expression.kind === 'symbol' ? expression.name : undefined;
|
|
182
|
+
}
|
|
183
|
+
function leftSymbolFixupTarget(expression) {
|
|
184
|
+
const symbol = expressionSymbol(expression.left);
|
|
185
|
+
const rightConstant = constantExpressionValue(expression.right);
|
|
186
|
+
if (!symbol || rightConstant === undefined)
|
|
187
|
+
return undefined;
|
|
188
|
+
return {
|
|
189
|
+
symbol,
|
|
190
|
+
addend: expression.operator === '+' ? rightConstant : -rightConstant,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function rightSymbolFixupTarget(expression) {
|
|
194
|
+
if (expression.operator !== '+')
|
|
195
|
+
return undefined;
|
|
196
|
+
const symbol = expressionSymbol(expression.right);
|
|
197
|
+
const leftConstant = constantExpressionValue(expression.left);
|
|
198
|
+
return symbol && leftConstant !== undefined
|
|
199
|
+
? { symbol, addend: leftConstant }
|
|
200
|
+
: undefined;
|
|
191
201
|
}
|
|
192
202
|
function constantExpressionValue(expression) {
|
|
193
203
|
switch (expression.kind) {
|
|
@@ -207,14 +217,7 @@ function constantUnaryExpressionValue(expression) {
|
|
|
207
217
|
if (value === undefined) {
|
|
208
218
|
return undefined;
|
|
209
219
|
}
|
|
210
|
-
|
|
211
|
-
case '+':
|
|
212
|
-
return value;
|
|
213
|
-
case '-':
|
|
214
|
-
return -value;
|
|
215
|
-
case '~':
|
|
216
|
-
return ~value;
|
|
217
|
-
}
|
|
220
|
+
return applyUnaryOperator(expression.operator, value);
|
|
218
221
|
}
|
|
219
222
|
function constantBinaryExpressionValue(expression) {
|
|
220
223
|
const left = constantExpressionValue(expression.left);
|
|
@@ -222,26 +225,5 @@ function constantBinaryExpressionValue(expression) {
|
|
|
222
225
|
if (left === undefined || right === undefined) {
|
|
223
226
|
return undefined;
|
|
224
227
|
}
|
|
225
|
-
|
|
226
|
-
case '*':
|
|
227
|
-
return left * right;
|
|
228
|
-
case '/':
|
|
229
|
-
return right === 0 ? undefined : Math.trunc(left / right);
|
|
230
|
-
case '%':
|
|
231
|
-
return right === 0 ? undefined : left % right;
|
|
232
|
-
case '+':
|
|
233
|
-
return left + right;
|
|
234
|
-
case '-':
|
|
235
|
-
return left - right;
|
|
236
|
-
case '&':
|
|
237
|
-
return left & right;
|
|
238
|
-
case '^':
|
|
239
|
-
return left ^ right;
|
|
240
|
-
case '|':
|
|
241
|
-
return left | right;
|
|
242
|
-
case '<<':
|
|
243
|
-
return left << right;
|
|
244
|
-
case '>>':
|
|
245
|
-
return left >> right;
|
|
246
|
-
}
|
|
228
|
+
return applyBinaryOperator(expression.operator, left, right);
|
|
247
229
|
}
|