@jhlagado/azm 0.2.6 → 0.2.8

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 (235) hide show
  1. package/README.md +170 -69
  2. package/dist/src/api-artifacts.d.ts +20 -0
  3. package/dist/src/api-artifacts.js +165 -0
  4. package/dist/src/api-compile.d.ts +8 -2
  5. package/dist/src/api-compile.js +31 -230
  6. package/dist/src/api-register-contracts.d.ts +9 -0
  7. package/dist/src/api-register-contracts.js +77 -0
  8. package/dist/src/api-tooling.d.ts +2 -2
  9. package/dist/src/api-tooling.js +1 -1
  10. package/dist/src/assembly/address-planning.d.ts +1 -2
  11. package/dist/src/assembly/address-planning.js +119 -218
  12. package/dist/src/assembly/address-symbols.d.ts +12 -0
  13. package/dist/src/assembly/address-symbols.js +118 -0
  14. package/dist/src/assembly/fixup-emission.js +30 -48
  15. package/dist/src/assembly/program-emission.js +163 -164
  16. package/dist/src/cli/artifact-files.d.ts +15 -0
  17. package/dist/src/cli/artifact-files.js +86 -0
  18. package/dist/src/cli/parse-args.d.ts +6 -5
  19. package/dist/src/cli/parse-args.js +162 -136
  20. package/dist/src/cli/run.js +4 -1
  21. package/dist/src/cli/usage.d.ts +1 -0
  22. package/dist/src/cli/usage.js +33 -0
  23. package/dist/src/cli/write-artifacts.js +18 -91
  24. package/dist/src/core/compile.js +51 -274
  25. package/dist/src/core/conditional-assembly.d.ts +6 -0
  26. package/dist/src/core/conditional-assembly.js +181 -0
  27. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  28. package/dist/src/expansion/op-constant-expression.js +52 -0
  29. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  30. package/dist/src/expansion/op-expand-selected.js +143 -0
  31. package/dist/src/expansion/op-expansion.d.ts +5 -53
  32. package/dist/src/expansion/op-expansion.js +85 -815
  33. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  34. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  35. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  36. package/dist/src/expansion/op-local-labels.js +166 -0
  37. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  38. package/dist/src/expansion/op-operand-splitting.js +44 -0
  39. package/dist/src/expansion/op-operands.d.ts +53 -0
  40. package/dist/src/expansion/op-operands.js +66 -0
  41. package/dist/src/expansion/op-selection.d.ts +18 -0
  42. package/dist/src/expansion/op-selection.js +172 -0
  43. package/dist/src/index.d.ts +2 -1
  44. package/dist/src/index.js +1 -1
  45. package/dist/src/model/diagnostic.d.ts +4 -0
  46. package/dist/src/model/diagnostic.js +4 -0
  47. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  48. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  49. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  50. package/dist/src/outputs/asm80-expressions.js +47 -0
  51. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  52. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  53. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-instructions.js +272 -0
  55. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  56. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  57. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  58. package/dist/src/outputs/asm80-strings.js +14 -0
  59. package/dist/src/outputs/d8-files.d.ts +10 -0
  60. package/dist/src/outputs/d8-files.js +103 -0
  61. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  62. package/dist/src/outputs/d8-helpers.js +136 -0
  63. package/dist/src/outputs/hex.js +26 -18
  64. package/dist/src/outputs/types.d.ts +16 -10
  65. package/dist/src/outputs/write-asm80.js +68 -597
  66. package/dist/src/outputs/write-d8.js +6 -216
  67. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  68. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  69. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  70. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  71. package/dist/src/register-contracts/analyze.js +73 -0
  72. package/dist/src/register-contracts/annotate.d.ts +11 -0
  73. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  74. package/dist/src/register-contracts/annotations.d.ts +8 -0
  75. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  76. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  77. package/dist/src/register-contracts/boundaryHints.js +24 -0
  78. package/dist/src/register-contracts/carriers.d.ts +2 -0
  79. package/dist/src/register-contracts/constants.d.ts +4 -0
  80. package/dist/src/register-contracts/constants.js +51 -0
  81. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  82. package/dist/src/register-contracts/controlFlow.js +55 -0
  83. package/dist/src/register-contracts/fix.d.ts +11 -0
  84. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  85. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  86. package/dist/src/register-contracts/instruction-head.js +3 -0
  87. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  88. package/dist/src/register-contracts/instruction-operands.js +101 -0
  89. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  90. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  91. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  92. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  93. package/dist/src/register-contracts/liveness.d.ts +3 -0
  94. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  95. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  96. package/dist/src/register-contracts/operand-register-name.js +13 -0
  97. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  98. package/dist/src/{register-care → register-contracts}/profiles.js +13 -2
  99. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  100. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  101. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  102. package/dist/src/register-contracts/programModel-routines.js +128 -0
  103. package/dist/src/register-contracts/programModel.d.ts +3 -0
  104. package/dist/src/register-contracts/programModel.js +14 -0
  105. package/dist/src/register-contracts/report.d.ts +5 -0
  106. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  107. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  108. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  109. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  110. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  111. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  112. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  113. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  114. package/dist/src/register-contracts/smartComments.js +92 -0
  115. package/dist/src/register-contracts/summaries.d.ts +12 -0
  116. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  117. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  118. package/dist/src/register-contracts/summary-boundary.js +40 -0
  119. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  120. package/dist/src/register-contracts/summary-contract.js +45 -0
  121. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  122. package/dist/src/register-contracts/summary-result.js +122 -0
  123. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  124. package/dist/src/register-contracts/summary-state.js +88 -0
  125. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  126. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  127. package/dist/src/register-contracts/summary.d.ts +3 -0
  128. package/dist/src/register-contracts/summary.js +266 -0
  129. package/dist/src/register-contracts/tooling.d.ts +57 -0
  130. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  131. package/dist/src/register-contracts/types.d.ts +188 -0
  132. package/dist/src/semantics/binary-operators.d.ts +2 -0
  133. package/dist/src/semantics/binary-operators.js +15 -0
  134. package/dist/src/semantics/byte-functions.d.ts +2 -0
  135. package/dist/src/semantics/byte-functions.js +7 -0
  136. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  137. package/dist/src/semantics/constant-operator-types.js +1 -0
  138. package/dist/src/semantics/constant-operators.d.ts +3 -0
  139. package/dist/src/semantics/constant-operators.js +3 -0
  140. package/dist/src/semantics/diagnostics.d.ts +3 -0
  141. package/dist/src/semantics/diagnostics.js +10 -0
  142. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  143. package/dist/src/semantics/expression-evaluation.js +22 -334
  144. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  145. package/dist/src/semantics/layout-evaluation.js +202 -0
  146. package/dist/src/semantics/layout-format.d.ts +5 -0
  147. package/dist/src/semantics/layout-format.js +31 -0
  148. package/dist/src/semantics/layout-path.d.ts +24 -0
  149. package/dist/src/semantics/layout-path.js +58 -0
  150. package/dist/src/semantics/unary-operators.d.ts +2 -0
  151. package/dist/src/semantics/unary-operators.js +8 -0
  152. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  153. package/dist/src/source/line-comment-scanner.js +51 -0
  154. package/dist/src/source/strip-line-comment.js +8 -44
  155. package/dist/src/syntax/directive-aliases.js +36 -22
  156. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  157. package/dist/src/syntax/expression-tokenizer.js +310 -0
  158. package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
  159. package/dist/src/syntax/parse-directive-statement.js +307 -0
  160. package/dist/src/syntax/parse-expression.d.ts +2 -2
  161. package/dist/src/syntax/parse-expression.js +7 -568
  162. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  163. package/dist/src/syntax/parse-layout-declarations.js +180 -0
  164. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  165. package/dist/src/syntax/parse-layout-expression.js +175 -0
  166. package/dist/src/syntax/parse-line.js +4 -272
  167. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  168. package/dist/src/syntax/parse-token-expression.js +133 -0
  169. package/dist/src/tooling/case-style.js +47 -30
  170. package/dist/src/z80/effect-groups.d.ts +38 -0
  171. package/dist/src/z80/effect-groups.js +265 -0
  172. package/dist/src/z80/effect-units.d.ts +18 -0
  173. package/dist/src/z80/effect-units.js +165 -0
  174. package/dist/src/z80/effects.d.ts +1 -1
  175. package/dist/src/z80/effects.js +94 -557
  176. package/dist/src/z80/encode-core.d.ts +2 -0
  177. package/dist/src/z80/encode-core.js +42 -0
  178. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  179. package/dist/src/z80/encode-ld-helpers.js +172 -0
  180. package/dist/src/z80/encode-ld.d.ts +2 -0
  181. package/dist/src/z80/encode-ld.js +285 -0
  182. package/dist/src/z80/encode.js +190 -542
  183. package/dist/src/z80/ld-support.d.ts +3 -0
  184. package/dist/src/z80/ld-support.js +146 -0
  185. package/dist/src/z80/operand-split-state.d.ts +8 -0
  186. package/dist/src/z80/operand-split-state.js +46 -0
  187. package/dist/src/z80/operand-split.d.ts +1 -0
  188. package/dist/src/z80/operand-split.js +13 -0
  189. package/dist/src/z80/parse-basic.d.ts +4 -0
  190. package/dist/src/z80/parse-basic.js +39 -0
  191. package/dist/src/z80/parse-branch.d.ts +4 -0
  192. package/dist/src/z80/parse-branch.js +218 -0
  193. package/dist/src/z80/parse-conditions.d.ts +6 -0
  194. package/dist/src/z80/parse-conditions.js +10 -0
  195. package/dist/src/z80/parse-exchange.d.ts +2 -0
  196. package/dist/src/z80/parse-exchange.js +30 -0
  197. package/dist/src/z80/parse-instruction.js +224 -1010
  198. package/dist/src/z80/parse-io-control.d.ts +5 -0
  199. package/dist/src/z80/parse-io-control.js +108 -0
  200. package/dist/src/z80/parse-ld.d.ts +2 -0
  201. package/dist/src/z80/parse-ld.js +83 -0
  202. package/dist/src/z80/parse-operands.d.ts +41 -0
  203. package/dist/src/z80/parse-operands.js +259 -0
  204. package/docs/reference/cli.md +42 -35
  205. package/docs/reference/tooling-api.md +20 -16
  206. package/package.json +1 -1
  207. package/dist/src/register-care/accept-output.d.ts +0 -2
  208. package/dist/src/register-care/analyze.js +0 -166
  209. package/dist/src/register-care/annotate.d.ts +0 -11
  210. package/dist/src/register-care/annotations.d.ts +0 -8
  211. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  212. package/dist/src/register-care/boundaryHints.js +0 -80
  213. package/dist/src/register-care/carriers.d.ts +0 -2
  214. package/dist/src/register-care/controlFlow.d.ts +0 -5
  215. package/dist/src/register-care/controlFlow.js +0 -38
  216. package/dist/src/register-care/fix.d.ts +0 -11
  217. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  218. package/dist/src/register-care/instruction-shape.js +0 -129
  219. package/dist/src/register-care/liveness.d.ts +0 -3
  220. package/dist/src/register-care/programModel.d.ts +0 -3
  221. package/dist/src/register-care/programModel.js +0 -266
  222. package/dist/src/register-care/report.d.ts +0 -5
  223. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  224. package/dist/src/register-care/smartComments.d.ts +0 -5
  225. package/dist/src/register-care/smartComments.js +0 -243
  226. package/dist/src/register-care/summaries.d.ts +0 -12
  227. package/dist/src/register-care/summary.d.ts +0 -3
  228. package/dist/src/register-care/summary.js +0 -474
  229. package/dist/src/register-care/tooling.d.ts +0 -43
  230. package/dist/src/register-care/types.d.ts +0 -172
  231. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  232. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  233. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  234. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  235. /package/dist/src/{register-care → register-contracts}/types.js +0 -0
