@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.
Files changed (235) hide show
  1. package/README.md +170 -69
  2. package/dist/src/api-artifacts.d.ts +20 -0
  3. package/dist/src/api-artifacts.js +165 -0
  4. package/dist/src/api-compile.d.ts +8 -2
  5. package/dist/src/api-compile.js +31 -230
  6. package/dist/src/api-register-contracts.d.ts +9 -0
  7. package/dist/src/api-register-contracts.js +77 -0
  8. package/dist/src/api-tooling.d.ts +2 -2
  9. package/dist/src/api-tooling.js +1 -1
  10. package/dist/src/assembly/address-planning.d.ts +1 -2
  11. package/dist/src/assembly/address-planning.js +119 -218
  12. package/dist/src/assembly/address-symbols.d.ts +12 -0
  13. package/dist/src/assembly/address-symbols.js +118 -0
  14. package/dist/src/assembly/fixup-emission.js +30 -48
  15. package/dist/src/assembly/program-emission.js +163 -164
  16. package/dist/src/cli/artifact-files.d.ts +15 -0
  17. package/dist/src/cli/artifact-files.js +86 -0
  18. package/dist/src/cli/parse-args.d.ts +6 -5
  19. package/dist/src/cli/parse-args.js +162 -136
  20. package/dist/src/cli/run.js +4 -1
  21. package/dist/src/cli/usage.d.ts +1 -0
  22. package/dist/src/cli/usage.js +33 -0
  23. package/dist/src/cli/write-artifacts.js +18 -91
  24. package/dist/src/core/compile.js +51 -274
  25. package/dist/src/core/conditional-assembly.d.ts +6 -0
  26. package/dist/src/core/conditional-assembly.js +181 -0
  27. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  28. package/dist/src/expansion/op-constant-expression.js +52 -0
  29. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  30. package/dist/src/expansion/op-expand-selected.js +143 -0
  31. package/dist/src/expansion/op-expansion.d.ts +5 -53
  32. package/dist/src/expansion/op-expansion.js +85 -815
  33. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  34. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  35. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  36. package/dist/src/expansion/op-local-labels.js +166 -0
  37. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  38. package/dist/src/expansion/op-operand-splitting.js +44 -0
  39. package/dist/src/expansion/op-operands.d.ts +53 -0
  40. package/dist/src/expansion/op-operands.js +66 -0
  41. package/dist/src/expansion/op-selection.d.ts +18 -0
  42. package/dist/src/expansion/op-selection.js +172 -0
  43. package/dist/src/index.d.ts +2 -1
  44. package/dist/src/index.js +1 -1
  45. package/dist/src/model/diagnostic.d.ts +4 -0
  46. package/dist/src/model/diagnostic.js +4 -0
  47. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  48. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  49. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  50. package/dist/src/outputs/asm80-expressions.js +47 -0
  51. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  52. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  53. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-instructions.js +272 -0
  55. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  56. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  57. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  58. package/dist/src/outputs/asm80-strings.js +14 -0
  59. package/dist/src/outputs/d8-files.d.ts +10 -0
  60. package/dist/src/outputs/d8-files.js +103 -0
  61. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  62. package/dist/src/outputs/d8-helpers.js +136 -0
  63. package/dist/src/outputs/hex.js +26 -18
  64. package/dist/src/outputs/types.d.ts +16 -10
  65. package/dist/src/outputs/write-asm80.js +68 -597
  66. package/dist/src/outputs/write-d8.js +6 -216
  67. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  68. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  69. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  70. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  71. package/dist/src/register-contracts/analyze.js +73 -0
  72. package/dist/src/register-contracts/annotate.d.ts +11 -0
  73. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  74. package/dist/src/register-contracts/annotations.d.ts +8 -0
  75. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  76. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  77. package/dist/src/register-contracts/boundaryHints.js +24 -0
  78. package/dist/src/register-contracts/carriers.d.ts +2 -0
  79. package/dist/src/register-contracts/constants.d.ts +4 -0
  80. package/dist/src/register-contracts/constants.js +51 -0
  81. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  82. package/dist/src/register-contracts/controlFlow.js +55 -0
  83. package/dist/src/register-contracts/fix.d.ts +11 -0
  84. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  85. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  86. package/dist/src/register-contracts/instruction-head.js +3 -0
  87. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  88. package/dist/src/register-contracts/instruction-operands.js +101 -0
  89. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  90. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  91. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  92. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  93. package/dist/src/register-contracts/liveness.d.ts +3 -0
  94. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  95. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  96. package/dist/src/register-contracts/operand-register-name.js +13 -0
  97. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  98. package/dist/src/{register-care → register-contracts}/profiles.js +2 -2
  99. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  100. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  101. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  102. package/dist/src/register-contracts/programModel-routines.js +128 -0
  103. package/dist/src/register-contracts/programModel.d.ts +3 -0
  104. package/dist/src/register-contracts/programModel.js +14 -0
  105. package/dist/src/register-contracts/report.d.ts +5 -0
  106. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  107. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  108. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  109. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  110. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  111. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  112. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  113. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  114. package/dist/src/register-contracts/smartComments.js +92 -0
  115. package/dist/src/register-contracts/summaries.d.ts +12 -0
  116. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  117. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  118. package/dist/src/register-contracts/summary-boundary.js +40 -0
  119. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  120. package/dist/src/register-contracts/summary-contract.js +45 -0
  121. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  122. package/dist/src/register-contracts/summary-result.js +122 -0
  123. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  124. package/dist/src/register-contracts/summary-state.js +88 -0
  125. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  126. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  127. package/dist/src/register-contracts/summary.d.ts +3 -0
  128. package/dist/src/register-contracts/summary.js +266 -0
  129. package/dist/src/register-contracts/tooling.d.ts +57 -0
  130. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  131. package/dist/src/register-contracts/types.d.ts +188 -0
  132. package/dist/src/semantics/binary-operators.d.ts +2 -0
  133. package/dist/src/semantics/binary-operators.js +15 -0
  134. package/dist/src/semantics/byte-functions.d.ts +2 -0
  135. package/dist/src/semantics/byte-functions.js +7 -0
  136. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  137. package/dist/src/semantics/constant-operator-types.js +1 -0
  138. package/dist/src/semantics/constant-operators.d.ts +3 -0
  139. package/dist/src/semantics/constant-operators.js +3 -0
  140. package/dist/src/semantics/diagnostics.d.ts +3 -0
  141. package/dist/src/semantics/diagnostics.js +10 -0
  142. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  143. package/dist/src/semantics/expression-evaluation.js +22 -334
  144. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  145. package/dist/src/semantics/layout-evaluation.js +202 -0
  146. package/dist/src/semantics/layout-format.d.ts +5 -0
  147. package/dist/src/semantics/layout-format.js +31 -0
  148. package/dist/src/semantics/layout-path.d.ts +24 -0
  149. package/dist/src/semantics/layout-path.js +58 -0
  150. package/dist/src/semantics/unary-operators.d.ts +2 -0
  151. package/dist/src/semantics/unary-operators.js +8 -0
  152. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  153. package/dist/src/source/line-comment-scanner.js +51 -0
  154. package/dist/src/source/strip-line-comment.js +8 -44
  155. package/dist/src/syntax/directive-aliases.js +36 -22
  156. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  157. package/dist/src/syntax/expression-tokenizer.js +310 -0
  158. package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
  159. package/dist/src/syntax/parse-directive-statement.js +307 -0
  160. package/dist/src/syntax/parse-expression.d.ts +2 -2
  161. package/dist/src/syntax/parse-expression.js +7 -568
  162. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  163. package/dist/src/syntax/parse-layout-declarations.js +180 -0
  164. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  165. package/dist/src/syntax/parse-layout-expression.js +175 -0
  166. package/dist/src/syntax/parse-line.js +4 -272
  167. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  168. package/dist/src/syntax/parse-token-expression.js +133 -0
  169. package/dist/src/tooling/case-style.js +47 -30
  170. package/dist/src/z80/effect-groups.d.ts +38 -0
  171. package/dist/src/z80/effect-groups.js +265 -0
  172. package/dist/src/z80/effect-units.d.ts +18 -0
  173. package/dist/src/z80/effect-units.js +165 -0
  174. package/dist/src/z80/effects.d.ts +1 -1
  175. package/dist/src/z80/effects.js +94 -557
  176. package/dist/src/z80/encode-core.d.ts +2 -0
  177. package/dist/src/z80/encode-core.js +42 -0
  178. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  179. package/dist/src/z80/encode-ld-helpers.js +172 -0
  180. package/dist/src/z80/encode-ld.d.ts +2 -0
  181. package/dist/src/z80/encode-ld.js +285 -0
  182. package/dist/src/z80/encode.js +190 -542
  183. package/dist/src/z80/ld-support.d.ts +3 -0
  184. package/dist/src/z80/ld-support.js +146 -0
  185. package/dist/src/z80/operand-split-state.d.ts +8 -0
  186. package/dist/src/z80/operand-split-state.js +46 -0
  187. package/dist/src/z80/operand-split.d.ts +1 -0
  188. package/dist/src/z80/operand-split.js +13 -0
  189. package/dist/src/z80/parse-basic.d.ts +4 -0
  190. package/dist/src/z80/parse-basic.js +39 -0
  191. package/dist/src/z80/parse-branch.d.ts +4 -0
  192. package/dist/src/z80/parse-branch.js +218 -0
  193. package/dist/src/z80/parse-conditions.d.ts +6 -0
  194. package/dist/src/z80/parse-conditions.js +10 -0
  195. package/dist/src/z80/parse-exchange.d.ts +2 -0
  196. package/dist/src/z80/parse-exchange.js +30 -0
  197. package/dist/src/z80/parse-instruction.js +224 -1010
  198. package/dist/src/z80/parse-io-control.d.ts +5 -0
  199. package/dist/src/z80/parse-io-control.js +108 -0
  200. package/dist/src/z80/parse-ld.d.ts +2 -0
  201. package/dist/src/z80/parse-ld.js +83 -0
  202. package/dist/src/z80/parse-operands.d.ts +41 -0
  203. package/dist/src/z80/parse-operands.js +259 -0
  204. package/docs/reference/cli.md +42 -35
  205. package/docs/reference/tooling-api.md +20 -16
  206. package/package.json +1 -1
  207. package/dist/src/register-care/accept-output.d.ts +0 -2
  208. package/dist/src/register-care/analyze.js +0 -166
  209. package/dist/src/register-care/annotate.d.ts +0 -11
  210. package/dist/src/register-care/annotations.d.ts +0 -8
  211. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  212. package/dist/src/register-care/boundaryHints.js +0 -80
  213. package/dist/src/register-care/carriers.d.ts +0 -2
  214. package/dist/src/register-care/controlFlow.d.ts +0 -5
  215. package/dist/src/register-care/controlFlow.js +0 -38
  216. package/dist/src/register-care/fix.d.ts +0 -11
  217. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  218. package/dist/src/register-care/instruction-shape.js +0 -129
  219. package/dist/src/register-care/liveness.d.ts +0 -3
  220. package/dist/src/register-care/programModel.d.ts +0 -3
  221. package/dist/src/register-care/programModel.js +0 -266
  222. package/dist/src/register-care/report.d.ts +0 -5
  223. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  224. package/dist/src/register-care/smartComments.d.ts +0 -5
  225. package/dist/src/register-care/smartComments.js +0 -243
  226. package/dist/src/register-care/summaries.d.ts +0 -12
  227. package/dist/src/register-care/summary.d.ts +0 -3
  228. package/dist/src/register-care/summary.js +0 -474
  229. package/dist/src/register-care/tooling.d.ts +0 -43
  230. package/dist/src/register-care/types.d.ts +0 -172
  231. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  232. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  233. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  234. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  235. /package/dist/src/{register-care → register-contracts}/types.js +0 -0
