@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
@@ -0,0 +1,189 @@
1
+ import { stripLineComment } from '../source/strip-line-comment.js';
2
+ import { parseTypeExpr } from './parse-expression.js';
3
+ export function parseLayoutDeclarationAt(lines, index) {
4
+ const line = lines[index];
5
+ if (line === undefined)
6
+ return undefined;
7
+ const text = stripLineComment(line.text).trim();
8
+ const typeAlias = parseTypeAlias(line, text);
9
+ if (typeAlias !== undefined) {
10
+ return { consumedUntilIndex: index, ...typeAlias };
11
+ }
12
+ const prefixLayoutHeader = /^\.(type|union)\s+([A-Za-z_][A-Za-z0-9_]*)\s*$/.exec(text);
13
+ if (prefixLayoutHeader) {
14
+ const directive = prefixLayoutHeader[1] ?? 'type';
15
+ return {
16
+ consumedUntilIndex: skipToLayoutEnd(lines, index, directive),
17
+ diagnostics: [
18
+ parseDiagnostic(line, `Use "${prefixLayoutHeader[2] ?? ''} .${directive}" for layouts.`),
19
+ ],
20
+ };
21
+ }
22
+ const layoutHeader = parseNameLeftLayoutHeader(text);
23
+ if (layoutHeader === undefined) {
24
+ return undefined;
25
+ }
26
+ return parseLayoutBlock(lines, index, layoutHeader);
27
+ }
28
+ function parseTypeAlias(line, text) {
29
+ const nameLeftTypeAlias = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.typealias\s+(.+)$/.exec(text);
30
+ if (nameLeftTypeAlias) {
31
+ const typeExprText = nameLeftTypeAlias[2] ?? '';
32
+ const typeExpr = parseTypeExpr(typeExprText);
33
+ if (!typeExpr) {
34
+ return { diagnostics: [parseDiagnostic(line, `invalid .typealias target: ${typeExprText}`)] };
35
+ }
36
+ return {
37
+ item: {
38
+ kind: 'type-alias',
39
+ name: nameLeftTypeAlias[1] ?? '',
40
+ typeExpr,
41
+ span: spanForLine(line),
42
+ },
43
+ diagnostics: [],
44
+ };
45
+ }
46
+ const oldTypeAlias = /^\.type\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$/.exec(text);
47
+ if (oldTypeAlias) {
48
+ return {
49
+ diagnostics: [
50
+ parseDiagnostic(line, `Use "${oldTypeAlias[1] ?? ''} .typealias ..." for type aliases.`),
51
+ ],
52
+ };
53
+ }
54
+ return undefined;
55
+ }
56
+ function parseNameLeftLayoutHeader(text) {
57
+ const match = /^([A-Za-z_][A-Za-z0-9_]*)(?::\s*|\s+)\.(type|union)\s*$/.exec(text);
58
+ return match
59
+ ? {
60
+ directive: match[2] ?? '',
61
+ name: match[1] ?? '',
62
+ }
63
+ : undefined;
64
+ }
65
+ function parseLayoutBlock(lines, index, header) {
66
+ const line = lines[index];
67
+ const layoutKind = header.directive === 'union' ? 'union' : 'record';
68
+ const endDirective = layoutKind === 'union' ? '.endunion' : '.endtype';
69
+ const fields = [];
70
+ const diagnostics = [];
71
+ let consumedUntilIndex = index;
72
+ let terminated = false;
73
+ for (let fieldIndex = index + 1; fieldIndex < lines.length; fieldIndex += 1) {
74
+ consumedUntilIndex = fieldIndex;
75
+ const fieldLine = lines[fieldIndex];
76
+ const fieldText = stripLineComment(fieldLine.text).trim();
77
+ if (fieldText.length === 0) {
78
+ continue;
79
+ }
80
+ if (fieldText === endDirective) {
81
+ terminated = true;
82
+ break;
83
+ }
84
+ const field = parseLayoutField(fieldText);
85
+ if (!field) {
86
+ diagnostics.push(parseDiagnostic(fieldLine, `invalid .${header.directive} field declaration`));
87
+ continue;
88
+ }
89
+ fields.push(field);
90
+ }
91
+ if (!terminated) {
92
+ diagnostics.push(parseDiagnostic(line, `.${header.directive} ${header.name} missing ${endDirective}`));
93
+ }
94
+ return {
95
+ consumedUntilIndex,
96
+ diagnostics,
97
+ item: {
98
+ kind: 'type',
99
+ name: header.name,
100
+ layoutKind,
101
+ fields,
102
+ span: spanForLine(line),
103
+ },
104
+ };
105
+ }
106
+ function spanForLine(line) {
107
+ return {
108
+ sourceName: line.sourceName,
109
+ line: line.line,
110
+ column: firstColumn(line.text),
111
+ ...(line.sourceUnit !== undefined ? { sourceUnit: line.sourceUnit } : {}),
112
+ ...(line.sourceRelation !== undefined ? { sourceRelation: line.sourceRelation } : {}),
113
+ };
114
+ }
115
+ function skipToLayoutEnd(lines, index, directive) {
116
+ const endDirective = directive === 'union' ? '.endunion' : '.endtype';
117
+ for (let next = index + 1; next < lines.length; next += 1) {
118
+ if (stripLineComment(lines[next].text).trim() === endDirective) {
119
+ return next;
120
+ }
121
+ }
122
+ return index;
123
+ }
124
+ function parseLayoutField(text) {
125
+ const match = /^([A-Za-z_][A-Za-z0-9_]*)\s+(\.(?:field|byte|word|addr))(?:\s+(.+))?$/.exec(text);
126
+ if (!match) {
127
+ return undefined;
128
+ }
129
+ const name = match[1] ?? '';
130
+ const directive = (match[2] ?? '').toLowerCase();
131
+ const operand = match[3]?.trim();
132
+ return directive === '.field'
133
+ ? parseNamedField(name, operand)
134
+ : parseScalarDirectiveField(name, directive, operand);
135
+ }
136
+ function parseNamedField(name, operand) {
137
+ return operand === undefined ? undefined : parseFieldOperand(name, operand);
138
+ }
139
+ function parseScalarDirectiveField(name, directive, operand) {
140
+ if (operand !== undefined) {
141
+ return undefined;
142
+ }
143
+ const size = scalarDirectiveSize(directive);
144
+ return size === undefined ? undefined : { name, size };
145
+ }
146
+ function scalarDirectiveSize(directive) {
147
+ if (directive === '.byte')
148
+ return 1;
149
+ if (directive === '.word' || directive === '.addr')
150
+ return 2;
151
+ return undefined;
152
+ }
153
+ function parseFieldOperand(name, operand) {
154
+ const size = /^[0-9]+$/.test(operand) ? Number.parseInt(operand, 10) : undefined;
155
+ if (size !== undefined) {
156
+ return size > 0 ? { name, size } : undefined;
157
+ }
158
+ const scalar = scalarFieldSize(operand);
159
+ if (scalar !== undefined) {
160
+ return { name, size: scalar };
161
+ }
162
+ const typeExpr = parseTypeExpr(operand);
163
+ return typeExpr ? { name, size: 0, typeExpr } : undefined;
164
+ }
165
+ function scalarFieldSize(typeName) {
166
+ switch (typeName.toLowerCase()) {
167
+ case 'byte':
168
+ return 1;
169
+ case 'word':
170
+ case 'addr':
171
+ return 2;
172
+ default:
173
+ return undefined;
174
+ }
175
+ }
176
+ function parseDiagnostic(line, message) {
177
+ return {
178
+ severity: 'error',
179
+ code: 'AZMN_PARSE',
180
+ message,
181
+ sourceName: line.sourceName,
182
+ line: line.line,
183
+ column: firstColumn(line.text),
184
+ };
185
+ }
186
+ function firstColumn(text) {
187
+ const match = /\S/.exec(text);
188
+ return match ? match.index + 1 : 1;
189
+ }
@@ -0,0 +1,5 @@
1
+ import type { Expression, TypeExpr } from '../model/expression.js';
2
+ export type ParseNestedExpression = (text: string) => Expression | undefined;
3
+ export declare function parseTypeExpr(text: string): TypeExpr | undefined;
4
+ export declare function parseLayoutExpression(text: string, parseNestedExpression: ParseNestedExpression): Expression | undefined;
5
+ export declare function findMatchingBracket(text: string): number | undefined;
@@ -0,0 +1,175 @@
1
+ export function parseTypeExpr(text) {
2
+ const trimmed = text.trim();
3
+ const match = /^([A-Za-z_][A-Za-z0-9_]*)(?:\[\s*([0-9]+)\s*\])?$/.exec(trimmed);
4
+ if (!match) {
5
+ return undefined;
6
+ }
7
+ const name = match[1] ?? '';
8
+ const lengthText = match[2];
9
+ if (lengthText === undefined) {
10
+ return { name };
11
+ }
12
+ const length = Number.parseInt(lengthText, 10);
13
+ return length >= 0 ? { name, length } : undefined;
14
+ }
15
+ export function parseLayoutExpression(text, parseNestedExpression) {
16
+ const trimmed = text.trim();
17
+ const layoutCast = parseLayoutCast(trimmed, parseNestedExpression);
18
+ if (layoutCast) {
19
+ return layoutCast;
20
+ }
21
+ const sizeof = /^sizeof\s*\((.*)\)$/.exec(trimmed);
22
+ if (sizeof) {
23
+ const typeExpr = parseTypeExpr(sizeof[1] ?? '');
24
+ return typeExpr ? { kind: 'sizeof', typeExpr } : undefined;
25
+ }
26
+ const offset = /^offset\s*\((.*),(.*)\)$/.exec(trimmed);
27
+ if (offset) {
28
+ const typeExpr = parseTypeExpr(offset[1] ?? '');
29
+ const path = parseOffsetPath(offset[2] ?? '');
30
+ return typeExpr && path ? { kind: 'offset', typeExpr, path } : undefined;
31
+ }
32
+ return undefined;
33
+ }
34
+ export function findMatchingBracket(text) {
35
+ let state = { depth: 0, quote: undefined, escaped: false };
36
+ for (let index = 0; index < text.length; index += 1) {
37
+ const char = text[index] ?? '';
38
+ if (state.quote !== undefined) {
39
+ state = scanQuotedBracketChar(char, state);
40
+ continue;
41
+ }
42
+ const quotedState = startBracketQuote(char, state);
43
+ if (quotedState) {
44
+ state = quotedState;
45
+ continue;
46
+ }
47
+ state = scanBracketDepth(char, state);
48
+ if (char === ']') {
49
+ if (state.depth === 0) {
50
+ return index;
51
+ }
52
+ }
53
+ }
54
+ return undefined;
55
+ }
56
+ function scanQuotedBracketChar(char, state) {
57
+ if (state.escaped)
58
+ return { ...state, escaped: false };
59
+ if (char === '\\')
60
+ return { ...state, escaped: true };
61
+ if (char === state.quote)
62
+ return { ...state, quote: undefined };
63
+ return state;
64
+ }
65
+ function startBracketQuote(char, state) {
66
+ return char === '"' || char === "'" ? { ...state, quote: char } : undefined;
67
+ }
68
+ function scanBracketDepth(char, state) {
69
+ if (char === '[')
70
+ return { ...state, depth: state.depth + 1 };
71
+ if (char === ']')
72
+ return { ...state, depth: state.depth - 1 };
73
+ return state;
74
+ }
75
+ function parseLayoutCast(text, parseNestedExpression) {
76
+ if (!text.startsWith('<')) {
77
+ return undefined;
78
+ }
79
+ const close = text.indexOf('>');
80
+ if (close <= 1) {
81
+ return undefined;
82
+ }
83
+ const typeExpr = parseTypeExpr(text.slice(1, close));
84
+ if (!typeExpr) {
85
+ return undefined;
86
+ }
87
+ const rest = text.slice(close + 1);
88
+ const base = /^(?:[A-Za-z_$][A-Za-z0-9_$?]*|\?[A-Za-z0-9_$?]+)/.exec(rest);
89
+ if (!base) {
90
+ return undefined;
91
+ }
92
+ const path = parseLayoutCastPath(rest.slice(base[0].length), parseNestedExpression);
93
+ if (!path) {
94
+ return undefined;
95
+ }
96
+ return {
97
+ kind: 'layout-cast',
98
+ typeExpr,
99
+ base: { kind: 'symbol', name: base[0] },
100
+ path,
101
+ };
102
+ }
103
+ function parseLayoutCastPath(text, parseNestedExpression) {
104
+ const parts = [];
105
+ let rest = text.trim();
106
+ while (rest.length > 0) {
107
+ const parsed = parseLayoutCastPathPart(rest, parseNestedExpression);
108
+ if (!parsed)
109
+ return undefined;
110
+ parts.push(parsed.part);
111
+ rest = parsed.rest.trim();
112
+ }
113
+ return parts.length > 0 ? parts : undefined;
114
+ }
115
+ function parseLayoutCastPathPart(text, parseNestedExpression) {
116
+ return text.startsWith('.')
117
+ ? parseLayoutCastField(text)
118
+ : parseLayoutCastIndex(text, parseNestedExpression);
119
+ }
120
+ function parseLayoutCastField(text) {
121
+ const field = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(text);
122
+ return field ? { part: { kind: 'field', name: field[1] ?? '' }, rest: text.slice(field[0].length) } : undefined;
123
+ }
124
+ function parseLayoutCastIndex(text, parseNestedExpression) {
125
+ if (!text.startsWith('['))
126
+ return undefined;
127
+ const close = findMatchingBracket(text);
128
+ if (close === undefined)
129
+ return undefined;
130
+ const expression = parseNestedExpression(text.slice(1, close));
131
+ return expression
132
+ ? { part: { kind: 'index', expression }, rest: text.slice(close + 1) }
133
+ : undefined;
134
+ }
135
+ function parseOffsetPath(text) {
136
+ const trimmed = text.trim();
137
+ if (trimmed.length === 0) {
138
+ return undefined;
139
+ }
140
+ const parts = [];
141
+ let rest = trimmed;
142
+ while (rest.length > 0) {
143
+ const parsed = parseOffsetPathPart(rest);
144
+ if (!parsed)
145
+ return undefined;
146
+ parts.push(parsed.part);
147
+ rest = parsed.rest;
148
+ if (rest.length === 0) {
149
+ break;
150
+ }
151
+ if (!rest.startsWith('.')) {
152
+ return undefined;
153
+ }
154
+ rest = rest.slice(1);
155
+ }
156
+ return parts.length > 0 ? parts : undefined;
157
+ }
158
+ function parseOffsetPathPart(text) {
159
+ return text.startsWith('[') ? parseOffsetIndex(text) : parseOffsetField(text);
160
+ }
161
+ function parseOffsetIndex(text) {
162
+ const index = /^\[\s*([0-9]+)\s*\]/.exec(text);
163
+ return index
164
+ ? {
165
+ part: { kind: 'index', index: Number.parseInt(index[1] ?? '', 10) },
166
+ rest: text.slice(index[0].length),
167
+ }
168
+ : undefined;
169
+ }
170
+ function parseOffsetField(text) {
171
+ const field = /^[A-Za-z_][A-Za-z0-9_]*/.exec(text);
172
+ return field
173
+ ? { part: { kind: 'field', name: field[0] }, rest: text.slice(field[0].length) }
174
+ : undefined;
175
+ }