@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,523 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
+ import { createRequire } from 'node:module';
4
+ import { dirname, extname, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { compile } from './compile.js';
7
+ import { isSupportedSourcePath, sourceExtensions } from './frontend/sourceExtensions.js';
8
+ import { defaultFormatWriters } from './formats/index.js';
9
+ import { normalizePathForCompare } from './pathCompare.js';
10
+ function usage() {
11
+ return [
12
+ 'azm [options] <entry.asm|entry.z80>',
13
+ '',
14
+ 'Options:',
15
+ ' -o, --output <file> Primary output path (must match --type extension)',
16
+ ' -t, --type <type> Primary output type: hex|bin (default: hex)',
17
+ ' -n, --nolist Suppress .lst',
18
+ ' --nobin Suppress .bin',
19
+ ' --nohex Suppress .hex',
20
+ ' --nod8m Suppress .d8.json',
21
+ ' --asm80 Emit assembler-valid lowered source (.z80)',
22
+ ' --case-style <m> Case-style lint mode: off|upper|lower|consistent',
23
+ ' --rc <m> Register-care mode: off|audit|warn|error|strict',
24
+ ' --reg-report Emit .regcare.txt report',
25
+ ' --reg-interface Emit inferred register-care interface (.asmi)',
26
+ ' --fix Apply conservative register-care source fixes',
27
+ ' --contracts Update source AZM contract blocks in place',
28
+ ' --accept-out <r:c> Promote inferred output candidate while annotating',
29
+ ' --interface <file> Load register-care interface contracts',
30
+ ' --reg-profile <p> Register-care profile: mon3',
31
+ ' --aliases <file> Load project directive alias JSON (repeatable)',
32
+ ' -I, --include <dir> Add include search path (repeatable)',
33
+ ' -V, --version Print version',
34
+ ' -h, --help Show help',
35
+ '',
36
+ 'Notes:',
37
+ ' - <entry.asm|entry.z80> must be the last argument (assembler-style).',
38
+ ' - Output artifacts are written next to the primary output using the artifact base name.',
39
+ '',
40
+ ].join('\n');
41
+ }
42
+ function fail(message) {
43
+ throw Object.assign(new Error(message), { name: 'CliError' });
44
+ }
45
+ function createDefaultCliState() {
46
+ return {
47
+ outputPath: undefined,
48
+ outputType: 'hex',
49
+ emitBin: true,
50
+ emitHex: true,
51
+ emitD8m: true,
52
+ emitListing: true,
53
+ emitAsm80: false,
54
+ caseStyle: 'off',
55
+ includeDirs: [],
56
+ directiveAliasFiles: [],
57
+ entryFile: undefined,
58
+ registerCare: 'off',
59
+ emitRegisterReport: false,
60
+ emitRegisterInterface: false,
61
+ annotateRegisterContracts: false,
62
+ fixRegisterContracts: false,
63
+ acceptRegisterOutputCandidates: [],
64
+ registerCareInterfaces: [],
65
+ };
66
+ }
67
+ function parseDirectiveAliasFileArg(arg, argv, indexRef, state) {
68
+ if (arg !== '--aliases' && !arg.startsWith('--aliases='))
69
+ return false;
70
+ const value = arg.includes('=')
71
+ ? arg.slice(arg.indexOf('=') + 1)
72
+ : readFlagValue(argv, indexRef, '--aliases');
73
+ if (!value)
74
+ fail(`--aliases expects a value`);
75
+ state.directiveAliasFiles.push(value);
76
+ return true;
77
+ }
78
+ function readFlagValue(argv, indexRef, flag) {
79
+ const value = argv[++indexRef.current];
80
+ if (!value)
81
+ fail(`${flag} expects a value`);
82
+ return value;
83
+ }
84
+ function readMatchedFlagValue(arg, argv, indexRef, flags) {
85
+ const flag = flags.find((candidate) => arg === candidate || arg.startsWith(`${candidate}=`)) ?? undefined;
86
+ if (!flag)
87
+ return undefined;
88
+ const value = arg.startsWith(`${flag}=`)
89
+ ? arg.slice(flag.length + 1)
90
+ : readFlagValue(argv, indexRef, flag);
91
+ if (!value)
92
+ fail(`${flag} expects a value`);
93
+ return { flag, value };
94
+ }
95
+ function parseOutputPathArg(arg, argv, indexRef, state) {
96
+ if (arg !== '-o' && arg !== '--output' && !arg.startsWith('--output='))
97
+ return false;
98
+ if (arg.startsWith('--output=')) {
99
+ const value = arg.slice('--output='.length);
100
+ if (!value)
101
+ fail(`--output expects a value`);
102
+ state.outputPath = value;
103
+ return true;
104
+ }
105
+ state.outputPath = readFlagValue(argv, indexRef, arg);
106
+ return true;
107
+ }
108
+ function parseOutputTypeArg(arg, argv, indexRef, state) {
109
+ if (arg !== '-t' && arg !== '--type' && !arg.startsWith('--type='))
110
+ return false;
111
+ const value = arg.startsWith('--type=')
112
+ ? arg.slice('--type='.length)
113
+ : readFlagValue(argv, indexRef, arg);
114
+ if (!value)
115
+ fail(`--type expects a value`);
116
+ if (value !== 'hex' && value !== 'bin')
117
+ fail(`Unsupported --type "${value}" (expected hex|bin)`);
118
+ state.outputType = value;
119
+ return true;
120
+ }
121
+ function parseCaseStyleArg(arg, argv, indexRef, state) {
122
+ if (arg !== '--case-style' && !arg.startsWith('--case-style='))
123
+ return false;
124
+ const value = arg.startsWith('--case-style=')
125
+ ? arg.slice('--case-style='.length)
126
+ : readFlagValue(argv, indexRef, '--case-style');
127
+ if (!value)
128
+ fail(`--case-style expects a value`);
129
+ if (value !== 'off' && value !== 'upper' && value !== 'lower' && value !== 'consistent') {
130
+ fail(`Unsupported --case-style "${value}" (expected off|upper|lower|consistent)`);
131
+ }
132
+ state.caseStyle = value;
133
+ return true;
134
+ }
135
+ function parseRegisterCareArg(arg, argv, indexRef, state) {
136
+ const parsed = readMatchedFlagValue(arg, argv, indexRef, ['--register-care', '--rc']);
137
+ if (!parsed)
138
+ return false;
139
+ const { flag, value } = parsed;
140
+ if (value !== 'off' &&
141
+ value !== 'audit' &&
142
+ value !== 'warn' &&
143
+ value !== 'error' &&
144
+ value !== 'strict') {
145
+ fail(`Unsupported ${flag} "${value}" (expected off|audit|warn|error|strict)`);
146
+ }
147
+ state.registerCare = value;
148
+ return true;
149
+ }
150
+ function parseRegisterProfileArg(arg, argv, indexRef, state) {
151
+ const parsed = readMatchedFlagValue(arg, argv, indexRef, ['--register-profile', '--reg-profile']);
152
+ if (!parsed)
153
+ return false;
154
+ const { flag, value } = parsed;
155
+ if (value !== 'mon3') {
156
+ fail(`Unsupported ${flag} "${value}" (expected mon3)`);
157
+ }
158
+ state.registerCareProfile = value;
159
+ return true;
160
+ }
161
+ function parseRegisterInterfaceInputArg(arg, argv, indexRef, state) {
162
+ if (arg !== '--interface' && !arg.startsWith('--interface='))
163
+ return false;
164
+ const value = arg.includes('=')
165
+ ? arg.slice(arg.indexOf('=') + 1)
166
+ : readFlagValue(argv, indexRef, '--interface');
167
+ if (!value)
168
+ fail(`--interface expects a value`);
169
+ state.registerCareInterfaces.push(value);
170
+ return true;
171
+ }
172
+ function parseAcceptRegisterOutputArg(arg, argv, indexRef, state) {
173
+ const parsed = readMatchedFlagValue(arg, argv, indexRef, [
174
+ '--accept-register-output',
175
+ '--accept-out',
176
+ ]);
177
+ if (!parsed)
178
+ return false;
179
+ const { value } = parsed;
180
+ state.acceptRegisterOutputCandidates.push(value);
181
+ return true;
182
+ }
183
+ function parseIncludeArg(arg, argv, indexRef, state) {
184
+ if (arg !== '-I' && arg !== '--include' && !arg.startsWith('--include='))
185
+ return false;
186
+ if (arg.startsWith('--include=')) {
187
+ const value = arg.slice('--include='.length);
188
+ if (!value)
189
+ fail(`--include expects a value`);
190
+ state.includeDirs.push(value);
191
+ return true;
192
+ }
193
+ state.includeDirs.push(readFlagValue(argv, indexRef, arg));
194
+ return true;
195
+ }
196
+ function handleCliFastPath(arg) {
197
+ if (arg === '-h' || arg === '--help') {
198
+ process.stdout.write(usage());
199
+ return { code: 0 };
200
+ }
201
+ if (arg === '-V' || arg === '--version') {
202
+ const require = createRequire(import.meta.url);
203
+ const here = dirname(fileURLToPath(import.meta.url));
204
+ const packageJsonPath = resolve(here, '..', '..', 'package.json');
205
+ const pkg = require(packageJsonPath);
206
+ process.stdout.write(`${String(pkg.version ?? '0.0.0')}\n`);
207
+ return { code: 0 };
208
+ }
209
+ return undefined;
210
+ }
211
+ function finalizeCliOptions(state) {
212
+ if (!state.entryFile) {
213
+ fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
214
+ }
215
+ if (!isSupportedSourcePath(state.entryFile)) {
216
+ const ext = extname(state.entryFile).toLowerCase() || '<none>';
217
+ fail(`Unsupported entry extension "${ext}" (expected ${sourceExtensions.join(', ')})`);
218
+ }
219
+ const emitsRegisterCareArtifact = state.emitRegisterReport ||
220
+ state.emitRegisterInterface ||
221
+ state.annotateRegisterContracts ||
222
+ state.fixRegisterContracts ||
223
+ state.acceptRegisterOutputCandidates.length > 0 ||
224
+ state.registerCareInterfaces.length > 0;
225
+ if (state.outputType === 'hex' && !state.emitHex && !emitsRegisterCareArtifact) {
226
+ fail(`--type hex requires HEX output to be enabled`);
227
+ }
228
+ if (state.outputType === 'bin' && !state.emitBin && !emitsRegisterCareArtifact) {
229
+ fail(`--type bin requires BIN output to be enabled`);
230
+ }
231
+ if (state.outputPath) {
232
+ const ext = extname(state.outputPath).toLowerCase();
233
+ const wantExt = state.outputType === 'hex' ? '.hex' : '.bin';
234
+ if (ext !== wantExt) {
235
+ fail(`--output must end with "${wantExt}" when --type is "${state.outputType}"`);
236
+ }
237
+ }
238
+ return {
239
+ entryFile: state.entryFile,
240
+ ...(state.outputPath ? { outputPath: state.outputPath } : {}),
241
+ outputType: state.outputType,
242
+ emitBin: state.emitBin,
243
+ emitHex: state.emitHex,
244
+ emitD8m: state.emitD8m,
245
+ emitListing: state.emitListing,
246
+ emitAsm80: state.emitAsm80,
247
+ caseStyle: state.caseStyle,
248
+ includeDirs: state.includeDirs,
249
+ directiveAliasFiles: state.directiveAliasFiles,
250
+ registerCare: state.registerCare,
251
+ emitRegisterReport: state.emitRegisterReport,
252
+ emitRegisterInterface: state.emitRegisterInterface,
253
+ annotateRegisterContracts: state.annotateRegisterContracts,
254
+ fixRegisterContracts: state.fixRegisterContracts,
255
+ acceptRegisterOutputCandidates: state.acceptRegisterOutputCandidates,
256
+ registerCareInterfaces: state.registerCareInterfaces,
257
+ ...(state.registerCareProfile !== undefined
258
+ ? { registerCareProfile: state.registerCareProfile }
259
+ : {}),
260
+ };
261
+ }
262
+ export function parseCliArgs(argv) {
263
+ const state = createDefaultCliState();
264
+ const indexRef = { current: 0 };
265
+ for (; indexRef.current < argv.length; indexRef.current++) {
266
+ const arg = argv[indexRef.current];
267
+ const fastPath = handleCliFastPath(arg);
268
+ if (fastPath)
269
+ return fastPath;
270
+ if (parseOutputPathArg(arg, argv, indexRef, state))
271
+ continue;
272
+ if (parseOutputTypeArg(arg, argv, indexRef, state))
273
+ continue;
274
+ if (arg === '-n' || arg === '--nolist') {
275
+ state.emitListing = false;
276
+ continue;
277
+ }
278
+ if (arg === '--nobin') {
279
+ state.emitBin = false;
280
+ continue;
281
+ }
282
+ if (arg === '--nohex') {
283
+ state.emitHex = false;
284
+ continue;
285
+ }
286
+ if (arg === '--nod8m') {
287
+ state.emitD8m = false;
288
+ continue;
289
+ }
290
+ if (arg === '--asm80') {
291
+ state.emitAsm80 = true;
292
+ continue;
293
+ }
294
+ if (parseCaseStyleArg(arg, argv, indexRef, state))
295
+ continue;
296
+ if (parseDirectiveAliasFileArg(arg, argv, indexRef, state))
297
+ continue;
298
+ if (parseRegisterCareArg(arg, argv, indexRef, state))
299
+ continue;
300
+ if (arg === '--emit-register-report' || arg === '--reg-report') {
301
+ state.emitRegisterReport = true;
302
+ continue;
303
+ }
304
+ if (arg === '--emit-register-interface' || arg === '--reg-interface') {
305
+ state.emitRegisterInterface = true;
306
+ continue;
307
+ }
308
+ if (arg === '--fix') {
309
+ state.fixRegisterContracts = true;
310
+ state.annotateRegisterContracts = true;
311
+ continue;
312
+ }
313
+ if (arg === '--annotate-register-contracts' || arg === '--contracts') {
314
+ state.annotateRegisterContracts = true;
315
+ continue;
316
+ }
317
+ if (parseAcceptRegisterOutputArg(arg, argv, indexRef, state))
318
+ continue;
319
+ if (parseRegisterInterfaceInputArg(arg, argv, indexRef, state))
320
+ continue;
321
+ if (parseRegisterProfileArg(arg, argv, indexRef, state))
322
+ continue;
323
+ if (parseIncludeArg(arg, argv, indexRef, state))
324
+ continue;
325
+ if (arg.startsWith('-')) {
326
+ fail(`Unknown option "${arg}"`);
327
+ }
328
+ if (state.entryFile !== undefined) {
329
+ fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
330
+ }
331
+ if (indexRef.current !== argv.length - 1) {
332
+ fail(`Expected exactly one <entry.asm|entry.z80> argument (and it must be last)`);
333
+ }
334
+ state.entryFile = arg;
335
+ }
336
+ return finalizeCliOptions(state);
337
+ }
338
+ function artifactBase(entryFile, outputType, outputPath) {
339
+ if (outputPath) {
340
+ const resolved = resolve(outputPath);
341
+ const ext = extname(resolved);
342
+ return ext.length > 0 ? resolved.slice(0, -ext.length) : resolved;
343
+ }
344
+ const entry = resolve(entryFile);
345
+ const ext = extname(entry);
346
+ const stem = ext.length > 0 ? entry.slice(0, -ext.length) : entry;
347
+ // Default primary output path is sibling of entry with extension derived from outputType.
348
+ return stem;
349
+ }
350
+ async function writeArtifacts(base, artifacts, outputType) {
351
+ const byKind = new Map();
352
+ for (const a of artifacts)
353
+ byKind.set(a.kind, a);
354
+ const hexPath = `${base}.hex`;
355
+ const binPath = `${base}.bin`;
356
+ const d8mPath = `${base}.d8.json`;
357
+ const lstPath = `${base}.lst`;
358
+ const asm80Path = `${base}.z80`;
359
+ const registerReportPath = `${base}.regcare.txt`;
360
+ const registerInterfacePath = `${base}.asmi`;
361
+ const writes = [];
362
+ const ensureDir = async (p) => mkdir(dirname(p), { recursive: true });
363
+ let primaryWrittenPath;
364
+ let registerReportWrittenPath;
365
+ let registerInterfaceWrittenPath;
366
+ let registerAnnotationWrittenPath;
367
+ const hex = byKind.get('hex');
368
+ if (hex && hex.kind === 'hex') {
369
+ await ensureDir(hexPath);
370
+ writes.push(writeFile(hexPath, hex.text, 'utf8'));
371
+ if (outputType === 'hex')
372
+ primaryWrittenPath = hexPath;
373
+ }
374
+ const bin = byKind.get('bin');
375
+ if (bin && bin.kind === 'bin') {
376
+ await ensureDir(binPath);
377
+ writes.push(writeFile(binPath, Buffer.from(bin.bytes)));
378
+ if (outputType === 'bin')
379
+ primaryWrittenPath = binPath;
380
+ }
381
+ const d8m = byKind.get('d8m');
382
+ if (d8m && d8m.kind === 'd8m') {
383
+ await ensureDir(d8mPath);
384
+ writes.push(writeFile(d8mPath, JSON.stringify(d8m.json, null, 2) + '\n', 'utf8'));
385
+ }
386
+ const lst = byKind.get('lst');
387
+ if (lst && lst.kind === 'lst') {
388
+ await ensureDir(lstPath);
389
+ writes.push(writeFile(lstPath, lst.text, 'utf8'));
390
+ }
391
+ const asm80 = byKind.get('asm80');
392
+ if (asm80 && asm80.kind === 'asm80') {
393
+ await ensureDir(asm80Path);
394
+ writes.push(writeFile(asm80Path, asm80.text, 'utf8'));
395
+ }
396
+ const registerReport = byKind.get('register-care-report');
397
+ if (registerReport && registerReport.kind === 'register-care-report') {
398
+ await ensureDir(registerReportPath);
399
+ writes.push(writeFile(registerReportPath, registerReport.text, 'utf8'));
400
+ registerReportWrittenPath = registerReportPath;
401
+ }
402
+ const registerInterface = byKind.get('register-care-interface');
403
+ if (registerInterface && registerInterface.kind === 'register-care-interface') {
404
+ await ensureDir(registerInterfacePath);
405
+ writes.push(writeFile(registerInterfacePath, registerInterface.text, 'utf8'));
406
+ registerInterfaceWrittenPath = registerInterfacePath;
407
+ }
408
+ const registerAnnotations = byKind.get('register-care-annotations');
409
+ if (registerAnnotations && registerAnnotations.kind === 'register-care-annotations') {
410
+ for (const file of registerAnnotations.files) {
411
+ await ensureDir(file.path);
412
+ writes.push(writeFile(file.path, file.text, 'utf8'));
413
+ registerAnnotationWrittenPath ??= file.path;
414
+ }
415
+ }
416
+ await Promise.all(writes);
417
+ const reportedPath = primaryWrittenPath ??
418
+ registerReportWrittenPath ??
419
+ registerInterfaceWrittenPath ??
420
+ registerAnnotationWrittenPath;
421
+ if (reportedPath) {
422
+ process.stdout.write(`${reportedPath}\n`);
423
+ }
424
+ }
425
+ function normalizeDiagnosticPath(file) {
426
+ const normalized = file.replace(/\\/g, '/');
427
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
428
+ }
429
+ function compareDiagnosticsForCli(a, b) {
430
+ const fileCmp = normalizeDiagnosticPath(a.file).localeCompare(normalizeDiagnosticPath(b.file));
431
+ if (fileCmp !== 0)
432
+ return fileCmp;
433
+ const lineCmp = (a.line ?? Number.POSITIVE_INFINITY) - (b.line ?? Number.POSITIVE_INFINITY);
434
+ if (lineCmp !== 0)
435
+ return lineCmp;
436
+ const colCmp = (a.column ?? Number.POSITIVE_INFINITY) - (b.column ?? Number.POSITIVE_INFINITY);
437
+ if (colCmp !== 0)
438
+ return colCmp;
439
+ const sevRank = (severity) => {
440
+ if (severity === 'error')
441
+ return 0;
442
+ if (severity === 'warning')
443
+ return 1;
444
+ return 2;
445
+ };
446
+ const sevCmp = sevRank(a.severity) - sevRank(b.severity);
447
+ if (sevCmp !== 0)
448
+ return sevCmp;
449
+ const idCmp = a.id.localeCompare(b.id);
450
+ if (idCmp !== 0)
451
+ return idCmp;
452
+ return a.message.localeCompare(b.message);
453
+ }
454
+ export async function runCli(argv) {
455
+ try {
456
+ const parsed = parseCliArgs(argv);
457
+ if ('code' in parsed)
458
+ return parsed.code;
459
+ const base = artifactBase(parsed.entryFile, parsed.outputType, parsed.outputPath);
460
+ const compileOptions = {
461
+ emitBin: parsed.emitBin,
462
+ emitHex: parsed.emitHex,
463
+ emitD8m: parsed.emitD8m,
464
+ emitListing: parsed.emitListing,
465
+ emitAsm80: parsed.emitAsm80,
466
+ caseStyle: parsed.caseStyle,
467
+ includeDirs: parsed.includeDirs,
468
+ directiveAliasFiles: parsed.directiveAliasFiles,
469
+ requireMain: false,
470
+ defaultCodeBase: 0,
471
+ registerCare: parsed.registerCare,
472
+ emitRegisterReport: parsed.emitRegisterReport,
473
+ emitRegisterInterface: parsed.emitRegisterInterface,
474
+ emitRegisterAnnotations: parsed.annotateRegisterContracts,
475
+ fixRegisterContracts: parsed.fixRegisterContracts,
476
+ acceptRegisterOutputCandidates: parsed.acceptRegisterOutputCandidates,
477
+ registerCareInterfaces: parsed.registerCareInterfaces,
478
+ ...(parsed.registerCareProfile !== undefined
479
+ ? { registerCareProfile: parsed.registerCareProfile }
480
+ : {}),
481
+ };
482
+ const res = await compile(parsed.entryFile, compileOptions, { formats: defaultFormatWriters });
483
+ const sortedDiagnostics = [...res.diagnostics].sort(compareDiagnosticsForCli);
484
+ if (sortedDiagnostics.length > 0) {
485
+ for (const d of sortedDiagnostics) {
486
+ const loc = d.line !== undefined && d.column !== undefined
487
+ ? `${d.file}:${d.line}:${d.column}`
488
+ : d.file;
489
+ process.stderr.write(`${loc}: ${d.severity}: [${d.id}] ${d.message}\n`);
490
+ }
491
+ }
492
+ if (sortedDiagnostics.some((d) => d.severity === 'error')) {
493
+ return 1;
494
+ }
495
+ await writeArtifacts(base, res.artifacts, parsed.outputType);
496
+ return 0;
497
+ }
498
+ catch (err) {
499
+ const msg = err instanceof Error ? err.message : String(err);
500
+ process.stderr.write(`azm: ${msg}\n`);
501
+ process.stderr.write(`${usage()}\n`);
502
+ return 2;
503
+ }
504
+ }
505
+ function samePath(a, b) {
506
+ return (normalizePathForCompare(a, { realpath: true }) ===
507
+ normalizePathForCompare(b, { realpath: true }));
508
+ }
509
+ function isDirectCliInvocation(invokedAs) {
510
+ if (!invokedAs)
511
+ return false;
512
+ const self = fileURLToPath(import.meta.url);
513
+ if (samePath(invokedAs, self))
514
+ return true;
515
+ const invoked = normalizePathForCompare(invokedAs, { realpath: true });
516
+ const normalizedSelf = normalizePathForCompare(self, { realpath: true });
517
+ // Windows CI can surface different canonical path spellings for the same file.
518
+ // Fall back to stable suffix matching for the built CLI entry path.
519
+ return invoked.endsWith('/dist/src/cli.js') && normalizedSelf.endsWith('/dist/src/cli.js');
520
+ }
521
+ if (isDirectCliInvocation(process.argv[1])) {
522
+ void runCli(process.argv.slice(2)).then((code) => process.exit(code));
523
+ }
@@ -0,0 +1,10 @@
1
+ import type { CompileFn } from './pipeline.js';
2
+ /**
3
+ * Compile an AZM/ASM80-family program starting from an entry file.
4
+ *
5
+ * - Expands textual includes transitively with deterministic cycle checks.
6
+ * - Runs parse → semantics → lowering → format writers.
7
+ * - Produces artifacts in-memory via `deps.formats`.
8
+ * - Defaults to emitting BIN + HEX + D8M unless an emit flag is explicitly provided.
9
+ */
10
+ export declare const compile: CompileFn;