@@ -0,0 +1,172 @@
1
+ import { expressionFitsKnownImm16, expressionFitsKnownImm8, } from './op-constant-expression.js';
2
+ import { formatOpOperand, isConditionToken, } from './op-operands.js';
3
+ const MATCHER_OPERAND_PREDICATES = {
4
+ reg8: (operand) => operand.kind === 'reg8',
5
+ reg16: (operand) => operand.kind === 'reg16',
6
+ imm8: (operand) => operand.kind === 'imm' && expressionFitsKnownImm8(operand.expression),
7
+ imm16: (operand) => operand.kind === 'imm' && expressionFitsKnownImm16(operand.expression),
8
+ cc: (operand) => isConditionToken(operand.text),
9
+ idx16: (operand) => operand.kind === 'indexed',
10
+ ea: (operand) => operand.kind === 'imm',
11
+ mem8: (operand) => isMemoryOperand(operand),
12
+ mem16: (operand) => isMemoryOperand(operand),
13
+ };
14
+ const MATCHER_EXPECTATIONS = {
15
+ reg8: 'reg8',
16
+ reg16: 'reg16',
17
+ imm8: 'imm8',
18
+ imm16: 'imm16',
19
+ cc: 'condition token NZ/Z/NC/C/PO/PE/P/M',
20
+ idx16: 'IX/IY indexed memory operand',
21
+ ea: 'ea',
22
+ mem8: 'mem8 dereference',
23
+ mem16: 'mem16 dereference',
24
+ };
25
+ export function selectOpOverload(overloads, operands) {
26
+ const arityMatches = overloads.filter((overload) => overload.params.length === operands.length);
27
+ if (arityMatches.length === 0) {
28
+ return { kind: 'arity_mismatch' };
29
+ }
30
+ const matches = arityMatches.filter((overload) => overload.params.every((param, index) => matcherMatchesOperand(param.matcher, operands[index])));
31
+ if (matches.length === 0) {
32
+ return { kind: 'no_match', candidates: arityMatches };
33
+ }
34
+ if (matches.length === 1) {
35
+ return { kind: 'selected', overload: matches[0] };
36
+ }
37
+ const selected = mostSpecificOverload(matches, operands);
38
+ return selected
39
+ ? { kind: 'selected', overload: selected }
40
+ : { kind: 'ambiguous', candidates: matches };
41
+ }
42
+ function mostSpecificOverload(overloads, operands) {
43
+ for (const candidate of overloads) {
44
+ let beatsAll = true;
45
+ for (const other of overloads) {
46
+ if (candidate === other)
47
+ continue;
48
+ if (compareOverloadSpecificity(candidate, other, operands) !== 'x') {
49
+ beatsAll = false;
50
+ break;
51
+ }
52
+ }
53
+ if (beatsAll)
54
+ return candidate;
55
+ }
56
+ return undefined;
57
+ }
58
+ function compareOverloadSpecificity(x, y, operands) {
59
+ const votes = operands.reduce((current, operand, index) => {
60
+ return addSpecificityVote(current, compareMatcherSpecificity(x.params[index].matcher, y.params[index].matcher, operand));
61
+ }, { x: 0, y: 0 });
62
+ return specificityFromVotes(votes);
63
+ }
64
+ function addSpecificityVote(votes, comparison) {
65
+ if (comparison === 'x')
66
+ return { ...votes, x: votes.x + 1 };
67
+ if (comparison === 'y')
68
+ return { ...votes, y: votes.y + 1 };
69
+ return votes;
70
+ }
71
+ function specificityFromVotes(votes) {
72
+ if (votes.x > 0 && votes.y === 0)
73
+ return 'x';
74
+ if (votes.y > 0 && votes.x === 0)
75
+ return 'y';
76
+ if (votes.x === 0 && votes.y === 0)
77
+ return 'equal';
78
+ return 'incomparable';
79
+ }
80
+ function compareMatcherSpecificity(x, y, operand) {
81
+ if (x.kind === y.kind)
82
+ return 'equal';
83
+ return (compareFixedMatcherSpecificity(x, y, operand) ??
84
+ compareImmediateMatcherSpecificity(x, y, operand) ??
85
+ 'equal');
86
+ }
87
+ function compareFixedMatcherSpecificity(x, y, operand) {
88
+ if (x.kind === 'fixed' && fixedTokenBeatsMatcher(x, y, operand))
89
+ return 'x';
90
+ if (y.kind === 'fixed' && fixedTokenBeatsMatcher(y, x, operand))
91
+ return 'y';
92
+ return undefined;
93
+ }
94
+ function compareImmediateMatcherSpecificity(x, y, operand) {
95
+ if (operand.kind !== 'imm' || !expressionFitsKnownImm8(operand.expression))
96
+ return undefined;
97
+ if (x.kind === 'imm8' && y.kind === 'imm16')
98
+ return 'x';
99
+ if (x.kind === 'imm16' && y.kind === 'imm8')
100
+ return 'y';
101
+ return undefined;
102
+ }
103
+ function fixedTokenBeatsMatcher(fixed, other, operand) {
104
+ return ((other.kind === 'reg8' && operand.kind === 'reg8' && operand.text === fixed.token) ||
105
+ (other.kind === 'reg16' && operand.kind === 'reg16' && operand.text === fixed.token) ||
106
+ (other.kind === 'cc' &&
107
+ isConditionToken(fixed.token) &&
108
+ operand.text.toUpperCase() === fixed.token));
109
+ }
110
+ function matcherMatchesOperand(matcher, operand) {
111
+ if (matcher.kind === 'fixed')
112
+ return operand.text.toUpperCase() === matcher.token;
113
+ return MATCHER_OPERAND_PREDICATES[matcher.kind]?.(operand) ?? false;
114
+ }
115
+ function isMemoryOperand(operand) {
116
+ return operand.kind === 'reg-indirect' || operand.kind === 'mem-abs' || operand.kind === 'indexed';
117
+ }
118
+ export function formatOpSelectionDiagnostic(selection, overloads, operands) {
119
+ const name = overloads[0]?.name ?? '<unknown>';
120
+ const operandSummary = `call-site operands: (${operands.map(formatOpOperand).join(', ')})`;
121
+ switch (selection.kind) {
122
+ case 'arity_mismatch':
123
+ return [
124
+ `No op overload of "${name}" accepts ${operands.length} operand(s).`,
125
+ 'available overloads:',
126
+ ...overloads.map((overload) => ` - ${formatOpSignature(overload)}`),
127
+ ].join('\n');
128
+ case 'no_match':
129
+ return noMatchDiagnostic(selection.candidates, operands, name, operandSummary);
130
+ case 'ambiguous':
131
+ return [
132
+ `Ambiguous op overload for "${name}" (${selection.candidates.length} matches).`,
133
+ operandSummary,
134
+ 'equally specific candidates:',
135
+ ...selection.candidates.map((candidate) => ` - ${formatOpSignatureWithLocation(candidate)}`),
136
+ ].join('\n');
137
+ }
138
+ }
139
+ function noMatchDiagnostic(candidates, operands, name, operandSummary) {
140
+ return [
141
+ `No matching op overload for "${name}" with provided operands.`,
142
+ operandSummary,
143
+ 'available overloads:',
144
+ ...candidates.map((candidate) => {
145
+ const mismatch = firstMismatchReason(candidate, operands);
146
+ return ` - ${formatOpSignatureWithLocation(candidate)}${mismatch ? ` ; ${mismatch}` : ''}`;
147
+ }),
148
+ ].join('\n');
149
+ }
150
+ function firstMismatchReason(overload, operands) {
151
+ for (let index = 0; index < overload.params.length; index += 1) {
152
+ const param = overload.params[index];
153
+ const operand = operands[index];
154
+ if (!matcherMatchesOperand(param.matcher, operand)) {
155
+ return `${param.name}: ${matcherMismatchReason(param.matcher, operand)}`;
156
+ }
157
+ }
158
+ return undefined;
159
+ }
160
+ function matcherMismatchReason(matcher, operand) {
161
+ const expected = matcher.kind === 'fixed' ? matcher.token : MATCHER_EXPECTATIONS[matcher.kind];
162
+ return `expects ${expected}, got ${formatOpOperand(operand)}`;
163
+ }
164
+ function formatOpSignature(op) {
165
+ return `${op.name}(${op.params.map((param) => `${param.name} ${formatMatcher(param.matcher)}`).join(', ')})`;
166
+ }
167
+ function formatOpSignatureWithLocation(op) {
168
+ return `${formatOpSignature(op)} (${op.sourceName}:${op.line})`;
169
+ }
170
+ function formatMatcher(matcher) {
171
+ return matcher.kind === 'fixed' ? matcher.token : matcher.kind;
172
+ }
@@ -6,9 +6,10 @@ export { formatDiagnostic, formatNextDiagnostic } from './diagnostics/format.js'
6
6
  export { analyzeProgram, loadProgram, analyzeProgramNext, loadProgramNext } from './tooling/api.js';