@@ -1,19 +1,16 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { dirname, normalize } from 'node:path';
1
+ import { normalize } from 'node:path';
3
2
  import { assembleProgram } from './assembly/assemble-program.js';
3
+ import { emitAssemblyArtifacts } from './api-artifacts.js';
4
+ import { runRegisterContracts, shouldAnalyzeRegisterContracts } from './api-register-contracts.js';
4
5
  import { analyzeProgramNext, loadProgramNext } from './tooling/api.js';
5
6
  import { defaultFormatWriters } from './outputs/index.js';
6
- import { UnsupportedAsm80LoweringError } from './outputs/write-asm80.js';
7
7
  import { writeHex } from './outputs/write-hex.js';
8
- import { analyzeRegisterCare } from './register-care/analyze.js';
9
- import { buildRegisterCareProgramModel } from './register-care/programModel.js';
10
- import { parseAcceptedOutputCandidates } from './register-care/accept-output.js';
11
- import { parseInterfaceContracts } from './register-care/smartComments.js';
8
+ import { buildRegisterContractsProgramModel } from './register-contracts/programModel.js';
12
9
  function parseUnresolvedSymbolName(message) {
13
10
  const match = /^Unresolved symbol "([^"]+)"/.exec(message);
14
11
  return match?.[1];
