@jhlagado/azm 0.1.0

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 (301) hide show
  1. package/LICENSE +649 -0
  2. package/README.md +142 -0
  3. package/dist/src/analysis.d.ts +11 -0
  4. package/dist/src/analysis.js +41 -0
  5. package/dist/src/api-compile.d.ts +8 -0
  6. package/dist/src/api-compile.js +3 -0
  7. package/dist/src/api-tooling.d.ts +25 -0
  8. package/dist/src/api-tooling.js +21 -0
  9. package/dist/src/cli.d.ts +30 -0
  10. package/dist/src/cli.js +523 -0
  11. package/dist/src/compile.d.ts +10 -0
  12. package/dist/src/compile.js +175 -0
  13. package/dist/src/compileShared.d.ts +3 -0
  14. package/dist/src/compileShared.js +7 -0
  15. package/dist/src/diagnosticTypes.d.ts +77 -0
  16. package/dist/src/diagnosticTypes.js +53 -0
  17. package/dist/src/formats/index.d.ts +7 -0
  18. package/dist/src/formats/index.js +17 -0
  19. package/dist/src/formats/range.d.ts +17 -0
  20. package/dist/src/formats/range.js +45 -0
  21. package/dist/src/formats/types.d.ts +208 -0
  22. package/dist/src/formats/types.js +1 -0
  23. package/dist/src/formats/writeAsm80.d.ts +6 -0
  24. package/dist/src/formats/writeAsm80.js +86 -0
  25. package/dist/src/formats/writeBin.d.ts +7 -0
  26. package/dist/src/formats/writeBin.js +23 -0
  27. package/dist/src/formats/writeD8m.d.ts +9 -0
  28. package/dist/src/formats/writeD8m.js +239 -0
  29. package/dist/src/formats/writeHex.d.ts +9 -0
  30. package/dist/src/formats/writeHex.js +39 -0
  31. package/dist/src/formats/writeListing.d.ts +8 -0
  32. package/dist/src/formats/writeListing.js +83 -0
  33. package/dist/src/frontend/asm80/asmLine.d.ts +39 -0
  34. package/dist/src/frontend/asm80/asmLine.js +89 -0
  35. package/dist/src/frontend/asm80/parseAsmRawValues.d.ts +4 -0
  36. package/dist/src/frontend/asm80/parseAsmRawValues.js +94 -0
  37. package/dist/src/frontend/asm80/quoteScan.d.ts +10 -0
  38. package/dist/src/frontend/asm80/quoteScan.js +25 -0
  39. package/dist/src/frontend/ast.d.ts +376 -0
  40. package/dist/src/frontend/ast.js +1 -0
  41. package/dist/src/frontend/directiveAliases.d.ts +14 -0
  42. package/dist/src/frontend/directiveAliases.js +189 -0
  43. package/dist/src/frontend/grammarData.d.ts +14 -0
  44. package/dist/src/frontend/grammarData.js +65 -0
  45. package/dist/src/frontend/immExprUtils.d.ts +2 -0
  46. package/dist/src/frontend/immExprUtils.js +12 -0
  47. package/dist/src/frontend/parseAsmFlatDirectiveLine.d.ts +17 -0
  48. package/dist/src/frontend/parseAsmFlatDirectiveLine.js +187 -0
  49. package/dist/src/frontend/parseAsmInstruction.d.ts +3 -0
  50. package/dist/src/frontend/parseAsmInstruction.js +73 -0
  51. package/dist/src/frontend/parseAsmStatements.d.ts +6 -0
  52. package/dist/src/frontend/parseAsmStatements.js +16 -0
  53. package/dist/src/frontend/parseAsmStream.d.ts +10 -0
  54. package/dist/src/frontend/parseAsmStream.js +33 -0
  55. package/dist/src/frontend/parseAsmTopLevel.d.ts +18 -0
  56. package/dist/src/frontend/parseAsmTopLevel.js +34 -0
  57. package/dist/src/frontend/parseDiagnostics.d.ts +9 -0
  58. package/dist/src/frontend/parseDiagnostics.js +16 -0
  59. package/dist/src/frontend/parseEnum.d.ts +12 -0
  60. package/dist/src/frontend/parseEnum.js +70 -0
  61. package/dist/src/frontend/parseImm.d.ts +10 -0
  62. package/dist/src/frontend/parseImm.js +397 -0
  63. package/dist/src/frontend/parseLogicalLines.d.ts +11 -0
  64. package/dist/src/frontend/parseLogicalLines.js +94 -0
  65. package/dist/src/frontend/parseOp.d.ts +25 -0
  66. package/dist/src/frontend/parseOp.js +120 -0
  67. package/dist/src/frontend/parseOpHeader.d.ts +20 -0
  68. package/dist/src/frontend/parseOpHeader.js +32 -0
  69. package/dist/src/frontend/parseOperands.d.ts +4 -0
  70. package/dist/src/frontend/parseOperands.js +290 -0
  71. package/dist/src/frontend/parseParams.d.ts +6 -0
  72. package/dist/src/frontend/parseParams.js +62 -0
  73. package/dist/src/frontend/parseParserRecovery.d.ts +12 -0
  74. package/dist/src/frontend/parseParserRecovery.js +17 -0
  75. package/dist/src/frontend/parseParserShared.d.ts +2 -0
  76. package/dist/src/frontend/parseParserShared.js +8 -0
  77. package/dist/src/frontend/parseRawDataDirectiveStart.d.ts +1 -0
  78. package/dist/src/frontend/parseRawDataDirectiveStart.js +3 -0
  79. package/dist/src/frontend/parseRawDataDirectives.d.ts +7 -0
  80. package/dist/src/frontend/parseRawDataDirectives.js +142 -0
  81. package/dist/src/frontend/parseRecordFieldDecl.d.ts +34 -0
  82. package/dist/src/frontend/parseRecordFieldDecl.js +177 -0
  83. package/dist/src/frontend/parseSourceItemDispatch.d.ts +46 -0
  84. package/dist/src/frontend/parseSourceItemDispatch.js +53 -0
  85. package/dist/src/frontend/parseSourceItemTable.d.ts +16 -0
  86. package/dist/src/frontend/parseSourceItemTable.js +68 -0
  87. package/dist/src/frontend/parseTopLevelCommon.d.ts +11 -0
  88. package/dist/src/frontend/parseTopLevelCommon.js +50 -0
  89. package/dist/src/frontend/parseTypes.d.ts +24 -0
  90. package/dist/src/frontend/parseTypes.js +77 -0
  91. package/dist/src/frontend/parser.d.ts +11 -0
  92. package/dist/src/frontend/parser.js +88 -0
  93. package/dist/src/frontend/source.d.ts +28 -0
  94. package/dist/src/frontend/source.js +58 -0
  95. package/dist/src/frontend/sourceExtensions.d.ts +2 -0
  96. package/dist/src/frontend/sourceExtensions.js +6 -0
  97. package/dist/src/index.d.ts +3 -0
  98. package/dist/src/index.js +2 -0
  99. package/dist/src/lintCaseStyle.d.ts +4 -0
  100. package/dist/src/lintCaseStyle.js +129 -0
  101. package/dist/src/lowering/asmDirectiveLowering.d.ts +4 -0
  102. package/dist/src/lowering/asmDirectiveLowering.js +229 -0
  103. package/dist/src/lowering/asmDirectiveTraversal.d.ts +47 -0
  104. package/dist/src/lowering/asmDirectiveTraversal.js +52 -0
  105. package/dist/src/lowering/asmEquResolution.d.ts +8 -0
  106. package/dist/src/lowering/asmEquResolution.js +69 -0
  107. package/dist/src/lowering/asmInstructionLdHelpers.d.ts +15 -0
  108. package/dist/src/lowering/asmInstructionLdHelpers.js +102 -0
  109. package/dist/src/lowering/asmInstructionLowering.d.ts +5 -0
  110. package/dist/src/lowering/asmInstructionLowering.js +54 -0
  111. package/dist/src/lowering/asmInstructionStream.d.ts +46 -0
  112. package/dist/src/lowering/asmInstructionStream.js +51 -0
  113. package/dist/src/lowering/asmLoweringBranchCall.d.ts +43 -0
  114. package/dist/src/lowering/asmLoweringBranchCall.js +254 -0
  115. package/dist/src/lowering/asmLoweringHost.d.ts +23 -0
  116. package/dist/src/lowering/asmLoweringHost.js +1 -0
  117. package/dist/src/lowering/asmLoweringLd.d.ts +28 -0
  118. package/dist/src/lowering/asmLoweringLd.js +144 -0
  119. package/dist/src/lowering/asmRangeLowering.d.ts +17 -0
  120. package/dist/src/lowering/asmRangeLowering.js +39 -0
  121. package/dist/src/lowering/asmRawDataLowering.d.ts +16 -0
  122. package/dist/src/lowering/asmRawDataLowering.js +209 -0
  123. package/dist/src/lowering/asmSourceEmitter.d.ts +4 -0
  124. package/dist/src/lowering/asmSourceEmitter.js +9 -0
  125. package/dist/src/lowering/asmSourceInstructionLowering.d.ts +4 -0
  126. package/dist/src/lowering/asmSourceInstructionLowering.js +14 -0
  127. package/dist/src/lowering/asmUtils.d.ts +13 -0
  128. package/dist/src/lowering/asmUtils.js +105 -0
  129. package/dist/src/lowering/assemblerFlowSetup.d.ts +54 -0
  130. package/dist/src/lowering/assemblerFlowSetup.js +128 -0
  131. package/dist/src/lowering/assemblerLoweringContext.d.ts +151 -0
  132. package/dist/src/lowering/assemblerLoweringContext.js +16 -0
  133. package/dist/src/lowering/assemblerLoweringContextSplit.d.ts +7 -0
  134. package/dist/src/lowering/assemblerLoweringContextSplit.js +75 -0
  135. package/dist/src/lowering/assemblerLoweringPhases.d.ts +66 -0
  136. package/dist/src/lowering/assemblerLoweringPhases.js +166 -0
  137. package/dist/src/lowering/bytePlacement.d.ts +7 -0
  138. package/dist/src/lowering/bytePlacement.js +37 -0
  139. package/dist/src/lowering/capabilities.d.ts +67 -0
  140. package/dist/src/lowering/capabilities.js +1 -0
  141. package/dist/src/lowering/eaResolution.d.ts +58 -0
  142. package/dist/src/lowering/eaResolution.js +159 -0
  143. package/dist/src/lowering/emissionCore.d.ts +17 -0
  144. package/dist/src/lowering/emissionCore.js +21 -0
  145. package/dist/src/lowering/emit.d.ts +17 -0
  146. package/dist/src/lowering/emit.js +46 -0
  147. package/dist/src/lowering/emitContextBuilder.d.ts +63 -0
  148. package/dist/src/lowering/emitContextBuilder.js +41 -0
  149. package/dist/src/lowering/emitFinalization.d.ts +61 -0
  150. package/dist/src/lowering/emitFinalization.js +66 -0
  151. package/dist/src/lowering/emitFinalizationSetup.d.ts +19 -0
  152. package/dist/src/lowering/emitFinalizationSetup.js +26 -0
  153. package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.d.ts +7 -0
  154. package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.js +119 -0
  155. package/dist/src/lowering/emitPhase1Helpers.d.ts +4 -0
  156. package/dist/src/lowering/emitPhase1Helpers.js +12 -0
  157. package/dist/src/lowering/emitPhase1Types.d.ts +21 -0
  158. package/dist/src/lowering/emitPhase1Types.js +1 -0
  159. package/dist/src/lowering/emitPhase1WirePipeline.d.ts +70 -0
  160. package/dist/src/lowering/emitPhase1WirePipeline.js +203 -0
  161. package/dist/src/lowering/emitPhase1Workspace.d.ts +82 -0
  162. package/dist/src/lowering/emitPhase1Workspace.js +55 -0
  163. package/dist/src/lowering/emitPipeline.d.ts +121 -0
  164. package/dist/src/lowering/emitPipeline.js +57 -0
  165. package/dist/src/lowering/emitProgramContext.d.ts +39 -0
  166. package/dist/src/lowering/emitProgramContext.js +29 -0
  167. package/dist/src/lowering/emitState.d.ts +90 -0
  168. package/dist/src/lowering/emitState.js +124 -0
  169. package/dist/src/lowering/fixupBaseResolution.d.ts +7 -0
  170. package/dist/src/lowering/fixupBaseResolution.js +23 -0
  171. package/dist/src/lowering/fixupEmission.d.ts +64 -0
  172. package/dist/src/lowering/fixupEmission.js +199 -0
  173. package/dist/src/lowering/immMath.d.ts +2 -0
  174. package/dist/src/lowering/immMath.js +34 -0
  175. package/dist/src/lowering/inputAssets.d.ts +7 -0
  176. package/dist/src/lowering/inputAssets.js +106 -0
  177. package/dist/src/lowering/ldEncoding.d.ts +15 -0
  178. package/dist/src/lowering/ldEncoding.js +12 -0
  179. package/dist/src/lowering/ldEncodingRegMemHelpers.d.ts +5 -0
  180. package/dist/src/lowering/ldEncodingRegMemHelpers.js +124 -0
  181. package/dist/src/lowering/ldFormSelection.d.ts +26 -0
  182. package/dist/src/lowering/ldFormSelection.js +92 -0
  183. package/dist/src/lowering/ldLowering.d.ts +7 -0
  184. package/dist/src/lowering/ldLowering.js +13 -0
  185. package/dist/src/lowering/loweredAsmByteEmission.d.ts +23 -0
  186. package/dist/src/lowering/loweredAsmByteEmission.js +185 -0
  187. package/dist/src/lowering/loweredAsmPlacement.d.ts +13 -0
  188. package/dist/src/lowering/loweredAsmPlacement.js +86 -0
  189. package/dist/src/lowering/loweredAsmStreamRecording.d.ts +27 -0
  190. package/dist/src/lowering/loweredAsmStreamRecording.js +215 -0
  191. package/dist/src/lowering/loweredAsmTypes.d.ts +202 -0
  192. package/dist/src/lowering/loweredAsmTypes.js +1 -0
  193. package/dist/src/lowering/loweredFormat.d.ts +3 -0
  194. package/dist/src/lowering/loweredFormat.js +26 -0
  195. package/dist/src/lowering/loweredItemSize.d.ts +4 -0
  196. package/dist/src/lowering/loweredItemSize.js +17 -0
  197. package/dist/src/lowering/loweringDiagnostics.d.ts +9 -0
  198. package/dist/src/lowering/loweringDiagnostics.js +55 -0
  199. package/dist/src/lowering/loweringTypes.d.ts +27 -0
  200. package/dist/src/lowering/loweringTypes.js +1 -0
  201. package/dist/src/lowering/opCandidateRegistry.d.ts +9 -0
  202. package/dist/src/lowering/opCandidateRegistry.js +9 -0
  203. package/dist/src/lowering/opExpansionExecution.d.ts +15 -0
  204. package/dist/src/lowering/opExpansionExecution.js +45 -0
  205. package/dist/src/lowering/opExpansionOrchestration.d.ts +15 -0
  206. package/dist/src/lowering/opExpansionOrchestration.js +88 -0
  207. package/dist/src/lowering/opExpansionStream.d.ts +12 -0
  208. package/dist/src/lowering/opExpansionStream.js +176 -0
  209. package/dist/src/lowering/opMatching.d.ts +52 -0
  210. package/dist/src/lowering/opMatching.js +355 -0
  211. package/dist/src/lowering/opSubstitution.d.ts +13 -0
  212. package/dist/src/lowering/opSubstitution.js +175 -0
  213. package/dist/src/lowering/prescanTypes.d.ts +7 -0
  214. package/dist/src/lowering/prescanTypes.js +1 -0
  215. package/dist/src/lowering/programLowering.d.ts +144 -0
  216. package/dist/src/lowering/programLowering.js +2 -0
  217. package/dist/src/lowering/programLoweringDeclarations.d.ts +5 -0
  218. package/dist/src/lowering/programLoweringDeclarations.js +5 -0
  219. package/dist/src/lowering/programLoweringFinalize.d.ts +18 -0
  220. package/dist/src/lowering/programLoweringFinalize.js +115 -0
  221. package/dist/src/lowering/programLoweringTraversal.d.ts +2 -0
  222. package/dist/src/lowering/programLoweringTraversal.js +93 -0
  223. package/dist/src/lowering/programPrescan.d.ts +3 -0
  224. package/dist/src/lowering/programPrescan.js +37 -0
  225. package/dist/src/lowering/traceFormat.d.ts +13 -0
  226. package/dist/src/lowering/traceFormat.js +211 -0
  227. package/dist/src/pathCompare.d.ts +3 -0
  228. package/dist/src/pathCompare.js +26 -0
  229. package/dist/src/pipeline.d.ts +78 -0
  230. package/dist/src/pipeline.js +1 -0
  231. package/dist/src/registerCare/analyze.d.ts +24 -0
  232. package/dist/src/registerCare/analyze.js +327 -0
  233. package/dist/src/registerCare/annotate.d.ts +11 -0
  234. package/dist/src/registerCare/annotate.js +76 -0
  235. package/dist/src/registerCare/boundaryHints.d.ts +2 -0
  236. package/dist/src/registerCare/boundaryHints.js +10 -0
  237. package/dist/src/registerCare/carriers.d.ts +4 -0
  238. package/dist/src/registerCare/carriers.js +78 -0
  239. package/dist/src/registerCare/controlFlow.d.ts +5 -0
  240. package/dist/src/registerCare/controlFlow.js +35 -0
  241. package/dist/src/registerCare/fix.d.ts +11 -0
  242. package/dist/src/registerCare/fix.js +119 -0
  243. package/dist/src/registerCare/liveness.d.ts +7 -0
  244. package/dist/src/registerCare/liveness.js +227 -0
  245. package/dist/src/registerCare/profiles.d.ts +11 -0
  246. package/dist/src/registerCare/profiles.js +45 -0
  247. package/dist/src/registerCare/programModel.d.ts +3 -0
  248. package/dist/src/registerCare/programModel.js +181 -0
  249. package/dist/src/registerCare/report.d.ts +5 -0
  250. package/dist/src/registerCare/report.js +139 -0
  251. package/dist/src/registerCare/smartComments.d.ts +5 -0
  252. package/dist/src/registerCare/smartComments.js +247 -0
  253. package/dist/src/registerCare/sourceText.d.ts +8 -0
  254. package/dist/src/registerCare/sourceText.js +15 -0
  255. package/dist/src/registerCare/summary.d.ts +3 -0
  256. package/dist/src/registerCare/summary.js +492 -0
  257. package/dist/src/registerCare/tooling.d.ts +42 -0
  258. package/dist/src/registerCare/tooling.js +50 -0
  259. package/dist/src/registerCare/types.d.ts +154 -0
  260. package/dist/src/registerCare/types.js +1 -0
  261. package/dist/src/semantics/declVisitor.d.ts +5 -0
  262. package/dist/src/semantics/declVisitor.js +11 -0
  263. package/dist/src/semantics/env.d.ts +28 -0
  264. package/dist/src/semantics/env.js +432 -0
  265. package/dist/src/semantics/layout.d.ts +21 -0
  266. package/dist/src/semantics/layout.js +226 -0
  267. package/dist/src/semantics/layoutCastFold.d.ts +22 -0
  268. package/dist/src/semantics/layoutCastFold.js +118 -0
  269. package/dist/src/semantics/semanticsDiagnostics.d.ts +2 -0
  270. package/dist/src/semantics/semanticsDiagnostics.js +4 -0
  271. package/dist/src/semantics/typeQueries.d.ts +31 -0
  272. package/dist/src/semantics/typeQueries.js +124 -0
  273. package/dist/src/sourceIncludeExpansion.d.ts +17 -0
  274. package/dist/src/sourceIncludeExpansion.js +124 -0
  275. package/dist/src/sourceIncludePaths.d.ts +1 -0
  276. package/dist/src/sourceIncludePaths.js +12 -0
  277. package/dist/src/sourceLoader.d.ts +15 -0
  278. package/dist/src/sourceLoader.js +118 -0
  279. package/dist/src/z80/effects.d.ts +3 -0
  280. package/dist/src/z80/effects.js +516 -0
  281. package/dist/src/z80/encode.d.ts +10 -0
  282. package/dist/src/z80/encode.js +412 -0
  283. package/dist/src/z80/encodeAlu.d.ts +7 -0
  284. package/dist/src/z80/encodeAlu.js +219 -0
  285. package/dist/src/z80/encodeBitOps.d.ts +7 -0
  286. package/dist/src/z80/encodeBitOps.js +123 -0
  287. package/dist/src/z80/encodeContext.d.ts +29 -0
  288. package/dist/src/z80/encodeContext.js +1 -0
  289. package/dist/src/z80/encodeControl.d.ts +26 -0
  290. package/dist/src/z80/encodeControl.js +180 -0
  291. package/dist/src/z80/encodeCoreOps.d.ts +7 -0
  292. package/dist/src/z80/encodeCoreOps.js +131 -0
  293. package/dist/src/z80/encodeIo.d.ts +9 -0
  294. package/dist/src/z80/encodeIo.js +128 -0
  295. package/dist/src/z80/encodeLd.d.ts +13 -0
  296. package/dist/src/z80/encodeLd.js +273 -0
  297. package/dist/src/z80/encoderRegistry.d.ts +13 -0
  298. package/dist/src/z80/encoderRegistry.js +169 -0
  299. package/docs/reference/cli.md +134 -0
  300. package/docs/reference/tooling-api.md +248 -0
  301. package/package.json +98 -0
