@jhlagado/azm 0.2.7 → 0.2.9

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 (253) hide show
  1. package/README.md +239 -76
  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 +55 -227
  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/assemble-program.js +5 -0
  15. package/dist/src/assembly/fixup-emission.js +30 -48
  16. package/dist/src/assembly/import-visibility.d.ts +3 -0
  17. package/dist/src/assembly/import-visibility.js +204 -0
  18. package/dist/src/assembly/program-emission.js +163 -164
  19. package/dist/src/cli/artifact-files.d.ts +15 -0
  20. package/dist/src/cli/artifact-files.js +86 -0
  21. package/dist/src/cli/parse-args.d.ts +6 -5
  22. package/dist/src/cli/parse-args.js +162 -136
  23. package/dist/src/cli/run.js +4 -1
  24. package/dist/src/cli/usage.d.ts +1 -0
  25. package/dist/src/cli/usage.js +33 -0
  26. package/dist/src/cli/write-artifacts.js +18 -91
  27. package/dist/src/core/compile.js +51 -274
  28. package/dist/src/core/conditional-assembly.d.ts +6 -0
  29. package/dist/src/core/conditional-assembly.js +181 -0
  30. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  31. package/dist/src/expansion/op-constant-expression.js +52 -0
  32. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  33. package/dist/src/expansion/op-expand-selected.js +143 -0
  34. package/dist/src/expansion/op-expansion.d.ts +5 -53
  35. package/dist/src/expansion/op-expansion.js +85 -815
  36. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  37. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  38. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  39. package/dist/src/expansion/op-local-labels.js +166 -0
  40. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  41. package/dist/src/expansion/op-operand-splitting.js +44 -0
  42. package/dist/src/expansion/op-operands.d.ts +53 -0
  43. package/dist/src/expansion/op-operands.js +66 -0
  44. package/dist/src/expansion/op-selection.d.ts +18 -0
  45. package/dist/src/expansion/op-selection.js +172 -0
  46. package/dist/src/index.d.ts +2 -1
  47. package/dist/src/index.js +1 -1
  48. package/dist/src/model/diagnostic.d.ts +4 -0
  49. package/dist/src/model/diagnostic.js +4 -0
  50. package/dist/src/node/source-host.js +40 -13
  51. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  52. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  53. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-expressions.js +47 -0
  55. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  56. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  57. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  58. package/dist/src/outputs/asm80-instructions.js +272 -0
  59. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  60. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  61. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  62. package/dist/src/outputs/asm80-strings.js +14 -0
  63. package/dist/src/outputs/d8-files.d.ts +10 -0
  64. package/dist/src/outputs/d8-files.js +103 -0
  65. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  66. package/dist/src/outputs/d8-helpers.js +136 -0
  67. package/dist/src/outputs/hex.js +26 -18
  68. package/dist/src/outputs/types.d.ts +16 -10
  69. package/dist/src/outputs/write-asm80.js +72 -597
  70. package/dist/src/outputs/write-d8.js +6 -216
  71. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  72. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  73. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  74. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  75. package/dist/src/register-contracts/analyze.js +73 -0
  76. package/dist/src/register-contracts/annotate.d.ts +11 -0
  77. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  78. package/dist/src/register-contracts/annotations.d.ts +8 -0
  79. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  80. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  81. package/dist/src/register-contracts/boundaryHints.js +24 -0
  82. package/dist/src/register-contracts/carriers.d.ts +2 -0
  83. package/dist/src/register-contracts/constants.d.ts +4 -0
  84. package/dist/src/register-contracts/constants.js +51 -0
  85. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  86. package/dist/src/register-contracts/controlFlow.js +55 -0
  87. package/dist/src/register-contracts/fix.d.ts +11 -0
  88. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  89. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  90. package/dist/src/register-contracts/instruction-head.js +3 -0
  91. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  92. package/dist/src/register-contracts/instruction-operands.js +101 -0
  93. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  94. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  95. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  96. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  97. package/dist/src/register-contracts/liveness.d.ts +3 -0
  98. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  99. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  100. package/dist/src/register-contracts/operand-register-name.js +13 -0
  101. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  102. package/dist/src/{register-care → register-contracts}/profiles.js +2 -2
  103. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  104. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  105. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  106. package/dist/src/register-contracts/programModel-routines.js +144 -0
  107. package/dist/src/register-contracts/programModel.d.ts +3 -0
  108. package/dist/src/register-contracts/programModel.js +14 -0
  109. package/dist/src/register-contracts/report.d.ts +5 -0
  110. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  111. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  112. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  113. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  114. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  115. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  116. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  117. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  118. package/dist/src/register-contracts/smartComments.js +92 -0
  119. package/dist/src/register-contracts/summaries.d.ts +12 -0
  120. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  121. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  122. package/dist/src/register-contracts/summary-boundary.js +40 -0
  123. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  124. package/dist/src/register-contracts/summary-contract.js +45 -0
  125. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  126. package/dist/src/register-contracts/summary-result.js +122 -0
  127. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  128. package/dist/src/register-contracts/summary-state.js +88 -0
  129. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  130. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  131. package/dist/src/register-contracts/summary.d.ts +3 -0
  132. package/dist/src/register-contracts/summary.js +266 -0
  133. package/dist/src/register-contracts/tooling.d.ts +57 -0
  134. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  135. package/dist/src/register-contracts/types.d.ts +188 -0
  136. package/dist/src/semantics/binary-operators.d.ts +2 -0
  137. package/dist/src/semantics/binary-operators.js +15 -0
  138. package/dist/src/semantics/byte-functions.d.ts +2 -0
  139. package/dist/src/semantics/byte-functions.js +7 -0
  140. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  141. package/dist/src/semantics/constant-operator-types.js +1 -0
  142. package/dist/src/semantics/constant-operators.d.ts +3 -0
  143. package/dist/src/semantics/constant-operators.js +3 -0
  144. package/dist/src/semantics/diagnostics.d.ts +3 -0
  145. package/dist/src/semantics/diagnostics.js +10 -0
  146. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  147. package/dist/src/semantics/expression-evaluation.js +22 -334
  148. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  149. package/dist/src/semantics/layout-evaluation.js +202 -0
  150. package/dist/src/semantics/layout-format.d.ts +5 -0
  151. package/dist/src/semantics/layout-format.js +31 -0
  152. package/dist/src/semantics/layout-path.d.ts +24 -0
  153. package/dist/src/semantics/layout-path.js +58 -0
  154. package/dist/src/semantics/unary-operators.d.ts +2 -0
  155. package/dist/src/semantics/unary-operators.js +8 -0
  156. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  157. package/dist/src/source/line-comment-scanner.js +51 -0
  158. package/dist/src/source/logical-lines.d.ts +3 -0
  159. package/dist/src/source/source-span.d.ts +2 -0
  160. package/dist/src/source/strip-line-comment.js +8 -44
  161. package/dist/src/syntax/directive-aliases.js +36 -22
  162. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  163. package/dist/src/syntax/expression-tokenizer.js +310 -0
  164. package/dist/src/syntax/parse-directive-statement.d.ts +9 -0
  165. package/dist/src/syntax/parse-directive-statement.js +309 -0
  166. package/dist/src/syntax/parse-expression.d.ts +2 -2
  167. package/dist/src/syntax/parse-expression.js +7 -568
  168. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  169. package/dist/src/syntax/parse-layout-declarations.js +189 -0
  170. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  171. package/dist/src/syntax/parse-layout-expression.js +175 -0
  172. package/dist/src/syntax/parse-line.js +21 -273
  173. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  174. package/dist/src/syntax/parse-token-expression.js +133 -0
  175. package/dist/src/tooling/api.js +1 -1
  176. package/dist/src/tooling/case-style.js +47 -30
  177. package/dist/src/z80/effect-groups.d.ts +38 -0
  178. package/dist/src/z80/effect-groups.js +265 -0
  179. package/dist/src/z80/effect-units.d.ts +18 -0
  180. package/dist/src/z80/effect-units.js +165 -0
  181. package/dist/src/z80/effects.d.ts +1 -1
  182. package/dist/src/z80/effects.js +94 -557
  183. package/dist/src/z80/encode-core.d.ts +2 -0
  184. package/dist/src/z80/encode-core.js +42 -0
  185. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  186. package/dist/src/z80/encode-ld-helpers.js +172 -0
  187. package/dist/src/z80/encode-ld.d.ts +2 -0
  188. package/dist/src/z80/encode-ld.js +285 -0
  189. package/dist/src/z80/encode.js +190 -542
  190. package/dist/src/z80/ld-support.d.ts +3 -0
  191. package/dist/src/z80/ld-support.js +146 -0
  192. package/dist/src/z80/operand-split-state.d.ts +8 -0
  193. package/dist/src/z80/operand-split-state.js +46 -0
  194. package/dist/src/z80/operand-split.d.ts +1 -0
  195. package/dist/src/z80/operand-split.js +13 -0
  196. package/dist/src/z80/parse-basic.d.ts +4 -0
  197. package/dist/src/z80/parse-basic.js +39 -0
  198. package/dist/src/z80/parse-branch.d.ts +4 -0
  199. package/dist/src/z80/parse-branch.js +218 -0
  200. package/dist/src/z80/parse-conditions.d.ts +6 -0
  201. package/dist/src/z80/parse-conditions.js +10 -0
  202. package/dist/src/z80/parse-exchange.d.ts +2 -0
  203. package/dist/src/z80/parse-exchange.js +30 -0
  204. package/dist/src/z80/parse-instruction.js +224 -1010
  205. package/dist/src/z80/parse-io-control.d.ts +5 -0
  206. package/dist/src/z80/parse-io-control.js +108 -0
  207. package/dist/src/z80/parse-ld.d.ts +2 -0
  208. package/dist/src/z80/parse-ld.js +83 -0
  209. package/dist/src/z80/parse-operands.d.ts +41 -0
  210. package/dist/src/z80/parse-operands.js +259 -0
  211. package/docs/codebase/01-orientation-and-repository-layout.md +192 -0
  212. package/docs/codebase/02-source-loading-and-parsing.md +263 -0
  213. package/docs/codebase/03-assembly-and-z80-emission.md +251 -0
  214. package/docs/codebase/04-ops-and-register-contracts.md +237 -0
  215. package/docs/codebase/05-interfaces-and-output-artifacts.md +253 -0
  216. package/docs/codebase/06-verification-and-maintenance.md +202 -0
  217. package/docs/codebase/appendices/a-directory-file-reference.md +253 -0
  218. package/docs/codebase/appendices/b-compile-flow-reference.md +103 -0
  219. package/docs/codebase/appendices/c-public-surface-reference.md +106 -0
  220. package/docs/codebase/appendices/index.md +16 -0
  221. package/docs/codebase/index.md +46 -0
  222. package/package.json +2 -3
  223. package/dist/src/register-care/accept-output.d.ts +0 -2
  224. package/dist/src/register-care/analyze.js +0 -166
  225. package/dist/src/register-care/annotate.d.ts +0 -11
  226. package/dist/src/register-care/annotations.d.ts +0 -8
  227. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  228. package/dist/src/register-care/boundaryHints.js +0 -80
  229. package/dist/src/register-care/carriers.d.ts +0 -2
  230. package/dist/src/register-care/controlFlow.d.ts +0 -5
  231. package/dist/src/register-care/controlFlow.js +0 -38
  232. package/dist/src/register-care/fix.d.ts +0 -11
  233. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  234. package/dist/src/register-care/instruction-shape.js +0 -129
  235. package/dist/src/register-care/liveness.d.ts +0 -3
  236. package/dist/src/register-care/programModel.d.ts +0 -3
  237. package/dist/src/register-care/programModel.js +0 -266
  238. package/dist/src/register-care/report.d.ts +0 -5
  239. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  240. package/dist/src/register-care/smartComments.d.ts +0 -5
  241. package/dist/src/register-care/smartComments.js +0 -243
  242. package/dist/src/register-care/summaries.d.ts +0 -12
  243. package/dist/src/register-care/summary.d.ts +0 -3
  244. package/dist/src/register-care/summary.js +0 -474
  245. package/dist/src/register-care/tooling.d.ts +0 -43
  246. package/dist/src/register-care/types.d.ts +0 -172
  247. package/docs/reference/cli.md +0 -151
  248. package/docs/reference/tooling-api.md +0 -316
  249. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  250. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  251. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  252. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  253. /package/dist/src/{register-care → register-contracts}/types.js +0 -0