15
12
  }
16
- function isSuppressedUnknownSymbolInRegisterCareMode(diagnostic, directCalls) {
13
+ function isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls) {
17
14
  if (directCalls === undefined || directCalls.length === 0) {
18
15
  return false;
19
16
  }
@@ -33,7 +30,6 @@ function isSuppressedUnknownSymbolInRegisterCareMode(diagnostic, directCalls) {
33
30
  call.column === diagnostic.column);
34
31
  }
35
32
  export { writeHex, defaultFormatWriters };
36
- let cachedPackageVersion;
37
33
  /**
38
34
  * Compile an AZM/ASM80-style program into in-memory artifacts.
39
35
  */
@@ -54,219 +50,49 @@ export async function compile(entryFile, options = {}, deps = { formats: default
54
50
  const analysis = analyzeProgramNext(loaded.loadedProgram, {
55
51
  ...(options.caseStyle !== undefined ? { caseStyle: options.caseStyle } : {}),
56
52
  });
57
- const registerCareMode = options.registerCare ?? 'off';
58
- const shouldAnalyzeRegisterCare = registerCareMode !== 'off' ||
59
- options.emitRegisterReport === true ||
60
- options.emitRegisterInterface === true ||
61
- options.emitRegisterAnnotations === true ||
62
- options.fixRegisterContracts === true ||
63
- (options.acceptRegisterOutputCandidates?.length ?? 0) > 0 ||
64
- (options.registerCareInterfaces?.length ?? 0) > 0;
65
- const directCalls = shouldAnalyzeRegisterCare
66
- ? buildRegisterCareProgramModel(loaded.loadedProgram.program.files[0]?.items ?? []).directCalls
53
+ const analyzeRegisterContractsNow = shouldAnalyzeRegisterContracts(options);
54
+ const directCalls = analyzeRegisterContractsNow
55
+ ? buildRegisterContractsProgramModel(loaded.loadedProgram.program.files[0]?.items ?? [])
56
+ .directCalls
67
57
  : undefined;
68
- diagnostics.push(...analysis.diagnostics.filter((diagnostic) => shouldAnalyzeRegisterCare
69
- ? !isSuppressedUnknownSymbolInRegisterCareMode(diagnostic, directCalls)
58
+ diagnostics.push(...analysis.diagnostics.filter((diagnostic) => analyzeRegisterContractsNow
59
+ ? !isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls)
70
60
  : true));
71
61
  const artifacts = [];
72
- if (shouldAnalyzeRegisterCare) {
73
- // Validate interface references and accepted output markers now; full analysis is deferred.
74
- const acceptedOutputCandidates = parseAcceptedOutputCandidates(options.acceptRegisterOutputCandidates ?? []);
75
- const interfaceContracts = [];
76
- for (const rawInterface of options.registerCareInterfaces ?? []) {
77
- const contractPath = normalize(rawInterface);
78
- if (contractPath.slice(-5).toLowerCase() !== '.asmi') {
79
- diagnostics.push({
80
- severity: 'error',
81
- code: 'AZMN_REGISTER_CARE',
82
- message: 'Register-care interface files must use the .asmi extension',
83
- sourceName: contractPath,
84
- });
85
- continue;
86
- }
87
- const interfaceText = await readFile(contractPath, 'utf8');
88
- for (const contract of parseInterfaceContracts(interfaceText, contractPath).values()) {
89
- interfaceContracts.push(contract);
90
- }
91
- }
92
- if (hasErrors(diagnostics)) {
93
- return { diagnostics, artifacts: [] };
94
- }
95
- const registerCare = analyzeRegisterCare(loaded.loadedProgram, {
96
- mode: registerCareMode,
97
- emitReport: options.emitRegisterReport === true,
98
- emitInterface: options.emitRegisterInterface === true,
99
- emitAnnotations: options.emitRegisterAnnotations === true || options.fixRegisterContracts === true,
100
- fixRegisterContracts: options.fixRegisterContracts === true,
101
- acceptedOutputCandidates,
102
- ...(options.registerCareProfile !== undefined
103
- ? { registerCareProfile: options.registerCareProfile }
104
- : {}),
105
- ...(interfaceContracts.length > 0 ? { interfaceContracts } : {}),
106
- });
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.annotations !== undefined && registerCare.annotations.length > 0) {
114
- const files = registerCare.annotations.map((item) => ({
115
- path: item.path,
116
- text: item.text,
117
- }));
118
- artifacts.push({ kind: 'register-care-annotations', files });
119
- }
120
- diagnostics.push(...registerCare.diagnostics);
62
+ if (analyzeRegisterContractsNow) {
63
+ const registerContracts = await runRegisterContracts(loaded.loadedProgram, options);
64
+ artifacts.push(...registerContracts.artifacts);
65
+ diagnostics.push(...registerContracts.diagnostics);
121
66
  if (hasErrors(diagnostics))
122
- return { diagnostics, artifacts: [] };
67
+ return { diagnostics, artifacts };
123
68
  }
124
69
  if (options.skipAssembly === true) {
125
70
  return { diagnostics, artifacts };
126
71
  }
127
72
  const program = loaded.loadedProgram.program.files[0]?.items ?? [];
128
73
  const assembled = assembleProgram(program);
129
- diagnostics.push(...assembled.diagnostics.filter((diagnostic) => shouldAnalyzeRegisterCare
130
- ? !isSuppressedUnknownSymbolInRegisterCareMode(diagnostic, directCalls)
74
+ diagnostics.push(...assembled.diagnostics.filter((diagnostic) => analyzeRegisterContractsNow
75
+ ? !isSuppressedUnknownSymbolInRegisterContractsMode(diagnostic, directCalls)
131
76
  : true));
132
77
  sortDiagnosticsInPlace(diagnostics);
133
78
  if (hasErrors(diagnostics)) {
134
79
  return { diagnostics, artifacts: [] };
135
80
  }
136
- const map = assembledImageToMap(assembled.bytes, assembled.origin, assembled.sourceSegments);
137
- const hexMap = assembledInitializedImageToMap(assembled.bytes, assembled.origin, assembled.initializedAddresses);
138
- const sidecarMap = assembledInitializedImageToMap(assembled.bytes, assembled.origin, assembled.initializedAddresses, assembled.sourceSegments);
139
- const symbols = collectSymbolEntries(program, assembled.symbols);
140
- const emit = compileArtifactDefaults(options);
141
- const d8Root = options.sourceRoot ?? dirname(normalizedEntry);
142
- if (emit.emitBin) {
143
- artifacts.push(deps.formats.writeBin(map, symbols));
144
- }
145
- if (emit.emitHex) {
146
- artifacts.push(deps.formats.writeHex(hexMap, symbols));
147
- }
148
- if (emit.emitD8m) {
149
- const main = symbols.find((symbol) => symbol.kind === 'label' && symbol.name.toLowerCase() === 'main');
150
- const d8mOpts = {
151
- rootDir: normalize(d8Root),
152
- packageVersion: await readPackageVersion(),
153
- inputs: {
154
- entry: normalizedEntry,
155
- ...(options.d8mInputs?.hex !== undefined ? { hex: options.d8mInputs.hex } : {}),
156
- ...(options.d8mInputs?.bin !== undefined ? { bin: options.d8mInputs.bin } : {}),
157
- },
158
- ...(main !== undefined ? { entrySymbol: main.name } : {}),
159
- ...(main !== undefined
160
- ? { entryAddress: main.kind === 'constant' ? main.value : main.address }
161
- : {}),
162
- };
163
- artifacts.push(deps.formats.writeD8m(sidecarMap, symbols, d8mOpts));
164
- }
165
- if (emit.emitAsm80) {
166
- if (deps.formats.writeAsm80 !== undefined) {
167
- try {
168
- artifacts.push(deps.formats.writeAsm80(program, symbols));
169
- }
170
- catch (error) {
171
- if (error instanceof UnsupportedAsm80LoweringError) {
172
- diagnostics.push({
173
- severity: 'error',
174
- code: 'AZMN_ASM80',
175
- message: error.message,
176
- sourceName: error.item.span.sourceName,
177
- line: error.item.span.line,
178
- column: error.item.span.column,
179
- });
180
- return { diagnostics, artifacts };
181
- }
182
- throw error;
183
- }
184
- }
185
- }
81
+ const emittedArtifacts = await emitAssemblyArtifacts({
82
+ entryFile: normalizedEntry,
83
+ options,
84
+ formats: deps.formats,
85
+ program,
86
+ bytes: assembled.bytes,
87
+ origin: assembled.origin,
88
+ sourceSegments: assembled.sourceSegments,
89
+ initializedAddresses: assembled.initializedAddresses,
90
+ symbols: assembled.symbols,
91
+ });
92
+ artifacts.push(...emittedArtifacts.artifacts);
93
+ diagnostics.push(...emittedArtifacts.diagnostics);
186
94
  return { diagnostics, artifacts };
187
95
  }
188
- function compileArtifactDefaults(options) {
189
- const anyPrimary = [options.emitBin, options.emitHex, options.emitD8m].some((value) => value !== undefined);
190
- const emitBin = anyPrimary ? (options.emitBin ?? false) : true;
191
- const emitHex = anyPrimary ? (options.emitHex ?? false) : true;
192
- const emitD8m = anyPrimary ? (options.emitD8m ?? false) : true;
193
- const emitAsm80 = options.emitAsm80 ?? false;
194
- return { emitBin, emitHex, emitD8m, emitAsm80 };
195
- }
196
- function assembledImageToMap(bytes, origin, sourceSegments = []) {
197
- const map = new Map();
198
- for (let offset = 0; offset < bytes.length; offset += 1) {
199
- map.set(origin + offset, bytes[offset] ?? 0);
200
- }
201
- const writtenRange = {
202
- start: origin,
203
- end: origin + bytes.length,
204
- };
205
- return { bytes: map, writtenRange, sourceSegments };
206
- }
207
- function assembledInitializedImageToMap(bytes, origin, initializedAddresses, sourceSegments = []) {
208
- const map = new Map();
209
- for (const address of initializedAddresses) {
210
- const offset = address - origin;
211
- if (offset >= 0 && offset < bytes.length) {
212
- map.set(address, bytes[offset] ?? 0);
213
- }
214
- }
215
- return { bytes: map, sourceSegments };
216
- }
217
- function collectSymbolEntries(items, resolvedSymbols) {
218
- const map = new Map();
219
- for (const item of items) {
220
- switch (item.kind) {
221
- case 'equ': {
222
- const value = resolvedSymbols[item.name];
223
- if (value !== undefined) {
224
- map.set(item.name, {
225
- kind: 'constant',
226
- name: item.name,
227
- value,
228
- file: item.span.sourceName,
229
- line: item.span.line,
230
- scope: 'global',
231
- });
232
- }
233
- break;
234
- }
235
- case 'label': {
236
- const address = resolvedSymbols[item.name];
237
- if (address !== undefined) {
238
- map.set(item.name, {
239
- kind: 'label',
240
- name: item.name,
241
- address,
242
- file: item.span.sourceName,
243
- line: item.span.line,
244
- scope: 'global',
245
- });
246
- }
247
- break;
248
- }
249
- case 'enum': {
250
- for (const member of item.members) {
251
- const fullName = `${item.name}.${member}`;
252
- const value = resolvedSymbols[fullName];
253
- if (value !== undefined) {
254
- map.set(fullName, {
255
- kind: 'constant',
256
- name: fullName,
257
- value,
258
- file: item.span.sourceName,
259
- line: item.span.line,
260
- scope: 'global',
261
- });
262
- }
263
- }
264
- break;
265
- }
266
- }
267
- }
268
- return [...map.values()];
269
- }
270
96
  function hasErrors(diagnostics) {
271
97
  return diagnostics.some((diagnostic) => diagnostic.severity === 'error');
272
98
  }
@@ -279,28 +105,3 @@ function sortDiagnosticsInPlace(diagnostics) {
279
105
  return (left.column ?? 0) - (right.column ?? 0);
280
106
  });
281
107
  }
282
- async function readPackageVersion() {
283
- if (cachedPackageVersion !== undefined) {
284
- return cachedPackageVersion;
285
- }
286
- const packageJsonCandidates = [
287
- new URL('../package.json', import.meta.url),
288
- new URL('../../package.json', import.meta.url),
289
- new URL('../../../package.json', import.meta.url),
290
- ];
291
- for (const candidate of packageJsonCandidates) {
292
- try {
293
- const raw = await readFile(candidate, 'utf8');
294
- const json = JSON.parse(raw);
295
- if (json.version !== undefined) {
296
- cachedPackageVersion = json.version;
297
- return cachedPackageVersion;
298
- }
299
- }
300
- catch {
301
- // Continue searching candidates.
302
- }
303
- }
304
- cachedPackageVersion = '0.0.0';
305
- return cachedPackageVersion;
306
- }
@@ -0,0 +1,9 @@
1
+ import type { Diagnostic } from './model/diagnostic.js';
2
+ import type { Artifact } from './outputs/types.js';
3
+ import type { LoadedProgramNext } from './tooling/api.js';
4
+ import type { CompileNextFunctionOptions } from './api-compile.js';
5
+ export declare function shouldAnalyzeRegisterContracts(options: CompileNextFunctionOptions): boolean;
6
+ export declare function runRegisterContracts(loadedProgram: LoadedProgramNext, options: CompileNextFunctionOptions): Promise<{
7
+ readonly artifacts: readonly Artifact[];
8
+ readonly diagnostics: readonly Diagnostic[];
9
+ }>;
@@ -0,0 +1,77 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { normalize } from 'node:path';
3
+ import { analyzeRegisterContracts } from './register-contracts/analyze.js';
4
+ import { parseAcceptedOutputCandidates } from './register-contracts/accept-output.js';
5
+ import { parseInterfaceContracts } from './register-contracts/interfaceContracts.js';
6
+ export function shouldAnalyzeRegisterContracts(options) {
7
+ const registerContractsMode = options.registerContracts ?? options.registerCare ?? 'off';
8
+ return (registerContractsMode !== 'off' ||
9
+ options.emitRegisterReport === true ||
10
+ options.emitRegisterInterface === true ||
11
+ options.emitRegisterAnnotations === true ||
12
+ options.fixRegisterContracts === true ||
13
+ (options.acceptRegisterOutputCandidates?.length ?? 0) > 0 ||
14
+ (options.registerContractsInterfaces?.length ?? options.registerCareInterfaces?.length ?? 0) > 0);
15
+ }
16
+ export async function runRegisterContracts(loadedProgram, options) {
17
+ const diagnostics = [];
18
+ const artifacts = [];
19
+ const interfaceContracts = await loadInterfaceContracts(options.registerContractsInterfaces ?? options.registerCareInterfaces ?? [], diagnostics);
20
+ if (hasErrors(diagnostics)) {
21
+ return { diagnostics, artifacts };
22
+ }
23
+ const registerContracts = analyzeRegisterContracts(loadedProgram, {
24
+ mode: options.registerContracts ?? options.registerCare ?? 'off',
25
+ emitReport: options.emitRegisterReport === true,
26
+ emitInterface: options.emitRegisterInterface === true,
27
+ emitAnnotations: options.emitRegisterAnnotations === true || options.fixRegisterContracts === true,
28
+ fixRegisterContracts: options.fixRegisterContracts === true,
29
+ acceptedOutputCandidates: parseAcceptedOutputCandidates(options.acceptRegisterOutputCandidates ?? []),
30
+ ...(options.registerContractsProfile !== undefined || options.registerCareProfile !== undefined
31
+ ? {
32
+ registerContractsProfile: options.registerContractsProfile ?? options.registerCareProfile,
33
+ }
34
+ : {}),
35
+ ...(interfaceContracts.length > 0 ? { interfaceContracts } : {}),
36
+ });
37
+ if (registerContracts.reportText !== undefined) {
38
+ artifacts.push({ kind: 'register-contracts-report', text: registerContracts.reportText });
39
+ }
40
+ if (registerContracts.interfaceText !== undefined) {
41
+ artifacts.push({ kind: 'register-contracts-interface', text: registerContracts.interfaceText });
42
+ }
43
+ if (registerContracts.annotations !== undefined && registerContracts.annotations.length > 0) {
44
+ artifacts.push({
45
+ kind: 'register-contracts-annotations',
46
+ files: registerContracts.annotations.map((item) => ({
47
+ path: item.path,
48
+ text: item.text,
49
+ })),
50
+ });
51
+ }
52
+ diagnostics.push(...registerContracts.diagnostics);
53
+ return { artifacts, diagnostics };
54
+ }
55
+ async function loadInterfaceContracts(interfaces, diagnostics) {
56
+ const interfaceContracts = [];
57
+ for (const rawInterface of interfaces) {
58
+ const contractPath = normalize(rawInterface);
59
+ if (contractPath.slice(-5).toLowerCase() !== '.asmi') {
60
+ diagnostics.push({
61
+ severity: 'error',
62
+ code: 'AZMN_REGISTER_CONTRACTS',
63
+ message: 'Register contracts interface files must use the .asmi extension',
64
+ sourceName: contractPath,
65
+ });
66
+ continue;
67
+ }
68
+ const interfaceText = await readFile(contractPath, 'utf8');
69
+ for (const contract of parseInterfaceContracts(interfaceText, contractPath).values()) {
70
+ interfaceContracts.push(contract);
71
+ }
72
+ }
73
+ return interfaceContracts;
74
+ }
75
+ function hasErrors(diagnostics) {
76
+ return diagnostics.some((diagnostic) => diagnostic.severity === 'error');
77
+ }
@@ -1,7 +1,7 @@
1
1
  export { analyzeProgram, analyzeProgramNext, loadProgram, loadProgramNext } from './tooling/api.js';
2
- export { analyzeRegisterCareForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, type RegisterCareTextEdit, } from './register-care/tooling.js';
2
+ export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, type AnalyzeRegisterCareForToolsOptions, type AnalyzeRegisterCareForToolsResult, type AnalyzeRegisterContractsForToolsOptions, type AnalyzeRegisterContractsForToolsResult, type RegisterCareCandidateDiagnostic, type RegisterCareCodeAction, type RegisterCareTextEdit, type RegisterContractsCandidateDiagnostic, type RegisterContractsCodeAction, type RegisterContractsTextEdit, } from './register-contracts/tooling.js';
3
3
  export { DiagnosticIds } from './model/diagnostic.js';
4
4
  export type { AnalyzeProgramOptions, AnalyzeProgramResult, LoadedProgram, LoadProgramOptions, LoadProgramResult, AnalyzeProgramNextOptions, AnalyzeProgramNextResult, LoadedProgramNext, LoadProgramNextOptions, LoadProgramNextResult, } from './tooling/api.js';
5
5
  export type { CaseStyleMode } from './tooling/case-style.js';
6
6
  export type { Diagnostic, DiagnosticId, DiagnosticSeverity } from './model/diagnostic.js';
7
- export type { RegisterCareMode, RegisterCareOutputCandidate, RegisterCareUnit, } from './register-care/types.js';
7
+ export type { RegisterCareMode, RegisterCareOutputCandidate, RegisterCareUnit, RegisterContractsMode, RegisterContractsOutputCandidate, RegisterContractsUnit, } from './register-contracts/types.js';
@@ -1,3 +1,3 @@
1
1
  export { analyzeProgram, analyzeProgramNext, loadProgram, loadProgramNext } from './tooling/api.js';
2
- export { analyzeRegisterCareForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, } from './register-care/tooling.js';
2
+ export { analyzeRegisterCareForTools, analyzeRegisterContractsForTools, codeActionForOutputCandidate, diagnosticForOutputCandidate, } from './register-contracts/tooling.js';
3
3
  export { DiagnosticIds } from './model/diagnostic.js';
@@ -1,7 +1,7 @@
1
1
  import type { Diagnostic } from '../model/diagnostic.js';
2
2
  import type { SourceItem } from '../model/source-item.js';
3
- import type { SymbolTable } from '../model/symbol.js';
4
3
  import { type EquateRecord, type LayoutRecord } from '../semantics/expression-evaluation.js';
4
+ export { resolveSymbols } from './address-symbols.js';
5
5
  export interface AddressState {
6
6
  readonly labels: Record<string, number>;
7
7
  readonly equates: Map<string, EquateRecord>;
@@ -16,4 +16,3 @@ export declare function buildAddressState(items: readonly SourceItem[], diagnost
16
16
  };
17
17
  export declare function stringDirectiveBytes(directive: 'cstr' | 'pstr' | 'istr', value: string): readonly number[];
18
18
  export declare function alignmentPadding(address: number, alignment: number): number;
19
- export declare function resolveSymbols(labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): SymbolTable;