@hyperscale0/hsx 1.0.0-rc.1 → 1.0.123

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 (311) hide show
  1. package/CHANGELOG.md +5 -239
  2. package/LICENSE.md +356 -0
  3. package/NOTICE.md +8 -0
  4. package/README.md +45 -43
  5. package/bin/hsx.ts +0 -5
  6. package/dist/bin/hsx.d.ts +0 -4
  7. package/dist/bin/hsx.d.ts.map +1 -1
  8. package/dist/bin/hsx.js +0 -4
  9. package/dist/bin/hsx.js.map +1 -1
  10. package/dist/src/ast.d.ts +113 -302
  11. package/dist/src/ast.d.ts.map +1 -1
  12. package/dist/src/ast.js +7 -47
  13. package/dist/src/ast.js.map +1 -1
  14. package/dist/src/attachment-economics.d.ts +5 -0
  15. package/dist/src/attachment-economics.d.ts.map +1 -0
  16. package/dist/src/attachment-economics.js +55 -0
  17. package/dist/src/attachment-economics.js.map +1 -0
  18. package/dist/src/binding-contract.d.ts +22 -0
  19. package/dist/src/binding-contract.d.ts.map +1 -0
  20. package/dist/src/binding-contract.js +74 -0
  21. package/dist/src/binding-contract.js.map +1 -0
  22. package/dist/src/cli.d.ts +4 -17
  23. package/dist/src/cli.d.ts.map +1 -1
  24. package/dist/src/cli.js +92 -259
  25. package/dist/src/cli.js.map +1 -1
  26. package/dist/src/compile.d.ts +34 -68
  27. package/dist/src/compile.d.ts.map +1 -1
  28. package/dist/src/compile.js +2949 -118
  29. package/dist/src/compile.js.map +1 -1
  30. package/dist/src/cost.d.ts +8 -75
  31. package/dist/src/cost.d.ts.map +1 -1
  32. package/dist/src/cost.js +54 -364
  33. package/dist/src/cost.js.map +1 -1
  34. package/dist/src/diagnostics.d.ts +14 -9
  35. package/dist/src/diagnostics.d.ts.map +1 -1
  36. package/dist/src/diagnostics.js +39 -416
  37. package/dist/src/diagnostics.js.map +1 -1
  38. package/dist/src/examples-bundle.d.ts +3 -0
  39. package/dist/src/examples-bundle.d.ts.map +1 -0
  40. package/dist/src/examples-bundle.js +18 -0
  41. package/dist/src/examples-bundle.js.map +1 -0
  42. package/dist/src/examples.d.ts +10 -0
  43. package/dist/src/examples.d.ts.map +1 -0
  44. package/dist/src/examples.js +2 -0
  45. package/dist/src/examples.js.map +1 -0
  46. package/dist/src/format.d.ts +8 -7
  47. package/dist/src/format.d.ts.map +1 -1
  48. package/dist/src/format.js +9 -175
  49. package/dist/src/format.js.map +1 -1
  50. package/dist/src/header-source.d.ts +3 -0
  51. package/dist/src/header-source.d.ts.map +1 -0
  52. package/dist/src/header-source.js +41 -0
  53. package/dist/src/header-source.js.map +1 -0
  54. package/dist/src/headers.d.ts +64 -0
  55. package/dist/src/headers.d.ts.map +1 -0
  56. package/dist/src/headers.js +167 -0
  57. package/dist/src/headers.js.map +1 -0
  58. package/dist/src/index.d.ts +8 -11
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/index.js +5 -8
  61. package/dist/src/index.js.map +1 -1
  62. package/dist/src/keywords.d.ts +56 -0
  63. package/dist/src/keywords.d.ts.map +1 -0
  64. package/dist/src/keywords.js +133 -0
  65. package/dist/src/keywords.js.map +1 -0
  66. package/dist/src/language.d.ts +26 -0
  67. package/dist/src/language.d.ts.map +1 -0
  68. package/dist/src/language.js +440 -0
  69. package/dist/src/language.js.map +1 -0
  70. package/dist/src/lex.d.ts +13 -28
  71. package/dist/src/lex.d.ts.map +1 -1
  72. package/dist/src/lex.js +119 -145
  73. package/dist/src/lex.js.map +1 -1
  74. package/dist/src/parse.d.ts +4 -17
  75. package/dist/src/parse.d.ts.map +1 -1
  76. package/dist/src/parse.js +484 -1036
  77. package/dist/src/parse.js.map +1 -1
  78. package/dist/src/std-bundle.d.ts +2 -0
  79. package/dist/src/std-bundle.d.ts.map +1 -0
  80. package/dist/src/std-bundle.js +15 -0
  81. package/dist/src/std-bundle.js.map +1 -0
  82. package/dist/src/std-library.d.ts +5 -0
  83. package/dist/src/std-library.d.ts.map +1 -0
  84. package/dist/src/std-library.js +5 -0
  85. package/dist/src/std-library.js.map +1 -0
  86. package/dist/src/tunables.d.ts +7 -0
  87. package/dist/src/tunables.d.ts.map +1 -0
  88. package/dist/src/tunables.js +27 -0
  89. package/dist/src/tunables.js.map +1 -0
  90. package/docs/README.md +528 -23
  91. package/docs/assets/brand/hsx-horizontal-white.svg +1 -0
  92. package/docs/assets/brand/hsx-horizontal.svg +1 -0
  93. package/docs/assets/brand/hsx-stacked-white.svg +1 -0
  94. package/docs/assets/brand/hsx-stacked.svg +1 -0
  95. package/docs/assets/brand/manifest.json +30 -0
  96. package/docs/assets/hsx.svg +11 -0
  97. package/examples/cards.hsx +34 -0
  98. package/examples/collections.hsx +37 -0
  99. package/examples/cost-table.json +633 -385
  100. package/examples/escrow.hsx +24 -0
  101. package/examples/financing.hsx +32 -0
  102. package/examples/insurance.hsx +30 -0
  103. package/examples/lending.hsx +57 -0
  104. package/examples/library.hsx +15 -0
  105. package/examples/marketplace.hsx +32 -0
  106. package/examples/money.hsx +19 -0
  107. package/examples/rental-deposit.hsx +60 -0
  108. package/examples/repair-approval.hsx +44 -0
  109. package/examples/reporting.hsx +28 -0
  110. package/examples/savings.hsx +21 -0
  111. package/examples/serviced.hsx +25 -0
  112. package/examples/wallet.hsx +24 -0
  113. package/package.json +27 -17
  114. package/src/ast.ts +84 -411
  115. package/src/attachment-economics.ts +103 -0
  116. package/src/binding-contract.ts +104 -0
  117. package/src/cli.ts +98 -309
  118. package/src/compile.ts +4063 -212
  119. package/src/cost.ts +71 -574
  120. package/src/diagnostics.ts +57 -437
  121. package/src/examples-bundle.ts +19 -0
  122. package/src/examples.ts +9 -0
  123. package/src/format.ts +12 -256
  124. package/src/header-source.ts +54 -0
  125. package/src/headers.ts +195 -0
  126. package/src/index.ts +16 -29
  127. package/src/keywords.ts +134 -0
  128. package/src/language.ts +629 -0
  129. package/src/lex.ts +131 -192
  130. package/src/parse.ts +489 -1195
  131. package/src/std-bundle.ts +15 -0
  132. package/src/std-library.ts +7 -0
  133. package/src/tunables.ts +36 -0
  134. package/std/cards.hsx +85 -0
  135. package/std/collections.hsx +90 -0
  136. package/std/escrow.hsx +73 -0
  137. package/std/financing.hsx +683 -0
  138. package/std/insurance.hsx +89 -0
  139. package/std/lending.hsx +138 -0
  140. package/std/marketplace.hsx +123 -0
  141. package/std/money.hsx +173 -0
  142. package/std/reporting.hsx +753 -0
  143. package/std/savings.hsx +68 -0
  144. package/std/wallet.hsx +57 -0
  145. package/LICENSE +0 -661
  146. package/LICENSING.md +0 -52
  147. package/TRADEMARKS.md +0 -35
  148. package/dist/src/emit.d.ts +0 -35
  149. package/dist/src/emit.d.ts.map +0 -1
  150. package/dist/src/emit.js +0 -359
  151. package/dist/src/emit.js.map +0 -1
  152. package/dist/src/entry-overrides.d.ts +0 -58
  153. package/dist/src/entry-overrides.d.ts.map +0 -1
  154. package/dist/src/entry-overrides.js +0 -284
  155. package/dist/src/entry-overrides.js.map +0 -1
  156. package/dist/src/ir.d.ts +0 -66
  157. package/dist/src/ir.d.ts.map +0 -1
  158. package/dist/src/ir.js +0 -15
  159. package/dist/src/ir.js.map +0 -1
  160. package/dist/src/limits.d.ts +0 -21
  161. package/dist/src/limits.d.ts.map +0 -1
  162. package/dist/src/limits.js +0 -21
  163. package/dist/src/limits.js.map +0 -1
  164. package/dist/src/modules.d.ts +0 -36
  165. package/dist/src/modules.d.ts.map +0 -1
  166. package/dist/src/modules.js +0 -372
  167. package/dist/src/modules.js.map +0 -1
  168. package/dist/src/typecheck.d.ts +0 -8
  169. package/dist/src/typecheck.d.ts.map +0 -1
  170. package/dist/src/typecheck.js +0 -2958
  171. package/dist/src/typecheck.js.map +0 -1
  172. package/dist/src/version.d.ts +0 -5
  173. package/dist/src/version.d.ts.map +0 -1
  174. package/dist/src/version.js +0 -5
  175. package/dist/src/version.js.map +0 -1
  176. package/docs/guide/01-first-program.md +0 -24
  177. package/docs/guide/02-money.md +0 -25
  178. package/docs/guide/03-instruments.md +0 -22
  179. package/docs/guide/04-lifecycles.md +0 -25
  180. package/docs/guide/05-fees-and-splits.md +0 -45
  181. package/docs/guide/06-schedules.md +0 -22
  182. package/docs/guide/07-composition.md +0 -46
  183. package/docs/guide/08-writing-a-module.md +0 -26
  184. package/docs/guide/09-cost.md +0 -24
  185. package/docs/guide/10-diagnostics.md +0 -27
  186. package/docs/llms-full.txt +0 -1738
  187. package/docs/llms.txt +0 -45
  188. package/docs/reference/cli.md +0 -33
  189. package/docs/reference/diagnostics.md +0 -619
  190. package/docs/reference/grammar.md +0 -39
  191. package/docs/reference/std/advance.md +0 -35
  192. package/docs/reference/std/cancellable_booking.md +0 -35
  193. package/docs/reference/std/captured_payment.md +0 -43
  194. package/docs/reference/std/conditional_disbursement.md +0 -33
  195. package/docs/reference/std/credit_facility.md +0 -35
  196. package/docs/reference/std/held_payment.md +0 -64
  197. package/docs/reference/std/instant_transfer.md +0 -30
  198. package/docs/reference/std/metered.md +0 -27
  199. package/docs/reference/std/pooled_split.md +0 -26
  200. package/docs/reference/std/premium_forward.md +0 -39
  201. package/docs/reference/std/reconciled_payout.md +0 -33
  202. package/docs/reference/std/recurring_collection.md +0 -25
  203. package/docs/reference/std/rotating_pool.md +0 -42
  204. package/docs/reference/std/scheduled.md +0 -51
  205. package/docs/reference/std/security_deposit.md +0 -46
  206. package/docs/reference/std/settlement_batch.md +0 -42
  207. package/docs/reference/std/swap.md +0 -46
  208. package/docs/reference/std/threshold_pool.md +0 -47
  209. package/docs/reference/std/weighted_distribution.md +0 -39
  210. package/docs/reference/types.md +0 -20
  211. package/docs/reference/udl-output.md +0 -14
  212. package/docs/sessions/2026-09-02-two-instruments.hsx +0 -21
  213. package/docs/sessions/2026-09-02-two-instruments.md +0 -41
  214. package/examples/01-first-program/README.md +0 -45
  215. package/examples/01-first-program/tip-jar.hsx +0 -17
  216. package/examples/02-imports-and-archetypes/README.md +0 -99
  217. package/examples/02-imports-and-archetypes/photo-booth.hsx +0 -37
  218. package/examples/03-diagnostics/README.md +0 -68
  219. package/examples/03-diagnostics/corner-shop-fixed.hsx +0 -22
  220. package/examples/03-diagnostics/corner-shop.hsx +0 -19
  221. package/examples/04-complete-product/README.md +0 -87
  222. package/examples/04-complete-product/study-hall.hsx +0 -67
  223. package/examples/05-watch-club/README.md +0 -9
  224. package/examples/05-watch-club/watch-club.hsx +0 -124
  225. package/examples/README.md +0 -18
  226. package/examples/advance/README.md +0 -3
  227. package/examples/advance/advance.hsx +0 -13
  228. package/examples/advance/advance.udl +0 -339
  229. package/examples/cancellable_booking/README.md +0 -3
  230. package/examples/cancellable_booking/cancellable_booking.hsx +0 -14
  231. package/examples/cancellable_booking/cancellable_booking.udl +0 -391
  232. package/examples/captured_payment/README.md +0 -3
  233. package/examples/captured_payment/captured_payment.hsx +0 -21
  234. package/examples/captured_payment/captured_payment.udl +0 -677
  235. package/examples/conditional_disbursement/README.md +0 -3
  236. package/examples/conditional_disbursement/conditional_disbursement.hsx +0 -17
  237. package/examples/conditional_disbursement/conditional_disbursement.udl +0 -412
  238. package/examples/credit_facility/README.md +0 -3
  239. package/examples/credit_facility/credit_facility.hsx +0 -27
  240. package/examples/credit_facility/credit_facility.udl +0 -1373
  241. package/examples/held_payment/README.md +0 -3
  242. package/examples/held_payment/held_payment.hsx +0 -13
  243. package/examples/held_payment/held_payment.udl +0 -507
  244. package/examples/instant_transfer/README.md +0 -3
  245. package/examples/instant_transfer/instant_transfer.hsx +0 -16
  246. package/examples/instant_transfer/instant_transfer.udl +0 -364
  247. package/examples/metered/README.md +0 -3
  248. package/examples/metered/metered.hsx +0 -13
  249. package/examples/metered/metered.udl +0 -247
  250. package/examples/pooled_split/README.md +0 -3
  251. package/examples/pooled_split/pooled_split.hsx +0 -15
  252. package/examples/pooled_split/pooled_split.udl +0 -425
  253. package/examples/premium_forward/README.md +0 -3
  254. package/examples/premium_forward/premium_forward.hsx +0 -19
  255. package/examples/premium_forward/premium_forward.udl +0 -594
  256. package/examples/reconciled_payout/README.md +0 -3
  257. package/examples/reconciled_payout/reconciled_payout.hsx +0 -13
  258. package/examples/reconciled_payout/reconciled_payout.udl +0 -303
  259. package/examples/recurring_collection/README.md +0 -3
  260. package/examples/recurring_collection/recurring_collection.hsx +0 -21
  261. package/examples/recurring_collection/recurring_collection.udl +0 -1130
  262. package/examples/rotating_pool/README.md +0 -3
  263. package/examples/rotating_pool/rotating_pool.hsx +0 -18
  264. package/examples/rotating_pool/rotating_pool.udl +0 -4352
  265. package/examples/scheduled/README.md +0 -3
  266. package/examples/scheduled/scheduled.hsx +0 -12
  267. package/examples/scheduled/scheduled.udl +0 -335
  268. package/examples/security_deposit/README.md +0 -3
  269. package/examples/security_deposit/security_deposit.hsx +0 -21
  270. package/examples/security_deposit/security_deposit.udl +0 -293
  271. package/examples/settlement_batch/README.md +0 -3
  272. package/examples/settlement_batch/settlement_batch.hsx +0 -19
  273. package/examples/settlement_batch/settlement_batch.udl +0 -753
  274. package/examples/swap/README.md +0 -3
  275. package/examples/swap/swap.hsx +0 -19
  276. package/examples/swap/swap.udl +0 -876
  277. package/examples/threshold_pool/README.md +0 -3
  278. package/examples/threshold_pool/threshold_pool.hsx +0 -16
  279. package/examples/threshold_pool/threshold_pool.udl +0 -667
  280. package/examples/weighted_distribution/README.md +0 -3
  281. package/examples/weighted_distribution/weighted_distribution.hsx +0 -20
  282. package/examples/weighted_distribution/weighted_distribution.udl +0 -337
  283. package/skills/hsx/SKILL.md +0 -483
  284. package/src/emit.ts +0 -447
  285. package/src/entry-overrides.ts +0 -428
  286. package/src/ir.ts +0 -99
  287. package/src/limits.ts +0 -20
  288. package/src/modules.ts +0 -444
  289. package/src/typecheck.ts +0 -3876
  290. package/src/version.ts +0 -5
  291. package/std/SEMANTICS.md +0 -130
  292. package/std/settlements/advance.hsx +0 -177
  293. package/std/settlements/cancellable_booking.hsx +0 -87
  294. package/std/settlements/captured_payment.hsx +0 -144
  295. package/std/settlements/conditional_disbursement.hsx +0 -185
  296. package/std/settlements/credit_facility.hsx +0 -167
  297. package/std/settlements/held_payment.hsx +0 -578
  298. package/std/settlements/index.hsx +0 -3
  299. package/std/settlements/instant_transfer.hsx +0 -190
  300. package/std/settlements/metered.hsx +0 -67
  301. package/std/settlements/pooled_split.hsx +0 -68
  302. package/std/settlements/premium_forward.hsx +0 -257
  303. package/std/settlements/reconciled_payout.hsx +0 -77
  304. package/std/settlements/recurring_collection.hsx +0 -27
  305. package/std/settlements/rotating_pool.hsx +0 -252
  306. package/std/settlements/scheduled.hsx +0 -641
  307. package/std/settlements/security_deposit.hsx +0 -166
  308. package/std/settlements/settlement_batch.hsx +0 -122
  309. package/std/settlements/swap.hsx +0 -1114
  310. package/std/settlements/threshold_pool.hsx +0 -221
  311. package/std/settlements/weighted_distribution.hsx +0 -141