@@ -1,69 +1,6 @@
1
- import { normalize, relative, resolve, isAbsolute } from 'node:path';
2
1
  import { getWrittenRange, getWrittenSegments } from './range.js';
3
- function toHexFilePath(path, rootDir) {
4
- const normalized = normalize(path).replace(/\\/g, '/');
5
- if (!rootDir) {
6
- return normalized;
7
- }
8
- const root = normalize(resolve(rootDir)).replace(/\\/g, '/');
9
- const resolvedPath = normalize(resolve(path)).replace(/\\/g, '/');
10
- const rel = relative(root, resolvedPath).replace(/\\/g, '/');
11
- if (rel.startsWith('..') || rel === '' || isAbsolute(rel)) {
12
- return resolvedPath;
13
- }
14
- return rel;
15
- }
16
- function compareSymbol(a, b) {
17
- const aClass = a.kind === 'constant' ? 1 : 0;
18
- const bClass = b.kind === 'constant' ? 1 : 0;
19
- if (aClass !== bClass)
20
- return aClass - bClass;
21
- const aAddress = a.kind === 'constant' ? (a.value ?? 0) & 0xffff : (a.address ?? 0) & 0xffff;
22
- const bAddress = b.kind === 'constant' ? (b.value ?? 0) & 0xffff : (b.address ?? 0) & 0xffff;
23
- if (aAddress !== bAddress) {
24
- return aAddress - bAddress;
25
- }
26
- const nameCmp = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
27
- if (nameCmp !== 0)
28
- return nameCmp;
29
- const kindCmp = a.kind.localeCompare(b.kind);
30
- if (kindCmp !== 0)
31
- return kindCmp;
32
- const fileCmp = (a.file ?? '').localeCompare(b.file ?? '');
33
- if (fileCmp !== 0)
34
- return fileCmp;
35
- const lineCmp = (a.line ?? 0) - (b.line ?? 0);
36
- if (lineCmp !== 0)
37
- return lineCmp;
38
- if (a.kind === 'constant' && b.kind === 'constant') {
39
- return (a.value ?? 0) - (b.value ?? 0);
40
- }
41
- return (a.size ?? 0) - (b.size ?? 0);
42
- }
43
- function compareFileSymbol(a, b) {
44
- return compareSymbol(a, b);
45
- }
46
- function compareSegment(a, b) {
47
- if (a.start !== b.start)
48
- return a.start - b.start;
49
- if (a.end !== b.end)
50
- return a.end - b.end;
51
- if (a.lstLine !== b.lstLine)
52
- return a.lstLine - b.lstLine;
53
- const lineCmp = (a.line ?? 0) - (b.line ?? 0);
54
- if (lineCmp !== 0)
55
- return lineCmp;
56
- const kindCmp = a.kind.localeCompare(b.kind);
57
- if (kindCmp !== 0)
58
- return kindCmp;
59
- return a.confidence.localeCompare(b.confidence);
60
- }
61
- function rangesOverlap(a, b) {
62
- return a.start < b.end && b.start < a.end;
63
- }
64
- function hasOverlappingSourceSegment(sourceSegmentsByFile, file, range) {
65
- return (sourceSegmentsByFile.get(file) ?? []).some((segment) => rangesOverlap({ start: segment.start, end: segment.end }, range));
66
- }
2
+ import { normalizeInputs, normalizeSourceSegments, toD8mSymbol, } from './d8-helpers.js';
3
+ import { buildD8mFiles } from './d8-files.js';
67
4
  export function writeD8m(map, symbols, opts) {
68
5
  const { start, end } = getWrittenRange(map);
69
6
  const writtenSegments = getWrittenSegments(map);
@@ -72,28 +9,8 @@ export function writeD8m(map, symbols, opts) {
72
9
  : start < end
73
10
  ? [{ start, end }]
74
11
  : [{ start: 0, end: 0 }];
75
- const jsonSymbols = symbols.map((symbol) => symbol.kind === 'constant'
76
- ? {
77
- name: symbol.name,
78
- kind: symbol.kind,
79
- value: symbol.value,
80
- ...(symbol.file !== undefined ? { file: toHexFilePath(symbol.file, opts?.rootDir) } : {}),
81
- ...(symbol.line !== undefined ? { line: symbol.line } : {}),
82
- ...(symbol.scope !== undefined ? { scope: symbol.scope } : {}),
83
- }
84
- : {
85
- name: symbol.name,
86
- kind: symbol.kind,
87
- address: symbol.address,
88
- ...(symbol.file !== undefined ? { file: toHexFilePath(symbol.file, opts?.rootDir) } : {}),
89
- ...(symbol.line !== undefined ? { line: symbol.line } : {}),
90
- ...(symbol.scope !== undefined ? { scope: symbol.scope } : {}),
91
- ...(symbol.size !== undefined ? { size: symbol.size } : {}),
92
- });
93
- const normalizedSourceSegments = coalesceSourceSegments((map.sourceSegments ?? []).flatMap((segment) => clipSourceSegmentToWrittenSegments(segment, segments).map((clipped) => ({
94
- ...clipped,
95
- file: toHexFilePath(clipped.file, opts?.rootDir),
96
- }))));
12
+ const jsonSymbols = symbols.map((symbol) => toD8mSymbol(symbol, opts?.rootDir));
13
+ const normalizedSourceSegments = normalizeSourceSegments(map.sourceSegments ?? [], segments, opts?.rootDir);
97
14
  const fileSet = new Set(jsonSymbols
98
15
  .map((symbol) => symbol.file)
99
16
  .filter((file) => typeof file === 'string' && file.length > 0));
@@ -102,88 +19,7 @@ export function writeD8m(map, symbols, opts) {
102
19
  fileSet.add(segment.file);
103
20
  }
104
21
  const fileList = [...fileSet].sort((a, b) => a.localeCompare(b));
105
- const entries = new Map();
106
- const ensureEntry = (file) => {
107
- let entry = entries.get(file);
108
- if (!entry) {
109
- entry = { symbols: [], segments: [] };
110
- entries.set(file, entry);
111
- }
112
- return entry;
113
- };
114
- const sortedSymbolList = [...jsonSymbols].sort(compareSymbol);
115
- for (const symbol of sortedSymbolList) {
116
- const entry = ensureEntry(symbol.file ?? '');
117
- const symbolWithoutFile = { ...symbol };
118
- delete symbolWithoutFile.file;
119
- entry.symbols?.push(symbolWithoutFile);
120
- }
121
- for (const segment of normalizedSourceSegments) {
122
- ensureEntry(segment.file).segments.push({
123
- start: segment.start,
124
- end: segment.end,
125
- line: segment.line,
126
- lstLine: segment.line,
127
- kind: segment.kind,
128
- confidence: segment.confidence,
129
- });
130
- }
131
- const sourceSegmentsByFile = new Map();
132
- for (const segment of normalizedSourceSegments) {
133
- const sourceSegments = sourceSegmentsByFile.get(segment.file);
134
- if (sourceSegments) {
135
- sourceSegments.push(segment);
136
- }
137
- else {
138
- sourceSegmentsByFile.set(segment.file, [segment]);
139
- }
140
- }
141
- const symbolRangesByFile = new Map();
142
- for (const symbol of sortedSymbolList) {
143
- if (symbol.kind === 'constant' || symbol.file === undefined)
144
- continue;
145
- if (symbol.address === undefined)
146
- continue;
147
- const size = symbol.size !== undefined && symbol.size > 0 ? symbol.size : 1;
148
- const ranges = symbolRangesByFile.get(symbol.file) ?? [];
149
- ranges.push({ start: symbol.address, end: Math.min(0x10000, symbol.address + size) });
150
- symbolRangesByFile.set(symbol.file, ranges);
151
- }
152
- for (const segment of segments) {
153
- const targetFiles = [...symbolRangesByFile.entries()]
154
- .filter(([, ranges]) => ranges.some((range) => rangesOverlap(range, segment)))
155
- .map(([file]) => file)
156
- .sort((a, b) => a.localeCompare(b));
157
- const targets = targetFiles.length > 0 ? targetFiles : [fileList[0] ?? ''];
158
- for (const target of targets) {
159
- if (hasOverlappingSourceSegment(sourceSegmentsByFile, target, segment))
160
- continue;
161
- ensureEntry(target).segments.push({
162
- start: segment.start,
163
- end: segment.end,
164
- lstLine: 1,
165
- kind: 'unknown',
166
- confidence: 'low',
167
- });
168
- }
169
- }
170
- for (const entry of entries.values()) {
171
- entry.symbols.sort(compareFileSymbol);
172
- entry.segments.sort(compareSegment);
173
- }
174
- const files = Object.fromEntries([...entries.entries()]
175
- .sort(([a], [b]) => a.localeCompare(b))
176
- .map(([path, fileEntry]) => [
177
- path,
178
- {
179
- ...(fileEntry.segments && fileEntry.segments.length > 0
180
- ? { segments: fileEntry.segments }
181
- : {}),
182
- ...(fileEntry.symbols && fileEntry.symbols.length > 0
183
- ? { symbols: fileEntry.symbols }
184
- : {}),
185
- },
186
- ]));
22
+ const { files, sortedSymbols } = buildD8mFiles(jsonSymbols, normalizedSourceSegments, segments, fileList);
187
23
  const generatorInputs = opts?.inputs !== undefined ? normalizeInputs(opts.inputs, opts.rootDir) : undefined;
188
24
  const generator = {
189
25
  name: 'azm',
@@ -204,54 +40,8 @@ export function writeD8m(map, symbols, opts) {
204
40
  files,
205
41
  segments,
206
42
  ...(fileList.length > 0 ? { fileList } : {}),
207
- symbols: sortedSymbolList,
43
+ symbols: sortedSymbols,
208
44
  generator,
209
45
  },
210
46
  };
211
47
  }
212
- function normalizeInputs(inputs, rootDir) {
213
- const out = {};
214
- for (const [key, value] of Object.entries(inputs)) {
215
- if (value !== undefined && value.length > 0) {
216
- out[key] = toHexFilePath(value, rootDir);
217
- }
218
- }
219
- return Object.keys(out).length > 0 ? out : undefined;
220
- }
221
- function clipSourceSegmentToWrittenSegments(segment, writtenSegments) {
222
- const clipped = [];
223
- for (const writtenSegment of writtenSegments) {
224
- const start = Math.max(segment.start, writtenSegment.start);
225
- const end = Math.min(segment.end, writtenSegment.end);
226
- if (end > start) {
227
- clipped.push({ ...segment, start, end });
228
- }
229
- }
230
- return clipped;
231
- }
232
- function coalesceSourceSegments(segments) {
233
- const sorted = [...segments].sort((a, b) => a.file.localeCompare(b.file) ||
234
- a.line - b.line ||
235
- a.column - b.column ||
236
- a.kind.localeCompare(b.kind) ||
237
- a.confidence.localeCompare(b.confidence) ||
238
- a.start - b.start ||
239
- a.end - b.end);
240
- const coalesced = [];
241
- for (const segment of sorted) {
242
- const previous = coalesced[coalesced.length - 1];
243
- if (previous &&
244
- previous.file === segment.file &&
245
- previous.line === segment.line &&
246
- previous.column === segment.column &&
247
- previous.kind === segment.kind &&
248
- previous.confidence === segment.confidence &&
249
- previous.end === segment.start) {
250
- coalesced[coalesced.length - 1] = { ...previous, end: segment.end };
251
- }
252
- else {
253
- coalesced.push(segment);
254
- }
255
- }
256
- return coalesced;
257
- }
@@ -0,0 +1,2 @@
1
+ import type { RegisterContractsUnit } from './types.js';
2
+ export declare function parseAcceptedOutputCandidates(items?: readonly string[]): Map<string, RegisterContractsUnit[]>;
@@ -0,0 +1,29 @@
1
+ import type { Diagnostic } from '../model/diagnostic.js';
2
+ import { unknownCallList } from './summaries.js';
3
+ import type { AnalyzeRegisterContractsOptions, RegisterContractsOutputCandidate, RegisterContractsReportModel, RegisterContractsRoutine, RegisterContractsUnit, RoutineSummary } from './types.js';
4
+ export declare function candidateMessageWithFixability(candidate: RegisterContractsOutputCandidate, autoFixable: boolean): string;
5
+ export declare function knownRoutineNames(routines: readonly RegisterContractsRoutine[], contractNames: Iterable<string>, profile: AnalyzeRegisterContractsOptions['registerContractsProfile']): Set<string>;
6
+ export declare function outputCandidatesWithFixability(routines: readonly RegisterContractsRoutine[], outputCandidates: readonly RegisterContractsOutputCandidate[]): {
7
+ outputCandidates: RegisterContractsOutputCandidate[];
8
+ outputCandidateFixability: ReadonlyMap<string, boolean>;
9
+ };
10
+ export declare function diagnosticsForConflicts(conflicts: readonly {
11
+ file: string;
12
+ line: number;
13
+ column: number;
14
+ message: string;
15
+ }[], mode: AnalyzeRegisterContractsOptions['mode']): Diagnostic[];
16
+ export declare function strictStackDiagnostics(routines: readonly RegisterContractsRoutine[], summaries: readonly RoutineSummary[]): Diagnostic[];
17
+ export declare function summariesForAnnotations(summariesByName: ReadonlyMap<string, RoutineSummary>, outputCandidates: readonly RegisterContractsOutputCandidate[]): Map<string, RoutineSummary>;
18
+ export declare function buildRegisterContractsReportModel(input: {
19
+ entryFile: string;
20
+ mode: AnalyzeRegisterContractsOptions['mode'];
21
+ summaries: readonly RoutineSummary[];
22
+ profileSummaries: readonly RoutineSummary[];
23
+ conflicts: RegisterContractsReportModel['conflicts'];
24
+ outputCandidates: readonly RegisterContractsOutputCandidate[];
25
+ profile: AnalyzeRegisterContractsOptions['registerContractsProfile'];
26
+ directBoundaries: Parameters<typeof unknownCallList>[0];
27
+ knownRoutines: ReadonlySet<string>;
28
+ }): RegisterContractsReportModel;
29
+ export declare function autoAcceptedOutputCandidateMap(routines: readonly RegisterContractsRoutine[], outputCandidates: readonly RegisterContractsOutputCandidate[], sourceTexts: ReadonlyMap<string, string>): ReadonlyMap<string, RegisterContractsUnit[]>;
@@ -0,0 +1,162 @@
1
+ import { autoFixableCandidateKeys, findExpectOutFixesForCandidates } from './fix.js';
2
+ import { buildOutputCandidateFixability, buildProfileSummaryLookup, outputCandidateKey, routineNames, unknownCallList, } from './summaries.js';
3
+ export function candidateMessageWithFixability(candidate, autoFixable) {
4
+ const carriers = candidate.carriers.join(',');
5
+ const expectation = candidate.carriers.length === 1 ? candidate.carriers[0] : `{${carriers}}`;
6
+ const base = `CALL ${candidate.routine} writes ${carriers} and caller reads it later`;
7
+ return autoFixable
8
+ ? `${base}; generated contracts promote this to \`out ${expectation}\` automatically.`
9
+ : `${base}; manual review required before adding \`; expects out ${expectation}\` because the later read is not a simple direct continuation.`;
10
+ }
11
+ export function knownRoutineNames(routines, contractNames, profile) {
12
+ const known = new Set(routineNames(routines));
13
+ for (const name of contractNames)
14
+ known.add(name);
15
+ for (const name of buildProfileSummaryLookup(profile).keys())
16
+ known.add(name);
17
+ return known;
18
+ }
19
+ export function outputCandidatesWithFixability(routines, outputCandidates) {
20
+ const outputCandidateFixability = buildOutputCandidateFixability(routines, outputCandidates, autoFixableCandidateKeys);
21
+ return {
22
+ outputCandidateFixability,
23
+ outputCandidates: outputCandidates.map((candidate) => {
24
+ const autoFixable = outputCandidateFixability.get(outputCandidateKey(candidate.file, candidate.line, candidate.column)) ?? false;
25
+ return {
26
+ ...candidate,
27
+ autoFixable,
28
+ message: candidateMessageWithFixability(candidate, autoFixable),
29
+ };
30
+ }),
31
+ };
32
+ }
33
+ export function diagnosticsForConflicts(conflicts, mode) {
34
+ if (mode === 'audit')
35
+ return [];
36
+ return conflicts.map((conflict) => ({
37
+ severity: mode === 'error' || mode === 'strict' ? 'error' : 'warning',
38
+ code: 'AZMN_REGISTER_CONTRACTS',
39
+ sourceName: conflict.file,
40
+ line: conflict.line,
41
+ column: conflict.column,
42
+ message: conflict.message,
43
+ }));
44
+ }
45
+ export function strictStackDiagnostics(routines, summaries) {
46
+ const routinesByName = new Map(routines.map((routine) => [routine.name, routine]));
47
+ const diagnostics = [];
48
+ for (const summary of summaries) {
49
+ const routine = routinesByName.get(summary.name);
50
+ if (routine === undefined)
51
+ continue;
52
+ const stackIssues = strictStackIssueText(summary);
53
+ if (stackIssues === undefined)
54
+ continue;
55
+ diagnostics.push({
56
+ severity: 'error',
57
+ code: 'AZMN_REGISTER_CONTRACTS',
58
+ sourceName: routine.span.file,
59
+ line: routine.span.start.line,
60
+ column: routine.span.start.column,
61
+ message: `Register contracts cannot prove stack discipline for ${summary.name}: ${stackIssues}. Keep PUSH/POP pairs and stack-changing exits inside one @ routine boundary, or split the code into explicit callable routines.`,
62
+ });
63
+ }
64
+ return diagnostics;
65
+ }
66
+ function strictStackIssueText(summary) {
67
+ const issues = [];
68
+ if (!summary.stackBalanced)
69
+ issues.push('stack is unbalanced');
70
+ if (summary.hasUnknownStackEffect === true)
71
+ issues.push('stack effect is unknown');
72
+ return issues.length > 0 ? issues.join('; ') : undefined;
73
+ }
74
+ export function summariesForAnnotations(summariesByName, outputCandidates) {
75
+ const summariesForAnnotations = new Map(summariesByName);
76
+ const outputCandidatesByRoutine = outputCandidateUnitsByRoutine(outputCandidates);
77
+ for (const [name, summary] of summariesForAnnotations) {
78
+ const candidates = outputCandidatesByRoutine.get(name);
79
+ if (candidates !== undefined && candidates.length > 0) {
80
+ summariesForAnnotations.set(name, { ...summary, outputCandidates: candidates });
81
+ }
82
+ }
83
+ return summariesForAnnotations;
84
+ }
85
+ function outputCandidateUnitsByRoutine(outputCandidates) {
86
+ const out = new Map();
87
+ for (const candidate of outputCandidates) {
88
+ const existing = out.get(candidate.routine) ?? [];
89
+ for (const unit of candidate.carriers) {
90
+ if (!existing.includes(unit))
91
+ existing.push(unit);
92
+ }
93
+ out.set(candidate.routine, existing);
94
+ }
95
+ return out;
96
+ }
97
+ export function buildRegisterContractsReportModel(input) {
98
+ return {
99
+ entryFile: input.entryFile,
100
+ mode: input.mode,
101
+ summaries: [...input.summaries, ...input.profileSummaries],
102
+ conflicts: [...input.conflicts],
103
+ outputCandidates: [...input.outputCandidates],
104
+ ...(input.profile !== undefined ? { profile: input.profile } : {}),
105
+ unknownCalls: input.mode === 'off' ? [] : unknownCallList(input.directBoundaries, input.knownRoutines),
106
+ };
107
+ }
108
+ export function autoAcceptedOutputCandidateMap(routines, outputCandidates, sourceTexts) {
109
+ const out = new Map();
110
+ const sourceMaybeOut = sourceMaybeOutByRoutine(routines, sourceTexts);
111
+ for (const fix of findExpectOutFixesForCandidates([...routines], [...outputCandidates])) {
112
+ const declaredMaybeOut = sourceMaybeOut.get(fix.routine) ?? [];
113
+ const eligibleCarriers = fix.carriers.filter((carrier) => declaredMaybeOut.includes(carrier));
114
+ if (eligibleCarriers.length === 0)
115
+ continue;
116
+ const carriers = out.get(fix.routine) ?? [];
117
+ for (const carrier of eligibleCarriers) {
118
+ if (!carriers.includes(carrier))
119
+ carriers.push(carrier);
120
+ }
121
+ out.set(fix.routine, carriers);
122
+ }
123
+ return out;
124
+ }
125
+ function sourceMaybeOutByRoutine(routines, sourceTexts) {
126
+ const out = new Map();
127
+ for (const routine of routines) {
128
+ const maybeOutUnits = sourceMaybeOutUnits(routine, sourceTexts);
129
+ if (maybeOutUnits.length === 0)
130
+ continue;
131
+ out.set(routine.name, maybeOutUnits);
132
+ for (const label of routine.labels)
133
+ out.set(label, maybeOutUnits);
134
+ for (const label of routine.entryLabels)
135
+ out.set(label, maybeOutUnits);
136
+ }
137
+ return out;
138
+ }
139
+ function sourceMaybeOutUnits(routine, sourceTexts) {
140
+ const source = sourceTexts.get(routine.span.file);
141
+ if (source === undefined)
142
+ return [];
143
+ const lines = source.split(/\r?\n/);
144
+ const units = [];
145
+ for (let index = routine.span.start.line - 2; index >= 0; index -= 1) {
146
+ const text = lines[index] ?? '';
147
+ if (!/^\s*;/.test(text))
148
+ break;
149
+ const match = /^\s*;\s*!\s*maybe-out\s+(.+)$/i.exec(text);
150
+ if (!match)
151
+ continue;
152
+ addUnits(units, match[1]);
153
+ }
154
+ return units;
155
+ }
156
+ function addUnits(out, text) {
157
+ for (const token of text.split(',')) {
158
+ const unit = token.trim();
159
+ if (unit.length > 0 && !out.includes(unit))
160
+ out.push(unit);
161
+ }
162
+ }
@@ -1,15 +1,15 @@
1
1
  import type { Diagnostic } from '../model/diagnostic.js';
2
2
  import type { SourceItem } from '../model/source-item.js';
3
- import type { AnalyzeRegisterCareOptions, RegisterCareAnnotationFile, RegisterCareOutputCandidate } from './types.js';
4
- interface AnalyzeRegisterCareResult {
3
+ import type { AnalyzeRegisterContractsOptions, RegisterContractsAnnotationFile, RegisterContractsOutputCandidate } from './types.js';
4
+ interface AnalyzeRegisterContractsResult {
5
5
  diagnostics: Diagnostic[];
6
- outputCandidates?: RegisterCareOutputCandidate[];
6
+ outputCandidates?: RegisterContractsOutputCandidate[];
7
7
  reportText?: string;
8
8
  interfaceText?: string;
9
- annotations?: readonly RegisterCareAnnotationFile[];
9
+ annotations?: readonly RegisterContractsAnnotationFile[];
10
10
  unknownCalls?: string[];
11
11
  }
12
- export declare function analyzeRegisterCare(loaded: {
12
+ export declare function analyzeRegisterContracts(loaded: {
13
13
  program: {
14
14
  files: readonly [
15
15
  {
@@ -22,5 +22,5 @@ export declare function analyzeRegisterCare(loaded: {
22
22
  };
23
23
  sourceLineComments: ReadonlyMap<string, ReadonlyMap<number, string>>;
24
24
  sourceTexts: ReadonlyMap<string, string>;
25
- }, options: AnalyzeRegisterCareOptions): AnalyzeRegisterCareResult;
25
+ }, options: AnalyzeRegisterContractsOptions): AnalyzeRegisterContractsResult;
26
26
  export {};
@@ -0,0 +1,73 @@
1
+ import { buildRegisterContractsProgramModel } from './programModel.js';
2
+ import { buildRoutineContracts, parseSmartComments } from './smartComments.js';
3
+ import { renderRegisterContractsInterface, renderRegisterContractsReport } from './report.js';
4
+ import { findCallerOutputCandidateObservations, findRegisterContractsConflicts, } from './liveness.js';
5
+ import { buildAnnotations } from './annotations.js';
6
+ import { autoAcceptedOutputCandidateMap, buildRegisterContractsReportModel, diagnosticsForConflicts, knownRoutineNames, outputCandidatesWithFixability, strictStackDiagnostics, summariesForAnnotations, } from './analyze-helpers.js';
7
+ import { buildProfileSummaries, buildSummaries, buildSummaryByName, outputCandidateKey, unknownBoundaryDiagnostics, withAcceptedOutputs, } from './summaries.js';
8
+ export function analyzeRegisterContracts(loaded, options) {
9
+ const file = loaded.program.files[0];
10
+ const items = file?.items ?? [];
11
+ const program = buildRegisterContractsProgramModel(items);
12
+ const smartComments = parseSmartComments(loaded.sourceLineComments);
13
+ const contractMap = buildRoutineContracts(smartComments, program.routines, loaded.sourceTexts);
14
+ if (options.interfaceContracts !== undefined) {
15
+ for (const contract of options.interfaceContracts) {
16
+ contractMap.set(contract.name, contract);
17
+ }
18
+ }
19
+ const profileSummaries = buildProfileSummaries(options.registerContractsProfile);
20
+ let summaries = buildSummaries(program.routines, contractMap, profileSummaries);
21
+ summaries = withAcceptedOutputs(summaries, options.acceptedOutputCandidates);
22
+ let summariesByName = buildSummaryByName(program.routines, summaries, profileSummaries);
23
+ const knownRoutines = knownRoutineNames(program.routines, contractMap.keys(), options.registerContractsProfile);
24
+ const shouldBuildOutputCandidates = options.mode !== 'off' ||
25
+ options.emitAnnotations === true ||
26
+ options.fixRegisterContracts === true;
27
+ const outputCandidates = shouldBuildOutputCandidates
28
+ ? findCallerOutputCandidateObservations(program.routines, summariesByName)
29
+ : [];
30
+ const autoAcceptedOutputs = autoAcceptedOutputCandidateMap(program.routines, outputCandidates, loaded.sourceTexts);
31
+ if (autoAcceptedOutputs.size > 0) {
32
+ summaries = withAcceptedOutputs(summaries, autoAcceptedOutputs);
33
+ summariesByName = buildSummaryByName(program.routines, summaries, profileSummaries);
34
+ }
35
+ const conflicts = shouldBuildOutputCandidates
36
+ ? program.routines.flatMap((routine) => findRegisterContractsConflicts(routine, summariesByName, smartComments))
37
+ : [];
38
+ const { outputCandidates: outputCandidatesWithAutoFixability, outputCandidateFixability } = outputCandidatesWithFixability(program.routines, outputCandidates);
39
+ const diagnostics = diagnosticsForConflicts(conflicts, options.mode);
40
+ if (options.mode === 'strict') {
41
+ diagnostics.push(...unknownBoundaryDiagnostics(program.directBoundaries, knownRoutines, 'error'));
42
+ diagnostics.push(...strictStackDiagnostics(program.routines, summaries));
43
+ }
44
+ const reportModel = buildRegisterContractsReportModel({
45
+ entryFile: loaded.program.entryFile,
46
+ mode: options.mode,
47
+ summaries,
48
+ profileSummaries,
49
+ conflicts,
50
+ outputCandidates: outputCandidatesWithAutoFixability,
51
+ profile: options.registerContractsProfile,
52
+ directBoundaries: program.directBoundaries,
53
+ knownRoutines,
54
+ });
55
+ const summariesForAnnotationsByName = summariesForAnnotations(summariesByName, outputCandidatesWithAutoFixability);
56
+ const annotations = options.emitAnnotations
57
+ ? buildAnnotations(loaded, program.routines, summariesForAnnotationsByName, outputCandidatesWithAutoFixability, {
58
+ fixOutputCandidates: options.fixRegisterContracts === true,
59
+ outputCandidateFixability,
60
+ outputCandidateKey,
61
+ })
62
+ : [];
63
+ return {
64
+ diagnostics,
65
+ outputCandidates: outputCandidatesWithAutoFixability,
66
+ ...(options.emitReport ? { reportText: renderRegisterContractsReport(reportModel) } : {}),
67
+ ...(options.emitInterface
68
+ ? { interfaceText: renderRegisterContractsInterface(summaries) }
69
+ : {}),
70
+ ...(annotations.length > 0 ? { annotations } : {}),
71
+ ...(reportModel.unknownCalls.length > 0 ? { unknownCalls: reportModel.unknownCalls } : {}),
72
+ };
73
+ }
@@ -0,0 +1,11 @@
1
+ import type { RegisterContractsRoutine, RoutineSummary } from './types.js';
2
+ export interface RegisterContractsAnnotatedFile {
3
+ path: string;
4
+ text: string;
5
+ }
6
+ interface RegisterContractsAnnotationInput {
7
+ routine: RegisterContractsRoutine;
8
+ summary: RoutineSummary;
9
+ }
10
+ export declare function annotateRegisterContractsContracts(sourceTexts: ReadonlyMap<string, string>, routines: RegisterContractsAnnotationInput[]): RegisterContractsAnnotatedFile[];
11
+ export {};
@@ -1,4 +1,4 @@
1
- import { renderRegisterCareSourceBlock } from './report.js';
1
+ import { renderRegisterContractsSourceBlock } from './report.js';
2
2
  import { joinSourceLines, splitSourceLines } from './sourceText.js';
3
3
  const GENERATED_COMPACT_LINE_RE = /^\s*;\s*!\s*(?:in|out|maybe-out|clobbers|preserves)(?:\s|$)/i;
4
4
  function isCommentLine(line) {
@@ -38,7 +38,7 @@ function annotateFile(source, routines) {
38
38
  const labelIndex = item.routine.span.start.line - 1;
39
39
  if (labelIndex < 0 || labelIndex > lines.length)
40
40
  continue;
41
- const block = renderRegisterCareSourceBlock(item.summary);
41
+ const block = renderRegisterContractsSourceBlock(item.summary);
42
42
  const hasContractContent = block.length > 0;
43
43
  const existing = generatedBlockBeforeLabel(lines, labelIndex);
44
44
  if (existing) {
@@ -54,7 +54,7 @@ function annotateFile(source, routines) {
54
54
  }
55
55
  return joinSourceLines(sourceLines);
56
56
  }
57
- export function annotateRegisterCareContracts(sourceTexts, routines) {
57
+ export function annotateRegisterContractsContracts(sourceTexts, routines) {
58
58
  const byFile = new Map();
59
59
  for (const item of routines) {
60
60
  if (!sourceTexts.has(item.routine.span.file))
@@ -0,0 +1,8 @@
1
+ import type { RegisterContractsAnnotationFile, RegisterContractsOutputCandidate, RegisterContractsRoutine, RoutineSummary } from './types.js';
2
+ export declare function buildAnnotations(loaded: {
3
+ sourceTexts: ReadonlyMap<string, string>;
4
+ }, programRoutines: readonly RegisterContractsRoutine[], summariesByName: ReadonlyMap<string, RoutineSummary>, outputCandidates: readonly RegisterContractsOutputCandidate[], options: {
5
+ fixOutputCandidates: boolean;
6
+ outputCandidateFixability: ReadonlyMap<string, boolean>;
7
+ outputCandidateKey: (file: string, line: number, column: number) => string;
8
+ }): readonly RegisterContractsAnnotationFile[];
@@ -1,5 +1,5 @@
1
- import { annotateRegisterCareContracts } from './annotate.js';
2
- import { applyExpectOutFixesToSource, findExpectOutFixesForCandidates, } from './fix.js';
1
+ import { annotateRegisterContractsContracts } from './annotate.js';
2
+ import { applyExpectOutFixesToSource, findExpectOutFixesForCandidates } from './fix.js';
3
3
  export function buildAnnotations(loaded, programRoutines, summariesByName, outputCandidates, options) {
4
4
  const routines = programRoutines
5
5
  .filter((routine) => summariesByName.has(routine.name))
@@ -7,7 +7,7 @@ export function buildAnnotations(loaded, programRoutines, summariesByName, outpu
7
7
  routine,
8
8
  summary: summariesByName.get(routine.name),
9
9
  }));
10
- const annotated = annotateRegisterCareContracts(loaded.sourceTexts, routines);
10
+ const annotated = annotateRegisterContractsContracts(loaded.sourceTexts, routines);
11
11
  if (!options.fixOutputCandidates) {
12
12
  return annotated.map((file) => ({ path: file.path, text: file.text }));
13
13
  }
@@ -0,0 +1,3 @@
1
+ import type { RegisterContractsInstruction } from './types.js';
2
+ export declare function precedingCServiceName(item: RegisterContractsInstruction | undefined): string | undefined;
3
+ export declare function precedingRegisterImmediateValue(item: RegisterContractsInstruction | undefined, register: string): number | undefined;
@@ -0,0 +1,24 @@
1
+ import { evaluateKnownConstant } from './constants.js';
2
+ export function precedingCServiceName(item) {
3
+ const instruction = item?.instruction;
4
+ if (!instruction || instruction.mnemonic !== 'ld')
5
+ return undefined;
6
+ if (instruction.target?.kind !== 'reg8' || instruction.target.register !== 'c')
7
+ return undefined;
8
+ if (instruction.source.kind === 'imm' && instruction.source.expression.kind === 'symbol') {
9
+ return instruction.source.expression.name;
10
+ }
11
+ return undefined;
12
+ }
13
+ export function precedingRegisterImmediateValue(item, register) {
14
+ const instruction = item?.instruction;
15
+ if (!instruction || instruction.mnemonic !== 'ld')
16
+ return undefined;
17
+ if (instruction.target?.kind !== 'reg8' ||
18
+ instruction.target.register !== register.toLowerCase()) {
19
+ return undefined;
20
+ }
21
+ if (instruction.source.kind !== 'imm')
22
+ return undefined;
23
+ return evaluateKnownConstant(instruction.source.expression, item.constants ?? new Map());
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { RegisterContractsUnit } from './types.js';
2
+ export declare function expandCarrierList(raw: readonly string[]): RegisterContractsUnit[] | undefined;
@@ -0,0 +1,4 @@
1
+ import type { Expression } from '../model/expression.js';
2
+ import type { SourceItem } from '../model/source-item.js';
3
+ export declare function evaluateKnownConstant(expression: Expression, constants: ReadonlyMap<string, number>): number | undefined;
4
+ export declare function collectConstants(items: readonly SourceItem[]): ReadonlyMap<string, number>;