7
7
  export { DiagnosticIds } from './model/diagnostic.js';
8
8
  export type { DiagnosticId, DiagnosticSeverity, Diagnostic } from './model/diagnostic.js';
9
- export { analyzeRegisterCareForTools, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, } from './register-care/tooling.js';
9
+ export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type AnalyzeRegisterContractsForToolsOptions, type AnalyzeRegisterContractsForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, type RegisterCareTextEdit, type RegisterContractsCandidateDiagnostic, type RegisterContractsCodeAction, type RegisterContractsTextEdit, } from './register-contracts/tooling.js';
10
10
  export { compile, defaultFormatWriters, writeHex } from './api-compile.js';
11
11
  export type { AddressRange, Artifact, CompileDependencies, CompileFunctionOptions, CompileResult, CompileNextDependencies, CompileNextFunctionOptions, EmittedByteMap, FormatWriters, CompileNextResult as CompileNextProgramResult, } from './api-compile.js';
12
12
  export type { AnalyzeProgramOptions, AnalyzeProgramResult, LoadProgramOptions, LoadProgramResult, LoadedProgram, AnalyzeProgramNextOptions, AnalyzeProgramNextResult, LoadProgramNextOptions, LoadProgramNextResult, LoadedProgramNext, } from './tooling/api.js';