package/src/ast.ts CHANGED
@@ -1,422 +1,95 @@
1
- /**
2
- * The HSX abstract syntax tree.
3
- *
4
- * Every node carries a byte-offset span into the original source. Spans are
5
- * the compiler's source-mapping currency: diagnostics at every later stage
6
- * (typecheck, lowering, verdicts) point at source coordinates, never at
7
- * lowered IR paths. Offsets convert to line/column via `lineColAt`.
8
- */
9
-
10
1
  export interface Span {
11
- /** Inclusive start byte offset into the source text. */
12
- readonly start: number;
13
- /** Exclusive end byte offset into the source text. */
14
- readonly end: number;
2
+ start: number;
3
+ end: number;
15
4
  }
16
-
17
- export interface LineCol {
18
- /** 1-indexed line. */
19
- readonly line: number;
20
- /** 1-indexed column, counted in UTF-16 code units. */
21
- readonly column: number;
22
- }
23
-
24
- /** Convert a byte offset to a 1-indexed line/column position. */
25
- export function lineColAt(source: string, offset: number): LineCol {
26
- let line = 1;
27
- let lineStart = 0;
28
- const clamped = Math.max(0, Math.min(offset, source.length));
29
- for (let index = 0; index < clamped; index += 1) {
30
- if (source.charCodeAt(index) === 10) {
31
- line += 1;
32
- lineStart = index + 1;
33
- }
34
- }
35
- return { column: clamped - lineStart + 1, line };
36
- }
37
-
38
- /**
39
- * One source scanned once, so many offsets resolve without rescanning it.
40
- * `lineColAt` walks from offset zero every time, which turns a run of d
41
- * diagnostics over an n-byte source into O(n*d) work. A caller holding this
42
- * pays O(n) once and O(log n) per offset.
43
- */
44
- export interface LineIndex {
45
- /** Source length, so `lineColIn` clamps exactly as `lineColAt` does. */
46
- readonly length: number;
47
- /** Offset of the first character of each line, ascending. Line 1 starts at 0. */
48
- readonly starts: readonly number[];
49
- }
50
-
51
- /** Scan a source once for the offset every line starts at. */
52
- export function lineIndex(source: string): LineIndex {
53
- const starts = [0];
54
- for (let index = 0; index < source.length; index += 1) {
55
- if (source.charCodeAt(index) === 10) starts.push(index + 1);
56
- }
57
- return { length: source.length, starts };
58
- }
59
-
60
- /**
61
- * Resolve one offset against a prebuilt index. Returns exactly what
62
- * `lineColAt` returns for the same source and offset.
63
- */
64
- export function lineColIn(index: LineIndex, offset: number): LineCol {
65
- const clamped = Math.max(0, Math.min(offset, index.length));
66
- let low = 0;
67
- let high = index.starts.length - 1;
68
- while (low < high) {
69
- const middle = Math.floor((low + high + 1) / 2);
70
- if ((index.starts[middle] as number) <= clamped) low = middle;
71
- else high = middle - 1;
72
- }
73
- return { column: clamped - (index.starts[low] as number) + 1, line: low + 1 };
74
- }
75
-
76
- // --- Expressions -----------------------------------------------------------
77
-
78
- export interface IdentExpr {
79
- readonly kind: "ident";
80
- readonly name: string;
81
- /** A literal quoted block key keeps its exact spelling during JSON lowering. */
82
- readonly quoted?: boolean;
83
- readonly span: Span;
84
- }
85
-
86
- export interface StringExpr {
87
- readonly kind: "string";
88
- readonly span: Span;
89
- readonly value: string;
90
- }
91
-
92
- export interface NumberExpr {
93
- readonly kind: "number";
94
- /** The literal exactly as written, e.g. "99.5". Interpretation is typed later. */
95
- readonly raw: string;
96
- readonly span: Span;
97
- }
98
-
99
- export interface BooleanExpr {
100
- readonly kind: "boolean";
101
- readonly span: Span;
102
- readonly value: boolean;
103
- }
104
-
105
- /** A currency-indexed literal. The checker converts it to integer minor units. */
106
- export interface MoneyExpr {
107
- readonly currency: IdentExpr;
108
- readonly kind: "money";
109
- readonly raw: string;
110
- readonly span: Span;
111
- }
112
-
113
- /** A dotted name used for modules, UDL operations, and field paths. */
114
- export interface PathExpr {
115
- readonly kind: "path";
116
- readonly parts: readonly IdentExpr[];
117
- readonly span: Span;
118
- }
119
-
120
- /** A nominal type application such as `money<SAR>` or `ref<invoice>`. */
121
- export interface TypeApplyExpr {
122
- readonly args: readonly Expr[];
123
- readonly callee: IdentExpr;
124
- readonly kind: "type_apply";
125
- readonly span: Span;
126
- }
127
-
128
- /** A general instrument or constant application, with optional type arguments. */
129
- export interface ApplyExpr {
130
- readonly args: readonly Expr[];
131
- readonly callee: PathExpr;
132
- readonly kind: "apply";
133
- readonly span: Span;
134
- readonly typeArgs: readonly Expr[];
135
- }
136
-
137
- export interface PercentExpr {
138
- /** Exact basis points: 99.5% is 9950. Percents never round. */
139
- readonly bps: number;
140
- readonly kind: "percent";
141
- readonly raw: string;
142
- readonly span: Span;
143
- }
144
-
145
- /** A type or constructor application: `money(SAR)`, `id(vehicle)`. */
146
- export interface CallExpr {
147
- readonly args: readonly Expr[];
148
- readonly callee: IdentExpr;
149
- readonly kind: "call";
150
- readonly span: Span;
151
- }
152
-
153
- /**
154
- * An exit amount chosen by a decision port and bounded by stored money:
155
- * `decided { field: damageAmount, bound: depositAmount, remainder: return }`.
156
- */
157
- export interface DecidedAmountExpr {
158
- readonly body: BlockExpr;
159
- readonly kind: "decided_amount";
160
- readonly span: Span;
161
- }
162
-
163
- /**
164
- * A reference to a decision port, optionally bounded (`port dispute within
165
- * P14D`) or carrying the date that decides when the port has not
166
- * (`port approve_release | at(releaseDueAt)`).
167
- */
168
- export interface PortRefExpr {
169
- /** `| at(<field>)`, the stored date field that resolves an undecided hold. */
170
- readonly deadline?: IdentExpr;
171
- readonly kind: "port_ref";
172
- readonly name: IdentExpr;
173
- readonly span: Span;
174
- readonly within?: IdentExpr;
175
- }
176
-
177
- /**
178
- * `retention.release`, one settlement naming another settlement's declared
179
- * referenceable exit. The checker resolves it wholly before lowering.
180
- */
181
- export interface SettlementRefExpr {
182
- readonly kind: "settlement_ref";
183
- /** The exit named on the owner, e.g. `release`. */
184
- readonly member: IdentExpr;
185
- /** The settlement being referenced. */
186
- readonly owner: IdentExpr;
187
- readonly span: Span;
188
- }
189
-
190
- export interface ListExpr {
191
- readonly items: readonly Expr[];
192
- readonly kind: "list";
193
- readonly span: Span;
194
- }
195
-
196
- /** A brace block of entries: `{ buyer: 1%, seller: 2% }`. */
197
- export interface BlockExpr {
198
- readonly entries: readonly Entry[];
199
- readonly kind: "block";
200
- readonly span: Span;
201
- }
202
-
203
- /**
204
- * A named typed binding inside an expression position:
205
- * `amount: price: money(SAR)` binds the field name `price` to type
206
- * `money(SAR)`: the entry key is `amount`, the value is this binding.
207
- */
208
- export interface BindingExpr {
209
- readonly kind: "binding";
210
- readonly name: IdentExpr;
211
- readonly span: Span;
212
- readonly type: Expr;
5
+ export interface Diagnostic {
6
+ source?: string;
7
+ related?: readonly { source: string; span: Span; message: string }[];
8
+ code: string;
9
+ message: string;
10
+ fix: string;
11
+ span: Span;
213
12
  }
214
-
215
13
  export type Expr =
216
- | ApplyExpr
217
- | BindingExpr
218
- | BlockExpr
219
- | BooleanExpr
220
- | CallExpr
221
- | DecidedAmountExpr
222
- | IdentExpr
223
- | ListExpr
224
- | MoneyExpr
225
- | NumberExpr
226
- | PathExpr
227
- | PercentExpr
228
- | PortRefExpr
229
- | SettlementRefExpr
230
- | StringExpr
231
- | TypeApplyExpr;
232
-
233
- // --- Entries ---------------------------------------------------------------
234
-
235
- /**
236
- * One keyed entry inside a declaration body. Three surface shapes normalize
237
- * here: `payer: buyer` (key + value), `fees { ... }` (key + block value),
238
- * and `on_cancel(funded) { ... }` (key + qualifiers + block value).
239
- */
14
+ | {
15
+ kind:
16
+ | "name"
17
+ | "text"
18
+ | "number"
19
+ | "money"
20
+ | "percent"
21
+ | "duration"
22
+ | "date";
23
+ value: string;
24
+ span: Span;
25
+ }
26
+ | { kind: "list"; items: Expr[]; span: Span }
27
+ | { kind: "block"; entries: Entry[]; span: Span }
28
+ | { kind: "call"; name: string; args: Expr[]; span: Span }
29
+ | {
30
+ kind: "type";
31
+ name: string;
32
+ target?: string;
33
+ owner?: string;
34
+ optional: boolean;
35
+ many?: boolean;
36
+ span: Span;
37
+ }
38
+ | { kind: "default"; type: Expr; value: Expr; span: Span }
39
+ | { kind: "capped"; rate: Expr; cap: Expr; span: Span };
240
40
  export interface Entry {
241
- /** `for item in bound { ... }`, expanded before binding or UDL lowering. */
242
- readonly iteration?: {
243
- readonly binding: IdentExpr;
244
- readonly bound: Expr;
245
- };
246
- readonly key: IdentExpr;
247
- readonly qualifiers: readonly IdentExpr[];
248
- readonly span: Span;
249
- readonly value: Expr;
250
- }
251
-
252
- // --- Declarations ----------------------------------------------------------
253
-
254
- /** `program used_car_escrow "Used-car escrow"` names the company program. */
255
- export interface ProgramDecl {
256
- readonly kind: "program";
257
- readonly name: IdentExpr;
258
- readonly span: Span;
259
- readonly title?: StringExpr;
260
- }
261
-
262
- /** `use held_settlement` selects one published catalog instrument. */
263
- export interface UseDecl {
264
- readonly instrument: IdentExpr;
265
- readonly kind: "use";
266
- readonly span: Span;
267
- }
268
-
269
- /** `expose held_settlement.release as releaseFunds` names a public action. */
270
- export interface ExposeDecl {
271
- readonly action: IdentExpr;
272
- readonly instrument: IdentExpr;
273
- readonly kind: "expose";
274
- readonly publicName: IdentExpr;
275
- readonly span: Span;
276
- }
277
-
278
- /** `import { held_payment } from "std/settlements"`. */
279
- export interface ImportDecl {
280
- readonly from: StringExpr;
281
- readonly kind: "import";
282
- readonly names: readonly IdentExpr[];
283
- readonly span: Span;
284
- }
285
-
286
- /** `party buyer: person` with an optional attribute block. */
287
- export interface PartyDecl {
288
- readonly attrs?: BlockExpr;
289
- readonly kind: "party";
290
- readonly name: IdentExpr;
291
- readonly partyKind: IdentExpr;
292
- readonly span: Span;
293
- }
294
-
295
- /** `asset vehicle: good { title_transfer: off_platform }`. */
296
- export interface AssetDecl {
297
- readonly assetKind: IdentExpr;
298
- readonly attrs?: BlockExpr;
299
- readonly kind: "asset";
300
- readonly name: IdentExpr;
301
- readonly span: Span;
302
- }
303
-
304
- /** A full UDL subject-kind declaration. `asset` remains shorthand for this form. */
305
- export interface SubjectDecl {
306
- readonly body: BlockExpr;
307
- readonly kind: "subject";
308
- readonly name: IdentExpr;
309
- readonly span: Span;
310
- }
311
-
312
- /** `port confirm_handover { allowed: [buyer], ... }`. */
313
- export interface PortDecl {
314
- readonly body: BlockExpr;
315
- readonly kind: "port";
316
- readonly name: IdentExpr;
317
- readonly span: Span;
318
- }
319
-
320
- /** `module std.settlements` gives a file its importable module name. */
321
- export interface ModuleDecl {
322
- readonly kind: "module";
323
- readonly name: PathExpr;
324
- readonly span: Span;
41
+ key: string;
42
+ value: Expr;
43
+ span: Span;
325
44
  }
326
-
327
- export interface TypeParameter {
328
- readonly name: IdentExpr;
329
- readonly span: Span;
330
- }
331
-
332
- export interface Parameter {
333
- readonly name: IdentExpr;
334
- readonly span: Span;
335
- readonly type: Expr;
336
- }
337
-
338
- /** The single general instrument definition form. */
339
45
  export interface InstrumentDecl {
340
- readonly body: BlockExpr;
341
- /** Module-local declarations carried only while this template is bound. */
342
- readonly declarationScope?: readonly ApplicationScopeDecl[];
343
- readonly exported: boolean;
344
- /** True when the source declared a parameter list, including an empty `()`. */
345
- readonly hasParameterList: boolean;
346
- readonly kind: "instrument";
347
- readonly name: IdentExpr;
348
- readonly parameters: readonly Parameter[];
349
- readonly span: Span;
350
- readonly typeParameters: readonly TypeParameter[];
351
- }
352
-
353
- /** Instantiation of an exported parameterized instrument. */
354
- export interface InstrumentApplyDecl {
355
- readonly application: ApplyExpr;
356
- /** Module-local declarations carried only while this application is bound. */
357
- readonly declarationScope?: readonly ApplicationScopeDecl[];
358
- readonly exported: boolean;
359
- readonly kind: "instrument_apply";
360
- readonly metadata?: BlockExpr;
361
- readonly name: IdentExpr;
362
- readonly span: Span;
46
+ kind: "instrument";
47
+ name: string;
48
+ parameters: Entry[];
49
+ body: Extract<Expr, { kind: "block" }>;
50
+ span: Span;
51
+ }
52
+ export interface AssignmentDecl {
53
+ kind: "assignment";
54
+ name: string;
55
+ target: string;
56
+ body: Extract<Expr, { kind: "block" }>;
57
+ span: Span;
58
+ }
59
+ export interface ObjectDecl {
60
+ kind: "object";
61
+ name: string;
62
+ title: string;
63
+ body: Extract<Expr, { kind: "block" }>;
64
+ span: Span;
363
65
  }
364
-
365
- export interface TypeDecl {
366
- readonly exported: boolean;
367
- readonly kind: "type";
368
- readonly name: IdentExpr;
369
- readonly span: Span;
370
- readonly value: Expr;
371
- }
372
-
373
- export interface ConstDecl {
374
- readonly exported: boolean;
375
- readonly kind: "const";
376
- readonly name: IdentExpr;
377
- readonly span: Span;
378
- readonly type?: Expr;
379
- readonly value: Expr;
380
- }
381
-
382
- export type ApplicationScopeDecl =
383
- | ConstDecl
384
- | InstrumentDecl
385
- | PartyDecl
386
- | PortDecl
387
- | TypeDecl;
388
-
389
66
  export type Decl =
390
- | AssetDecl
391
- | ConstDecl
392
- | ExposeDecl
393
- | ImportDecl
394
- | InstrumentApplyDecl
395
67
  | InstrumentDecl
396
- | ModuleDecl
397
- | PartyDecl
398
- | PortDecl
399
- | ProgramDecl
400
- | SubjectDecl
401
- | TypeDecl
402
- | UseDecl;
403
-
404
- // --- Program ---------------------------------------------------------------
405
-
68
+ | AssignmentDecl
69
+ | ObjectDecl
70
+ | {
71
+ kind: "party";
72
+ name: string;
73
+ partyKind: string;
74
+ role?: string;
75
+ span: Span;
76
+ }
77
+ | { kind: "use"; name: string; span: Span }
78
+ | { kind: "expose"; target: string; name: string; span: Span }
79
+ | { kind: "hide"; target: string; span: Span };
406
80
  export interface Program {
407
- readonly decls: readonly Decl[];
408
- readonly span: Span;
409
- }
410
-
411
- // --- Diagnostics -----------------------------------------------------------
412
-
413
- /**
414
- * A parse-stage problem, worded for the program's author. Parsing is total:
415
- * it never throws, it returns the best-effort tree plus these.
416
- */
417
- export interface Diagnostic {
418
- readonly code?: string;
419
- readonly fix?: string;
420
- readonly message: string;
421
- readonly span: Span;
422
- }
81
+ name: string;
82
+ title: string;
83
+ currency: string;
84
+ header: boolean;
85
+ decls: Decl[];
86
+ span: Span;
87
+ }
88
+ export const lineColAt = (source: string, offset: number) => {
89
+ const before = source.slice(0, offset);
90
+ return {
91
+ line: before.split("\n").length,
92
+ column: offset - before.lastIndexOf("\n"),
93
+ };
94
+ };
95
+ export type BlockExpr = Extract<Expr, { kind: "block" }>;
@@ -0,0 +1,103 @@
1
+ import {
2
+ subjectPartyRoles,
3
+ udlMoveSchema,
4
+ type AttachmentPartyBinding,
5
+ type SubjectPartyRole,
6
+ type UdlDocument,
7
+ type UdlInstrument,
8
+ } from "@hyperscale0/udl";
9
+ import type { Entry, Expr } from "./ast.ts";
10
+ import { fail } from "./diagnostics.ts";
11
+
12
+ /** An attachment specializes its own instrument; imported definitions stay generic. */
13
+ export function applyAttachmentEconomics(
14
+ document: UdlDocument,
15
+ instrument: UdlInstrument,
16
+ parties: Record<string, AttachmentPartyBinding>,
17
+ declarations: Entry[],
18
+ data: (expression: Expr) => unknown,
19
+ ): void {
20
+ const selected = new Set<object>();
21
+ for (const declaration of declarations) {
22
+ const selector = declaration.key.slice("economics ".length);
23
+ const [actionName, moveKey, extra] = selector.split(".");
24
+ const action = Object.hasOwn(instrument.actions, actionName!)
25
+ ? instrument.actions[actionName!]
26
+ : undefined;
27
+ if (!action)
28
+ fail(
29
+ declaration,
30
+ `unknown economics action ${actionName}`,
31
+ `choose ${instrument.actionOrder.join(", ")}, before its public alias`,
32
+ );
33
+ const move = moveKey
34
+ ? action.moves.find((move) => move.key === moveKey)
35
+ : action.moves.length === 1
36
+ ? action.moves[0]
37
+ : undefined;
38
+ if (!move || extra)
39
+ fail(
40
+ declaration,
41
+ `economics ${selector} must select one money move`,
42
+ action.moves.length
43
+ ? `choose ${action.moves.map((move) => `${actionName}.${move.key}`).join(", ")}`
44
+ : "choose an action that transfers or reserves money",
45
+ );
46
+ if (move.operation === "internal_transfer.void")
47
+ fail(
48
+ declaration,
49
+ `economics ${selector} cannot classify a void`,
50
+ "declare the purpose on the reservation or its posting",
51
+ );
52
+ if (selected.has(move))
53
+ fail(
54
+ declaration,
55
+ `repeated economics for ${selector}`,
56
+ "declare each money move's purpose once",
57
+ );
58
+ selected.add(move);
59
+ const parsed = udlMoveSchema.safeParse({
60
+ ...move,
61
+ economics: data(declaration.value),
62
+ });
63
+ if (!parsed.success || !parsed.data.economics)
64
+ fail(
65
+ declaration,
66
+ `invalid economics for ${selector}`,
67
+ "declare purpose and sourceParty using the move economics fields",
68
+ );
69
+ const economics = parsed.data.economics;
70
+ if (
71
+ move.economics &&
72
+ (move.economics.purpose !== economics.purpose ||
73
+ move.economics.sourceParty !== economics.sourceParty ||
74
+ move.economics.reversalOf !== economics.reversalOf)
75
+ )
76
+ fail(
77
+ declaration,
78
+ `economics ${selector} conflicts with the instrument's declared purpose`,
79
+ "keep the instrument's economics or choose an unclassified move",
80
+ );
81
+ const source = economics.sourceParty;
82
+ const role = subjectPartyRoles.includes(source as SubjectPartyRole);
83
+ if (!role && document.parties[source]?.kind !== "business")
84
+ fail(
85
+ declaration,
86
+ `unknown economic source party ${source}`,
87
+ "bind sourceParty to owner, actor, operator or a declared business",
88
+ );
89
+ if (
90
+ !Object.values(parties).some((binding) =>
91
+ "role" in binding ? binding.role === source : binding.party === source,
92
+ )
93
+ ) {
94
+ let key = "economicSource";
95
+ for (let index = 2; Object.hasOwn(parties, key); index++)
96
+ key = `economicSource${index}`;
97
+ parties[key] = role
98
+ ? { role: source as SubjectPartyRole }
99
+ : { party: source };
100
+ }
101
+ move.economics = economics;
102
+ }
103
+ }