@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,3 @@
1
+ export { applyBinaryOperator } from './binary-operators.js';
2
+ export { applyByteFunction } from './byte-functions.js';
3
+ export { applyUnaryOperator } from './unary-operators.js';
@@ -0,0 +1,3 @@
1
+ import type { Diagnostic } from '../model/diagnostic.js';
2
+ import type { SourceSpan } from '../source/source-span.js';
3
+ export declare function diagnostic(span: SourceSpan, message: string): Diagnostic;
@@ -0,0 +1,10 @@
1
+ export function diagnostic(span, message) {
2
+ return {
3
+ severity: 'error',
4
+ code: 'AZMN_SYMBOL',
5
+ message,
6
+ sourceName: span.sourceName,
7
+ line: span.line,
8
+ column: span.column,
9
+ };
10
+ }
@@ -1,7 +1,9 @@
1
1
  import type { Diagnostic } from '../model/diagnostic.js';
2
- import type { Expression, TypeExpr } from '../model/expression.js';
3
- import type { LayoutField } from '../model/source-item.js';
2
+ import type { Expression } from '../model/expression.js';
4
3
  import type { SourceSpan } from '../source/source-span.js';
4
+ import { type LayoutRecord } from './layout-evaluation.js';
5
+ export { diagnostic } from './diagnostics.js';
6
+ export { validateLayouts, type LayoutRecord } from './layout-evaluation.js';
5
7
  export interface EquateRecord {
6
8
  readonly expression: Expression;
7
9
  readonly span: SourceSpan;
@@ -9,25 +11,15 @@ export interface EquateRecord {
9
11
  readonly enumMember?: boolean;
10
12
  readonly stringValue?: string;
11
13
  }
12
- export type LayoutRecord = {
13
- readonly kind: 'record' | 'union';
14
- readonly fields: readonly LayoutField[];
15
- readonly span: SourceSpan;
16
- } | {
17
- readonly kind: 'alias';
18
- readonly typeExpr: TypeExpr;
19
- readonly span: SourceSpan;
20
- };
14
+ export interface EvaluateExpressionOptions {
15
+ readonly currentLocation: number;
16
+ readonly layouts?: ReadonlyMap<string, LayoutRecord> | undefined;
17
+ readonly visiting?: ReadonlySet<string>;
18
+ readonly reportUnknown?: boolean;
19
+ }
21
20
  export declare function lookupEquateRecord(equates: ReadonlyMap<string, EquateRecord>, name: string): {
22
21
  readonly key: string;
23
22
  readonly record: EquateRecord;
24
23
  } | undefined;
25
24
  export declare function lookupSymbolValue(symbols: Readonly<Record<string, number>>, name: string): number | undefined;
26
- export declare function evaluateExpression(expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: {
27
- readonly currentLocation: number;
28
- readonly layouts?: ReadonlyMap<string, LayoutRecord> | undefined;
29
- readonly visiting?: ReadonlySet<string>;
30
- readonly reportUnknown?: boolean;
31
- }): number | undefined;
32
- export declare function diagnostic(span: SourceSpan, message: string): Diagnostic;
33
- export declare function validateLayouts(layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): void;
25
+ export declare function evaluateExpression(expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions): number | undefined;
@@ -1,3 +1,9 @@
1
+ import { applyBinaryOperator, applyByteFunction, applyUnaryOperator, } from './constant-operators.js';
2
+ import { diagnostic } from './diagnostics.js';
3
+ import { evaluateLayoutCast, evaluateOffset, evaluateSizeof, typeExprSize, } from './layout-evaluation.js';
4
+ import { formatTypeExpr, scalarSize } from './layout-format.js';
5
+ export { diagnostic } from './diagnostics.js';
6
+ export { validateLayouts } from './layout-evaluation.js';
1
7
  function canonicalSymbolKey(name) {
2
8
  return name.toLowerCase();
3
9
  }
@@ -44,7 +50,7 @@ export function evaluateExpression(expression, labels, equates, span, diagnostic
44
50
  case 'offset':
45
51
  return evaluateOffset(expression.typeExpr, expression.path, options.layouts, span, diagnostics);
46
52
  case 'layout-cast':
47
- return evaluateLayoutCast(expression, labels, equates, span, diagnostics, options);
53
+ return evaluateLayoutCast(expression, labels, equates, span, diagnostics, options, evaluateExpression);
48
54
  case 'symbol':
49
55
  return evaluateSymbol(expression.name, labels, equates, span, diagnostics, options);
50
56
  case 'unary':
@@ -58,7 +64,7 @@ function evaluateByteFunction(expression, labels, equates, span, diagnostics, op
58
64
  if (value === undefined) {
59
65
  return undefined;
60
66
  }
61
- return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
67
+ return applyByteFunction(expression.function, value);
62
68
  }
63
69
  function evaluateTypeSize(typeExpr, labels, equates, span, diagnostics, options) {
64
70
  if (options.layouts) {
@@ -78,33 +84,6 @@ function evaluateTypeSize(typeExpr, labels, equates, span, diagnostics, options)
78
84
  }
79
85
  return evaluateSymbol(typeExpr.name, labels, equates, span, diagnostics, options);
80
86
  }
81
- function evaluateLayoutCast(expression, labels, equates, span, diagnostics, options) {
82
- const base = evaluateExpression(expression.base, labels, equates, span, diagnostics, options);
83
- if (base === undefined) {
84
- return undefined;
85
- }
86
- if (!options.layouts) {
87
- diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(expression.typeExpr)}`));
88
- return undefined;
89
- }
90
- const offset = layoutCastOffset(expression.typeExpr, expression.path, labels, equates, options.layouts, span, diagnostics, options);
91
- return offset === undefined ? undefined : base + offset;
92
- }
93
- export function diagnostic(span, message) {
94
- return {
95
- severity: 'error',
96
- code: 'AZMN_SYMBOL',
97
- message,
98
- sourceName: span.sourceName,
99
- line: span.line,
100
- column: span.column,
101
- };
102
- }
103
- export function validateLayouts(layouts, diagnostics) {
104
- for (const [name, layout] of layouts) {
105
- layoutSize(name, layout, layouts, layout.span, diagnostics, new Set([name]));
106
- }
107
- }
108
87
  function evaluateSymbol(name, labels, equates, span, diagnostics, options) {
109
88
  const label = lookupLabelValue(labels, name);
110
89
  if (label !== undefined) {
@@ -132,275 +111,6 @@ function evaluateSymbol(name, labels, equates, span, diagnostics, options) {
132
111
  }
133
112
  return undefined;
134
113
  }
135
- function evaluateSizeof(typeExpr, layouts, span, diagnostics) {
136
- if (!layouts) {
137
- diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(typeExpr)}`));
138
- return undefined;
139
- }
140
- return typeExprSize(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
141
- }
142
- function evaluateOffset(typeExpr, path, layouts, span, diagnostics) {
143
- if (!layouts) {
144
- diagnostics.push(diagnostic(span, `unknown type: ${formatTypeExpr(typeExpr)}`));
145
- return undefined;
146
- }
147
- const diagnosticCount = diagnostics.length;
148
- const offset = offsetPath(typeExpr, path, layouts, span, diagnostics);
149
- if (offset !== undefined) {
150
- return offset;
151
- }
152
- if (diagnostics.length === diagnosticCount) {
153
- diagnostics.push(diagnostic(span, `unknown field "${formatOffsetPath(path)}" in type ${formatTypeExpr(typeExpr)}`));
154
- }
155
- return undefined;
156
- }
157
- function typeExprSize(typeExpr, layouts, span, diagnostics, visiting) {
158
- const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, visiting);
159
- if (!resolvedTypeExpr) {
160
- return undefined;
161
- }
162
- if (resolvedTypeExpr !== typeExpr) {
163
- return typeExprSize(resolvedTypeExpr, layouts, span, diagnostics, visiting);
164
- }
165
- const scalar = scalarSize(typeExpr.name);
166
- const baseSize = scalar ??
167
- (() => {
168
- const layout = layouts.get(typeExpr.name);
169
- if (!layout) {
170
- diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
171
- return undefined;
172
- }
173
- return layoutSize(typeExpr.name, layout, layouts, span, diagnostics, visiting);
174
- })();
175
- if (baseSize === undefined) {
176
- return undefined;
177
- }
178
- return typeExpr.length === undefined ? baseSize : baseSize * typeExpr.length;
179
- }
180
- function layoutSize(typeName, layout, layouts, span, diagnostics, visiting) {
181
- if (layout.kind === 'alias') {
182
- return typeExprSize(layout.typeExpr, layouts, span, diagnostics, visiting);
183
- }
184
- const fieldSizes = [];
185
- for (const field of layout.fields) {
186
- const size = fieldSize(field, layouts, span, diagnostics, visiting);
187
- if (size === undefined) {
188
- return undefined;
189
- }
190
- fieldSizes.push(size);
191
- }
192
- return layout.kind === 'union'
193
- ? fieldSizes.reduce((largest, size) => Math.max(largest, size), 0)
194
- : fieldSizes.reduce((sum, size) => sum + size, 0);
195
- }
196
- function fieldSize(field, layouts, span, diagnostics, visiting) {
197
- if (field.typeExpr === undefined) {
198
- return field.size;
199
- }
200
- if (visiting.has(field.typeExpr.name)) {
201
- diagnostics.push(diagnostic(span, visiting.size === 1
202
- ? `Self-referential field type "${field.typeExpr.name}" has no finite size; use .addr for a pointer field.`
203
- : `recursive type: ${field.typeExpr.name}`));
204
- return undefined;
205
- }
206
- return typeExprSize(field.typeExpr, layouts, span, diagnostics, new Set([...visiting, field.typeExpr.name]));
207
- }
208
- function offsetPath(typeExpr, parts, layouts, span, diagnostics) {
209
- const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
210
- if (!resolvedTypeExpr) {
211
- return undefined;
212
- }
213
- if (resolvedTypeExpr !== typeExpr) {
214
- return offsetPath(resolvedTypeExpr, parts, layouts, span, diagnostics);
215
- }
216
- const [head, ...tail] = parts;
217
- if (head === undefined) {
218
- return undefined;
219
- }
220
- if (head.kind === 'index') {
221
- if (typeExpr.length === undefined) {
222
- return undefined;
223
- }
224
- if (head.index >= typeExpr.length) {
225
- diagnostics.push(diagnostic(span, `array index ${head.index} out of range for ${formatTypeExpr(typeExpr)}`));
226
- return undefined;
227
- }
228
- const elementTypeExpr = { name: typeExpr.name };
229
- const stride = typeExprSize(elementTypeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
230
- if (stride === undefined) {
231
- return undefined;
232
- }
233
- if (tail.length === 0) {
234
- return head.index * stride;
235
- }
236
- const nestedOffset = offsetPath(elementTypeExpr, tail, layouts, span, diagnostics);
237
- return nestedOffset === undefined ? undefined : head.index * stride + nestedOffset;
238
- }
239
- if (typeExpr.length !== undefined) {
240
- return undefined;
241
- }
242
- const layout = layouts.get(typeExpr.name);
243
- if (!layout) {
244
- diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
245
- return undefined;
246
- }
247
- if (layout.kind === 'alias') {
248
- return offsetPath(layout.typeExpr, parts, layouts, span, diagnostics);
249
- }
250
- let currentOffset = 0;
251
- for (const field of layout.fields) {
252
- const fieldOffset = layout.kind === 'union' ? 0 : currentOffset;
253
- if (field.name === head.name) {
254
- if (field.typeExpr !== undefined) {
255
- const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
256
- if (size === undefined) {
257
- return undefined;
258
- }
259
- }
260
- if (tail.length === 0) {
261
- return fieldOffset;
262
- }
263
- if (field.typeExpr === undefined) {
264
- return undefined;
265
- }
266
- const nestedOffset = offsetPath(field.typeExpr, tail, layouts, span, diagnostics);
267
- return nestedOffset === undefined ? undefined : fieldOffset + nestedOffset;
268
- }
269
- const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
270
- if (size === undefined) {
271
- return undefined;
272
- }
273
- currentOffset += size;
274
- }
275
- return undefined;
276
- }
277
- function layoutCastOffset(typeExpr, parts, labels, equates, layouts, span, diagnostics, options) {
278
- const resolvedTypeExpr = resolveLayoutAlias(typeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
279
- if (!resolvedTypeExpr) {
280
- return undefined;
281
- }
282
- if (resolvedTypeExpr !== typeExpr) {
283
- return layoutCastOffset(resolvedTypeExpr, parts, labels, equates, layouts, span, diagnostics, options);
284
- }
285
- const [head, ...tail] = parts;
286
- if (head === undefined) {
287
- return 0;
288
- }
289
- if (head.kind === 'index') {
290
- if (typeExpr.length === undefined) {
291
- return undefined;
292
- }
293
- const registerName = registerIndexName(head.expression);
294
- if (registerName) {
295
- diagnostics.push(diagnostic(span, `runtime register index "${registerName}" is not supported in layout casts`));
296
- return undefined;
297
- }
298
- const index = evaluateExpression(head.expression, labels, equates, span, diagnostics, {
299
- ...options,
300
- layouts,
301
- });
302
- if (index === undefined) {
303
- return undefined;
304
- }
305
- if (index < 0 || index >= typeExpr.length) {
306
- diagnostics.push(diagnostic(span, `array index ${index} out of range for ${formatTypeExpr(typeExpr)}`));
307
- return undefined;
308
- }
309
- const elementTypeExpr = { name: typeExpr.name };
310
- const stride = typeExprSize(elementTypeExpr, layouts, span, diagnostics, new Set([typeExpr.name]));
311
- if (stride === undefined) {
312
- return undefined;
313
- }
314
- const nestedOffset = layoutCastOffset(elementTypeExpr, tail, labels, equates, layouts, span, diagnostics, options);
315
- return nestedOffset === undefined ? undefined : index * stride + nestedOffset;
316
- }
317
- if (typeExpr.length !== undefined) {
318
- return undefined;
319
- }
320
- const layout = layouts.get(typeExpr.name);
321
- if (!layout) {
322
- diagnostics.push(diagnostic(span, `unknown type: ${typeExpr.name}`));
323
- return undefined;
324
- }
325
- if (layout.kind === 'alias') {
326
- return layoutCastOffset(layout.typeExpr, parts, labels, equates, layouts, span, diagnostics, options);
327
- }
328
- let currentOffset = 0;
329
- for (const field of layout.fields) {
330
- const fieldOffset = layout.kind === 'union' ? 0 : currentOffset;
331
- if (field.name === head.name) {
332
- if (field.typeExpr !== undefined) {
333
- const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
334
- if (size === undefined) {
335
- return undefined;
336
- }
337
- }
338
- if (tail.length === 0) {
339
- return fieldOffset;
340
- }
341
- if (field.typeExpr === undefined) {
342
- return undefined;
343
- }
344
- const nestedOffset = layoutCastOffset(field.typeExpr, tail, labels, equates, layouts, span, diagnostics, options);
345
- return nestedOffset === undefined ? undefined : fieldOffset + nestedOffset;
346
- }
347
- const size = fieldSize(field, layouts, span, diagnostics, new Set([typeExpr.name]));
348
- if (size === undefined) {
349
- return undefined;
350
- }
351
- currentOffset += size;
352
- }
353
- return undefined;
354
- }
355
- function registerIndexName(expression) {
356
- switch (expression.kind) {
357
- case 'symbol':
358
- return /^(a|b|c|d|e|h|l|af|bc|de|hl|ix|iy|sp|i|r|ixh|ixl|iyh|iyl)$/i.test(expression.name)
359
- ? expression.name.toUpperCase()
360
- : undefined;
361
- case 'unary':
362
- return registerIndexName(expression.expression);
363
- case 'binary':
364
- return registerIndexName(expression.left) ?? registerIndexName(expression.right);
365
- default:
366
- return undefined;
367
- }
368
- }
369
- function formatTypeExpr(typeExpr) {
370
- return typeExpr.length === undefined ? typeExpr.name : `${typeExpr.name}[${typeExpr.length}]`;
371
- }
372
- function resolveLayoutAlias(typeExpr, layouts, span, diagnostics, visiting) {
373
- const layout = layouts.get(typeExpr.name);
374
- if (!layout || layout.kind !== 'alias') {
375
- return typeExpr;
376
- }
377
- if (visiting.has(layout.typeExpr.name)) {
378
- diagnostics.push(diagnostic(span, `recursive type: ${typeExpr.name}`));
379
- return undefined;
380
- }
381
- const target = resolveLayoutAlias(layout.typeExpr, layouts, span, diagnostics, new Set([...visiting, layout.typeExpr.name]));
382
- if (!target) {
383
- return undefined;
384
- }
385
- const length = typeExpr.length === undefined
386
- ? target.length
387
- : (target.length ?? 1) * typeExpr.length;
388
- return length === undefined ? { name: target.name } : { name: target.name, length };
389
- }
390
- function formatOffsetPath(path) {
391
- return path.map((part) => (part.kind === 'field' ? part.name : `[${part.index}]`)).join('.');
392
- }
393
- function scalarSize(typeName) {
394
- switch (typeName.toLowerCase()) {
395
- case 'byte':
396
- return 1;
397
- case 'word':
398
- case 'addr':
399
- return 2;
400
- default:
401
- return undefined;
402
- }
403
- }
404
114
  function hasUnqualifiedEnumMember(name, equates) {
405
115
  if (name.includes('.')) {
406
116
  return false;
@@ -418,14 +128,18 @@ function evaluateUnary(expression, labels, equates, span, diagnostics, options)
418
128
  if (value === undefined) {
419
129
  return undefined;
420
130
  }
421
- switch (expression.operator) {
422
- case '+':
423
- return value;
424
- case '-':
425
- return -value;
426
- case '~':
427
- return ~value;
131
+ return applyUnaryOperator(expression.operator, value);
132
+ }
133
+ function reportInvalidBinaryExpression(operator, right, span, diagnostics) {
134
+ if (operator === '/' && right === 0) {
135
+ diagnostics.push(diagnostic(span, 'Divide by zero in imm expression.'));
136
+ return true;
428
137
  }
138
+ if (operator === '%' && right === 0) {
139
+ diagnostics.push(diagnostic(span, 'modulo by zero in expression'));
140
+ return true;
141
+ }
142
+ return false;
429
143
  }
430
144
  function evaluateBinary(expression, labels, equates, span, diagnostics, options) {
431
145
  const left = evaluateExpression(expression.left, labels, equates, span, diagnostics, options);
@@ -433,34 +147,8 @@ function evaluateBinary(expression, labels, equates, span, diagnostics, options)
433
147
  if (left === undefined || right === undefined) {
434
148
  return undefined;
435
149
  }
436
- switch (expression.operator) {
437
- case '*':
438
- return left * right;
439
- case '/':
440
- if (right === 0) {
441
- diagnostics.push(diagnostic(span, 'Divide by zero in imm expression.'));
442
- return undefined;
443
- }
444
- return Math.trunc(left / right);
445
- case '%':
446
- if (right === 0) {
447
- diagnostics.push(diagnostic(span, 'modulo by zero in expression'));
448
- return undefined;
449
- }
450
- return left % right;
451
- case '+':
452
- return left + right;
453
- case '-':
454
- return left - right;
455
- case '&':
456
- return left & right;
457
- case '^':
458
- return left ^ right;
459
- case '|':
460
- return left | right;
461
- case '<<':
462
- return left << right;
463
- case '>>':
464
- return left >> right;
150
+ if (reportInvalidBinaryExpression(expression.operator, right, span, diagnostics)) {
151
+ return undefined;
465
152
  }
153
+ return applyBinaryOperator(expression.operator, left, right);
466
154
  }
@@ -0,0 +1,23 @@
1
+ import type { Diagnostic } from '../model/diagnostic.js';
2
+ import type { Expression, OffsetPathPart, TypeExpr } from '../model/expression.js';
3
+ import type { LayoutField } from '../model/source-item.js';
4
+ import type { SourceSpan } from '../source/source-span.js';
5
+ import type { EquateRecord, EvaluateExpressionOptions } from './expression-evaluation.js';
6
+ export type LayoutRecord = {
7
+ readonly kind: 'record' | 'union';
8
+ readonly fields: readonly LayoutField[];
9
+ readonly span: SourceSpan;
10
+ } | {
11
+ readonly kind: 'alias';
12
+ readonly typeExpr: TypeExpr;
13
+ readonly span: SourceSpan;
14
+ };
15
+ type EvaluateNestedExpression = (expression: Expression, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions) => number | undefined;
16
+ export declare function evaluateSizeof(typeExpr: TypeExpr, layouts: ReadonlyMap<string, LayoutRecord> | undefined, span: SourceSpan, diagnostics: Diagnostic[]): number | undefined;
17
+ export declare function evaluateOffset(typeExpr: TypeExpr, path: readonly OffsetPathPart[], layouts: ReadonlyMap<string, LayoutRecord> | undefined, span: SourceSpan, diagnostics: Diagnostic[]): number | undefined;
18
+ export declare function evaluateLayoutCast(expression: Extract<Expression, {
19
+ readonly kind: 'layout-cast';
20
+ }>, labels: Readonly<Record<string, number>>, equates: ReadonlyMap<string, EquateRecord>, span: SourceSpan, diagnostics: Diagnostic[], options: EvaluateExpressionOptions, evaluateExpression: EvaluateNestedExpression): number | undefined;
21
+ export declare function validateLayouts(layouts: ReadonlyMap<string, LayoutRecord>, diagnostics: Diagnostic[]): void;
22
+ export declare function typeExprSize(typeExpr: TypeExpr, layouts: ReadonlyMap<string, LayoutRecord>, span: SourceSpan, diagnostics: Diagnostic[], visiting: Set<string>): number | undefined;
23
+ export {};