@hyperscale0/hsx 5.2.0 → 5.4.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 +40 -0
- package/README.md +2 -2
- package/bin/hsx.ts +0 -2
- package/dist/bin/hsx.js +0 -2
- package/dist/bin/hsx.js.map +1 -1
- package/dist/src/ast.d.ts +0 -1
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast.js +0 -11
- package/dist/src/ast.js.map +1 -1
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +10 -5
- package/dist/src/cli.js.map +1 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +204 -107
- package/dist/src/compile.js.map +1 -1
- package/dist/src/diagnostics.d.ts +14 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +20 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/header-source.d.ts +3 -0
- package/dist/src/header-source.d.ts.map +1 -0
- package/dist/src/header-source.js +41 -0
- package/dist/src/header-source.js.map +1 -0
- package/dist/src/headers.d.ts.map +1 -1
- package/dist/src/headers.js +4 -6
- package/dist/src/headers.js.map +1 -1
- package/dist/src/keywords.d.ts +8 -2
- package/dist/src/keywords.d.ts.map +1 -1
- package/dist/src/keywords.js +13 -5
- package/dist/src/keywords.js.map +1 -1
- package/dist/src/lex.d.ts +1 -1
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lex.js +11 -3
- package/dist/src/lex.js.map +1 -1
- package/dist/src/parse.d.ts.map +1 -1
- package/dist/src/parse.js +22 -5
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.js +12 -12
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/tunables.d.ts.map +1 -1
- package/dist/src/tunables.js +2 -1
- package/dist/src/tunables.js.map +1 -1
- package/dist/src/version.d.ts +1 -2
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -2
- package/dist/src/version.js.map +1 -1
- package/docs/README.md +54 -7
- package/docs/headers.md +1 -1
- package/package.json +3 -3
- package/src/ast.ts +0 -10
- package/src/cli.ts +13 -7
- package/src/compile.ts +296 -133
- package/src/diagnostics.ts +28 -0
- package/src/header-source.ts +54 -0
- package/src/headers.ts +4 -6
- package/src/keywords.ts +13 -5
- package/src/lex.ts +13 -5
- package/src/parse.ts +29 -5
- package/src/std-bundle.ts +12 -12
- package/src/tunables.ts +6 -1
- package/src/version.ts +1 -2
- package/std/cards.hsx +12 -0
- package/std/collections.hsx +11 -0
- package/std/escrow.hsx +16 -2
- package/std/financing.hsx +36 -5
- package/std/insurance.hsx +20 -5
- package/std/lending.hsx +14 -0
- package/std/marketplace.hsx +14 -0
- package/std/money.hsx +13 -0
- package/std/reporting.hsx +10 -0
- package/std/savings.hsx +28 -11
- package/std/travel.hsx +22 -4
- package/std/wallet.hsx +9 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,k6JAAk6J,CAAC;IACj7J,CAAC,iBAAiB,EAAE,s8LAAs8L,CAAC;IAC39L,CAAC,YAAY,EAAE,00FAA00F,CAAC;IAC11F,CAAC,eAAe,EAAE,2z0DAA2z0D,CAAC;IAC900D,CAAC,eAAe,EAAE,0+IAA0+I,CAAC;IAC7/I,CAAC,aAAa,EAAE,oyRAAoyR,CAAC;IACrzR,CAAC,iBAAiB,EAAE,y1RAAy1R,CAAC;IAC92R,CAAC,WAAW,EAAE,0yTAA0yT,CAAC;IACzzT,CAAC,eAAe,EAAE,uq9CAAuq9C,CAAC;IAC1r9C,CAAC,aAAa,EAAE,o+IAAo+I,CAAC;IACr/I,CAAC,YAAY,EAAE,s6OAAs6O,CAAC;IACt7O,CAAC,YAAY,EAAE,qjFAAqjF,CAAC;CACtkF,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunables.d.ts","sourceRoot":"","sources":["../../src/tunables.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tunables.d.ts","sourceRoot":"","sources":["../../src/tunables.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAErC,wEAAwE;AACxE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,GACT;IAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,SAAS,CA6BpE"}
|
package/dist/src/tunables.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fail } from "./diagnostics.js";
|
|
1
2
|
/** Bounds use UDL units: minor units, basis points and milliseconds. */
|
|
2
3
|
export function tunableBounds(type) {
|
|
3
4
|
const name = type.kind === "call" || type.kind === "type"
|
|
@@ -18,7 +19,7 @@ export function tunableBounds(type) {
|
|
|
18
19
|
if (numbers.length !== 2 ||
|
|
19
20
|
numbers.some((value) => !Number.isSafeInteger(value)) ||
|
|
20
21
|
numbers[0] > numbers[1])
|
|
21
|
-
|
|
22
|
+
fail(type, "integer tunable needs ordered safe integer bounds", "write integer(1, 12)");
|
|
22
23
|
return { minimum: numbers[0], maximum: numbers[1] };
|
|
23
24
|
}
|
|
24
25
|
return { minimum: 0, maximum: Number.MAX_SAFE_INTEGER };
|
package/dist/src/tunables.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunables.js","sourceRoot":"","sources":["../../src/tunables.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tunables.js","sourceRoot":"","sources":["../../src/tunables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGxC,wEAAwE;AACxE,MAAM,UAAU,aAAa,CAC3B,IAAU;IAEV,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAC1C,CAAC,CAAC,IAAI,CAAC,IAAI;QACX,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM;YACpB,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,EAAE,CAAC;IACX,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC7E,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9D,IAAI,IAAI,KAAK,UAAU;QACrB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC;IAC1D,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACpC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAChD,CAAC;QACF,IACE,OAAO,CAAC,MAAM,KAAK,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACrD,OAAO,CAAC,CAAC,CAAE,GAAG,OAAO,CAAC,CAAC,CAAE;YAEzB,IAAI,CACF,IAAI,EACJ,mDAAmD,EACnD,sBAAsB,CACvB,CAAC;QACJ,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC;AAC1D,CAAC"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAU,CAAC"}
|
package/dist/src/version.js
CHANGED
package/dist/src/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC"}
|
package/docs/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# HSX
|
|
1
|
+
# HSX
|
|
2
2
|
|
|
3
3
|
A program declares business objects and financial instruments. Objects contain
|
|
4
4
|
optional metadata. Attachments expose named actions against an object.
|
|
@@ -18,7 +18,8 @@ business, or a declared staff party with a supported role. Configure declared
|
|
|
18
18
|
business participants per Build. Declared person parties cannot bind attachments.
|
|
19
19
|
`owner` is the object's resolved customer or business, `actor` is the authenticated
|
|
20
20
|
caller, and `operator` is the program operator. A parameter with one of these
|
|
21
|
-
names binds by name. Other party parameters
|
|
21
|
+
names binds by name. Other party parameters use a same-named eligible declaration,
|
|
22
|
+
a header default, or an explicit binding. Explicit bindings take precedence.
|
|
22
23
|
Unbound parameters report `subject_party_unbound`. These bindings are frozen in
|
|
23
24
|
UDL `objects[].attachments[].parties`; no caller supplies party IDs at creation.
|
|
24
25
|
|
|
@@ -48,6 +49,9 @@ library's declared reference type. References can name a child, such as
|
|
|
48
49
|
objects of type T. `on: [plan_3, plan_6]` creates one late-charge or collections
|
|
49
50
|
policy. Its references can point into either plan; selections can span both.
|
|
50
51
|
A plain `ref<T>` accepts one object only.
|
|
52
|
+
Tunable constructors are `enum(choices)` and `integer(minimum, maximum)`.
|
|
53
|
+
Other constructors, including `party(business)` and bounded `money(...)`, are
|
|
54
|
+
rejected at the header declaration. Their arguments do not restrict bindings.
|
|
51
55
|
Imports are `use header`; there are no file imports, macros or executable strings.
|
|
52
56
|
|
|
53
57
|
Amounts use `750 SAR`; percentages use `2.5%`; durations use `48h`, `3d`, or `1w`.
|
|
@@ -77,8 +81,9 @@ same book and key within the Product. Providers remain outside parties.
|
|
|
77
81
|
A missing binding refuses before money moves. Reference paths such as
|
|
78
82
|
`self.cover.insurer` use the referenced agreement's account.
|
|
79
83
|
|
|
80
|
-
Insurance collection
|
|
81
|
-
|
|
84
|
+
Insurance collection pays the premium net of commission to the insurer account
|
|
85
|
+
and pays commission separately to the bound broker, which defaults to the operator.
|
|
86
|
+
Refunds return those two portions directly from insurer and broker to holder.
|
|
82
87
|
Claims reserve from the cover's insurer account. These moves record ledger money;
|
|
83
88
|
external confirmation still needs the boundary protocol.
|
|
84
89
|
`account(buyer, claim, contra, "debt")` declares the borrower's claim contra account.
|
|
@@ -113,7 +118,8 @@ provider confirmation, not an internal account balance change.
|
|
|
113
118
|
For a new record type, declare `instrument name { fields { ... } lifecycle { ... }
|
|
114
119
|
action create { ... } }`. Fields are `money`, `account of buyer`, `ref<order>`,
|
|
115
120
|
`date`, `duration`, `text`, `integer`, `percent`, `boolean`, `enum(a, b)` or
|
|
116
|
-
`list(date, 12)`. `?` makes a
|
|
121
|
+
`list(date, 12)`. `?` makes a plain type or `ref<T>` optional. Call types such as
|
|
122
|
+
`list(date, 12)` do not accept `?`. `= value` fixes a constant or a typed
|
|
117
123
|
calculation. Actions declare `input { reason: text }`. Headers and expert records
|
|
118
124
|
write ordered requirements and moves as expressions:
|
|
119
125
|
|
|
@@ -125,7 +131,7 @@ moves self.price from self.held to payee fee fee
|
|
|
125
131
|
```
|
|
126
132
|
|
|
127
133
|
Comparisons accept `==`, `!=`, `<`, `<=`, `>` and `>=`. A path beginning with
|
|
128
|
-
`self`, `input` or `
|
|
134
|
+
`self`, `input`, `party` or `subject` is a field operand; a quoted string, amount or number is
|
|
129
135
|
a literal. `requires unique "order" on [self.order]` fixes an identity namespace.
|
|
130
136
|
`requires count of { instrument: child, reference: "parent", anchor: self.id,
|
|
131
137
|
states: [pending], limit: 12 } == 12` checks a typed selection; `sum "amount" of`
|
|
@@ -269,7 +275,7 @@ adapters are bound, participants have funds, or the flow can finish.
|
|
|
269
275
|
| `lending.distribution` | Cash distribution needs an eligible recorded settlement, `prepare_cash`, one share record per funded commitment, then `distribute_cash`. Attaching it moves nothing. |
|
|
270
276
|
| `insurance.cover.slice` | `collect` credits premium net of commission to the insurer account. The tenant retains commission. `refund` returns both portions; claims reserve insurer funds. External settlement uses the boundary protocol. |
|
|
271
277
|
| `travel.booking` | From `deposit_paid` or `paid`, early cancellation returns the full held balance, middle returns held balance minus deposit, and late has no buyer refund transfer. State, time and balance requirements still apply. A deposit-only early cancellation refunds the deposit; a deposit-only middle cancellation refunds zero. |
|
|
272
|
-
| `financing.installments`, `savings.circle` | Supply explicit date lists when creating agreements. A term count does not generate a monthly calendar. Savings supports at most 60 distinct member
|
|
278
|
+
| `financing.installments`, `savings.circle` | Supply explicit date lists when creating agreements. A term count does not generate a monthly calendar. Savings supports at most 60 distinct member seats. |
|
|
273
279
|
| `escrow.hold` | `fund` takes the whole price. Financing into pending escrow collects the remaining down payment and adds capital principal at disbursement; `fund` is not a down-payment checkout. |
|
|
274
280
|
| `escrow.hold` | Acceptance timeout enters `disputed` without paying the seller. Delivery and return verification belong to `payee`; rebinding it also changes who receives accepted funds. |
|
|
275
281
|
| `financing.late_charge` | `fine` is a fixed money amount, not a percentage of overdue principal. |
|
|
@@ -280,3 +286,44 @@ commitment creation, and cash prepare/distribute actions. Its repayment and shar
|
|
|
280
286
|
child actions still lack a public execution path. It is a composition example,
|
|
281
287
|
not a complete public repayment flow. Callers still need dates, agreement inputs,
|
|
282
288
|
funded wallets, eligible settlements and the distribution's share records.
|
|
289
|
+
|
|
290
|
+
## Checkout and reversals
|
|
291
|
+
|
|
292
|
+
For financed checkout, expose `installments.collect_down_payment` after `create`
|
|
293
|
+
and `sign`. It credits the linked pending escrow with the missing down payment.
|
|
294
|
+
It does not disburse principal or activate the plan. The later `disburse` action
|
|
295
|
+
uses that credit before collecting any remainder. Borrower-directed financing
|
|
296
|
+
has no checkout collection action. The plan and escrow must agree on payer and
|
|
297
|
+
price.
|
|
298
|
+
|
|
299
|
+
Expose escrow `cancel` to return money credited before full funding. Plan `void`
|
|
300
|
+
cancels the signed financing agreement but does not cancel its escrow. After
|
|
301
|
+
funding and delivery, the default return path needs three separate aliases for
|
|
302
|
+
`dispute`, `verify_return` and `refund`. The payee supplies return evidence and
|
|
303
|
+
returns the full price to the payer. `accept` pays the payee instead.
|
|
304
|
+
Marketplace order fulfillment alone does not execute any of these money actions.
|
|
305
|
+
|
|
306
|
+
Expose `late_charge.create` to create an assessment with matching plan, slice
|
|
307
|
+
and borrower. Only that existing assessment can reach clock-owned `assess` after
|
|
308
|
+
grace. A payment can collect part of a fine without settling the rest. A recovery
|
|
309
|
+
cost assessment is a separate record.
|
|
310
|
+
|
|
311
|
+
## Separate payments and states
|
|
312
|
+
|
|
313
|
+
Bind `insurance.cover.broker` to the agency that receives commission. Collection
|
|
314
|
+
pays the insurer's net premium and the broker's commission as two moves. Refunds
|
|
315
|
+
reverse those same portions. The default broker is the program operator.
|
|
316
|
+
`claim.deny` accepts only `submitted`; after approval, `pay` or expiry consumes
|
|
317
|
+
the reservation.
|
|
318
|
+
|
|
319
|
+
A booking cancellation refunds only its own held cash. Expose `cover.cancel`
|
|
320
|
+
separately for eligible premium refunds before the paid period starts. Active
|
|
321
|
+
and expired premium periods are excluded. A card transaction needs a captured
|
|
322
|
+
authorization and its own record before refund, but no authorization-expiry wait.
|
|
323
|
+
|
|
324
|
+
A savings membership becomes `received` after its pot payout. Its contribution
|
|
325
|
+
records become `paid` independently. Future contributions can remain pending
|
|
326
|
+
after the member receives the pot; paying a contribution does not advance their
|
|
327
|
+
payout seat. Late contributions remain eligible while the membership is
|
|
328
|
+
`active` or `received` and the circle is `active`. These guards do not promise
|
|
329
|
+
scheduler retries or permit a payout larger than the available cash.
|
package/docs/headers.md
CHANGED
|
@@ -29,7 +29,7 @@ Bind party parameters to owner, actor, operator or declared parties. Configure d
|
|
|
29
29
|
| lending.round | `borrower: party`, `plan: ref<financing.installments> = object(financing.installments)`, `operator: party = programOperator`, `minimum_ticket: money = 100 SAR`, `investor_cap: percent = 20%`, `commitments: ref<lending.commitment> = object(lending.commitment)` |
|
|
30
30
|
| lending.commitment | `round: ref<lending.round>`, `wallet: ref<wallet.balance>`, `investor: party = party(person)` |
|
|
31
31
|
| lending.distribution | `round: ref<lending.round>`, `receipt: ref`, `commitments: ref<lending.commitment> = object(lending.commitment)`, `mode: enum(cash, loss) = cash`, `residual_to: party = programOperator`, `operator: party = programOperator`, `fee: percent = 1%`, `tax: percent = 15%` |
|
|
32
|
-
| insurance.cover | `holder: party`, `adapter: text`, `commission: percent = 0%`, `covers: ref`, `premium: money = runtime` |
|
|
32
|
+
| insurance.cover | `holder: party`, `adapter: text`, `commission: percent = 0%`, `broker: party = programOperator`, `covers: ref`, `premium: money = runtime` |
|
|
33
33
|
| insurance.claim | `cover: ref<insurance.cover>`, `inspector: party` |
|
|
34
34
|
| collections.case | `on: ref<financing.installments>[]`, `agency: party`, `capital: party = programOperator`, `overdue: duration = 3d`, `fee: percent = 20%` |
|
|
35
35
|
| collections.contact | `case: ref<collections.case>[]`, `agency: party`, `max_contacts: integer = 10`, `window: duration = 30d`, `contact_from: integer(0, 23) = 8`, `contact_until: integer(1, 23) = 20`, `timezone: text = "Asia/Riyadh"`; contact_from less_than contact_until |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperscale0/hsx",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "The strictly typed HSX language: compile total financial programs into canonical UDL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hsx",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"@hyperscale0/adl": "1.0.0-beta.8",
|
|
89
|
-
"@hyperscale0/udl": "4.
|
|
89
|
+
"@hyperscale0/udl": "4.5.0",
|
|
90
90
|
"fast-sha256": "1.3.0"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
"Amir Ayub",
|
|
99
99
|
"Sara AlBakaawi"
|
|
100
100
|
],
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "4141f2296d9427b30d04933c735be4af1ba88dec"
|
|
102
102
|
}
|
package/src/ast.ts
CHANGED
|
@@ -92,14 +92,4 @@ export const lineColAt = (source: string, offset: number) => {
|
|
|
92
92
|
column: offset - before.lastIndexOf("\n"),
|
|
93
93
|
};
|
|
94
94
|
};
|
|
95
|
-
export function byteOffsetToCodeUnit(source: string, offset: number): number {
|
|
96
|
-
let bytes = 0;
|
|
97
|
-
let units = 0;
|
|
98
|
-
for (const c of source) {
|
|
99
|
-
bytes += new TextEncoder().encode(c).length;
|
|
100
|
-
if (bytes > offset) break;
|
|
101
|
-
units += c.length;
|
|
102
|
-
}
|
|
103
|
-
return units;
|
|
104
|
-
}
|
|
105
95
|
export type BlockExpr = Extract<Expr, { kind: "block" }>;
|
package/src/cli.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { HSX_VERSION } from "./version.ts";
|
|
|
5
5
|
import { compile } from "./compile.ts";
|
|
6
6
|
import { format } from "./format.ts";
|
|
7
7
|
import { serializeUdl } from "@hyperscale0/udl";
|
|
8
|
+
const usage =
|
|
9
|
+
"hsx build|format|cost <file> [--out path]\nhsx check <file>\nhsx headers --json";
|
|
8
10
|
const standardLibrary = {
|
|
9
11
|
source: (header: string) => {
|
|
10
12
|
for (const base of ["../std/", "../../std/"]) {
|
|
@@ -20,8 +22,6 @@ export interface Io {
|
|
|
20
22
|
err(line: string): void;
|
|
21
23
|
readFile(path: string): Promise<string>;
|
|
22
24
|
writeFile(path: string, text: string): Promise<void>;
|
|
23
|
-
stdin?: NodeJS.ReadableStream;
|
|
24
|
-
stdout?: NodeJS.WritableStream;
|
|
25
25
|
}
|
|
26
26
|
export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
27
27
|
const [command, file, ...options] = argv;
|
|
@@ -34,7 +34,7 @@ export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
|
34
34
|
return 0;
|
|
35
35
|
}
|
|
36
36
|
if (["--help", "help", "-h"].includes(command ?? "")) {
|
|
37
|
-
io.out(
|
|
37
|
+
io.out(usage);
|
|
38
38
|
return 0;
|
|
39
39
|
}
|
|
40
40
|
if (command === "--version") {
|
|
@@ -46,14 +46,20 @@ export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
|
46
46
|
!file ||
|
|
47
47
|
!["build", "check", "format", "cost"].includes(command)
|
|
48
48
|
) {
|
|
49
|
-
io.err(
|
|
49
|
+
io.err(`usage:\n${usage}`);
|
|
50
50
|
return 2;
|
|
51
51
|
}
|
|
52
52
|
let output: string | undefined;
|
|
53
53
|
for (let i = 0; i < options.length; i++) {
|
|
54
|
-
if (
|
|
54
|
+
if (
|
|
55
|
+
command !== "check" &&
|
|
56
|
+
options[i] === "--out" &&
|
|
57
|
+
options[i + 1] &&
|
|
58
|
+
!options[i + 1]!.startsWith("--") &&
|
|
59
|
+
output === undefined
|
|
60
|
+
)
|
|
55
61
|
output = options[++i];
|
|
56
|
-
else
|
|
62
|
+
else {
|
|
57
63
|
io.err(`unknown option ${options[i]}`);
|
|
58
64
|
return 2;
|
|
59
65
|
}
|
|
@@ -72,7 +78,7 @@ export async function runCli(argv: readonly string[], io: Io): Promise<number> {
|
|
|
72
78
|
const result = compile(source, { standardLibrary });
|
|
73
79
|
for (const d of result.diagnostics)
|
|
74
80
|
io.err(
|
|
75
|
-
`${file}:${d.line}:${d.column}: ${d.code} ${d.message}. ${d.fix}`,
|
|
81
|
+
`${d.source && d.source !== "program" ? d.source : file}:${d.line}:${d.column}: ${d.code} ${d.message}. ${d.fix}`,
|
|
76
82
|
);
|
|
77
83
|
if (!result.artifacts || result.verdict !== "valid") return 1;
|
|
78
84
|
if (command === "check") return 0;
|