@@ -0,0 +1,176 @@
1
+ import { cloneEaExpr, cloneImmExpr, cloneOperand, flattenEaDottedName } from './asmUtils.js';
2
+ import { expandInlineOpBodyItems } from './opExpansionExecution.js';
3
+ import { createOpMatchingHelpers } from './opMatching.js';
4
+ import { createOpSubstitutionHelpers } from './opSubstitution.js';
5
+ const REG8_NAMES = new Set(['A', 'B', 'C', 'D', 'E', 'H', 'L']);
6
+ const CONDITION_CODES = new Set(['NZ', 'Z', 'NC', 'C', 'PO', 'PE', 'P', 'M']);
7
+ const MAX_OP_EXPANSION_DEPTH = 64;
8
+ const EMPTY_OP_SUBSTITUTION_ENV = {
9
+ equates: new Map(),
10
+ enums: new Map(),
11
+ types: new Map(),
12
+ };
13
+ function isIxIyIndexedMem(op) {
14
+ return (op.kind === 'Mem' &&
15
+ ((op.expr.kind === 'EaName' && /^(IX|IY)$/i.test(op.expr.name)) ||
16
+ ((op.expr.kind === 'EaAdd' || op.expr.kind === 'EaSub') &&
17
+ op.expr.base.kind === 'EaName' &&
18
+ /^(IX|IY)$/i.test(op.expr.base.name))));
19
+ }
20
+ function normalizeFixedToken(op) {
21
+ switch (op.kind) {
22
+ case 'Reg':
23
+ return op.name.toUpperCase();
24
+ case 'Imm':
25
+ return op.expr.kind === 'ImmName' ? op.expr.name.toUpperCase() : undefined;
26
+ case 'Ea': {
27
+ const name = flattenEaDottedName(op.expr);
28
+ return name ? name.toUpperCase() : undefined;
29
+ }
30
+ default:
31
+ return undefined;
32
+ }
33
+ }
34
+ function evalImmNoDiag(expr) {
35
+ switch (expr.kind) {
36
+ case 'ImmLiteral':
37
+ return expr.value;
38
+ case 'ImmUnary': {
39
+ const value = evalImmNoDiag(expr.expr);
40
+ if (value === undefined)
41
+ return undefined;
42
+ if (expr.op === '-')
43
+ return -value;
44
+ if (expr.op === '+')
45
+ return value;
46
+ return undefined;
47
+ }
48
+ case 'ImmBinary': {
49
+ const left = evalImmNoDiag(expr.left);
50
+ const right = evalImmNoDiag(expr.right);
51
+ if (left === undefined || right === undefined)
52
+ return undefined;
53
+ if (expr.op === '+')
54
+ return left + right;
55
+ if (expr.op === '-')
56
+ return left - right;
57
+ if (expr.op === '*')
58
+ return left * right;
59
+ return undefined;
60
+ }
61
+ default:
62
+ return undefined;
63
+ }
64
+ }
65
+ const { selectOpOverload } = createOpMatchingHelpers({
66
+ reg8: REG8_NAMES,
67
+ isIxIyIndexedMem,
68
+ flattenEaDottedName,
69
+ isEnumName: () => false,
70
+ normalizeFixedToken,
71
+ conditionOpcodeFromName: (name) => (CONDITION_CODES.has(name.toUpperCase()) ? 0 : undefined),
72
+ evalImmNoDiag,
73
+ inferMemWidth: () => undefined,
74
+ });
75
+ function addOpDeclForFile(ctx, file, key, op) {
76
+ let fileOps = ctx.localOpsByFile.get(file);
77
+ if (!fileOps) {
78
+ fileOps = new Map();
79
+ ctx.localOpsByFile.set(file, fileOps);
80
+ }
81
+ const local = fileOps.get(key);
82
+ if (local)
83
+ local.push(op);
84
+ else
85
+ fileOps.set(key, [op]);
86
+ }
87
+ function collectOpDeclsFromItems(items, ctx, sourceUnitFile) {
88
+ for (const item of items) {
89
+ if (item.kind !== 'OpDecl')
90
+ continue;
91
+ const op = item;
92
+ const key = op.name.toLowerCase();
93
+ addOpDeclForFile(ctx, sourceUnitFile, key, op);
94
+ if (op.span.file !== sourceUnitFile)
95
+ addOpDeclForFile(ctx, op.span.file, key, op);
96
+ }
97
+ }
98
+ function buildOpExpansionContext(program) {
99
+ const ctx = {
100
+ localOpsByFile: new Map(),
101
+ nextSyntheticLabelId: 0,
102
+ };
103
+ for (const file of program.files) {
104
+ collectOpDeclsFromItems(file.items, ctx, file.path);
105
+ }
106
+ return ctx;
107
+ }
108
+ function resolveOpCandidates(inst, ctx) {
109
+ const lower = inst.head.toLowerCase();
110
+ return ctx.localOpsByFile.get(inst.span.file)?.get(lower);
111
+ }
112
+ export function createInlineOpInstructionStreamExpander(program) {
113
+ const ctx = buildOpExpansionContext(program);
114
+ function expandInstruction(inst, stack = new Set()) {
115
+ if (stack.size >= MAX_OP_EXPANSION_DEPTH)
116
+ return [{ kind: 'instruction', instruction: inst }];
117
+ const candidates = resolveOpCandidates(inst, ctx);
118
+ if (!candidates || candidates.length === 0)
119
+ return [{ kind: 'instruction', instruction: inst }];
120
+ const selection = selectOpOverload(candidates, inst.operands);
121
+ if (selection.kind !== 'selected')
122
+ return [{ kind: 'instruction', instruction: inst }];
123
+ const opDecl = selection.overload;
124
+ const opKey = `${opDecl.name.toLowerCase()}:${opDecl.span.file}:${opDecl.span.start.line}`;
125
+ if (stack.has(opKey))
126
+ return [{ kind: 'instruction', instruction: inst }];
127
+ const nextStack = new Set(stack);
128
+ nextStack.add(opKey);
129
+ const bindings = new Map();
130
+ for (let index = 0; index < opDecl.params.length; index += 1) {
131
+ bindings.set(opDecl.params[index].name.toLowerCase(), inst.operands[index]);
132
+ }
133
+ const { substituteOperandWithOpLabels } = createOpSubstitutionHelpers({
134
+ bindings,
135
+ env: EMPTY_OP_SUBSTITUTION_ENV,
136
+ diagnostics: [],
137
+ diagAt: () => { },
138
+ cloneImmExpr,
139
+ cloneEaExpr,
140
+ cloneOperand,
141
+ flattenEaDottedName,
142
+ });
143
+ const out = [];
144
+ const expansionId = ctx.nextSyntheticLabelId;
145
+ ctx.nextSyntheticLabelId += 1;
146
+ const expandedItems = expandInlineOpBodyItems({
147
+ opDecl,
148
+ allocateLocalLabel: (labelName) => `.__azm_op_${opDecl.name.toLowerCase()}_${expansionId}_${labelName.replace(/^\.+/, '')}`,
149
+ substituteOperandWithOpLabels,
150
+ });
151
+ for (const bodyItem of expandedItems) {
152
+ if (bodyItem.kind === 'AsmLabel') {
153
+ out.push({
154
+ kind: 'label',
155
+ label: {
156
+ kind: 'AsmLabel',
157
+ span: inst.span,
158
+ name: bodyItem.name,
159
+ },
160
+ });
161
+ continue;
162
+ }
163
+ if (bodyItem.kind !== 'AsmInstruction')
164
+ continue;
165
+ const expanded = {
166
+ kind: 'AsmInstruction',
167
+ span: inst.span,
168
+ head: bodyItem.head,
169
+ operands: bodyItem.operands,
170
+ };
171
+ out.push(...expandInstruction(expanded, nextStack));
172
+ }
173
+ return out;
174
+ }
175
+ return { expandInstruction };
176
+ }
@@ -0,0 +1,52 @@
1
+ import type { AsmOperandNode, EaExprNode, ImmExprNode, OpDeclNode, OpMatcherNode } from '../frontend/ast.js';
2
+ type OpMatchingContext = {
3
+ /** 8-bit register names for matching. */
4
+ reg8: Set<string>;
5
+ /** True when operand uses IX/IY indexed memory form. */
6
+ isIxIyIndexedMem: (operand: AsmOperandNode) => boolean;
7
+ /** Flattens dotted EA; `undefined` if not expressible as dotted. */
8
+ flattenEaDottedName: (ea: EaExprNode) => string | undefined;
9
+ /** True for declared enum names. */
10
+ isEnumName: (name: string) => boolean;
11
+ /** Normalizes fixed tokens for overload keys. */
12
+ normalizeFixedToken: (operand: AsmOperandNode) => string | undefined;
13
+ /** Maps condition name to opcode; `undefined` if unknown. */
14
+ conditionOpcodeFromName: (name: string) => number | undefined;
15
+ /** Best-effort imm evaluation. */
16
+ evalImmNoDiag: (expr: ImmExprNode) => number | undefined;
17
+ /** Infers memory operand width in bytes; `undefined` if unknown. */
18
+ inferMemWidth: (operand: AsmOperandNode) => number | undefined;
19
+ };
20
+ export type OpOverloadSelection = {
21
+ kind: 'arity_mismatch';
22
+ /** Candidate overloads. */
23
+ overloads: OpDeclNode[];
24
+ /** Rendered arity signatures for diagnostics. */
25
+ signatures: string[];
26
+ } | {
27
+ kind: 'no_match';
28
+ /** Candidate overloads. */
29
+ overloads: OpDeclNode[];
30
+ /** Per-operand mismatch notes. */
31
+ mismatchDetails: string[];
32
+ } | {
33
+ kind: 'ambiguous';
34
+ /** Competing overloads. */
35
+ overloads: OpDeclNode[];
36
+ /** Rendered definitions for diagnostics. */
37
+ definitions: string[];
38
+ } | {
39
+ kind: 'selected';
40
+ /** Chosen overload. */
41
+ overload: OpDeclNode;
42
+ };
43
+ export declare function createOpMatchingHelpers(ctx: OpMatchingContext): {
44
+ matcherMatchesOperand: (matcher: OpMatcherNode, operand: AsmOperandNode) => boolean;
45
+ selectMostSpecificOpOverload: (candidates: OpDeclNode[], operands: AsmOperandNode[]) => OpDeclNode | undefined;
46
+ selectOpOverload: (overloads: OpDeclNode[], operands: AsmOperandNode[]) => OpOverloadSelection;
47
+ formatAsmOperandForOpDiag: (operand: AsmOperandNode) => string;
48
+ formatOpSignature: (opDecl: OpDeclNode) => string;
49
+ formatOpDefinitionForDiag: (opDecl: OpDeclNode) => string;
50
+ firstOpOverloadMismatchReason: (opDecl: OpDeclNode, operands: AsmOperandNode[]) => string | undefined;
51
+ };
52
+ export {};
@@ -0,0 +1,355 @@
1
+ import { formatEaExpr } from './traceFormat.js';
2
+ const fitsImm8 = (value) => value >= -0x80 && value <= 0xff;
3
+ const fitsImm16 = (value) => value >= -0x8000 && value <= 0xffff;
4
+ export function createOpMatchingHelpers(ctx) {
5
+ const enumImmExprFromOperand = (op) => {
6
+ switch (op.kind) {
7
+ case 'Imm':
8
+ return op.expr;
9
+ case 'Reg':
10
+ return { kind: 'ImmName', span: op.span, name: op.name };
11
+ case 'Ea': {
12
+ const name = ctx.flattenEaDottedName(op.expr);
13
+ if (!name || !ctx.isEnumName(name))
14
+ return undefined;
15
+ return { kind: 'ImmName', span: op.span, name };
16
+ }
17
+ default:
18
+ return undefined;
19
+ }
20
+ };
21
+ const matcherMatchesOperand = (matcher, operand) => {
22
+ switch (matcher.kind) {
23
+ case 'MatcherReg8':
24
+ return operand.kind === 'Reg' && ctx.reg8.has(operand.name.toUpperCase());
25
+ case 'MatcherReg16':
26
+ return (operand.kind === 'Reg' &&
27
+ (operand.name.toUpperCase() === 'BC' ||
28
+ operand.name.toUpperCase() === 'DE' ||
29
+ operand.name.toUpperCase() === 'HL' ||
30
+ operand.name.toUpperCase() === 'SP'));
31
+ case 'MatcherIdx16':
32
+ return ctx.isIxIyIndexedMem(operand);
33
+ case 'MatcherCc': {
34
+ const token = ctx.normalizeFixedToken(operand);
35
+ return token !== undefined && ctx.conditionOpcodeFromName(token) !== undefined;
36
+ }
37
+ case 'MatcherImm8': {
38
+ const expr = enumImmExprFromOperand(operand);
39
+ if (!expr)
40
+ return false;
41
+ const v = ctx.evalImmNoDiag(expr);
42
+ return v !== undefined && fitsImm8(v);
43
+ }
44
+ case 'MatcherImm16': {
45
+ const expr = enumImmExprFromOperand(operand);
46
+ if (!expr)
47
+ return false;
48
+ const v = ctx.evalImmNoDiag(expr);
49
+ return v !== undefined && fitsImm16(v);
50
+ }
51
+ case 'MatcherEa':
52
+ return operand.kind === 'Ea';
53
+ case 'MatcherMem8': {
54
+ if (operand.kind !== 'Mem')
55
+ return false;
56
+ const width = ctx.inferMemWidth(operand);
57
+ return width === undefined ? true : width === 1;
58
+ }
59
+ case 'MatcherMem16': {
60
+ if (operand.kind !== 'Mem')
61
+ return false;
62
+ const width = ctx.inferMemWidth(operand);
63
+ return width === undefined ? true : width === 2;
64
+ }
65
+ case 'MatcherFixed': {
66
+ const got = ctx.normalizeFixedToken(operand);
67
+ return got !== undefined && got === matcher.token.toUpperCase();
68
+ }
69
+ default:
70
+ return false;
71
+ }
72
+ };
73
+ const fixedTokenBeatsClassMatcher = (fixed, other, operand) => {
74
+ const fixedToken = fixed.token.toUpperCase();
75
+ switch (other.kind) {
76
+ case 'MatcherReg8':
77
+ return (operand.kind === 'Reg' &&
78
+ operand.name.toUpperCase() === fixedToken &&
79
+ ctx.reg8.has(fixedToken));
80
+ case 'MatcherReg16':
81
+ return (operand.kind === 'Reg' &&
82
+ operand.name.toUpperCase() === fixedToken &&
83
+ (fixedToken === 'BC' || fixedToken === 'DE' || fixedToken === 'HL' || fixedToken === 'SP'));
84
+ case 'MatcherCc':
85
+ return ctx.conditionOpcodeFromName(fixedToken) !== undefined;
86
+ default:
87
+ return false;
88
+ }
89
+ };
90
+ const compareMatcherSpecificity = (matcherX, matcherY, operand) => {
91
+ if (matcherX.kind === matcherY.kind)
92
+ return 'equal';
93
+ if (matcherX.kind === 'MatcherFixed' &&
94
+ fixedTokenBeatsClassMatcher(matcherX, matcherY, operand)) {
95
+ return 'x_more_specific';
96
+ }
97
+ if (matcherY.kind === 'MatcherFixed' &&
98
+ fixedTokenBeatsClassMatcher(matcherY, matcherX, operand)) {
99
+ return 'y_more_specific';
100
+ }
101
+ if (matcherX.kind === 'MatcherImm8' && matcherY.kind === 'MatcherImm16') {
102
+ const expr = enumImmExprFromOperand(operand);
103
+ if (!expr)
104
+ return 'equal';
105
+ const value = ctx.evalImmNoDiag(expr);
106
+ return value !== undefined && fitsImm8(value) ? 'x_more_specific' : 'equal';
107
+ }
108
+ if (matcherX.kind === 'MatcherImm16' && matcherY.kind === 'MatcherImm8') {
109
+ const expr = enumImmExprFromOperand(operand);
110
+ if (!expr)
111
+ return 'equal';
112
+ const value = ctx.evalImmNoDiag(expr);
113
+ return value !== undefined && fitsImm8(value) ? 'y_more_specific' : 'equal';
114
+ }
115
+ if ((matcherX.kind === 'MatcherMem8' || matcherX.kind === 'MatcherMem16') &&
116
+ matcherY.kind === 'MatcherEa' &&
117
+ operand.kind === 'Mem') {
118
+ return 'x_more_specific';
119
+ }
120
+ if (matcherX.kind === 'MatcherEa' &&
121
+ (matcherY.kind === 'MatcherMem8' || matcherY.kind === 'MatcherMem16') &&
122
+ operand.kind === 'Mem') {
123
+ return 'y_more_specific';
124
+ }
125
+ return 'equal';
126
+ };
127
+ const compareOpOverloadSpecificity = (overloadX, overloadY, operands) => {
128
+ let xBetter = 0;
129
+ let yBetter = 0;
130
+ for (let i = 0; i < operands.length; i++) {
131
+ const xMatcher = overloadX.params[i].matcher;
132
+ const yMatcher = overloadY.params[i].matcher;
133
+ const cmp = compareMatcherSpecificity(xMatcher, yMatcher, operands[i]);
134
+ if (cmp === 'x_more_specific')
135
+ xBetter++;
136
+ if (cmp === 'y_more_specific')
137
+ yBetter++;
138
+ }
139
+ if (xBetter > 0 && yBetter === 0)
140
+ return 'x_wins';
141
+ if (yBetter > 0 && xBetter === 0)
142
+ return 'y_wins';
143
+ if (xBetter === 0 && yBetter === 0)
144
+ return 'equal';
145
+ return 'incomparable';
146
+ };
147
+ const selectMostSpecificOpOverload = (candidates, operands) => {
148
+ if (candidates.length === 0)
149
+ return undefined;
150
+ if (candidates.length === 1)
151
+ return candidates[0];
152
+ for (let i = 0; i < candidates.length; i++) {
153
+ const candidate = candidates[i];
154
+ let beatsAll = true;
155
+ for (let j = 0; j < candidates.length; j++) {
156
+ if (i === j)
157
+ continue;
158
+ const cmp = compareOpOverloadSpecificity(candidate, candidates[j], operands);
159
+ if (cmp !== 'x_wins') {
160
+ beatsAll = false;
161
+ break;
162
+ }
163
+ }
164
+ if (beatsAll)
165
+ return candidate;
166
+ }
167
+ return undefined;
168
+ };
169
+ const formatOpMatcher = (matcher) => {
170
+ switch (matcher.kind) {
171
+ case 'MatcherReg8':
172
+ return 'reg8';
173
+ case 'MatcherReg16':
174
+ return 'reg16';
175
+ case 'MatcherIdx16':
176
+ return 'idx16';
177
+ case 'MatcherCc':
178
+ return 'cc';
179
+ case 'MatcherImm8':
180
+ return 'imm8';
181
+ case 'MatcherImm16':
182
+ return 'imm16';
183
+ case 'MatcherEa':
184
+ return 'ea';
185
+ case 'MatcherMem8':
186
+ return 'mem8';
187
+ case 'MatcherMem16':
188
+ return 'mem16';
189
+ case 'MatcherFixed':
190
+ return matcher.token;
191
+ default:
192
+ return 'unknown';
193
+ }
194
+ };
195
+ const formatImmExprForOpDiag = (expr) => {
196
+ switch (expr.kind) {
197
+ case 'ImmLiteral':
198
+ return String(expr.value);
199
+ case 'ImmName':
200
+ return expr.name;
201
+ case 'ImmSizeof':
202
+ return 'sizeof(...)';
203
+ case 'ImmOffset':
204
+ return 'offset(...)';
205
+ case 'ImmUnary':
206
+ return `${expr.op}${formatImmExprForOpDiag(expr.expr)}`;
207
+ case 'ImmBinary':
208
+ return `${formatImmExprForOpDiag(expr.left)} ${expr.op} ${formatImmExprForOpDiag(expr.right)}`;
209
+ default:
210
+ return 'imm';
211
+ }
212
+ };
213
+ const formatAsmOperandForOpDiag = (operand) => {
214
+ switch (operand.kind) {
215
+ case 'Reg':
216
+ return operand.name;
217
+ case 'Imm':
218
+ return formatImmExprForOpDiag(operand.expr);
219
+ case 'Ea':
220
+ return formatEaExpr(operand.expr, {
221
+ formatImmExpr: formatImmExprForOpDiag,
222
+ wrapImmEa: true,
223
+ });
224
+ case 'Mem':
225
+ return `(${formatEaExpr(operand.expr, { formatImmExpr: formatImmExprForOpDiag, wrapImmEa: true })})`;
226
+ case 'PortC':
227
+ return '(C)';
228
+ case 'PortImm8':
229
+ return `(${formatImmExprForOpDiag(operand.expr)})`;
230
+ default:
231
+ return '?';
232
+ }
233
+ };
234
+ const formatOpSignature = (opDecl) => {
235
+ const params = opDecl.params.map((p) => `${p.name} ${formatOpMatcher(p.matcher)}`).join(', ');
236
+ return `${opDecl.name}(${params})`;
237
+ };
238
+ const formatOpDefinitionForDiag = (opDecl) => `${formatOpSignature(opDecl)} (${opDecl.span.file}:${opDecl.span.start.line})`;
239
+ const matcherMismatchReason = (matcher, operand) => {
240
+ const got = formatAsmOperandForOpDiag(operand);
241
+ switch (matcher.kind) {
242
+ case 'MatcherReg8':
243
+ return `expects reg8, got ${got}`;
244
+ case 'MatcherReg16':
245
+ return `expects reg16, got ${got}`;
246
+ case 'MatcherIdx16':
247
+ return `expects IX/IY indexed memory operand, got ${got}`;
248
+ case 'MatcherCc':
249
+ return 'expects condition token NZ/Z/NC/C/PO/PE/P/M, got ' + got;
250
+ case 'MatcherImm8': {
251
+ const expr = enumImmExprFromOperand(operand);
252
+ if (!expr)
253
+ return `expects imm8, got ${got}`;
254
+ const value = ctx.evalImmNoDiag(expr);
255
+ if (value === undefined)
256
+ return `expects imm8, got ${got}`;
257
+ if (!fitsImm8(value))
258
+ return `expects imm8 (-128..255), got ${got}`;
259
+ return `expects imm8, got ${got}`;
260
+ }
261
+ case 'MatcherImm16': {
262
+ const expr = enumImmExprFromOperand(operand);
263
+ if (!expr)
264
+ return `expects imm16, got ${got}`;
265
+ const value = ctx.evalImmNoDiag(expr);
266
+ if (value === undefined)
267
+ return `expects imm16, got ${got}`;
268
+ if (!fitsImm16(value))
269
+ return `expects imm16 (-32768..65535), got ${got}`;
270
+ return `expects imm16, got ${got}`;
271
+ }
272
+ case 'MatcherEa':
273
+ return `expects ea, got ${got}`;
274
+ case 'MatcherMem8': {
275
+ if (operand.kind !== 'Mem')
276
+ return `expects mem8 dereference, got ${got}`;
277
+ const width = ctx.inferMemWidth(operand);
278
+ if (width !== undefined && width !== 1)
279
+ return `expects mem8 dereference, got mem${width * 8}`;
280
+ return `expects mem8 dereference, got ${got}`;
281
+ }
282
+ case 'MatcherMem16': {
283
+ if (operand.kind !== 'Mem')
284
+ return `expects mem16 dereference, got ${got}`;
285
+ const width = ctx.inferMemWidth(operand);
286
+ if (width !== undefined && width !== 2)
287
+ return `expects mem16 dereference, got mem${width * 8}`;
288
+ return `expects mem16 dereference, got ${got}`;
289
+ }
290
+ case 'MatcherFixed':
291
+ return `expects ${matcher.token}, got ${got}`;
292
+ default:
293
+ return `operand mismatch: expected ${formatOpMatcher(matcher)}, got ${got}`;
294
+ }
295
+ };
296
+ const firstOpOverloadMismatchReason = (opDecl, operands) => {
297
+ for (let i = 0; i < opDecl.params.length && i < operands.length; i++) {
298
+ const param = opDecl.params[i];
299
+ const operand = operands[i];
300
+ if (matcherMatchesOperand(param.matcher, operand))
301
+ continue;
302
+ return `${param.name}: ${matcherMismatchReason(param.matcher, operand)}`;
303
+ }
304
+ return undefined;
305
+ };
306
+ const selectOpOverload = (overloads, operands) => {
307
+ const arityMatches = overloads.filter((candidate) => candidate.params.length === operands.length);
308
+ if (arityMatches.length === 0) {
309
+ return {
310
+ kind: 'arity_mismatch',
311
+ overloads,
312
+ signatures: overloads.map((candidate) => formatOpSignature(candidate)),
313
+ };
314
+ }
315
+ const matches = arityMatches.filter((candidate) => {
316
+ if (candidate.params.length !== operands.length)
317
+ return false;
318
+ for (let idx = 0; idx < candidate.params.length; idx++) {
319
+ const param = candidate.params[idx];
320
+ const arg = operands[idx];
321
+ if (!matcherMatchesOperand(param.matcher, arg))
322
+ return false;
323
+ }
324
+ return true;
325
+ });
326
+ if (matches.length === 0) {
327
+ return {
328
+ kind: 'no_match',
329
+ overloads: arityMatches,
330
+ mismatchDetails: arityMatches.map((candidate) => {
331
+ const reason = firstOpOverloadMismatchReason(candidate, operands);
332
+ return `${formatOpDefinitionForDiag(candidate)}${reason ? ` ; ${reason}` : ''}`;
333
+ }),
334
+ };
335
+ }
336
+ const selected = selectMostSpecificOpOverload(matches, operands);
337
+ if (!selected) {
338
+ return {
339
+ kind: 'ambiguous',
340
+ overloads: matches,
341
+ definitions: matches.map((candidate) => formatOpDefinitionForDiag(candidate)),
342
+ };
343
+ }
344
+ return { kind: 'selected', overload: selected };
345
+ };
346
+ return {
347
+ matcherMatchesOperand,
348
+ selectMostSpecificOpOverload,
349
+ selectOpOverload,
350
+ formatAsmOperandForOpDiag,
351
+ formatOpSignature,
352
+ formatOpDefinitionForDiag,
353
+ firstOpOverloadMismatchReason,
354
+ };
355
+ }
@@ -0,0 +1,13 @@
1
+ import type { AsmOperandNode, ImmExprNode, SourceSpan } from '../frontend/ast.js';
2
+ import type { AstCloneCapability, CompileEnvCapability, DottedEaNameCapability, LoweringDiagnosticsCapability } from './capabilities.js';
3
+ type OpSubstitutionContext = LoweringDiagnosticsCapability & CompileEnvCapability & AstCloneCapability & DottedEaNameCapability & {
4
+ bindings: Map<string, AsmOperandNode>;
5
+ };
6
+ export declare function createOpSubstitutionHelpers(ctx: OpSubstitutionContext): {
7
+ bindingAsImmExpr: (bound: AsmOperandNode | undefined, span: SourceSpan) => ImmExprNode | undefined;
8
+ substituteImm: (expr: ImmExprNode) => ImmExprNode;
9
+ substituteOperand: (operand: AsmOperandNode) => AsmOperandNode;
10
+ substituteImmWithOpLabels: (expr: ImmExprNode, localLabelMap: Map<string, string>) => ImmExprNode;
11
+ substituteOperandWithOpLabels: (operand: AsmOperandNode, localLabelMap: Map<string, string>) => AsmOperandNode;
12
+ };
13
+ export {};