@jhlagado/azm 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/README.md +239 -76
  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 +55 -227
  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/assemble-program.js +5 -0
  15. package/dist/src/assembly/fixup-emission.js +30 -48
  16. package/dist/src/assembly/import-visibility.d.ts +3 -0
  17. package/dist/src/assembly/import-visibility.js +204 -0
  18. package/dist/src/assembly/program-emission.js +163 -164
  19. package/dist/src/cli/artifact-files.d.ts +15 -0
  20. package/dist/src/cli/artifact-files.js +86 -0
  21. package/dist/src/cli/parse-args.d.ts +6 -5
  22. package/dist/src/cli/parse-args.js +162 -136
  23. package/dist/src/cli/run.js +4 -1
  24. package/dist/src/cli/usage.d.ts +1 -0
  25. package/dist/src/cli/usage.js +33 -0
  26. package/dist/src/cli/write-artifacts.js +18 -91
  27. package/dist/src/core/compile.js +51 -274
  28. package/dist/src/core/conditional-assembly.d.ts +6 -0
  29. package/dist/src/core/conditional-assembly.js +181 -0
  30. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  31. package/dist/src/expansion/op-constant-expression.js +52 -0
  32. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  33. package/dist/src/expansion/op-expand-selected.js +143 -0
  34. package/dist/src/expansion/op-expansion.d.ts +5 -53
  35. package/dist/src/expansion/op-expansion.js +85 -815
  36. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  37. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  38. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  39. package/dist/src/expansion/op-local-labels.js +166 -0
  40. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  41. package/dist/src/expansion/op-operand-splitting.js +44 -0
  42. package/dist/src/expansion/op-operands.d.ts +53 -0
  43. package/dist/src/expansion/op-operands.js +66 -0
  44. package/dist/src/expansion/op-selection.d.ts +18 -0
  45. package/dist/src/expansion/op-selection.js +172 -0
  46. package/dist/src/index.d.ts +2 -1
  47. package/dist/src/index.js +1 -1
  48. package/dist/src/model/diagnostic.d.ts +4 -0
  49. package/dist/src/model/diagnostic.js +4 -0
  50. package/dist/src/node/source-host.js +40 -13
  51. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  52. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  53. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-expressions.js +47 -0
  55. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  56. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  57. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  58. package/dist/src/outputs/asm80-instructions.js +272 -0
  59. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  60. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  61. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  62. package/dist/src/outputs/asm80-strings.js +14 -0
  63. package/dist/src/outputs/d8-files.d.ts +10 -0
  64. package/dist/src/outputs/d8-files.js +103 -0
  65. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  66. package/dist/src/outputs/d8-helpers.js +136 -0
  67. package/dist/src/outputs/hex.js +26 -18
  68. package/dist/src/outputs/types.d.ts +16 -10
  69. package/dist/src/outputs/write-asm80.js +72 -597
  70. package/dist/src/outputs/write-d8.js +6 -216
  71. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  72. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  73. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  74. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  75. package/dist/src/register-contracts/analyze.js +73 -0
  76. package/dist/src/register-contracts/annotate.d.ts +11 -0
  77. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  78. package/dist/src/register-contracts/annotations.d.ts +8 -0
  79. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  80. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  81. package/dist/src/register-contracts/boundaryHints.js +24 -0
  82. package/dist/src/register-contracts/carriers.d.ts +2 -0
  83. package/dist/src/register-contracts/constants.d.ts +4 -0
  84. package/dist/src/register-contracts/constants.js +51 -0
  85. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  86. package/dist/src/register-contracts/controlFlow.js +55 -0
  87. package/dist/src/register-contracts/fix.d.ts +11 -0
  88. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  89. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  90. package/dist/src/register-contracts/instruction-head.js +3 -0
  91. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  92. package/dist/src/register-contracts/instruction-operands.js +101 -0
  93. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  94. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  95. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  96. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  97. package/dist/src/register-contracts/liveness.d.ts +3 -0
  98. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  99. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  100. package/dist/src/register-contracts/operand-register-name.js +13 -0
  101. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  102. package/dist/src/{register-care → register-contracts}/profiles.js +2 -2
  103. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  104. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  105. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  106. package/dist/src/register-contracts/programModel-routines.js +144 -0
  107. package/dist/src/register-contracts/programModel.d.ts +3 -0
  108. package/dist/src/register-contracts/programModel.js +14 -0
  109. package/dist/src/register-contracts/report.d.ts +5 -0
  110. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  111. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  112. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  113. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  114. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  115. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  116. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  117. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  118. package/dist/src/register-contracts/smartComments.js +92 -0
  119. package/dist/src/register-contracts/summaries.d.ts +12 -0
  120. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  121. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  122. package/dist/src/register-contracts/summary-boundary.js +40 -0
  123. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  124. package/dist/src/register-contracts/summary-contract.js +45 -0
  125. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  126. package/dist/src/register-contracts/summary-result.js +122 -0
  127. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  128. package/dist/src/register-contracts/summary-state.js +88 -0
  129. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  130. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  131. package/dist/src/register-contracts/summary.d.ts +3 -0
  132. package/dist/src/register-contracts/summary.js +266 -0
  133. package/dist/src/register-contracts/tooling.d.ts +57 -0
  134. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  135. package/dist/src/register-contracts/types.d.ts +188 -0
  136. package/dist/src/semantics/binary-operators.d.ts +2 -0
  137. package/dist/src/semantics/binary-operators.js +15 -0
  138. package/dist/src/semantics/byte-functions.d.ts +2 -0
  139. package/dist/src/semantics/byte-functions.js +7 -0
  140. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  141. package/dist/src/semantics/constant-operator-types.js +1 -0
  142. package/dist/src/semantics/constant-operators.d.ts +3 -0
  143. package/dist/src/semantics/constant-operators.js +3 -0
  144. package/dist/src/semantics/diagnostics.d.ts +3 -0
  145. package/dist/src/semantics/diagnostics.js +10 -0
  146. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  147. package/dist/src/semantics/expression-evaluation.js +22 -334
  148. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  149. package/dist/src/semantics/layout-evaluation.js +202 -0
  150. package/dist/src/semantics/layout-format.d.ts +5 -0
  151. package/dist/src/semantics/layout-format.js +31 -0
  152. package/dist/src/semantics/layout-path.d.ts +24 -0
  153. package/dist/src/semantics/layout-path.js +58 -0
  154. package/dist/src/semantics/unary-operators.d.ts +2 -0
  155. package/dist/src/semantics/unary-operators.js +8 -0
  156. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  157. package/dist/src/source/line-comment-scanner.js +51 -0
  158. package/dist/src/source/logical-lines.d.ts +3 -0
  159. package/dist/src/source/source-span.d.ts +2 -0
  160. package/dist/src/source/strip-line-comment.js +8 -44
  161. package/dist/src/syntax/directive-aliases.js +36 -22
  162. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  163. package/dist/src/syntax/expression-tokenizer.js +310 -0
  164. package/dist/src/syntax/parse-directive-statement.d.ts +9 -0
  165. package/dist/src/syntax/parse-directive-statement.js +309 -0
  166. package/dist/src/syntax/parse-expression.d.ts +2 -2
  167. package/dist/src/syntax/parse-expression.js +7 -568
  168. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  169. package/dist/src/syntax/parse-layout-declarations.js +189 -0
  170. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  171. package/dist/src/syntax/parse-layout-expression.js +175 -0
  172. package/dist/src/syntax/parse-line.js +21 -273
  173. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  174. package/dist/src/syntax/parse-token-expression.js +133 -0
  175. package/dist/src/tooling/api.js +1 -1
  176. package/dist/src/tooling/case-style.js +47 -30
  177. package/dist/src/z80/effect-groups.d.ts +38 -0
  178. package/dist/src/z80/effect-groups.js +265 -0
  179. package/dist/src/z80/effect-units.d.ts +18 -0
  180. package/dist/src/z80/effect-units.js +165 -0
  181. package/dist/src/z80/effects.d.ts +1 -1
  182. package/dist/src/z80/effects.js +94 -557
  183. package/dist/src/z80/encode-core.d.ts +2 -0
  184. package/dist/src/z80/encode-core.js +42 -0
  185. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  186. package/dist/src/z80/encode-ld-helpers.js +172 -0
  187. package/dist/src/z80/encode-ld.d.ts +2 -0
  188. package/dist/src/z80/encode-ld.js +285 -0
  189. package/dist/src/z80/encode.js +190 -542
  190. package/dist/src/z80/ld-support.d.ts +3 -0
  191. package/dist/src/z80/ld-support.js +146 -0
  192. package/dist/src/z80/operand-split-state.d.ts +8 -0
  193. package/dist/src/z80/operand-split-state.js +46 -0
  194. package/dist/src/z80/operand-split.d.ts +1 -0
  195. package/dist/src/z80/operand-split.js +13 -0
  196. package/dist/src/z80/parse-basic.d.ts +4 -0
  197. package/dist/src/z80/parse-basic.js +39 -0
  198. package/dist/src/z80/parse-branch.d.ts +4 -0
  199. package/dist/src/z80/parse-branch.js +218 -0
  200. package/dist/src/z80/parse-conditions.d.ts +6 -0
  201. package/dist/src/z80/parse-conditions.js +10 -0
  202. package/dist/src/z80/parse-exchange.d.ts +2 -0
  203. package/dist/src/z80/parse-exchange.js +30 -0
  204. package/dist/src/z80/parse-instruction.js +224 -1010
  205. package/dist/src/z80/parse-io-control.d.ts +5 -0
  206. package/dist/src/z80/parse-io-control.js +108 -0
  207. package/dist/src/z80/parse-ld.d.ts +2 -0
  208. package/dist/src/z80/parse-ld.js +83 -0
  209. package/dist/src/z80/parse-operands.d.ts +41 -0
  210. package/dist/src/z80/parse-operands.js +259 -0
  211. package/docs/codebase/01-orientation-and-repository-layout.md +192 -0
  212. package/docs/codebase/02-source-loading-and-parsing.md +263 -0
  213. package/docs/codebase/03-assembly-and-z80-emission.md +251 -0
  214. package/docs/codebase/04-ops-and-register-contracts.md +237 -0
  215. package/docs/codebase/05-interfaces-and-output-artifacts.md +253 -0
  216. package/docs/codebase/06-verification-and-maintenance.md +202 -0
  217. package/docs/codebase/appendices/a-directory-file-reference.md +253 -0
  218. package/docs/codebase/appendices/b-compile-flow-reference.md +103 -0
  219. package/docs/codebase/appendices/c-public-surface-reference.md +106 -0
  220. package/docs/codebase/appendices/index.md +16 -0
  221. package/docs/codebase/index.md +46 -0
  222. package/package.json +2 -3
  223. package/dist/src/register-care/accept-output.d.ts +0 -2
  224. package/dist/src/register-care/analyze.js +0 -166
  225. package/dist/src/register-care/annotate.d.ts +0 -11
  226. package/dist/src/register-care/annotations.d.ts +0 -8
  227. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  228. package/dist/src/register-care/boundaryHints.js +0 -80
  229. package/dist/src/register-care/carriers.d.ts +0 -2
  230. package/dist/src/register-care/controlFlow.d.ts +0 -5
  231. package/dist/src/register-care/controlFlow.js +0 -38
  232. package/dist/src/register-care/fix.d.ts +0 -11
  233. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  234. package/dist/src/register-care/instruction-shape.js +0 -129
  235. package/dist/src/register-care/liveness.d.ts +0 -3
  236. package/dist/src/register-care/programModel.d.ts +0 -3
  237. package/dist/src/register-care/programModel.js +0 -266
  238. package/dist/src/register-care/report.d.ts +0 -5
  239. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  240. package/dist/src/register-care/smartComments.d.ts +0 -5
  241. package/dist/src/register-care/smartComments.js +0 -243
  242. package/dist/src/register-care/summaries.d.ts +0 -12
  243. package/dist/src/register-care/summary.d.ts +0 -3
  244. package/dist/src/register-care/summary.js +0 -474
  245. package/dist/src/register-care/tooling.d.ts +0 -43
  246. package/dist/src/register-care/types.d.ts +0 -172
  247. package/docs/reference/cli.md +0 -151
  248. package/docs/reference/tooling-api.md +0 -316
  249. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  250. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  251. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  252. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  253. /package/dist/src/{register-care → register-contracts}/types.js +0 -0
