@hyperscale0/hsx 2.1.0 → 2.2.0
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.
- package/CHANGELOG.md +36 -7
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +39 -5
- package/dist/src/cli.js.map +1 -1
- package/dist/src/compile.d.ts +0 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +15 -1
- package/dist/src/compile.js.map +1 -1
- package/dist/src/cost.d.ts +3 -3
- package/dist/src/cost.d.ts.map +1 -1
- package/dist/src/cost.js +22 -12
- package/dist/src/cost.js.map +1 -1
- package/dist/src/parse.d.ts.map +1 -1
- package/dist/src/parse.js +10 -14
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.d.ts.map +1 -1
- package/dist/src/std-bundle.js +20 -84
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/typecheck.d.ts.map +1 -1
- package/dist/src/typecheck.js +171 -39
- package/dist/src/typecheck.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.md +8 -2
- package/docs/guide/01-first-program.md +1 -1
- package/docs/guide/06-schedules.md +5 -1
- package/docs/guide/08-writing-a-module.md +48 -0
- package/docs/llms-full.txt +1928 -421
- package/docs/llms.txt +2 -3
- package/docs/piece-plans.md +120 -0
- package/docs/reference/cli.md +6 -5
- package/docs/reference/diagnostics.md +9 -9
- package/docs/reference/grammar.md +2 -3
- package/docs/reference/std/advance.md +94 -17
- package/docs/reference/std/cancellable_booking.md +138 -17
- package/docs/reference/std/captured_payment.md +96 -24
- package/docs/reference/std/conditional_disbursement.md +82 -14
- package/docs/reference/std/credit_facility.md +89 -16
- package/docs/reference/std/held_payment.md +155 -55
- package/docs/reference/std/instant_transfer.md +79 -12
- package/docs/reference/std/metered.md +71 -9
- package/docs/reference/std/pooled_split.md +76 -7
- package/docs/reference/std/premium_forward.md +100 -20
- package/docs/reference/std/reconciled_payout.md +84 -14
- package/docs/reference/std/rotating_pool.md +112 -24
- package/docs/reference/std/scheduled.md +117 -32
- package/docs/reference/std/security_deposit.md +119 -27
- package/docs/reference/std/settlement_batch.md +105 -24
- package/docs/reference/std/swap.md +113 -26
- package/docs/reference/std/threshold_pool.md +120 -29
- package/docs/reference/std/weighted_distribution.md +117 -21
- package/docs/reference/types.md +15 -15
- package/docs/reference/udl-output.md +6 -6
- package/examples/01-first-program/README.md +1 -1
- package/examples/{02-imports-and-archetypes → 02-imports-and-modules}/README.md +1 -1
- package/examples/{02-imports-and-archetypes → 02-imports-and-modules}/photo-booth.hsx +1 -1
- package/examples/04-complete-product/README.md +1 -1
- package/examples/05-authored-instrument/README.md +5 -0
- package/examples/05-authored-instrument/payment.hsx +37 -0
- package/examples/05-watch-club/watch-club.hsx +0 -1
- package/examples/README.md +1 -2
- package/examples/advance/advance.udl +29 -6
- package/examples/cancellable_booking/cancellable_booking.udl +19 -0
- package/examples/captured_payment/captured_payment.hsx +0 -4
- package/examples/captured_payment/captured_payment.udl +6 -0
- package/examples/conditional_disbursement/conditional_disbursement.hsx +0 -2
- package/examples/conditional_disbursement/conditional_disbursement.udl +4 -0
- package/examples/cost-table.json +136 -8
- package/examples/credit_facility/credit_facility.hsx +0 -3
- package/examples/credit_facility/credit_facility.udl +17 -1
- package/examples/held_payment/held_payment.udl +16 -0
- package/examples/instant_transfer/instant_transfer.udl +6 -0
- package/examples/metered/metered.udl +5 -1
- package/examples/pooled_split/pooled_split.udl +4 -0
- package/examples/premium_forward/premium_forward.udl +4 -0
- package/examples/reconciled_payout/reconciled_payout.udl +7 -0
- package/examples/rotating_pool/rotating_pool.udl +8 -0
- package/examples/scheduled/scheduled.udl +18 -3
- package/examples/security_deposit/security_deposit.udl +13 -0
- package/examples/settlement_batch/settlement_batch.udl +4 -0
- package/examples/swap/swap.udl +10 -0
- package/examples/threshold_pool/threshold_pool.udl +11 -0
- package/examples/weighted_distribution/weighted_distribution.udl +9 -0
- package/package.json +10 -10
- package/skills/hsx/SKILL.md +2 -36
- package/src/cli.ts +41 -5
- package/src/compile.ts +14 -6
- package/src/cost.ts +13 -16
- package/src/parse.ts +15 -10
- package/src/std-bundle.ts +21 -88
- package/src/typecheck.ts +207 -34
- package/src/version.ts +1 -1
- package/std/SEMANTICS.md +33 -128
- package/std/money_flows/advance.hsx +39 -26
- package/std/money_flows/cancellable_booking.hsx +275 -8
- package/std/money_flows/captured_payment.hsx +1 -9
- package/std/money_flows/conditional_disbursement.hsx +0 -6
- package/std/money_flows/credit_facility.hsx +0 -9
- package/std/money_flows/held_payment.hsx +39 -1
- package/std/money_flows/index.hsx +2 -1
- package/std/money_flows/metered.hsx +1 -5
- package/std/money_flows/scheduled.hsx +29 -119
- package/std/money_flows/threshold_pool.hsx +40 -5
- package/std/money_flows/weighted_distribution.hsx +47 -5
- package/docs/reference/std/recurring_collection.md +0 -25
- package/examples/recurring_collection/README.md +0 -3
- package/examples/recurring_collection/recurring_collection.hsx +0 -21
- package/examples/recurring_collection/recurring_collection.udl +0 -1135
- package/std/money_flows/recurring_collection.hsx +0 -72
|
@@ -296,6 +296,19 @@
|
|
|
296
296
|
"currency"
|
|
297
297
|
],
|
|
298
298
|
"summary": "Refundable deposit from renter held for owner",
|
|
299
|
+
"templateBinding": {
|
|
300
|
+
"id": "security_deposit",
|
|
301
|
+
"parameters": {
|
|
302
|
+
"claimCapture": false,
|
|
303
|
+
"claimInput": false,
|
|
304
|
+
"claimTo": false,
|
|
305
|
+
"deadline": false,
|
|
306
|
+
"fundFailurePoint": false,
|
|
307
|
+
"idPrefixOverride": false,
|
|
308
|
+
"memo": false,
|
|
309
|
+
"returnTo": false
|
|
310
|
+
}
|
|
311
|
+
},
|
|
299
312
|
"title": "Security deposit"
|
|
300
313
|
}
|
|
301
314
|
],
|
package/examples/swap/swap.udl
CHANGED
|
@@ -871,6 +871,16 @@
|
|
|
871
871
|
"currency"
|
|
872
872
|
],
|
|
873
873
|
"summary": "Two-party atomic trade between buyer and seller",
|
|
874
|
+
"templateBinding": {
|
|
875
|
+
"id": "swap",
|
|
876
|
+
"parameters": {
|
|
877
|
+
"actionBindings": false,
|
|
878
|
+
"fixedPrefix": false,
|
|
879
|
+
"lifecycleStateOrder": false,
|
|
880
|
+
"parkedStates": false,
|
|
881
|
+
"sideNames": false
|
|
882
|
+
}
|
|
883
|
+
},
|
|
874
884
|
"title": "Exchange"
|
|
875
885
|
}
|
|
876
886
|
],
|
|
@@ -219,6 +219,17 @@
|
|
|
219
219
|
"maxContributors"
|
|
220
220
|
],
|
|
221
221
|
"summary": "Threshold contribution pool for company",
|
|
222
|
+
"templateBinding": {
|
|
223
|
+
"id": "threshold_pool",
|
|
224
|
+
"parameters": {
|
|
225
|
+
"beneficiaryAccount": false,
|
|
226
|
+
"contributionInstrument": false,
|
|
227
|
+
"fundingJoin": false,
|
|
228
|
+
"maxContributors": 100,
|
|
229
|
+
"memo": false,
|
|
230
|
+
"wording": false
|
|
231
|
+
}
|
|
232
|
+
},
|
|
222
233
|
"title": "Round"
|
|
223
234
|
},
|
|
224
235
|
{
|
|
@@ -130,6 +130,15 @@
|
|
|
130
130
|
"maxRecipients"
|
|
131
131
|
],
|
|
132
132
|
"summary": "Frozen largest-remainder distribution",
|
|
133
|
+
"templateBinding": {
|
|
134
|
+
"id": "weighted_distribution",
|
|
135
|
+
"parameters": {
|
|
136
|
+
"flat": false,
|
|
137
|
+
"idPrefixOverride": false,
|
|
138
|
+
"maxRecipients": 12,
|
|
139
|
+
"receipts": false
|
|
140
|
+
}
|
|
141
|
+
},
|
|
133
142
|
"title": "Proceeds"
|
|
134
143
|
},
|
|
135
144
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperscale0/hsx",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "The strictly typed HSX language: compile total financial programs into canonical UDL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hsx",
|
|
@@ -70,22 +70,22 @@
|
|
|
70
70
|
"access": "public"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
|
-
"build": "tsc -p tsconfig.build.json",
|
|
74
|
-
"check": "bun
|
|
75
|
-
"docs:build": "bun scripts/docs/build.ts",
|
|
76
|
-
"docs:check": "bun scripts/docs/check.ts",
|
|
73
|
+
"build": "bun run generate && tsc -p tsconfig.build.json",
|
|
74
|
+
"check": "bun run generate && bun test && bun run playground:check && tsc -p tsconfig.json && bun run build && bun scripts/check-bin.ts",
|
|
75
|
+
"docs:build": "bun scripts/docs/build.ts && bun scripts/docs/check.ts",
|
|
77
76
|
"examples:build": "bun scripts/examples/build.ts",
|
|
78
77
|
"playground:build": "bun scripts/build-playground.ts",
|
|
79
78
|
"playground:check": "bun scripts/build-playground.ts --check",
|
|
80
79
|
"postpack": "bun scripts/pack-exports.ts restore",
|
|
81
80
|
"prepack": "bun run build && bun scripts/pack-exports.ts apply",
|
|
82
81
|
"std:bundle": "bun scripts/bundle-std.ts",
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
82
|
+
"test": "bun run generate && bun test",
|
|
83
|
+
"typecheck": "bun run generate && tsc -p tsconfig.json",
|
|
84
|
+
"prepare": "bun run std:bundle",
|
|
85
|
+
"generate": "bun run std:bundle && bun run docs:build && bun run playground:build"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@hyperscale0/udl": "2.
|
|
88
|
+
"@hyperscale0/udl": "2.4.0"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"bun-types": "1.4.2",
|
|
@@ -96,5 +96,5 @@
|
|
|
96
96
|
"Amir Ayub",
|
|
97
97
|
"Sara AlBakaawi"
|
|
98
98
|
],
|
|
99
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "b2d3d1954db0038f654894b1be983ad2bae7c2d0"
|
|
100
100
|
}
|
package/skills/hsx/SKILL.md
CHANGED
|
@@ -23,7 +23,6 @@ Choose the module whose lifecycle and money path already match the product. Do n
|
|
|
23
23
|
- `cancellable_booking` quotes a cancellation penalty before commitment.
|
|
24
24
|
- `captured_payment` reserves, captures, settles, voids, or corrects a payment.
|
|
25
25
|
- `scheduled` expands finite installments or a bounded obligation.
|
|
26
|
-
- `recurring_collection` records collection periods.
|
|
27
26
|
- `advance` disburses now against finite repayment or a referenced release.
|
|
28
27
|
- `credit_facility` controls draws against a referenced obligation.
|
|
29
28
|
- `conditional_disbursement` releases a capped amount on stored evidence.
|
|
@@ -107,10 +106,6 @@ settlement card_payment = captured_payment {
|
|
|
107
106
|
reserve_until: reserveUntil
|
|
108
107
|
correction: port correct_capture
|
|
109
108
|
external_reversal: port reverse_capture within P14D
|
|
110
|
-
capture_mode: partial_then_full
|
|
111
|
-
correction_mode: full_only
|
|
112
|
-
negative_position: reject
|
|
113
|
-
timeout: reject
|
|
114
109
|
}
|
|
115
110
|
port correct_capture { allowed: [payee] }
|
|
116
111
|
port reverse_capture {
|
|
@@ -132,8 +127,6 @@ settlement claim_payment = conditional_disbursement {
|
|
|
132
127
|
cap: policyLimit: money(SAR)
|
|
133
128
|
amount: approvedAmount: money(SAR)
|
|
134
129
|
decision: port approve_claim
|
|
135
|
-
reopen_policy: refuse
|
|
136
|
-
recovery_policy: separate_transfer
|
|
137
130
|
}
|
|
138
131
|
port approve_claim {
|
|
139
132
|
allowed: [source]
|
|
@@ -167,9 +160,6 @@ settlement facility = credit_facility {
|
|
|
167
160
|
limit: facilityLimit: money(SAR)
|
|
168
161
|
expires_at: expiresAt
|
|
169
162
|
obligation: repayment.obligation
|
|
170
|
-
availability_policy: revolving
|
|
171
|
-
expiry_policy: freeze_draws
|
|
172
|
-
close_policy: no_open_draws
|
|
173
163
|
}
|
|
174
164
|
```
|
|
175
165
|
|
|
@@ -339,32 +329,6 @@ settlement supplier_payout = reconciled_payout {
|
|
|
339
329
|
}
|
|
340
330
|
```
|
|
341
331
|
|
|
342
|
-
<!-- hsx-brick: recurring_collection -->
|
|
343
|
-
|
|
344
|
-
```hsx
|
|
345
|
-
program recurring_collection_example "Recurring collection example"
|
|
346
|
-
import { recurring_collection, scheduled } from "std/money_flows"
|
|
347
|
-
party debtor: person
|
|
348
|
-
party repayment_source: business
|
|
349
|
-
party recipient: business
|
|
350
|
-
settlement obligation = scheduled {
|
|
351
|
-
mode: obligation
|
|
352
|
-
payer: repayment_source
|
|
353
|
-
payee: recipient
|
|
354
|
-
debtor: debtor
|
|
355
|
-
amount: principal: money(SAR)
|
|
356
|
-
count: 2
|
|
357
|
-
every: P30D
|
|
358
|
-
first_due: firstDueAt
|
|
359
|
-
mandate: port mandate_evidence
|
|
360
|
-
}
|
|
361
|
-
settlement collection = recurring_collection {}
|
|
362
|
-
port mandate_evidence {
|
|
363
|
-
allowed: [repayment_source]
|
|
364
|
-
shape: { evidenceReference: text }
|
|
365
|
-
}
|
|
366
|
-
```
|
|
367
|
-
|
|
368
332
|
<!-- hsx-brick: rotating_pool -->
|
|
369
333
|
|
|
370
334
|
```hsx
|
|
@@ -481,3 +445,5 @@ port snapshot_entitlements {
|
|
|
481
445
|
## Output boundary
|
|
482
446
|
|
|
483
447
|
Use `compile` or the Hyperscale CLI to obtain canonical UDL, the origin map, and the cost manifest. The engine reads UDL and never HSX. When a task needs direct UDL work, use the UDL skill instead.
|
|
448
|
+
|
|
449
|
+
Programs that `use` published instruments need the selected catalogue when checked outside the engine: `hsx check --strict --catalog catalog.udl company.hsx`. Obtain that canonical UDL from the catalogue publisher. The CLI does not fetch or choose a revision.
|
package/src/cli.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* asserting on a subprocess's scrollback.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { parseUdl, type UdlDocument } from "@hyperscale0/udl";
|
|
13
14
|
import { fileURLToPath } from "node:url";
|
|
14
15
|
import { compile, type CompileResult } from "./compile.ts";
|
|
15
16
|
import type { UdlCostManifest, UdlCostTables } from "./cost.ts";
|
|
@@ -39,9 +40,9 @@ const USAGE = 2;
|
|
|
39
40
|
export const USAGE_TEXT = `hsx ${HSX_VERSION}, the HSX compiler
|
|
40
41
|
|
|
41
42
|
Usage:
|
|
42
|
-
hsx check <file.hsx> [--strict]
|
|
43
|
-
hsx build <file.hsx> [--out <file.json>] [--strict]
|
|
44
|
-
hsx cost <file.hsx> [--json] [--out <file.json>] [--strict]
|
|
43
|
+
hsx check <file.hsx> [--catalog <catalog.udl>] [--strict]
|
|
44
|
+
hsx build <file.hsx> [--catalog <catalog.udl>] [--out <file.json>] [--strict]
|
|
45
|
+
hsx cost <file.hsx> [--catalog <catalog.udl>] [--json] [--out <file.json>] [--strict]
|
|
45
46
|
hsx explain <HSX####>
|
|
46
47
|
hsx format <file.hsx>
|
|
47
48
|
hsx lsp
|
|
@@ -57,6 +58,7 @@ Commands:
|
|
|
57
58
|
lsp Run the language server over stdin and stdout.
|
|
58
59
|
|
|
59
60
|
Options:
|
|
61
|
+
--catalog <file> Read the published instrument catalogue as canonical UDL JSON.
|
|
60
62
|
--json Print the cost manifest as JSON instead of a table.
|
|
61
63
|
--out <file> Write build or cost JSON to this path instead of stdout.
|
|
62
64
|
--strict Treat warning-severity diagnostics as failures.
|
|
@@ -134,7 +136,21 @@ export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
|
134
136
|
io.err(`hsx: cannot read the packaged cost table: ${messageOf(cause)}`);
|
|
135
137
|
return USAGE;
|
|
136
138
|
}
|
|
137
|
-
|
|
139
|
+
let publishedCatalog: UdlDocument | undefined;
|
|
140
|
+
if (parsed.catalog !== undefined) {
|
|
141
|
+
try {
|
|
142
|
+
publishedCatalog = parseUdl(await io.readFile(parsed.catalog));
|
|
143
|
+
} catch (cause) {
|
|
144
|
+
io.err(
|
|
145
|
+
`hsx: cannot read catalogue ${parsed.catalog}: ${messageOf(cause)}`,
|
|
146
|
+
);
|
|
147
|
+
return USAGE;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const result = compile(source, {
|
|
151
|
+
costTable,
|
|
152
|
+
...(publishedCatalog === undefined ? {} : { publishedCatalog }),
|
|
153
|
+
});
|
|
138
154
|
for (const line of diagnosticLines(parsed.file, result)) io.err(line);
|
|
139
155
|
|
|
140
156
|
const refused =
|
|
@@ -174,6 +190,7 @@ export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
|
174
190
|
}
|
|
175
191
|
|
|
176
192
|
interface Options {
|
|
193
|
+
readonly catalog?: string;
|
|
177
194
|
readonly file: string;
|
|
178
195
|
readonly json: boolean;
|
|
179
196
|
readonly out?: string;
|
|
@@ -185,6 +202,7 @@ function parseOptions(
|
|
|
185
202
|
command: "build" | "check" | "cost" | "format",
|
|
186
203
|
): Options | { readonly error: string } {
|
|
187
204
|
let file: string | undefined;
|
|
205
|
+
let catalog: string | undefined;
|
|
188
206
|
let json = false;
|
|
189
207
|
let out: string | undefined;
|
|
190
208
|
let strict = false;
|
|
@@ -203,6 +221,18 @@ function parseOptions(
|
|
|
203
221
|
json = true;
|
|
204
222
|
continue;
|
|
205
223
|
}
|
|
224
|
+
if (argument === "--catalog") {
|
|
225
|
+
if (command === "format")
|
|
226
|
+
return { error: "--catalog belongs to check, build or cost" };
|
|
227
|
+
const value = args[index + 1];
|
|
228
|
+
if (value === undefined || value.startsWith("--"))
|
|
229
|
+
return { error: "--catalog needs a file path" };
|
|
230
|
+
if (catalog !== undefined)
|
|
231
|
+
return { error: "--catalog may be supplied only once" };
|
|
232
|
+
catalog = value;
|
|
233
|
+
index += 1;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
206
236
|
if (argument === "--out") {
|
|
207
237
|
if (command !== "build" && command !== "cost") {
|
|
208
238
|
return { error: "--out belongs to hsx build or hsx cost" };
|
|
@@ -225,7 +255,13 @@ function parseOptions(
|
|
|
225
255
|
}
|
|
226
256
|
|
|
227
257
|
if (file === undefined) return { error: `hsx ${command} needs a file` };
|
|
228
|
-
return {
|
|
258
|
+
return {
|
|
259
|
+
file,
|
|
260
|
+
json,
|
|
261
|
+
...(catalog === undefined ? {} : { catalog }),
|
|
262
|
+
...(out === undefined ? {} : { out }),
|
|
263
|
+
strict,
|
|
264
|
+
};
|
|
229
265
|
}
|
|
230
266
|
|
|
231
267
|
function explainDiagnostic(args: readonly string[], io: Io): number {
|
package/src/compile.ts
CHANGED
|
@@ -66,7 +66,6 @@ interface CompileArtifacts {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export interface CompileOptions extends HsxCompilerHost {
|
|
69
|
-
readonly composesCatalogBlueprint?: boolean;
|
|
70
69
|
/** One table, or one per billing currency; the program's money fields pick. */
|
|
71
70
|
readonly costTable?: UdlCostTables;
|
|
72
71
|
}
|
|
@@ -136,6 +135,19 @@ export function compile(
|
|
|
136
135
|
});
|
|
137
136
|
};
|
|
138
137
|
|
|
138
|
+
const optionKeys = new Set([
|
|
139
|
+
"costTable",
|
|
140
|
+
"moduleName",
|
|
141
|
+
"publishedCatalog",
|
|
142
|
+
"resolveModule",
|
|
143
|
+
"standardLibrary",
|
|
144
|
+
]);
|
|
145
|
+
for (const key of Object.keys(options)) {
|
|
146
|
+
if (optionKeys.has(key)) continue;
|
|
147
|
+
at("bind", "error", `unknown compile option ${key}`, { start: 0, end: 0 });
|
|
148
|
+
}
|
|
149
|
+
if (diagnostics.length > 0) return { diagnostics, verdict: "invalid" };
|
|
150
|
+
|
|
139
151
|
const parsed = parseProgram(source);
|
|
140
152
|
for (const diagnostic of parsed.diagnostics) {
|
|
141
153
|
at(
|
|
@@ -185,11 +197,7 @@ export function compile(
|
|
|
185
197
|
);
|
|
186
198
|
}
|
|
187
199
|
if (!checked.program) return { diagnostics, verdict: "invalid" };
|
|
188
|
-
const cost = buildCostManifest(
|
|
189
|
-
checked.program,
|
|
190
|
-
options.costTable,
|
|
191
|
-
options.composesCatalogBlueprint ?? false,
|
|
192
|
-
);
|
|
200
|
+
const cost = buildCostManifest(checked.program, options.costTable);
|
|
193
201
|
if (!cost.ok) {
|
|
194
202
|
for (const diagnostic of cost.diagnostics) {
|
|
195
203
|
at(
|
package/src/cost.ts
CHANGED
|
@@ -90,7 +90,6 @@ export type CostManifestResult =
|
|
|
90
90
|
export function buildCostManifest(
|
|
91
91
|
program: TypedProgram,
|
|
92
92
|
tables: UdlCostTables | undefined,
|
|
93
|
-
composesCatalogBlueprint: boolean,
|
|
94
93
|
): CostManifestResult {
|
|
95
94
|
const priced = tables === undefined ? [] : [tables].flat();
|
|
96
95
|
if (priced.length === 0) {
|
|
@@ -164,7 +163,7 @@ export function buildCostManifest(
|
|
|
164
163
|
}
|
|
165
164
|
}
|
|
166
165
|
const fixed = fixedCost(
|
|
167
|
-
typedStructuralCounts(program
|
|
166
|
+
typedStructuralCounts(program),
|
|
168
167
|
table,
|
|
169
168
|
program.origin,
|
|
170
169
|
diagnostics,
|
|
@@ -222,11 +221,10 @@ function ledgerCostTable(
|
|
|
222
221
|
export function computeUdlFixedCost(
|
|
223
222
|
document: UdlDocument,
|
|
224
223
|
table: UdlCostTable,
|
|
225
|
-
composesCatalogBlueprint: boolean,
|
|
226
224
|
): UdlCostManifest["fixed"] {
|
|
227
225
|
const diagnostics: GeneralDiagnostic[] = [];
|
|
228
226
|
const fixed = fixedCost(
|
|
229
|
-
udlStructuralCounts(document
|
|
227
|
+
udlStructuralCounts(document),
|
|
230
228
|
table,
|
|
231
229
|
{ start: 0, end: 0 },
|
|
232
230
|
diagnostics,
|
|
@@ -238,7 +236,6 @@ export function computeUdlFixedCost(
|
|
|
238
236
|
export function buildUdlCostManifest(
|
|
239
237
|
document: UdlDocument,
|
|
240
238
|
table: UdlCostTable,
|
|
241
|
-
composesCatalogBlueprint: boolean,
|
|
242
239
|
): UdlCostManifest {
|
|
243
240
|
if (!CURRENCY.test(table.currency)) {
|
|
244
241
|
throw new Error(
|
|
@@ -286,11 +283,7 @@ export function buildUdlCostManifest(
|
|
|
286
283
|
);
|
|
287
284
|
}
|
|
288
285
|
}
|
|
289
|
-
return manifest(
|
|
290
|
-
table,
|
|
291
|
-
computeUdlFixedCost(document, table, composesCatalogBlueprint),
|
|
292
|
-
actions,
|
|
293
|
-
);
|
|
286
|
+
return manifest(table, computeUdlFixedCost(document, table), actions);
|
|
294
287
|
}
|
|
295
288
|
|
|
296
289
|
export function evaluateUdlCostManifest(
|
|
@@ -473,6 +466,16 @@ function fixedCost(
|
|
|
473
466
|
): UdlCostManifest["fixed"] {
|
|
474
467
|
const components: UdlCostManifest["fixed"]["components"][number][] = [];
|
|
475
468
|
let complexityScore = 0;
|
|
469
|
+
for (const weight of Object.keys(table.fixed.weights)) {
|
|
470
|
+
if (Object.hasOwn(counts, weight)) continue;
|
|
471
|
+
diagnostics.push({
|
|
472
|
+
code: "HSX1302",
|
|
473
|
+
fix: `remove the unknown ${weight} weight from cost table ${table.version}`,
|
|
474
|
+
message: `cost table ${table.version} has an unknown ${weight} complexity weight`,
|
|
475
|
+
severity: "error",
|
|
476
|
+
span,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
476
479
|
for (const [weight, count] of Object.entries(counts)) {
|
|
477
480
|
if (count === 0) continue;
|
|
478
481
|
const value = table.fixed.weights[weight];
|
|
@@ -518,7 +521,6 @@ function fixedCost(
|
|
|
518
521
|
|
|
519
522
|
function typedStructuralCounts(
|
|
520
523
|
program: TypedProgram,
|
|
521
|
-
blueprint: boolean,
|
|
522
524
|
): Readonly<Record<string, number>> {
|
|
523
525
|
const subjectKinds = new Set<string>();
|
|
524
526
|
const decisions = new Set<string>();
|
|
@@ -562,13 +564,11 @@ function typedStructuralCounts(
|
|
|
562
564
|
aggregate,
|
|
563
565
|
gate,
|
|
564
566
|
timer,
|
|
565
|
-
blueprint,
|
|
566
567
|
);
|
|
567
568
|
}
|
|
568
569
|
|
|
569
570
|
function udlStructuralCounts(
|
|
570
571
|
document: UdlDocument,
|
|
571
|
-
blueprint: boolean,
|
|
572
572
|
): Readonly<Record<string, number>> {
|
|
573
573
|
const subjectKinds = new Set<string>();
|
|
574
574
|
const decisions = new Set<string>();
|
|
@@ -611,7 +611,6 @@ function udlStructuralCounts(
|
|
|
611
611
|
aggregate,
|
|
612
612
|
gate,
|
|
613
613
|
timer,
|
|
614
|
-
blueprint,
|
|
615
614
|
);
|
|
616
615
|
}
|
|
617
616
|
|
|
@@ -625,7 +624,6 @@ function countRecord(
|
|
|
625
624
|
aggregateInvariant: number,
|
|
626
625
|
gate: number,
|
|
627
626
|
timer: number,
|
|
628
|
-
blueprint: boolean,
|
|
629
627
|
): Readonly<Record<string, number>> {
|
|
630
628
|
return {
|
|
631
629
|
instrument,
|
|
@@ -637,7 +635,6 @@ function countRecord(
|
|
|
637
635
|
aggregate_invariant: aggregateInvariant,
|
|
638
636
|
gate,
|
|
639
637
|
timer,
|
|
640
|
-
blueprint: blueprint ? 1 : 0,
|
|
641
638
|
};
|
|
642
639
|
}
|
|
643
640
|
|
package/src/parse.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { udlClauseVocabulary } from "@hyperscale0/udl";
|
|
2
|
+
|
|
3
|
+
const compoundClauseHeads = new Set(
|
|
4
|
+
udlClauseVocabulary
|
|
5
|
+
.filter((clause) => clause.spelling.includes(" "))
|
|
6
|
+
.map((clause) => clause.spelling.split(" ")[0]),
|
|
7
|
+
);
|
|
8
|
+
|
|
1
9
|
/**
|
|
2
10
|
* The HSX parser. Recursive descent over the lexer's token stream, total:
|
|
3
11
|
* it always returns a best-effort `Program` plus diagnostics, recovering at
|
|
@@ -495,15 +503,15 @@ class Parser {
|
|
|
495
503
|
if (
|
|
496
504
|
!this.expectPunct(
|
|
497
505
|
"=",
|
|
498
|
-
`settlement ${name.name} instantiates
|
|
506
|
+
`settlement ${name.name} instantiates a module: settlement ${name.name} = held_payment { ... }`,
|
|
499
507
|
)
|
|
500
508
|
) {
|
|
501
509
|
return undefined;
|
|
502
510
|
}
|
|
503
|
-
const
|
|
504
|
-
`expected
|
|
511
|
+
const moduleName = this.expectIdent(
|
|
512
|
+
`expected a module name for settlement ${name.name}`,
|
|
505
513
|
);
|
|
506
|
-
if (!
|
|
514
|
+
if (!moduleName) return undefined;
|
|
507
515
|
if (!this.atPunct("{")) {
|
|
508
516
|
this.error(
|
|
509
517
|
this.peek().span,
|
|
@@ -521,9 +529,9 @@ class Parser {
|
|
|
521
529
|
span: row.value.span,
|
|
522
530
|
type: row.value,
|
|
523
531
|
})),
|
|
524
|
-
callee: { kind: "path", parts: [
|
|
532
|
+
callee: { kind: "path", parts: [moduleName], span: moduleName.span },
|
|
525
533
|
kind: "apply",
|
|
526
|
-
span: { start:
|
|
534
|
+
span: { start: moduleName.span.start, end: body.span.end },
|
|
527
535
|
typeArgs: [],
|
|
528
536
|
},
|
|
529
537
|
exported: false,
|
|
@@ -807,10 +815,7 @@ class Parser {
|
|
|
807
815
|
}
|
|
808
816
|
}
|
|
809
817
|
|
|
810
|
-
if (
|
|
811
|
-
(key.name === "requires" || key.name === "computes") &&
|
|
812
|
-
this.isName(this.peek())
|
|
813
|
-
) {
|
|
818
|
+
if (compoundClauseHeads.has(key.name) && this.isName(this.peek())) {
|
|
814
819
|
while (this.isName(this.peek())) qualifiers.push(this.parseIdent());
|
|
815
820
|
}
|
|
816
821
|
|