13
13
  export type { CaseStyleMode } from './tooling/case-style.js';
14
+ export type { RegisterCareMode, RegisterCareOutputCandidate, RegisterCareUnit, RegisterContractsMode, RegisterContractsOutputCandidate, RegisterContractsUnit, } from './register-contracts/types.js';
14
15
  export type { D8mArtifact, D8mGenerator, D8mJson, D8mFileEntry, D8mFileSymbol, D8mSegment, D8mSymbol, SymbolEntry, WriteD8mOptions, } from './outputs/types.js';
package/dist/src/index.js CHANGED
@@ -3,5 +3,5 @@ export { compileArtifacts, compileNextArtifacts } from './core/compile-artifacts
3
3
  export { formatDiagnostic, formatNextDiagnostic } from './diagnostics/format.js';
4
4
  export { analyzeProgram, loadProgram, analyzeProgramNext, loadProgramNext } from './tooling/api.js';
5
5
  export { DiagnosticIds } from './model/diagnostic.js';
6
- export { analyzeRegisterCareForTools, } from './register-care/tooling.js';
6
+ export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, } from './register-contracts/tooling.js';
7
7
  export { compile, defaultFormatWriters, writeHex } from './api-compile.js';
@@ -44,7 +44,11 @@ export declare const DiagnosticIds: {
44
44
  readonly TypeError: "AZM403";
45
45
  readonly CaseStyleLint: "AZM500";
46
46
  readonly IndexParenRedundant: "AZM501";
47
+ readonly RegisterContractsConflict: "AZM600";
48
+ readonly RegisterContractsUnknownBoundary: "AZM601";
49
+ /** @deprecated Use RegisterContractsConflict. */
47
50
  readonly RegisterCareConflict: "AZM600";
51
+ /** @deprecated Use RegisterContractsUnknownBoundary. */
48
52
  readonly RegisterCareUnknownBoundary: "AZM601";
49
53
  };
