@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,154 @@
1
+ import type { AsmInstructionNode, SourceSpan } from '../frontend/ast.js';
2
+ export type RegisterCareMode = 'off' | 'audit' | 'warn' | 'error' | 'strict';
3
+ export type RegisterCareUnit = 'A' | 'B' | 'C' | 'D' | 'E' | 'H' | 'L' | 'IXH' | 'IXL' | 'IYH' | 'IYL' | 'SPH' | 'SPL' | 'carry' | 'zero' | 'sign' | 'parity' | 'halfCarry';
4
+ type StackEffect = {
5
+ kind: 'none';
6
+ } | {
7
+ kind: 'push';
8
+ units: RegisterCareUnit[];
9
+ } | {
10
+ kind: 'pop';
11
+ units: RegisterCareUnit[];
12
+ } | {
13
+ kind: 'exchangeTop';
14
+ units: RegisterCareUnit[];
15
+ } | {
16
+ kind: 'unknown';
17
+ };
18
+ export type ControlEffect = {
19
+ kind: 'fallthrough';
20
+ } | {
21
+ kind: 'call';
22
+ target?: string;
23
+ conditional: boolean;
24
+ } | {
25
+ kind: 'rst';
26
+ vector?: number;
27
+ } | {
28
+ kind: 'return';
29
+ } | {
30
+ kind: 'jump';
31
+ target?: string;
32
+ conditional: boolean;
33
+ } | {
34
+ kind: 'unknown';
35
+ };
36
+ export interface InstructionEffect {
37
+ reads: RegisterCareUnit[];
38
+ writes: RegisterCareUnit[];
39
+ stack: StackEffect;
40
+ control: ControlEffect;
41
+ }
42
+ export type SmartComment = {
43
+ kind: 'extern';
44
+ name: string;
45
+ } | {
46
+ kind: 'end';
47
+ } | {
48
+ kind: 'in';
49
+ carriers: RegisterCareUnit[];
50
+ name?: string;
51
+ } | {
52
+ kind: 'out';
53
+ carriers: RegisterCareUnit[];
54
+ name?: string;
55
+ } | {
56
+ kind: 'clobbers';
57
+ carriers: RegisterCareUnit[];
58
+ } | {
59
+ kind: 'preserves';
60
+ carriers: RegisterCareUnit[];
61
+ } | {
62
+ kind: 'expectOut';
63
+ carriers: RegisterCareUnit[];
64
+ name?: string;
65
+ };
66
+ export interface LocatedSmartComment {
67
+ file: string;
68
+ line: number;
69
+ comment: SmartComment;
70
+ }
71
+ export interface RoutineContract {
72
+ name: string;
73
+ in: RegisterCareUnit[];
74
+ out: RegisterCareUnit[];
75
+ clobbers: RegisterCareUnit[];
76
+ preserves: RegisterCareUnit[];
77
+ complete?: boolean;
78
+ }
79
+ export interface RegisterCareInstruction {
80
+ instruction: AsmInstructionNode;
81
+ head: string;
82
+ file: string;
83
+ line: number;
84
+ column: number;
85
+ labels: string[];
86
+ }
87
+ export interface RegisterCareRoutine {
88
+ name: string;
89
+ span: SourceSpan;
90
+ labels: string[];
91
+ entryLabels?: string[];
92
+ instructions: RegisterCareInstruction[];
93
+ }
94
+ export interface RegisterCareDirectCall {
95
+ target: string;
96
+ subject: string;
97
+ file: string;
98
+ line: number;
99
+ column: number;
100
+ }
101
+ export interface RegisterCareProgramModel {
102
+ routines: RegisterCareRoutine[];
103
+ directCallTargets: string[];
104
+ directCalls: RegisterCareDirectCall[];
105
+ directBoundaries: RegisterCareDirectCall[];
106
+ }
107
+ export interface ValueRelation {
108
+ out: RegisterCareUnit[];
109
+ from: RegisterCareUnit[];
110
+ }
111
+ export interface RoutineSummary {
112
+ name: string;
113
+ mayRead: RegisterCareUnit[];
114
+ mayWrite: RegisterCareUnit[];
115
+ preserved: RegisterCareUnit[];
116
+ valueRelations: ValueRelation[];
117
+ outputCandidates?: RegisterCareUnit[];
118
+ stackBalanced: boolean;
119
+ hasUnknownStackEffect: boolean;
120
+ }
121
+ export interface RegisterCareConflict {
122
+ file: string;
123
+ line: number;
124
+ column: number;
125
+ callTarget: string;
126
+ carriers: RegisterCareUnit[];
127
+ message: string;
128
+ }
129
+ export interface RegisterCareUnknownBoundary {
130
+ file: string;
131
+ line: number;
132
+ column: number;
133
+ target: string;
134
+ message: string;
135
+ }
136
+ export interface RegisterCareOutputCandidate {
137
+ file: string;
138
+ line: number;
139
+ column: number;
140
+ routine: string;
141
+ carriers: RegisterCareUnit[];
142
+ autoFixable?: boolean;
143
+ message: string;
144
+ }
145
+ export interface RegisterCareReportModel {
146
+ entryFile: string;
147
+ mode: RegisterCareMode;
148
+ profile?: string;
149
+ summaries: RoutineSummary[];
150
+ conflicts: RegisterCareConflict[];
151
+ outputCandidates?: RegisterCareOutputCandidate[];
152
+ unknownCalls: string[];
153
+ }
154
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { SourceItemNode } from '../frontend/ast.js';
2
+ type DeclNode = SourceItemNode;
3
+ type DeclVisitContext = Record<string, never>;
4
+ export declare function visitDeclTree(items: SourceItemNode[], visit: (item: DeclNode, ctx: DeclVisitContext) => void): void;
5
+ export {};
@@ -0,0 +1,11 @@
1
+ export function visitDeclTree(items, visit) {
2
+ const walkEntry = (entry, ctx) => {
3
+ if (entry.kind === 'AsmLabel' || entry.kind === 'AsmInstruction') {
4
+ return;
5
+ }
6
+ visit(entry, ctx);
7
+ };
8
+ for (const item of items) {
9
+ walkEntry(item, {});
10
+ }
11
+ }
@@ -0,0 +1,28 @@
1
+ import type { Diagnostic } from '../diagnosticTypes.js';
2
+ import type { ImmExprNode, ProgramNode, TypeDeclNode, UnionDeclNode } from '../frontend/ast.js';
3
+ export interface CompileEnv {
4
+ /**
5
+ * Map of equate name -> evaluated numeric value.
6
+ *
7
+ * Values are plain JavaScript numbers; interpretation (imm8/imm16 wrapping, etc.) happens at use sites.
8
+ */
9
+ equates: Map<string, number>;
10
+ /**
11
+ * Map of enum member name -> evaluated numeric value.
12
+ */
13
+ enums: Map<string, number>;
14
+ /**
15
+ * Map of type name -> type declaration.
16
+ *
17
+ * Layout declarations used by sizeof/offset and layout casts.
18
+ */
19
+ types: Map<string, TypeDeclNode | UnionDeclNode>;
20
+ asmEquExprs?: Map<string, {
21
+ expr: ImmExprNode;
22
+ currentLocation?: number;
23
+ }>;
24
+ }
25
+ export declare function evalImmExpr(expr: ImmExprNode, env: CompileEnv, diagnostics?: Diagnostic[], options?: {
26
+ currentLocation?: number;
27
+ }): number | undefined;
28
+ export declare function buildEnv(program: ProgramNode, diagnostics: Diagnostic[]): CompileEnv;
@@ -0,0 +1,432 @@
1
+ import { DiagnosticIds } from '../diagnosticTypes.js';
2
+ import { containsCurrentLocation } from '../frontend/immExprUtils.js';
3
+ import { offsetPathInTypeExpr, sizeOfTypeExpr } from './layout.js';
4
+ import { visitDeclTree } from './declVisitor.js';
5
+ import { diagSemanticsError } from './semanticsDiagnostics.js';
6
+ function reportImmArithmeticError(diagnostics, expr, id, message) {
7
+ diagnostics?.push({
8
+ id,
9
+ severity: 'error',
10
+ message,
11
+ file: expr.span.file,
12
+ line: expr.span.start.line,
13
+ column: expr.span.start.column,
14
+ });
15
+ }
16
+ const diag = diagSemanticsError;
17
+ export function evalImmExpr(expr, env, diagnostics, options) {
18
+ const hasUnqualifiedEnumMember = (name) => {
19
+ if (name.includes('.'))
20
+ return false;
21
+ const suffix = `.${name}`;
22
+ for (const key of env.enums.keys()) {
23
+ if (key.endsWith(suffix))
24
+ return true;
25
+ }
26
+ return false;
27
+ };
28
+ switch (expr.kind) {
29
+ case 'ImmLiteral':
30
+ return expr.value;
31
+ case 'ImmCurrentLocation':
32
+ return options?.currentLocation;
33
+ case 'ImmName': {
34
+ const fromConst = env.equates.get(expr.name) ?? env.equates.get(expr.name.toLowerCase());
35
+ if (fromConst !== undefined)
36
+ return fromConst;
37
+ const fromEnum = env.enums.get(expr.name);
38
+ if (fromEnum !== undefined)
39
+ return fromEnum;
40
+ if (diagnostics && hasUnqualifiedEnumMember(expr.name)) {
41
+ diagnostics.push({
42
+ id: DiagnosticIds.SemanticsError,
43
+ severity: 'error',
44
+ message: `Enum member "${expr.name}" must be qualified.`,
45
+ file: expr.span.file,
46
+ line: expr.span.start.line,
47
+ column: expr.span.start.column,
48
+ });
49
+ }
50
+ return undefined;
51
+ }
52
+ case 'ImmSizeof': {
53
+ return sizeOfTypeExpr(expr.typeExpr, env, diagnostics);
54
+ }
55
+ case 'ImmOffset': {
56
+ return offsetPathInTypeExpr(expr.typeExpr, expr.path, env, (inner) => evalImmExpr(inner, env, diagnostics, options), diagnostics);
57
+ }
58
+ case 'ImmUnary': {
59
+ const v = evalImmExpr(expr.expr, env, diagnostics, options);
60
+ if (v === undefined)
61
+ return undefined;
62
+ switch (expr.op) {
63
+ case '+':
64
+ return +v;
65
+ case '-':
66
+ return -v;
67
+ case '~':
68
+ return ~v;
69
+ }
70
+ return undefined;
71
+ }
72
+ case 'ImmBinary': {
73
+ const l = evalImmExpr(expr.left, env, diagnostics, options);
74
+ const r = evalImmExpr(expr.right, env, diagnostics, options);
75
+ if (l === undefined || r === undefined)
76
+ return undefined;
77
+ switch (expr.op) {
78
+ case '*':
79
+ return l * r;
80
+ case '/':
81
+ if (r === 0) {
82
+ reportImmArithmeticError(diagnostics, expr, DiagnosticIds.ImmDivideByZero, 'Divide by zero in imm expression.');
83
+ return undefined;
84
+ }
85
+ return (l / r) | 0;
86
+ case '%':
87
+ if (r === 0) {
88
+ reportImmArithmeticError(diagnostics, expr, DiagnosticIds.ImmModuloByZero, 'Modulo by zero in imm expression.');
89
+ return undefined;
90
+ }
91
+ return l % r;
92
+ case '+':
93
+ return l + r;
94
+ case '-':
95
+ return l - r;
96
+ case '&':
97
+ return l & r;
98
+ case '^':
99
+ return l ^ r;
100
+ case '|':
101
+ return l | r;
102
+ case '<<':
103
+ return l << r;
104
+ case '>>':
105
+ return l >> r;
106
+ }
107
+ return undefined;
108
+ }
109
+ }
110
+ }
111
+ function isAsmEquNode(item) {
112
+ return (item.kind === 'AsmEqu' &&
113
+ typeof item.name === 'string' &&
114
+ item.value?.kind !== undefined);
115
+ }
116
+ function constValueExpr(item) {
117
+ const expr = item.value;
118
+ if (!expr)
119
+ throw new Error('ASM equ directive is missing an expression.');
120
+ return expr;
121
+ }
122
+ function isAsmDirectiveItem(item) {
123
+ return (item.kind === 'AsmOrg' ||
124
+ item.kind === 'AsmEqu' ||
125
+ item.kind === 'AsmRawData' ||
126
+ item.kind === 'AsmLabel' ||
127
+ item.kind === 'AsmInstruction');
128
+ }
129
+ function isIndexedOperand(op) {
130
+ if (!op)
131
+ return false;
132
+ const expr = op.kind === 'Mem' ? op.expr : op.kind === 'Ea' ? op.expr : undefined;
133
+ return expr?.kind === 'EaIndex' && expr.index.kind === 'IndexMemIxIy';
134
+ }
135
+ function reg(op) {
136
+ if (!op)
137
+ return undefined;
138
+ if (op.kind === 'Reg')
139
+ return op.name.toUpperCase();
140
+ if (op.kind === 'Imm' && op.expr.kind === 'ImmName')
141
+ return op.expr.name.toUpperCase();
142
+ return undefined;
143
+ }
144
+ function asmInstructionSize(item) {
145
+ const head = item.head.toLowerCase();
146
+ const ops = item.operands;
147
+ const r0 = reg(ops[0]);
148
+ const r1 = reg(ops[1]);
149
+ const indexed = isIndexedOperand(ops[0]) || isIndexedOperand(ops[1]);
150
+ const ixiyReg = (name) => name === 'IX' ||
151
+ name === 'IY' ||
152
+ name === 'IXH' ||
153
+ name === 'IXL' ||
154
+ name === 'IYH' ||
155
+ name === 'IYL';
156
+ if (['cpi', 'cpir', 'ldi', 'ldir', 'lddr', 'ini', 'outi', 'neg', 'reti', 'retn', 'rld'].includes(head)) {
157
+ return 2;
158
+ }
159
+ if (['nop', 'ccf', 'cpl', 'daa', 'exx', 'rlca', 'rrca', 'rla', 'rra', 'scf'].includes(head)) {
160
+ return 1;
161
+ }
162
+ if (head === 'jr' || head === 'djnz')
163
+ return 2;
164
+ if (head === 'call')
165
+ return 3;
166
+ if (head === 'jp')
167
+ return ops[0]?.kind === 'Mem' && ixiyReg(regFromMem(ops[0]))
168
+ ? 2
169
+ : ops[0]?.kind === 'Mem'
170
+ ? 1
171
+ : 3;
172
+ if (head === 'ret')
173
+ return 1;
174
+ if (head === 'rst')
175
+ return 1;
176
+ if (head === 'push' || head === 'pop')
177
+ return ixiyReg(r0) ? 2 : 1;
178
+ if (head === 'ex')
179
+ return ixiyReg(r1) || indexed ? 2 : 1;
180
+ if (head === 'in' || head === 'out')
181
+ return 2;
182
+ if (['bit', 'res', 'set', 'rl', 'rr', 'rlc', 'rrc', 'sla', 'srl'].includes(head))
183
+ return indexed ? 4 : 2;
184
+ if (head === 'inc' || head === 'dec')
185
+ return indexed ? 3 : ixiyReg(r0) ? 2 : 1;
186
+ if (['add', 'adc', 'sbc'].includes(head)) {
187
+ if (r0 === 'HL' && r1)
188
+ return 1;
189
+ if ((r0 === 'IX' || r0 === 'IY') && r1)
190
+ return 2;
191
+ if (r0 === 'HL')
192
+ return 2;
193
+ if (indexed)
194
+ return 3;
195
+ return ops[1]?.kind === 'Imm' || (ops.length === 1 && ops[0]?.kind === 'Imm') ? 2 : 1;
196
+ }
197
+ if (['sub', 'and', 'or', 'xor', 'cp'].includes(head))
198
+ return indexed ? 3 : ops[0]?.kind === 'Imm' ? 2 : 1;
199
+ if (head === 'ld') {
200
+ if (indexed)
201
+ return ops[0]?.kind === 'Imm' || ops[1]?.kind === 'Imm' ? 4 : 3;
202
+ if (ops[0]?.kind === 'Mem' || ops[1]?.kind === 'Mem') {
203
+ const memOp = ops[0]?.kind === 'Mem' ? ops[0] : ops[1];
204
+ const memReg = ops[0]?.kind === 'Mem' ? r1 : r0;
205
+ const indirectReg = regFromMem(memOp);
206
+ if (indirectReg) {
207
+ if (memReg === 'A' && (indirectReg === 'BC' || indirectReg === 'DE'))
208
+ return 1;
209
+ if (indirectReg === 'HL')
210
+ return 1;
211
+ }
212
+ return memReg && ['BC', 'DE', 'SP', 'IX', 'IY'].includes(memReg) ? 4 : 3;
213
+ }
214
+ if (ixiyReg(r0) || ixiyReg(r1))
215
+ return ops[1]?.kind === 'Imm' ? 4 : 2;
216
+ if (ops[1]?.kind === 'Imm')
217
+ return r0 && ['BC', 'DE', 'HL', 'SP'].includes(r0) ? 3 : 2;
218
+ return 1;
219
+ }
220
+ return 1;
221
+ }
222
+ function regFromMem(op) {
223
+ if (!op || op.kind !== 'Mem')
224
+ return undefined;
225
+ if (op.expr.kind === 'EaName')
226
+ return op.expr.name.toUpperCase();
227
+ if (op.expr.kind === 'EaIndex' && op.expr.index.kind === 'IndexMemIxIy')
228
+ return op.expr.index.base;
229
+ return undefined;
230
+ }
231
+ function asmRawDataSize(item, env) {
232
+ const values = item.values ?? [];
233
+ if (item.directive === 'ds') {
234
+ if (!item.size)
235
+ return 0;
236
+ if (item.size.kind === 'ImmName') {
237
+ const constValue = env.equates.get(item.size.name) ?? env.equates.get(item.size.name.toLowerCase());
238
+ const enumValue = env.enums.get(item.size.name);
239
+ if (constValue === undefined && enumValue === undefined) {
240
+ const typeSize = sizeOfTypeExpr({ kind: 'TypeName', span: item.size.span, name: item.size.name }, env, undefined);
241
+ if (typeSize !== undefined)
242
+ return typeSize;
243
+ }
244
+ }
245
+ return evalImmExpr(item.size, env) ?? 0;
246
+ }
247
+ if (item.directive === 'dw')
248
+ return values.length * 2;
249
+ if (item.directive === 'cstr')
250
+ return asmStringLength(values[0]) + 1;
251
+ if (item.directive === 'pstr')
252
+ return asmStringLength(values[0]) + 1;
253
+ if (item.directive === 'istr')
254
+ return asmStringLength(values[0]);
255
+ return values.reduce((size, value) => size + asmStringLength(value, 1), 0);
256
+ }
257
+ function asmStringLength(value, fallback = 0) {
258
+ if (typeof value === 'string')
259
+ return value.length;
260
+ if (value && typeof value === 'object' && 'kind' in value && value.kind === 'AsmString') {
261
+ return 'value' in value && typeof value.value === 'string' ? value.value.length : fallback;
262
+ }
263
+ return fallback;
264
+ }
265
+ function seedAsmCurrentLocationEquates(program, env) {
266
+ for (const mf of program.files) {
267
+ if (!mf.items.some((item) => isAsmDirectiveItem(item)))
268
+ continue;
269
+ const scratchEnv = { ...env, equates: new Map(env.equates) };
270
+ let current = 0;
271
+ for (const item of mf.items) {
272
+ const kind = item.kind;
273
+ switch (kind) {
274
+ case 'AsmOrg': {
275
+ const expr = item.value;
276
+ const value = expr ? evalImmExpr(expr, scratchEnv) : undefined;
277
+ if (value !== undefined)
278
+ current = value;
279
+ break;
280
+ }
281
+ case 'AsmLabel': {
282
+ const label = item;
283
+ scratchEnv.equates.set(label.name, current);
284
+ scratchEnv.equates.set(label.name.toLowerCase(), current);
285
+ break;
286
+ }
287
+ case 'AsmEqu': {
288
+ const equ = item;
289
+ if (env.types.has(equ.name))
290
+ break;
291
+ const expr = equ.value;
292
+ if (expr) {
293
+ env.asmEquExprs?.set(equ.name, { expr, currentLocation: current });
294
+ env.asmEquExprs?.set(equ.name.toLowerCase(), { expr, currentLocation: current });
295
+ const value = containsCurrentLocation(expr)
296
+ ? evalImmExpr(expr, scratchEnv, undefined, { currentLocation: current })
297
+ : evalImmExpr(expr, scratchEnv);
298
+ if (value !== undefined) {
299
+ env.equates.set(equ.name, value);
300
+ env.equates.set(equ.name.toLowerCase(), value);
301
+ scratchEnv.equates.set(equ.name, value);
302
+ scratchEnv.equates.set(equ.name.toLowerCase(), value);
303
+ }
304
+ }
305
+ break;
306
+ }
307
+ case 'AsmRawData':
308
+ {
309
+ const raw = item;
310
+ if (raw.name) {
311
+ scratchEnv.equates.set(raw.name, current);
312
+ scratchEnv.equates.set(raw.name.toLowerCase(), current);
313
+ }
314
+ current += asmRawDataSize(raw, scratchEnv);
315
+ }
316
+ break;
317
+ case 'AsmInstruction':
318
+ current += asmInstructionSize(item);
319
+ break;
320
+ }
321
+ }
322
+ }
323
+ }
324
+ export function buildEnv(program, diagnostics) {
325
+ const equates = new Map();
326
+ const asmEquExprs = new Map();
327
+ const enums = new Map();
328
+ const types = new Map();
329
+ if (program.files.length === 0) {
330
+ diag(diagnostics, program.entryFile, 'No source files to compile.');
331
+ return {
332
+ equates,
333
+ enums,
334
+ types,
335
+ };
336
+ }
337
+ const collectedByFile = new Map();
338
+ for (const mf of program.files) {
339
+ const collected = {
340
+ types: [],
341
+ enums: [],
342
+ equates: [],
343
+ };
344
+ visitDeclTree(mf.items, (item) => {
345
+ if (item.kind === 'TypeDecl' || item.kind === 'UnionDecl') {
346
+ collected.types.push(item);
347
+ return;
348
+ }
349
+ if (item.kind === 'EnumDecl') {
350
+ collected.enums.push(item);
351
+ return;
352
+ }
353
+ if (isAsmEquNode(item)) {
354
+ collected.equates.push(item);
355
+ }
356
+ });
357
+ collectedByFile.set(mf.path, collected);
358
+ }
359
+ const globalLower = new Map();
360
+ const claim = (kind, name, file) => {
361
+ const k = name.toLowerCase();
362
+ const prev = globalLower.get(k);
363
+ if (prev) {
364
+ diag(diagnostics, file, `Name "${name}" collides with ${prev.kind} "${prev.name}".`);
365
+ return false;
366
+ }
367
+ globalLower.set(k, { kind, name, file });
368
+ return true;
369
+ };
370
+ for (const mf of program.files) {
371
+ const collected = collectedByFile.get(mf.path);
372
+ if (!collected)
373
+ continue;
374
+ for (const item of collected.types) {
375
+ const kind = item.kind === 'TypeDecl' ? 'type' : 'union';
376
+ const name = item.name;
377
+ if (!claim(kind, name, item.span.file))
378
+ continue;
379
+ types.set(name, item);
380
+ }
381
+ }
382
+ for (const mf of program.files) {
383
+ const collected = collectedByFile.get(mf.path);
384
+ if (!collected)
385
+ continue;
386
+ for (const e of collected.enums) {
387
+ claim('enum', e.name, e.span.file);
388
+ for (let idx = 0; idx < e.members.length; idx++) {
389
+ const name = e.members[idx];
390
+ const qualifiedName = `${e.name}.${name}`;
391
+ if (!claim('enum member', qualifiedName, e.span.file))
392
+ continue;
393
+ enums.set(qualifiedName, idx);
394
+ }
395
+ }
396
+ }
397
+ const env = {
398
+ equates,
399
+ enums,
400
+ types,
401
+ asmEquExprs,
402
+ };
403
+ seedAsmCurrentLocationEquates(program, env);
404
+ for (const mf of program.files) {
405
+ const collected = collectedByFile.get(mf.path);
406
+ if (!collected)
407
+ continue;
408
+ for (const item of collected.equates) {
409
+ if (types.has(item.name)) {
410
+ diag(diagnostics, item.span.file, `Equate name "${item.name}" collides with a type name.`);
411
+ continue;
412
+ }
413
+ if (!claim('equate', item.name, item.span.file))
414
+ continue;
415
+ if (equates.has(item.name.toLowerCase()))
416
+ continue;
417
+ const expr = constValueExpr(item);
418
+ if (!asmEquExprs.has(item.name))
419
+ asmEquExprs.set(item.name, { expr });
420
+ if (!asmEquExprs.has(item.name.toLowerCase())) {
421
+ asmEquExprs.set(item.name.toLowerCase(), { expr });
422
+ }
423
+ const v = evalImmExpr(expr, env, diagnostics);
424
+ if (v === undefined) {
425
+ continue;
426
+ }
427
+ equates.set(item.name, v);
428
+ equates.set(item.name.toLowerCase(), v);
429
+ }
430
+ }
431
+ return env;
432
+ }
@@ -0,0 +1,21 @@
1
+ import type { Diagnostic } from '../diagnosticTypes.js';
2
+ import type { ImmExprNode, OffsetPathNode, TypeExprNode } from '../frontend/ast.js';
3
+ import type { CompileEnv } from './env.js';
4
+ interface TypeLayoutInfo {
5
+ size: number;
6
+ }
7
+ export declare function layoutInfoForTypeExpr(typeExpr: TypeExprNode, env: CompileEnv, diagnostics?: Diagnostic[]): TypeLayoutInfo | undefined;
8
+ /**
9
+ * Compute the exact semantic size in bytes of a type expression.
10
+ */
11
+ export declare function sizeOfTypeExpr(typeExpr: TypeExprNode, env: CompileEnv, diagnostics?: Diagnostic[]): number | undefined;
12
+ /**
13
+ * Compute the byte offset of a field path inside a type expression.
14
+ *
15
+ * Rules:
16
+ * - Record fields contribute exact sizes of preceding fields.
17
+ * - Union field offsets are always 0.
18
+ * - Array indices must be compile-time constants and contribute index * element exact size.
19
+ */
20
+ export declare function offsetPathInTypeExpr(typeExpr: TypeExprNode, path: OffsetPathNode, env: CompileEnv, evalImm: (expr: ImmExprNode) => number | undefined, diagnostics?: Diagnostic[]): number | undefined;
21
+ export {};