@@ -0,0 +1,3 @@
1
+ import type { Z80Instruction } from '../z80/instruction.js';
2
+ import type { OpOperand } from './op-expansion.js';
3
+ export declare function instantiateTemplateInstruction(mnemonic: string, concrete: readonly OpOperand[]): Z80Instruction | undefined;
@@ -0,0 +1,194 @@
1
+ import { parseLogicalLine } from '../syntax/parse-line.js';
2
+ export function instantiateTemplateInstruction(mnemonic, concrete) {
3
+ return (instantiateLoadInstruction(mnemonic, concrete) ??
4
+ instantiatePortInstruction(mnemonic, concrete) ??
5
+ instantiateIncDecInstruction(mnemonic, concrete) ??
6
+ instantiateBranchInstruction(mnemonic, concrete) ??
7
+ instantiateAluInstruction(mnemonic, concrete) ??
8
+ parseExpandedInstruction(mnemonic, concrete));
9
+ }
10
+ function instantiateLoadInstruction(mnemonic, concrete) {
11
+ if (mnemonic !== 'ld' || concrete.length !== 2)
12
+ return undefined;
13
+ const target = toZ80Operand(concrete[0]);
14
+ const source = toZ80Operand(concrete[1]);
15
+ return target && source ? { mnemonic: 'ld', target, source } : undefined;
16
+ }
17
+ function instantiatePortInstruction(mnemonic, concrete) {
18
+ if (mnemonic === 'in')
19
+ return instantiateInInstruction(concrete);
20
+ if (mnemonic === 'out')
21
+ return instantiateOutInstruction(concrete);
22
+ return undefined;
23
+ }
24
+ function instantiateInInstruction(concrete) {
25
+ if (concrete.length !== 2 || concrete[0]?.kind !== 'reg8')
26
+ return undefined;
27
+ const port = toPortOperand(concrete[1]);
28
+ return port
29
+ ? {
30
+ mnemonic: 'in',
31
+ target: { kind: 'reg8', register: concrete[0].register },
32
+ port,
33
+ }
34
+ : undefined;
35
+ }
36
+ function instantiateOutInstruction(concrete) {
37
+ if (concrete.length !== 2)
38
+ return undefined;
39
+ const port = toPortOperand(concrete[0]);
40
+ const source = concrete[1]?.kind === 'reg8' ? concrete[1] : undefined;
41
+ return port && source
42
+ ? {
43
+ mnemonic: 'out',
44
+ port,
45
+ source: { kind: 'reg8', register: source.register },
46
+ }
47
+ : undefined;
48
+ }
49
+ function instantiateIncDecInstruction(mnemonic, concrete) {
50
+ if ((mnemonic !== 'inc' && mnemonic !== 'dec') || concrete.length !== 1)
51
+ return undefined;
52
+ const operand = toIncDecOperand(concrete[0]);
53
+ return operand ? { mnemonic, operand } : undefined;
54
+ }
55
+ function instantiateBranchInstruction(mnemonic, concrete) {
56
+ if (mnemonic === 'jp')
57
+ return instantiateJpInstruction(concrete);
58
+ if (mnemonic === 'jr')
59
+ return instantiateJrInstruction(concrete);
60
+ return undefined;
61
+ }
62
+ function instantiateJpInstruction(concrete) {
63
+ if (isSingleImmediate(concrete)) {
64
+ return { mnemonic: 'jp', expression: concrete[0].expression };
65
+ }
66
+ if (isConditionalImmediate(concrete, isConditionToken)) {
67
+ return {
68
+ mnemonic: 'jp-cc',
69
+ condition: concrete[0].text.toLowerCase(),
70
+ expression: concrete[1].expression,
71
+ };
72
+ }
73
+ return undefined;
74
+ }
75
+ function instantiateJrInstruction(concrete) {
76
+ if (isSingleImmediate(concrete)) {
77
+ return { mnemonic: 'jr', expression: concrete[0].expression };
78
+ }
79
+ if (isConditionalImmediate(concrete, isRelativeConditionToken)) {
80
+ return {
81
+ mnemonic: 'jr-cc',
82
+ condition: concrete[0].text.toLowerCase(),
83
+ expression: concrete[1].expression,
84
+ };
85
+ }
86
+ return undefined;
87
+ }
88
+ function isSingleImmediate(concrete) {
89
+ return concrete.length === 1 && concrete[0]?.kind === 'imm';
90
+ }
91
+ function isConditionalImmediate(concrete, isCondition) {
92
+ return (concrete.length === 2 &&
93
+ isCondition(concrete[0]?.text ?? '') &&
94
+ concrete[1]?.kind === 'imm');
95
+ }
96
+ function instantiateAluInstruction(mnemonic, concrete) {
97
+ if (!isAluMnemonic(mnemonic))
98
+ return undefined;
99
+ if (isRegisterPairAluShape(mnemonic, concrete)) {
100
+ return instantiateRegisterPairAluInstruction(mnemonic, concrete);
101
+ }
102
+ return instantiateAccumulatorAluInstruction(mnemonic, concrete);
103
+ }
104
+ function isRegisterPairAluShape(mnemonic, concrete) {
105
+ return ((mnemonic === 'add' || mnemonic === 'adc' || mnemonic === 'sbc') &&
106
+ concrete.length === 2 &&
107
+ concrete[0]?.kind === 'reg16' &&
108
+ concrete[1]?.kind === 'reg16');
109
+ }
110
+ function instantiateRegisterPairAluInstruction(mnemonic, concrete) {
111
+ const target = toZ80Operand(concrete[0]);
112
+ const source = toZ80Operand(concrete[1]);
113
+ return target?.kind === 'reg16' && source?.kind === 'reg16'
114
+ ? { mnemonic, target, source }
115
+ : undefined;
116
+ }
117
+ function instantiateAccumulatorAluInstruction(mnemonic, concrete) {
118
+ if (concrete.length === 1) {
119
+ const source = toZ80Operand(concrete[0]);
120
+ return source ? { mnemonic, source } : undefined;
121
+ }
122
+ if (!isExplicitAccumulatorAluShape(concrete))
123
+ return undefined;
124
+ const source = toZ80Operand(concrete[1]);
125
+ return source ? { mnemonic, source } : undefined;
126
+ }
127
+ function isExplicitAccumulatorAluShape(concrete) {
128
+ return concrete.length === 2 && concrete[0]?.kind === 'reg8' && concrete[0].register === 'a';
129
+ }
130
+ function toZ80Operand(operand) {
131
+ switch (operand.kind) {
132
+ case 'reg8':
133
+ return { kind: 'reg8', register: operand.register };
134
+ case 'reg16':
135
+ return { kind: 'reg16', register: operand.register };
136
+ case 'reg-indirect':
137
+ return { kind: 'reg-indirect', register: operand.register };
138
+ case 'mem-abs':
139
+ return { kind: 'mem-abs', expression: operand.expression };
140
+ case 'indexed':
141
+ return {
142
+ kind: 'indexed',
143
+ register: operand.register,
144
+ displacement: operand.displacement,
145
+ };
146
+ case 'imm':
147
+ return { kind: 'imm', expression: operand.expression };
148
+ }
149
+ }
150
+ function toPortOperand(operand) {
151
+ if (operand.kind === 'reg8' && operand.register === 'c') {
152
+ return { kind: 'c' };
153
+ }
154
+ return operand.kind === 'imm' ? { kind: 'imm', expression: operand.expression } : undefined;
155
+ }
156
+ function toIncDecOperand(operand) {
157
+ switch (operand.kind) {
158
+ case 'reg8':
159
+ return { kind: 'reg8', register: operand.register };
160
+ case 'reg16':
161
+ return { kind: 'reg16', register: operand.register };
162
+ case 'reg-indirect':
163
+ return { kind: 'reg-indirect', register: operand.register };
164
+ case 'indexed':
165
+ return {
166
+ kind: 'indexed',
167
+ register: operand.register,
168
+ displacement: operand.displacement,
169
+ };
170
+ case 'imm':
171
+ return undefined;
172
+ }
173
+ }
174
+ function isAluMnemonic(mnemonic) {
175
+ return /^(add|adc|sub|sbc|and|or|xor|cp)$/.test(mnemonic);
176
+ }
177
+ function isConditionToken(text) {
178
+ return /^(NZ|Z|NC|C|PO|PE|P|M)$/i.test(text);
179
+ }
180
+ function isRelativeConditionToken(text) {
181
+ return /^(NZ|Z|NC|C)$/i.test(text);
182
+ }
183
+ function parseExpandedInstruction(mnemonic, operands) {
184
+ const text = `${mnemonic} ${operands.map(formatOpOperand).join(', ')}`.trim();
185
+ const result = parseLogicalLine({ sourceName: '<op-expansion>', line: 1, text });
186
+ if (result.diagnostics.length > 0 || result.items.length !== 1) {
187
+ return undefined;
188
+ }
189
+ const item = result.items[0];
190
+ return item?.kind === 'instruction' ? item.instruction : undefined;
191
+ }
192
+ function formatOpOperand(operand) {
193
+ return operand.kind === 'imm' ? operand.text : operand.text.toUpperCase();
194
+ }
@@ -0,0 +1,8 @@
1
+ import type { SourceItem } from '../model/source-item.js';
2
+ import type { Z80Instruction } from '../z80/instruction.js';
3
+ import type { OpDecl } from './op-expansion.js';
4
+ export declare function buildLocalLabelMap(op: OpDecl, line: {
5
+ readonly line: number;
6
+ }): ReadonlyMap<string, string>;
7
+ export declare function renameSourceItems(items: readonly SourceItem[], localLabelMap: ReadonlyMap<string, string>): readonly SourceItem[];
8
+ export declare function renameInstructionExpressions(instruction: Z80Instruction, localLabelMap: ReadonlyMap<string, string>): Z80Instruction;
@@ -0,0 +1,166 @@
1
+ const EXPRESSION_ITEM_KINDS = new Set(['org', 'equ', 'binfrom', 'binto']);
2
+ const SOURCE_OPERAND_MNEMONICS = new Set([
3
+ 'and',
4
+ 'or',
5
+ 'xor',
6
+ 'cp',
7
+ ]);
8
+ const JUMP_EXPRESSION_MNEMONICS = new Set([
9
+ 'jp',
10
+ 'call',
11
+ 'jr',
12
+ 'djnz',
13
+ 'jp-cc',
14
+ 'call-cc',
15
+ 'jr-cc',
16
+ ]);
17
+ export function buildLocalLabelMap(op, line) {
18
+ const map = new Map();
19
+ let ordinal = 0;
20
+ for (const item of op.body) {
21
+ if (item.kind !== 'source-items')
22
+ continue;
23
+ for (const sourceItem of item.items) {
24
+ if (sourceItem.kind === 'label' && !map.has(sourceItem.name)) {
25
+ map.set(sourceItem.name, `__azm_op_${op.name}_${sourceItem.name}_${line.line}_${ordinal}`);
26
+ ordinal += 1;
27
+ }
28
+ }
29
+ }
30
+ return map;
31
+ }
32
+ export function renameSourceItems(items, localLabelMap) {
33
+ if (localLabelMap.size === 0)
34
+ return items;
35
+ return items.map((item) => renameSourceItem(item, localLabelMap));
36
+ }
37
+ function renameSourceItem(item, localLabelMap) {
38
+ if (item.kind === 'label')
39
+ return renameLabelItem(item, localLabelMap);
40
+ if (isExpressionItem(item))
41
+ return renameExpressionItem(item, localLabelMap);
42
+ if (item.kind === 'db')
43
+ return renameDbItem(item, localLabelMap);
44
+ if (item.kind === 'dw')
45
+ return renameDwItem(item, localLabelMap);
46
+ if (item.kind === 'ds')
47
+ return renameDsItem(item, localLabelMap);
48
+ if (item.kind === 'align')
49
+ return renameAlignItem(item, localLabelMap);
50
+ if (item.kind === 'instruction')
51
+ return renameInstructionItem(item, localLabelMap);
52
+ return item;
53
+ }
54
+ export function renameInstructionExpressions(instruction, localLabelMap) {
55
+ if (localLabelMap.size === 0)
56
+ return instruction;
57
+ if (instruction.mnemonic === 'ld')
58
+ return renameLdInstruction(instruction, localLabelMap);
59
+ if (instruction.mnemonic === 'ld-a-imm')
60
+ return renameExpressionInstruction(instruction, localLabelMap);
61
+ if (instruction.mnemonic === 'in' || instruction.mnemonic === 'out') {
62
+ return { ...instruction, port: renamePortExpression(instruction.port, localLabelMap) };
63
+ }
64
+ if (isAluSourceInstruction(instruction))
65
+ return renameSourceOperandInstruction(instruction, localLabelMap);
66
+ if (isJumpExpressionInstruction(instruction))
67
+ return renameExpressionInstruction(instruction, localLabelMap);
68
+ return instruction;
69
+ }
70
+ function renameLabelItem(item, localLabelMap) {
71
+ return { ...item, name: localLabelMap.get(item.name) ?? item.name };
72
+ }
73
+ function isExpressionItem(item) {
74
+ return EXPRESSION_ITEM_KINDS.has(item.kind);
75
+ }
76
+ function renameExpressionItem(item, localLabelMap) {
77
+ return { ...item, expression: renameExpression(item.expression, localLabelMap) };
78
+ }
79
+ function renameDbItem(item, localLabelMap) {
80
+ return {
81
+ ...item,
82
+ values: item.values.map((value) => value.kind === 'string-fragment' ? value : renameExpression(value, localLabelMap)),
83
+ };
84
+ }
85
+ function renameDwItem(item, localLabelMap) {
86
+ return { ...item, values: item.values.map((value) => renameExpression(value, localLabelMap)) };
87
+ }
88
+ function renameDsItem(item, localLabelMap) {
89
+ return item.fill
90
+ ? {
91
+ ...item,
92
+ size: renameExpression(item.size, localLabelMap),
93
+ fill: renameExpression(item.fill, localLabelMap),
94
+ }
95
+ : { ...item, size: renameExpression(item.size, localLabelMap) };
96
+ }
97
+ function renameAlignItem(item, localLabelMap) {
98
+ return { ...item, alignment: renameExpression(item.alignment, localLabelMap) };
99
+ }
100
+ function renameInstructionItem(item, localLabelMap) {
101
+ return {
102
+ ...item,
103
+ instruction: renameInstructionExpressions(item.instruction, localLabelMap),
104
+ };
105
+ }
106
+ function renameLdInstruction(instruction, localLabelMap) {
107
+ return {
108
+ ...instruction,
109
+ target: renameOperandExpression(instruction.target, localLabelMap),
110
+ source: renameOperandExpression(instruction.source, localLabelMap),
111
+ };
112
+ }
113
+ function renameExpressionInstruction(instruction, localLabelMap) {
114
+ return { ...instruction, expression: renameExpression(instruction.expression, localLabelMap) };
115
+ }
116
+ function isAluSourceInstruction(instruction) {
117
+ return SOURCE_OPERAND_MNEMONICS.has(instruction.mnemonic) || isAccumulatorAluInstruction(instruction);
118
+ }
119
+ function isAccumulatorAluInstruction(instruction) {
120
+ return ((instruction.mnemonic === 'add' ||
121
+ instruction.mnemonic === 'adc' ||
122
+ instruction.mnemonic === 'sub' ||
123
+ instruction.mnemonic === 'sbc') &&
124
+ !('target' in instruction));
125
+ }
126
+ function renameSourceOperandInstruction(instruction, localLabelMap) {
127
+ return { ...instruction, source: renameOperandExpression(instruction.source, localLabelMap) };
128
+ }
129
+ function isJumpExpressionInstruction(instruction) {
130
+ return JUMP_EXPRESSION_MNEMONICS.has(instruction.mnemonic);
131
+ }
132
+ function renameOperandExpression(operand, localLabelMap) {
133
+ switch (operand.kind) {
134
+ case 'imm':
135
+ return { ...operand, expression: renameExpression(operand.expression, localLabelMap) };
136
+ case 'mem-abs':
137
+ return { ...operand, expression: renameExpression(operand.expression, localLabelMap) };
138
+ case 'indexed':
139
+ return { ...operand, displacement: renameExpression(operand.displacement, localLabelMap) };
140
+ default:
141
+ return operand;
142
+ }
143
+ }
144
+ function renamePortExpression(port, localLabelMap) {
145
+ return port.kind === 'imm'
146
+ ? { ...port, expression: renameExpression(port.expression, localLabelMap) }
147
+ : port;
148
+ }
149
+ function renameExpression(expression, localLabelMap) {
150
+ switch (expression.kind) {
151
+ case 'symbol':
152
+ return { ...expression, name: localLabelMap.get(expression.name) ?? expression.name };
153
+ case 'unary':
154
+ return { ...expression, expression: renameExpression(expression.expression, localLabelMap) };
155
+ case 'binary':
156
+ return {
157
+ ...expression,
158
+ left: renameExpression(expression.left, localLabelMap),
159
+ right: renameExpression(expression.right, localLabelMap),
160
+ };
161
+ case 'layout-cast':
162
+ return { ...expression, base: renameExpression(expression.base, localLabelMap) };
163
+ default:
164
+ return expression;
165
+ }
166
+ }
@@ -0,0 +1 @@
1
+ export declare function splitOperands(text: string): string[];
@@ -0,0 +1,44 @@
1
+ export function splitOperands(text) {
2
+ const state = {
3
+ depth: 0,
4
+ quote: undefined,
5
+ escaped: false,
6
+ start: 0,
7
+ values: [],
8
+ };
9
+ for (let index = 0; index < text.length; index += 1) {
10
+ advanceOperandSplitState(state, text, index);
11
+ }
12
+ state.values.push(text.slice(state.start).trim());
13
+ return state.values;
14
+ }
15
+ function advanceOperandSplitState(state, text, index) {
16
+ const char = text[index];
17
+ if (state.escaped) {
18
+ state.escaped = false;
19
+ return;
20
+ }
21
+ if (char === '\\' && state.quote) {
22
+ state.escaped = true;
23
+ return;
24
+ }
25
+ if (char === '"' || char === "'") {
26
+ state.quote = state.quote === char ? undefined : (state.quote ?? char);
27
+ return;
28
+ }
29
+ if (state.quote)
30
+ return;
31
+ updateOperandSplitDepthOrValue(state, text, index, char);
32
+ }
33
+ function updateOperandSplitDepthOrValue(state, text, index, char) {
34
+ if (char === '(') {
35
+ state.depth += 1;
36
+ }
37
+ else if (char === ')') {
38
+ state.depth -= 1;
39
+ }
40
+ else if (char === ',' && state.depth === 0) {
41
+ state.values.push(text.slice(state.start, index).trim());
42
+ state.start = index + 1;
43
+ }
44
+ }
@@ -0,0 +1,53 @@
1
+ import type { Expression } from '../model/expression.js';
2
+ export type OpMatcher = {
3
+ readonly kind: 'reg8';
4
+ } | {
5
+ readonly kind: 'reg16';
6
+ } | {
7
+ readonly kind: 'imm8';
8
+ } | {
9
+ readonly kind: 'imm16';
10
+ } | {
11
+ readonly kind: 'cc';
12
+ } | {
13
+ readonly kind: 'idx16';
14
+ } | {
15
+ readonly kind: 'ea';
16
+ } | {
17
+ readonly kind: 'mem8';
18
+ } | {
19
+ readonly kind: 'mem16';
20
+ } | {
21
+ readonly kind: 'fixed';
22
+ readonly token: string;
23
+ };
24
+ export type OpOperand = {
25
+ readonly kind: 'reg8';
26
+ readonly register: string;
27
+ readonly text: string;
28
+ } | {
29
+ readonly kind: 'reg16';
30
+ readonly register: string;
31
+ readonly text: string;
32
+ } | {
33
+ readonly kind: 'reg-indirect';
34
+ readonly register: 'hl';
35
+ readonly text: string;
36
+ } | {
37
+ readonly kind: 'mem-abs';
38
+ readonly expression: Expression;
39
+ readonly text: string;
40
+ } | {
41
+ readonly kind: 'indexed';
42
+ readonly register: 'ix' | 'iy';
43
+ readonly displacement: Expression;
44
+ readonly text: string;
45
+ } | {
46
+ readonly kind: 'imm';
47
+ readonly expression: Expression;
48
+ readonly text: string;
49
+ };
50
+ export declare function parseOpMatcher(text: string): OpMatcher | undefined;
51
+ export declare function parseOpOperand(text: string): OpOperand | undefined;
52
+ export declare function isConditionToken(text: string): boolean;
53
+ export declare function formatOpOperand(operand: OpOperand): string;
@@ -0,0 +1,66 @@
1
+ import { parseExpression } from '../syntax/parse-expression.js';
2
+ const MATCHERS = new Map([
3
+ ['reg8', { kind: 'reg8' }],
4
+ ['reg16', { kind: 'reg16' }],
5
+ ['imm8', { kind: 'imm8' }],
6
+ ['imm16', { kind: 'imm16' }],
7
+ ['cc', { kind: 'cc' }],
8
+ ['idx16', { kind: 'idx16' }],
9
+ ['ea', { kind: 'ea' }],
10
+ ['mem8', { kind: 'mem8' }],
11
+ ['mem16', { kind: 'mem16' }],
12
+ ]);
13
+ export function parseOpMatcher(text) {
14
+ const matcher = MATCHERS.get(text.toLowerCase());
15
+ if (matcher)
16
+ return matcher;
17
+ return /^[A-Za-z][A-Za-z0-9_]*$/.test(text)
18
+ ? { kind: 'fixed', token: text.toUpperCase() }
19
+ : undefined;
20
+ }
21
+ export function parseOpOperand(text) {
22
+ const trimmed = text.trim();
23
+ if (/^(A|B|C|D|E|H|L)$/i.test(trimmed)) {
24
+ return { kind: 'reg8', register: trimmed.toLowerCase(), text: trimmed.toUpperCase() };
25
+ }
26
+ if (/^(BC|DE|HL|SP)$/i.test(trimmed)) {
27
+ return { kind: 'reg16', register: trimmed.toLowerCase(), text: trimmed.toUpperCase() };
28
+ }
29
+ if (/^\(HL\)$/i.test(trimmed)) {
30
+ return { kind: 'reg-indirect', register: 'hl', text: '(HL)' };
31
+ }
32
+ const indexed = parseIndexedOperand(trimmed);
33
+ if (indexed)
34
+ return indexed;
35
+ if (trimmed.startsWith('(') && trimmed.endsWith(')')) {
36
+ const expression = parseExpression(trimmed.slice(1, -1).trim());
37
+ return expression ? { kind: 'mem-abs', expression, text: trimmed } : undefined;
38
+ }
39
+ const expression = parseExpression(trimmed);
40
+ return expression ? { kind: 'imm', expression, text: trimmed } : undefined;
41
+ }
42
+ function parseIndexedOperand(text) {
43
+ const trimmed = text.trim();
44
+ if (!trimmed.startsWith('(') || !trimmed.endsWith(')'))
45
+ return undefined;
46
+ const inner = trimmed.slice(1, -1).trim();
47
+ const match = /^(IX|IY)(?:\s*([+-])\s*(.+))?$/i.exec(inner);
48
+ if (!match)
49
+ return undefined;
50
+ const displacementText = match[3] ?? '0';
51
+ const displacement = parseExpression(match[2] === '-' ? `-${displacementText}` : displacementText);
52
+ return displacement
53
+ ? {
54
+ kind: 'indexed',
55
+ register: (match[1] ?? '').toLowerCase(),
56
+ displacement,
57
+ text: trimmed,
58
+ }
59
+ : undefined;
60
+ }
61
+ export function isConditionToken(text) {
62
+ return /^(NZ|Z|NC|C|PO|PE|P|M)$/i.test(text);
63
+ }
64
+ export function formatOpOperand(operand) {
65
+ return operand.kind === 'imm' ? operand.text : operand.text.toUpperCase();
66
+ }
@@ -0,0 +1,18 @@
1
+ import type { OpDecl } from './op-expansion.js';
2
+ import { type OpOperand } from './op-operands.js';
3
+ export type OpSelection = {
4
+ readonly kind: 'selected';
5
+ readonly overload: OpDecl;
6
+ } | {
7
+ readonly kind: 'arity_mismatch';
8
+ } | {
9
+ readonly kind: 'no_match';
10
+ readonly candidates: readonly OpDecl[];
11
+ } | {
12
+ readonly kind: 'ambiguous';
13
+ readonly candidates: readonly OpDecl[];
14
+ };
15
+ export declare function selectOpOverload(overloads: readonly OpDecl[], operands: readonly OpOperand[]): OpSelection;
16
+ export declare function formatOpSelectionDiagnostic(selection: Exclude<OpSelection, {
17
+ readonly kind: 'selected';
18
+ }>, overloads: readonly OpDecl[], operands: readonly OpOperand[]): string;