50
54
  export type DiagnosticId = (typeof DiagnosticIds)[keyof typeof DiagnosticIds];
@@ -24,6 +24,10 @@ export const DiagnosticIds = {
24
24
  TypeError: 'AZM403',
25
25
  CaseStyleLint: 'AZM500',
26
26
  IndexParenRedundant: 'AZM501',
27
+ RegisterContractsConflict: 'AZM600',
28
+ RegisterContractsUnknownBoundary: 'AZM601',
29
+ /** @deprecated Use RegisterContractsConflict. */
27
30
  RegisterCareConflict: 'AZM600',
31
+ /** @deprecated Use RegisterContractsUnknownBoundary. */
28
32
  RegisterCareUnknownBoundary: 'AZM601',
29
33
  };
@@ -0,0 +1,10 @@
1
+ import type { Expression } from '../model/expression.js';
2
+ import { type LayoutRecord } from '../semantics/expression-evaluation.js';
3
+ export type ConstantMap = ReadonlyMap<string, number>;
4
+ export type LayoutMap = ReadonlyMap<string, LayoutRecord>;
5
+ export type LoweredEvalContext = {
6
+ readonly constants: ConstantMap;
7
+ readonly symbols: ConstantMap;
8
+ readonly layouts: LayoutMap;
9
+ };
10
+ export declare function evaluateLoweredConstant(expression: Expression, evalContext: LoweredEvalContext): number | undefined;
@@ -0,0 +1,75 @@
1
+ import { evaluateExpression, } from '../semantics/expression-evaluation.js';
2
+ import { applyBinaryOperator, applyByteFunction, applyUnaryOperator, } from '../semantics/constant-operators.js';
3
+ const silentSpan = { sourceName: '', line: 0, column: 0 };
4
+ export function evaluateLoweredConstant(expression, evalContext) {
5
+ switch (expression.kind) {
6
+ case 'number':
7
+ return expression.value;
8
+ case 'symbol':
9
+ return evalContext.constants.get(expression.name);
10
+ case 'type-size':
11
+ return evaluateLoweredTypeSize(expression, evalContext);
12
+ case 'offset':
13
+ case 'sizeof':
14
+ return evaluateLayoutExpression(expression, evalContext);
15
+ case 'byte-function':
16
+ return evaluateLoweredByteFunction(expression, evalContext);
17
+ case 'unary':
18
+ return evaluateLoweredUnary(expression, evalContext);
19
+ case 'binary':
20
+ return evaluateLoweredBinary(expression, evalContext);
21
+ default:
22
+ return undefined;
23
+ }
24
+ }
25
+ function evaluateLoweredTypeSize(expression, evalContext) {
26
+ const constant = evalContext.constants.get(expression.typeExpr.name);
27
+ return constant ?? evaluateLayoutExpression(expression, evalContext);
28
+ }
29
+ function evaluateLayoutExpression(expression, evalContext) {
30
+ return evaluateExpression(expression, {}, new Map(), silentSpan, [], {
31
+ currentLocation: 0,
32
+ layouts: evalContext.layouts,
33
+ reportUnknown: false,
34
+ });
35
+ }
36
+ function evaluateLoweredByteFunction(expression, evalContext) {
37
+ const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
38
+ return value === undefined ? undefined : applyByteFunction(expression.function, value);
39
+ }
40
+ function evaluateLoweredUnary(expression, evalContext) {
41
+ const value = evaluateLoweredConstant(expression.expression, evalContext);
42
+ return value === undefined ? undefined : applyUnaryOperator(expression.operator, value);
43
+ }
44
+ function evaluateLoweredBinary(expression, evalContext) {
45
+ const left = evaluateLoweredConstant(expression.left, evalContext);
46
+ const right = evaluateLoweredConstant(expression.right, evalContext);
47
+ return left === undefined || right === undefined
48
+ ? undefined
49
+ : applyBinaryOperator(expression.operator, left, right);
50
+ }
51
+ function evaluateLoweredResolvedConstant(expression, evalContext) {
52
+ switch (expression.kind) {
53
+ case 'symbol':
54
+ return evalContext.symbols.get(expression.name) ?? evalContext.constants.get(expression.name);
55
+ case 'unary':
56
+ return evaluateResolvedUnary(expression, evalContext);
57
+ case 'binary':
58
+ return evaluateResolvedBinary(expression, evalContext);
59
+ case 'byte-function':
60
+ return evaluateLoweredByteFunction(expression, evalContext);
61
+ default:
62
+ return evaluateLoweredConstant(expression, evalContext);
63
+ }
64
+ }
65
+ function evaluateResolvedUnary(expression, evalContext) {
66
+ const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
67
+ return value === undefined ? undefined : applyUnaryOperator(expression.operator, value);
68
+ }
69
+ function evaluateResolvedBinary(expression, evalContext) {
70
+ const left = evaluateLoweredResolvedConstant(expression.left, evalContext);
71
+ const right = evaluateLoweredResolvedConstant(expression.right, evalContext);
72
+ return left === undefined || right === undefined
73
+ ? undefined
74
+ : applyBinaryOperator(expression.operator, left, right);
75
+ }
@@ -0,0 +1,5 @@
1
+ import type { Expression } from '../model/expression.js';
2
+ import { type LoweredEvalContext } from './asm80-expression-evaluation.js';
3
+ export { evaluateLoweredConstant, type ConstantMap, type LayoutMap, type LoweredEvalContext, } from './asm80-expression-evaluation.js';
4
+ export declare function formatExpression(expression: Expression, evalContext: LoweredEvalContext, width: 'byte' | 'word' | 'auto'): string | undefined;
5
+ export declare function formatLoweredNumber(value: number, width: 'byte' | 'word' | 'auto'): string;
@@ -0,0 +1,47 @@
1
+ import { evaluateLoweredConstant } from './asm80-expression-evaluation.js';
2
+ export { evaluateLoweredConstant, } from './asm80-expression-evaluation.js';
3
+ const formatUnaryExpression = {
4
+ '+': (inner) => inner,
5
+ '-': (inner) => `-${inner}`,
6
+ '~': () => undefined,
7
+ };
8
+ export function formatExpression(expression, evalContext, width) {
9
+ const value = evaluateLoweredConstant(expression, evalContext);
10
+ if (value !== undefined) {
11
+ return formatLoweredNumber(value, width);
12
+ }
13
+ return formatUnevaluatedExpression(expression, evalContext, width);
14
+ }
15
+ export function formatLoweredNumber(value, width) {
16
+ const normalized = value < 0 ? value & 0xffff : value;
17
+ const digits = normalized.toString(16).toUpperCase();
18
+ const minWidth = width === 'word' || (width === 'auto' && normalized > 0xff) ? 4 : 2;
19
+ return `$${digits.padStart(minWidth, '0')}`;
20
+ }
21
+ function formatUnevaluatedExpression(expression, evalContext, width) {
22
+ switch (expression.kind) {
23
+ case 'symbol':
24
+ return expression.name;
25
+ case 'type-size':
26
+ return expression.typeExpr.name;
27
+ case 'current-location':
28
+ return '$';
29
+ case 'unary':
30
+ return formatUnary(expression, evalContext, width);
31
+ case 'binary':
32
+ return formatBinary(expression, evalContext, width);
33
+ default:
34
+ return undefined;
35
+ }
36
+ }
37
+ function formatUnary(expression, evalContext, width) {
38
+ const inner = formatExpression(expression.expression, evalContext, width);
39
+ return inner === undefined ? undefined : formatUnaryExpression[expression.operator](inner);
40
+ }
41
+ function formatBinary(expression, evalContext, width) {
42
+ const left = formatExpression(expression.left, evalContext, width);
43
+ const right = formatExpression(expression.right, evalContext, width);
44
+ return left === undefined || right === undefined
45
+ ? undefined
46
+ : `${left}${expression.operator}${right}`;
47
+ }
@@ -0,0 +1,16 @@
1
+ import type { Z80Instruction } from '../z80/instruction.js';
2
+ import { type LoweredEvalContext } from './asm80-expressions.js';
3
+ import { formatIndexedMemory, formatLd, type LdOperand } from './asm80-ld-operands.js';
4
+ export type BitInstruction = Extract<Z80Instruction, {
5
+ readonly mnemonic: 'bit' | 'res' | 'set';
6
+ }>;
7
+ export type RotateShiftInstruction = Extract<Z80Instruction, {
8
+ readonly mnemonic: 'rlc' | 'rrc' | 'rl' | 'rr' | 'sla' | 'sra' | 'sll' | 'sls' | 'srl';
9
+ }>;
10
+ export { formatIndexedMemory, formatLd, type LdOperand };
11
+ export declare function formatRotateShift(instruction: RotateShiftInstruction, evalContext: LoweredEvalContext): {
12
+ readonly text: string;
13
+ } | undefined;
14
+ export declare function formatBitOp(instruction: BitInstruction, evalContext: LoweredEvalContext): {
15
+ readonly text: string;
16
+ } | undefined;
@@ -0,0 +1,38 @@
1
+ import { formatLoweredNumber } from './asm80-expressions.js';
2
+ import { formatIndexedMemory, formatLd } from './asm80-ld-operands.js';
3
+ export { formatIndexedMemory, formatLd };
4
+ export function formatRotateShift(instruction, evalContext) {
5
+ const operand = formatBitOperand(instruction.operand, evalContext);
6
+ if (operand === undefined) {
7
+ return undefined;
8
+ }
9
+ const parts = [operand];
10
+ if (instruction.destination) {
11
+ parts.push(instruction.destination.register);
12
+ }
13
+ return { text: `${instruction.mnemonic} ${parts.join(', ')}` };
14
+ }
15
+ export function formatBitOp(instruction, evalContext) {
16
+ const bit = formatLoweredNumber(instruction.bit, 'byte');
17
+ const operand = formatBitOperand(instruction.operand, evalContext);
18
+ if (operand === undefined) {
19
+ return undefined;
20
+ }
21
+ const parts = [bit, operand];
22
+ if (instruction.destination) {
23
+ parts.push(instruction.destination.register);
24
+ }
25
+ return { text: `${instruction.mnemonic} ${parts.join(', ')}` };
26
+ }
27
+ function formatBitOperand(operand, evalContext) {
28
+ if (operand.kind === 'reg8') {
29
+ return operand.register;
30
+ }
31
+ if (operand.kind === 'reg-indirect' && operand.register === 'hl') {
32
+ return '(HL)';
33
+ }
34
+ if (operand.kind === 'indexed') {
35
+ return formatIndexedMemory(operand.register, operand.displacement, evalContext);
36
+ }
37
+ return undefined;
38
+ }
@@ -0,0 +1,5 @@
1
+ import type { Z80Instruction } from '../z80/instruction.js';
2
+ import { type LoweredEvalContext } from './asm80-expressions.js';
3
+ export declare function formatInstruction(instruction: Z80Instruction, evalContext: LoweredEvalContext): {
4
+ readonly text: string;
5
+ } | undefined;