@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,175 @@
1
+ import { dirname, extname } from 'node:path';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { analyzeLoadedProgram } from './analysis.js';
4
+ import { hasErrors, normalizePath } from './compileShared.js';
5
+ import { DiagnosticIds } from './diagnosticTypes.js';
6
+ import { buildDirectiveAliasPolicy, defaultDirectiveAliasProfileName, readDirectiveAliasProfile, } from './frontend/directiveAliases.js';
7
+ import { isSupportedSourcePath } from './frontend/sourceExtensions.js';
8
+ import { emitProgram } from './lowering/emit.js';
9
+ import { loadProgram } from './sourceLoader.js';
10
+ import { analyzeRegisterCare } from './registerCare/analyze.js';
11
+ import { parseInterfaceContracts } from './registerCare/smartComments.js';
12
+ function withDefaults(options) {
13
+ const anyPrimaryEmitSpecified = [options.emitBin, options.emitHex, options.emitD8m].some((v) => v !== undefined);
14
+ const emitBin = anyPrimaryEmitSpecified ? (options.emitBin ?? false) : true;
15
+ const emitHex = anyPrimaryEmitSpecified ? (options.emitHex ?? false) : true;
16
+ const emitD8m = anyPrimaryEmitSpecified ? (options.emitD8m ?? false) : true;
17
+ // Listing is a sidecar artifact: default to on unless explicitly suppressed.
18
+ const emitListing = options.emitListing ?? true;
19
+ const emitAsm80 = options.emitAsm80 ?? false;
20
+ return { emitBin, emitHex, emitD8m, emitListing, emitAsm80 };
21
+ }
22
+ /**
23
+ * Compile an AZM/ASM80-family program starting from an entry file.
24
+ *
25
+ * - Expands textual includes transitively with deterministic cycle checks.
26
+ * - Runs parse → semantics → lowering → format writers.
27
+ * - Produces artifacts in-memory via `deps.formats`.
28
+ * - Defaults to emitting BIN + HEX + D8M unless an emit flag is explicitly provided.
29
+ */
30
+ export const compile = async (entryFile, options, deps) => {
31
+ const entryPath = normalizePath(entryFile);
32
+ const diagnostics = [];
33
+ const artifacts = [];
34
+ if (!isSupportedSourcePath(entryPath)) {
35
+ diagnostics.push({
36
+ id: DiagnosticIds.Unknown,
37
+ severity: 'error',
38
+ message: 'Unsupported source file extension (expected .asm or .z80)',
39
+ file: entryPath,
40
+ });
41
+ return { diagnostics, artifacts };
42
+ }
43
+ const projectAliasProfiles = [];
44
+ for (const path of options.directiveAliasFiles ?? []) {
45
+ projectAliasProfiles.push(await readDirectiveAliasProfile(normalizePath(path)));
46
+ }
47
+ const directiveAliasPolicy = buildDirectiveAliasPolicy(defaultDirectiveAliasProfileName(), projectAliasProfiles);
48
+ const loaded = await loadProgram(entryPath, diagnostics, {
49
+ ...options,
50
+ directiveAliasPolicy,
51
+ });
52
+ if (!loaded)
53
+ return { diagnostics, artifacts };
54
+ const { program, sourceTexts, sourceLineComments } = loaded;
55
+ if (hasErrors(diagnostics)) {
56
+ return { diagnostics, artifacts };
57
+ }
58
+ const analysis = analyzeLoadedProgram(loaded, {
59
+ ...(options.caseStyle !== undefined ? { caseStyle: options.caseStyle } : {}),
60
+ ...(options.requireMain !== undefined ? { requireMain: options.requireMain } : {}),
61
+ });
62
+ diagnostics.push(...analysis.diagnostics);
63
+ if (hasErrors(diagnostics) || !analysis.env)
64
+ return { diagnostics, artifacts };
65
+ const env = analysis.env;
66
+ const registerCareMode = options.registerCare ?? 'off';
67
+ const shouldAnalyzeRegisterCare = registerCareMode !== 'off' ||
68
+ options.emitRegisterReport === true ||
69
+ options.emitRegisterInterface === true ||
70
+ options.emitRegisterAnnotations === true ||
71
+ options.fixRegisterContracts === true ||
72
+ (options.acceptRegisterOutputCandidates?.length ?? 0) > 0 ||
73
+ (options.registerCareInterfaces?.length ?? 0) > 0;
74
+ if (shouldAnalyzeRegisterCare) {
75
+ const interfaceContracts = [];
76
+ for (const path of options.registerCareInterfaces ?? []) {
77
+ const resolved = normalizePath(path);
78
+ if (extname(resolved).toLowerCase() !== '.asmi') {
79
+ diagnostics.push({
80
+ id: DiagnosticIds.Unknown,
81
+ severity: 'error',
82
+ message: 'Register-care interface files must use the .asmi extension',
83
+ file: resolved,
84
+ });
85
+ continue;
86
+ }
87
+ const text = await readFile(resolved, 'utf8');
88
+ interfaceContracts.push(...parseInterfaceContracts(text, resolved).values());
89
+ }
90
+ if (hasErrors(diagnostics))
91
+ return { diagnostics, artifacts };
92
+ const registerCare = analyzeRegisterCare(loaded, {
93
+ mode: registerCareMode,
94
+ emitReport: options.emitRegisterReport === true,
95
+ emitInterface: options.emitRegisterInterface === true,
96
+ emitAnnotations: options.emitRegisterAnnotations === true || options.fixRegisterContracts === true,
97
+ fixRegisterContracts: options.fixRegisterContracts === true,
98
+ ...(options.acceptRegisterOutputCandidates !== undefined
99
+ ? { acceptOutputCandidates: options.acceptRegisterOutputCandidates }
100
+ : {}),
101
+ ...(options.registerCareProfile !== undefined
102
+ ? { profile: options.registerCareProfile }
103
+ : {}),
104
+ ...(interfaceContracts.length > 0 ? { interfaceContracts } : {}),
105
+ });
106
+ diagnostics.push(...registerCare.diagnostics);
107
+ if (registerCare.reportText !== undefined) {
108
+ artifacts.push({ kind: 'register-care-report', text: registerCare.reportText });
109
+ }
110
+ if (registerCare.interfaceText !== undefined) {
111
+ artifacts.push({ kind: 'register-care-interface', text: registerCare.interfaceText });
112
+ }
113
+ if (registerCare.annotatedFiles !== undefined) {
114
+ artifacts.push({ kind: 'register-care-annotations', files: registerCare.annotatedFiles });
115
+ }
116
+ if (hasErrors(diagnostics)) {
117
+ return { diagnostics, artifacts };
118
+ }
119
+ }
120
+ const { map, symbols, placedLoweredAsmProgram } = emitProgram(program, env, diagnostics, {
121
+ ...(options.includeDirs ? { includeDirs: options.includeDirs } : {}),
122
+ ...(options.defaultCodeBase !== undefined ? { defaultCodeBase: options.defaultCodeBase } : {}),
123
+ sourceTexts,
124
+ sourceLineComments,
125
+ });
126
+ if (hasErrors(diagnostics)) {
127
+ return { diagnostics, artifacts };
128
+ }
129
+ const emit = withDefaults(options);
130
+ if (emit.emitBin) {
131
+ artifacts.push(deps.formats.writeBin(map, symbols));
132
+ }
133
+ if (emit.emitHex) {
134
+ artifacts.push(deps.formats.writeHex(map, symbols));
135
+ }
136
+ if (emit.emitD8m) {
137
+ const mainEntry = symbols.find((s) => s.kind === 'label' && s.name.toLowerCase() === 'main');
138
+ artifacts.push(deps.formats.writeD8m(map, symbols, {
139
+ rootDir: dirname(entryPath),
140
+ ...(mainEntry
141
+ ? {
142
+ entrySymbol: mainEntry.name,
143
+ entryAddress: mainEntry.address & 0xffff,
144
+ }
145
+ : {}),
146
+ }));
147
+ }
148
+ if (emit.emitListing) {
149
+ if (deps.formats.writeListing) {
150
+ artifacts.push(deps.formats.writeListing(map, symbols));
151
+ }
152
+ else {
153
+ diagnostics.push({
154
+ id: DiagnosticIds.Unknown,
155
+ severity: 'warning',
156
+ message: 'emitListing=true but no listing writer is configured; skipping .lst artifact.',
157
+ file: program.entryFile,
158
+ });
159
+ }
160
+ }
161
+ if (emit.emitAsm80) {
162
+ if (deps.formats.writeAsm80) {
163
+ artifacts.push(deps.formats.writeAsm80(placedLoweredAsmProgram));
164
+ }
165
+ else {
166
+ diagnostics.push({
167
+ id: DiagnosticIds.Unknown,
168
+ severity: 'warning',
169
+ message: 'emitAsm80=true but no asm80 writer is configured; skipping .asm artifact.',
170
+ file: program.entryFile,
171
+ });
172
+ }
173
+ }
174
+ return { diagnostics, artifacts };
175
+ };
@@ -0,0 +1,3 @@
1
+ import type { Diagnostic } from './diagnosticTypes.js';
2
+ export declare function hasErrors(diagnostics: Diagnostic[]): boolean;
3
+ export declare function normalizePath(p: string): string;
@@ -0,0 +1,7 @@
1
+ import { resolve } from 'node:path';
2
+ export function hasErrors(diagnostics) {
3
+ return diagnostics.some((d) => d.severity === 'error');
4
+ }
5
+ export function normalizePath(p) {
6
+ return resolve(p);
7
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Severity level for a diagnostic.
3
+ */
4
+ export type DiagnosticSeverity = 'error' | 'warning' | 'info';
5
+ /**
6
+ * A compiler diagnostic (error/warning/info) with an optional source location.
7
+ *
8
+ * Diagnostics must have stable IDs so downstream tooling can rely on them.
9
+ */
10
+ export interface Diagnostic {
11
+ /** Stable diagnostic identifier (e.g., `AZM001`). */
12
+ id: DiagnosticId;
13
+ severity: DiagnosticSeverity;
14
+ message: string;
15
+ file: string;
16
+ /** 1-based line number, when known. */
17
+ line?: number;
18
+ /** 1-based column number, when known. */
19
+ column?: number;
20
+ }
21
+ /**
22
+ * Known diagnostic IDs.
23
+ *
24
+ * PR0 started with a minimal set; later PRs should extend this via contract changes.
25
+ */
26
+ export declare const DiagnosticIds: {
27
+ /**
28
+ * Unknown/unclassified diagnostic.
29
+ *
30
+ * Use a more specific ID when possible; this remains for forward compatibility.
31
+ */
32
+ readonly Unknown: "AZM000";
33
+ /** Failed to read a source file from disk. */
34
+ readonly IoReadFailed: "AZM001";
35
+ /** Internal error during parsing (unexpected exception). */
36
+ readonly InternalParseError: "AZM002";
37
+ /** Include could not be resolved on any search path. */
38
+ readonly IncludeNotFound: "AZM003";
39
+ /** Generic parse error (syntax / unsupported in current PR subset). */
40
+ readonly ParseError: "AZM100";
41
+ /** Generic instruction encoding error (unsupported mnemonic/operands, out-of-range imm, etc.). */
42
+ readonly EncodeError: "AZM200";
43
+ /** Generic emission/lowering error (layout/packing/symbol collisions, etc.). */
44
+ readonly EmitError: "AZM300";
45
+ /** Generic emission/lowering warning. */
46
+ readonly EmitWarning: "AZM301";
47
+ /** Op invocation arity mismatch against available overload set. */
48
+ readonly OpArityMismatch: "AZM310";
49
+ /** No overload match for an op invocation with the provided operands. */
50
+ readonly OpNoMatchingOverload: "AZM311";
51
+ /** Ambiguous overload resolution for an op invocation. */
52
+ readonly OpAmbiguousOverload: "AZM312";
53
+ /** Cyclic op expansion detected in inline expansion graph. */
54
+ readonly OpExpansionCycle: "AZM313";
55
+ /** Op expansion produced an invalid concrete instruction after substitution. */
56
+ readonly OpInvalidExpansion: "AZM314";
57
+ /** Generic semantic evaluation error (env building, imm evaluation, etc.). */
58
+ readonly SemanticsError: "AZM400";
59
+ /** Divide by zero in an imm expression. */
60
+ readonly ImmDivideByZero: "AZM401";
61
+ /** Modulo by zero in an imm expression. */
62
+ readonly ImmModuloByZero: "AZM402";
63
+ /** Type/layout error (unknown type, recursion, missing array length, etc.). */
64
+ readonly TypeError: "AZM403";
65
+ /** Case-style lint warning for keyword/register casing policy. */
66
+ readonly CaseStyleLint: "AZM500";
67
+ /** Redundant outer parentheses in a constant-only array index expression. */
68
+ readonly IndexParenRedundant: "AZM501";
69
+ /** Register-care conflict where a call may destroy a live caller value. */
70
+ readonly RegisterCareConflict: "AZM600";
71
+ /** Register-care analysis cannot prove an external or indirect call contract. */
72
+ readonly RegisterCareUnknownBoundary: "AZM601";
73
+ };
74
+ /**
75
+ * Union type of all defined diagnostic IDs.
76
+ */
77
+ export type DiagnosticId = (typeof DiagnosticIds)[keyof typeof DiagnosticIds];
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Known diagnostic IDs.
3
+ *
4
+ * PR0 started with a minimal set; later PRs should extend this via contract changes.
5
+ */
6
+ export const DiagnosticIds = {
7
+ /**
8
+ * Unknown/unclassified diagnostic.
9
+ *
10
+ * Use a more specific ID when possible; this remains for forward compatibility.
11
+ */
12
+ Unknown: 'AZM000',
13
+ /** Failed to read a source file from disk. */
14
+ IoReadFailed: 'AZM001',
15
+ /** Internal error during parsing (unexpected exception). */
16
+ InternalParseError: 'AZM002',
17
+ /** Include could not be resolved on any search path. */
18
+ IncludeNotFound: 'AZM003',
19
+ /** Generic parse error (syntax / unsupported in current PR subset). */
20
+ ParseError: 'AZM100',
21
+ /** Generic instruction encoding error (unsupported mnemonic/operands, out-of-range imm, etc.). */
22
+ EncodeError: 'AZM200',
23
+ /** Generic emission/lowering error (layout/packing/symbol collisions, etc.). */
24
+ EmitError: 'AZM300',
25
+ /** Generic emission/lowering warning. */
26
+ EmitWarning: 'AZM301',
27
+ /** Op invocation arity mismatch against available overload set. */
28
+ OpArityMismatch: 'AZM310',
29
+ /** No overload match for an op invocation with the provided operands. */
30
+ OpNoMatchingOverload: 'AZM311',
31
+ /** Ambiguous overload resolution for an op invocation. */
32
+ OpAmbiguousOverload: 'AZM312',
33
+ /** Cyclic op expansion detected in inline expansion graph. */
34
+ OpExpansionCycle: 'AZM313',
35
+ /** Op expansion produced an invalid concrete instruction after substitution. */
36
+ OpInvalidExpansion: 'AZM314',
37
+ /** Generic semantic evaluation error (env building, imm evaluation, etc.). */
38
+ SemanticsError: 'AZM400',
39
+ /** Divide by zero in an imm expression. */
40
+ ImmDivideByZero: 'AZM401',
41
+ /** Modulo by zero in an imm expression. */
42
+ ImmModuloByZero: 'AZM402',
43
+ /** Type/layout error (unknown type, recursion, missing array length, etc.). */
44
+ TypeError: 'AZM403',
45
+ /** Case-style lint warning for keyword/register casing policy. */
46
+ CaseStyleLint: 'AZM500',
47
+ /** Redundant outer parentheses in a constant-only array index expression. */
48
+ IndexParenRedundant: 'AZM501',
49
+ /** Register-care conflict where a call may destroy a live caller value. */
50
+ RegisterCareConflict: 'AZM600',
51
+ /** Register-care analysis cannot prove an external or indirect call contract. */
52
+ RegisterCareUnknownBoundary: 'AZM601',
53
+ };
@@ -0,0 +1,7 @@
1
+ import type { FormatWriters } from './types.js';
2
+ /**
3
+ * Default in-memory artifact writers for PR1.
4
+ *
5
+ * These writers implement the `FormatWriters` contract and return artifacts without writing to disk.
6
+ */
7
+ export declare const defaultFormatWriters: FormatWriters;
@@ -0,0 +1,17 @@
1
+ import { writeBin } from './writeBin.js';
2
+ import { writeD8m } from './writeD8m.js';
3
+ import { writeHex } from './writeHex.js';
4
+ import { writeListing } from './writeListing.js';
5
+ import { writeAsm80 } from './writeAsm80.js';
6
+ /**
7
+ * Default in-memory artifact writers for PR1.
8
+ *
9
+ * These writers implement the `FormatWriters` contract and return artifacts without writing to disk.
10
+ */
11
+ export const defaultFormatWriters = {
12
+ writeHex,
13
+ writeBin,
14
+ writeD8m,
15
+ writeListing,
16
+ writeAsm80,
17
+ };
@@ -0,0 +1,17 @@
1
+ import type { AddressRange, EmittedByteMap } from './types.js';
2
+ /**
3
+ * Compute contiguous written segments from an emitted byte map.
4
+ *
5
+ * - Segments are half-open `[start, end)`.
6
+ * - Segment boundaries are based on concrete written byte addresses.
7
+ * - For an empty map, `[]` is returned.
8
+ */
9
+ export declare function getWrittenSegments(map: EmittedByteMap): AddressRange[];
10
+ /**
11
+ * Compute the effective written range for an emitted byte map.
12
+ *
13
+ * - If `map.writtenRange` is present, it is returned directly.
14
+ * - Otherwise, the range is derived from the min/max written addresses.
15
+ * - For an empty map, `{ start: 0, end: 0 }` is returned.
16
+ */
17
+ export declare function getWrittenRange(map: EmittedByteMap): AddressRange;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Compute contiguous written segments from an emitted byte map.
3
+ *
4
+ * - Segments are half-open `[start, end)`.
5
+ * - Segment boundaries are based on concrete written byte addresses.
6
+ * - For an empty map, `[]` is returned.
7
+ */
8
+ export function getWrittenSegments(map) {
9
+ if (map.bytes.size === 0)
10
+ return [];
11
+ const sorted = [...new Set(map.bytes.keys())].sort((a, b) => a - b);
12
+ const segments = [];
13
+ let start = sorted[0];
14
+ let prev = start;
15
+ for (let index = 1; index < sorted.length; index++) {
16
+ const addr = sorted[index];
17
+ if (addr <= prev + 1) {
18
+ prev = addr;
19
+ continue;
20
+ }
21
+ segments.push({ start, end: prev + 1 });
22
+ start = addr;
23
+ prev = addr;
24
+ }
25
+ segments.push({ start, end: prev + 1 });
26
+ return segments;
27
+ }
28
+ /**
29
+ * Compute the effective written range for an emitted byte map.
30
+ *
31
+ * - If `map.writtenRange` is present, it is returned directly.
32
+ * - Otherwise, the range is derived from the min/max written addresses.
33
+ * - For an empty map, `{ start: 0, end: 0 }` is returned.
34
+ */
35
+ export function getWrittenRange(map) {
36
+ if (map.writtenRange)
37
+ return map.writtenRange;
38
+ const segments = getWrittenSegments(map);
39
+ if (segments.length === 0)
40
+ return { start: 0, end: 0 };
41
+ return {
42
+ start: segments[0].start,
43
+ end: segments[segments.length - 1].end,
44
+ };
45
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Half-open address range in the Z80 16-bit address space.
3
+ */
4
+ export interface AddressRange {
5
+ /** Inclusive start address. */
6
+ start: number;
7
+ /** Exclusive end address. */
8
+ end: number;
9
+ }
10
+ /**
11
+ * Address->byte map for all emitted machine-code bytes.
12
+ */
13
+ export interface EmittedByteMap {
14
+ /**
15
+ * Address -> byte (0..255). Addresses are 0..65535 for Z80.
16
+ */
17
+ bytes: Map<number, number>;
18
+ writtenRange?: AddressRange;
19
+ /**
20
+ * Optional source-attributed code segments emitted by lowering.
21
+ *
22
+ * Addresses are absolute in the final 16-bit address space.
23
+ */
24
+ sourceSegments?: EmittedSourceSegment[];
25
+ }
26
+ /**
27
+ * Source-attributed emitted range used by debug-map writers.
28
+ */
29
+ export interface EmittedSourceSegment {
30
+ start: number;
31
+ end: number;
32
+ file: string;
33
+ line: number;
34
+ column: number;
35
+ kind: 'code' | 'data' | 'directive' | 'label' | 'macro' | 'unknown';
36
+ confidence: 'high' | 'medium' | 'low';
37
+ }
38
+ /**
39
+ * A symbol entry for debug maps and listings.
40
+ */
41
+ export type SymbolEntry = {
42
+ kind: 'constant';
43
+ name: string;
44
+ /**
45
+ * Constant value (not an address).
46
+ *
47
+ * D8M serialization includes this as `value`.
48
+ */
49
+ value: number;
50
+ file?: string;
51
+ line?: number;
52
+ scope?: 'global' | 'local';
53
+ } | {
54
+ kind: 'label' | 'data' | 'unknown';
55
+ name: string;
56
+ address: number;
57
+ file?: string;
58
+ line?: number;
59
+ scope?: 'global' | 'local';
60
+ size?: number;
61
+ };
62
+ /**
63
+ * Options for Intel HEX writing.
64
+ */
65
+ export interface WriteHexOptions {
66
+ /**
67
+ * Line ending to use when emitting text formats.
68
+ */
69
+ lineEnding?: '\n' | '\r\n';
70
+ }
71
+ /**
72
+ * Options for BIN writing (reserved for future options).
73
+ */
74
+ export interface WriteBinOptions {
75
+ }
76
+ /**
77
+ * Options for D8M writing (reserved for future options).
78
+ */
79
+ export interface WriteD8mOptions {
80
+ /**
81
+ * Base directory used to normalize file paths in D8M symbol entries.
82
+ * When provided, file paths are made project-relative and use `/` separators.
83
+ */
84
+ rootDir?: string;
85
+ /**
86
+ * Optional runnable entry symbol metadata for harnesses.
87
+ */
88
+ entrySymbol?: string;
89
+ /**
90
+ * Optional resolved entry address metadata for harnesses.
91
+ */
92
+ entryAddress?: number;
93
+ }
94
+ /**
95
+ * Options for listing writing.
96
+ *
97
+ * Note: the listing format is currently a deterministic byte dump plus a symbol table.
98
+ */
99
+ export interface WriteListingOptions {
100
+ /**
101
+ * Line ending to use when emitting text formats.
102
+ */
103
+ lineEnding?: '\n' | '\r\n';
104
+ /**
105
+ * Number of bytes shown per listing line.
106
+ */
107
+ bytesPerLine?: number;
108
+ }
109
+ /**
110
+ * Options for ASM80 source emission.
111
+ */
112
+ export interface WriteAsm80Options {
113
+ /**
114
+ * Line ending to use when emitting text formats.
115
+ */
116
+ lineEnding?: '\n' | '\r\n';
117
+ }
118
+ /**
119
+ * In-memory Intel HEX artifact.
120
+ */
121
+ export interface HexArtifact {
122
+ kind: 'hex';
123
+ path?: string;
124
+ text: string;
125
+ }
126
+ /**
127
+ * In-memory flat binary artifact.
128
+ */
129
+ export interface BinArtifact {
130
+ kind: 'bin';
131
+ path?: string;
132
+ bytes: Uint8Array;
133
+ }
134
+ /**
135
+ * In-memory listing artifact.
136
+ */
137
+ export interface ListingArtifact {
138
+ kind: 'lst';
139
+ path?: string;
140
+ text: string;
141
+ }
142
+ /**
143
+ * In-memory ASM80 `.z80` artifact.
144
+ */
145
+ export interface Asm80Artifact {
146
+ kind: 'asm80';
147
+ path?: string;
148
+ text: string;
149
+ }
150
+ /**
151
+ * In-memory D8 Debug Map (D8M) artifact.
152
+ */
153
+ export interface D8mArtifact {
154
+ kind: 'd8m';
155
+ path?: string;
156
+ json: D8mJson;
157
+ }
158
+ /**
159
+ * In-memory register-care audit report artifact.
160
+ */
161
+ export interface RegisterCareReportArtifact {
162
+ kind: 'register-care-report';
163
+ path?: string;
164
+ text: string;
165
+ }
166
+ /**
167
+ * In-memory inferred register-care interface artifact.
168
+ */
169
+ export interface RegisterCareInterfaceArtifact {
170
+ kind: 'register-care-interface';
171
+ path?: string;
172
+ text: string;
173
+ }
174
+ /**
175
+ * In-memory register-care source annotation artifact.
176
+ */
177
+ export interface RegisterCareAnnotationsArtifact {
178
+ kind: 'register-care-annotations';
179
+ files: Array<{
180
+ path: string;
181
+ text: string;
182
+ }>;
183
+ }
184
+ /**
185
+ * Union of all artifact kinds produced by the compiler.
186
+ */
187
+ export type Artifact = HexArtifact | BinArtifact | ListingArtifact | D8mArtifact | Asm80Artifact | RegisterCareReportArtifact | RegisterCareInterfaceArtifact | RegisterCareAnnotationsArtifact;
188
+ /**
189
+ * Minimal D8 Debug Map (D8M) v1 JSON shape.
190
+ *
191
+ * Writers may add additional keys as needed.
192
+ */
193
+ export type D8mJson = {
194
+ format: 'd8-debug-map';
195
+ version: 1;
196
+ arch: 'z80';
197
+ [key: string]: unknown;
198
+ };
199
+ /**
200
+ * Format writers used by the pipeline to turn emitted bytes/symbols into artifacts.
201
+ */
202
+ export interface FormatWriters {
203
+ writeHex(map: EmittedByteMap, symbols: SymbolEntry[], opts?: WriteHexOptions): HexArtifact;
204
+ writeBin(map: EmittedByteMap, symbols: SymbolEntry[], opts?: WriteBinOptions): BinArtifact;
205
+ writeD8m(map: EmittedByteMap, symbols: SymbolEntry[], opts?: WriteD8mOptions): D8mArtifact;
206
+ writeListing?(map: EmittedByteMap, symbols: SymbolEntry[], opts?: WriteListingOptions): ListingArtifact;
207
+ writeAsm80?(program: import('../lowering/loweredAsmTypes.js').LoweredAsmProgram, opts?: WriteAsm80Options): Asm80Artifact;
208
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { Asm80Artifact, WriteAsm80Options } from './types.js';
2
+ import type { LoweredAsmProgram } from '../lowering/loweredAsmTypes.js';
3
+ /**
4
+ * Emit ASM80-compatible source from a placed lowered assembly program.
5
+ */
6
+ export declare function writeAsm80(program: LoweredAsmProgram, opts?: WriteAsm80Options): Asm80Artifact;