@hyperscale0/hsx 1.0.0-alpha.1
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/AUTHORS +8 -0
- package/CHANGELOG.md +59 -0
- package/LICENSE +661 -0
- package/LICENSING.md +52 -0
- package/README.md +170 -0
- package/SECURITY.md +47 -0
- package/TRADEMARKS.md +35 -0
- package/bin/hsx.ts +15 -0
- package/dist/bin/hsx.d.ts +7 -0
- package/dist/bin/hsx.d.ts.map +1 -0
- package/dist/bin/hsx.js +14 -0
- package/dist/bin/hsx.js.map +1 -0
- package/dist/src/ast.d.ts +172 -0
- package/dist/src/ast.d.ts.map +1 -0
- package/dist/src/ast.js +22 -0
- package/dist/src/ast.js.map +1 -0
- package/dist/src/check.d.ts +11 -0
- package/dist/src/check.d.ts.map +1 -0
- package/dist/src/check.js +1214 -0
- package/dist/src/check.js.map +1 -0
- package/dist/src/cli.d.ts +20 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +137 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/compile.d.ts +39 -0
- package/dist/src/compile.d.ts.map +1 -0
- package/dist/src/compile.js +59 -0
- package/dist/src/compile.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lex.d.ts +23 -0
- package/dist/src/lex.d.ts.map +1 -0
- package/dist/src/lex.js +125 -0
- package/dist/src/lex.js.map +1 -0
- package/dist/src/lower.d.ts +93 -0
- package/dist/src/lower.d.ts.map +1 -0
- package/dist/src/lower.js +2081 -0
- package/dist/src/lower.js.map +1 -0
- package/dist/src/model.d.ts +307 -0
- package/dist/src/model.d.ts.map +1 -0
- package/dist/src/model.js +15 -0
- package/dist/src/model.js.map +1 -0
- package/dist/src/parse.d.ts +19 -0
- package/dist/src/parse.d.ts.map +1 -0
- package/dist/src/parse.js +484 -0
- package/dist/src/parse.js.map +1 -0
- package/dist/src/version.d.ts +16 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +16 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +79 -0
- package/spec/hsx-ir.schema.json +522 -0
- package/src/ast.ts +231 -0
- package/src/check.ts +1699 -0
- package/src/cli.ts +173 -0
- package/src/compile.ts +98 -0
- package/src/index.ts +16 -0
- package/src/lex.ts +161 -0
- package/src/lower.ts +2619 -0
- package/src/model.ts +340 -0
- package/src/parse.ts +580 -0
- package/src/version.ts +17 -0
package/LICENSING.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Licensing
|
|
2
|
+
|
|
3
|
+
The code in this repository is Copyright 2026 Hyperscale LLC and is licensed
|
|
4
|
+
under the GNU Affero General Public License version 3 only
|
|
5
|
+
(`AGPL-3.0-only`). The full text is in [`LICENSE`](./LICENSE).
|
|
6
|
+
|
|
7
|
+
## What the AGPL asks of you
|
|
8
|
+
|
|
9
|
+
Two obligations matter in practice.
|
|
10
|
+
|
|
11
|
+
**If you distribute a copy in object form**, modified or not, you make its
|
|
12
|
+
Corresponding Source available under the same license.
|
|
13
|
+
|
|
14
|
+
**If you run a modified copy as a network service**, section 13 applies: the
|
|
15
|
+
users interacting with it over the network get an offer of the source of the
|
|
16
|
+
version you are running. Compiling HSX with an unmodified copy behind your own
|
|
17
|
+
service does not trigger this. Changing the lexer, the parser, the lowering, or
|
|
18
|
+
the emitted IR and then serving that change does.
|
|
19
|
+
|
|
20
|
+
Using `@hyperscale0/hsx` as a library inside your own program is a combined
|
|
21
|
+
work under the AGPL. If that does not fit how you ship, take the commercial
|
|
22
|
+
license instead.
|
|
23
|
+
|
|
24
|
+
## Commercial license
|
|
25
|
+
|
|
26
|
+
Hyperscale LLC sells a commercial license to organisations that cannot accept
|
|
27
|
+
the AGPL, for the usual reasons: a proprietary product that links the compiler,
|
|
28
|
+
a hosted service you will not open, a procurement policy that refuses copyleft.
|
|
29
|
+
It grants the same code under ordinary commercial terms with no source
|
|
30
|
+
obligation.
|
|
31
|
+
|
|
32
|
+
Ask through <https://hyperscale0.ai>.
|
|
33
|
+
|
|
34
|
+
## The license covers code, not marks
|
|
35
|
+
|
|
36
|
+
"Hyperscale" and "HSX" are trademarks of Hyperscale LLC. A copyright license
|
|
37
|
+
says nothing about trademarks in either direction, so
|
|
38
|
+
[`TRADEMARKS.md`](./TRADEMARKS.md) draws that boundary.
|
|
39
|
+
|
|
40
|
+
## The language is not the compiler
|
|
41
|
+
|
|
42
|
+
HSX the language and the HSX-JSON IR are separate from this compiler. The IR
|
|
43
|
+
schema in [`spec/`](./spec) and the fixtures under [`examples/`](./examples)
|
|
44
|
+
are data describing a language, and anyone may write their own compiler,
|
|
45
|
+
formatter, or runtime against them, in any language, under any license, without
|
|
46
|
+
touching this code.
|
|
47
|
+
|
|
48
|
+
What you may then say about it is a trademark question, not a copyright one.
|
|
49
|
+
[`TRADEMARKS.md`](./TRADEMARKS.md) has the rule: claim compatibility with an
|
|
50
|
+
HSX IR version only when your implementation emits IR that validates against
|
|
51
|
+
that version's published schema, from the published example programs,
|
|
52
|
+
unmodified.
|
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# HSX
|
|
2
|
+
|
|
3
|
+
HSX is a language for describing how money moves through a financial product.
|
|
4
|
+
You write the product's parties, the things they trade, and the settlements
|
|
5
|
+
between them; the compiler turns that into an intermediate representation the
|
|
6
|
+
Hyperscale engine executes.
|
|
7
|
+
|
|
8
|
+
Seventeen lines of HSX ([`car-escrow.hsx`](./test/fixtures/car-escrow.hsx)) are
|
|
9
|
+
a used-car escrow: the buyer's money is held, the buyer's own backend confirms
|
|
10
|
+
the handover, the platform takes asymmetric fees, and a cancellation splits the
|
|
11
|
+
held amount to the basis point. There is no account provisioning in it, no
|
|
12
|
+
lifecycle table, no transfer plumbing. That is the point: those are consequences
|
|
13
|
+
of the settlement you named, so the compiler derives them instead of asking you
|
|
14
|
+
to hand-write them and get them right.
|
|
15
|
+
|
|
16
|
+
The line here is the one HCL draws with Terraform. **The language is open.**
|
|
17
|
+
The lexer, the parser, the typechecker, the lowering, the diagnostics, the IR
|
|
18
|
+
schema, and this compiler are AGPL-3.0-only and live in this repository. **The
|
|
19
|
+
runtime that executes the IR is the product**, and it is not open. HSX targets
|
|
20
|
+
it the way HCL targets a provider: you can read every rule the compiler
|
|
21
|
+
enforces, compile any program, and inspect the exact document that gets
|
|
22
|
+
executed.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @hyperscale0/hsx@alpha
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The `@alpha` tag is not optional. There is no `latest` tag before 1.0.0, so a
|
|
31
|
+
bare `npm install @hyperscale0/hsx` fails loudly rather than quietly installing
|
|
32
|
+
something you did not choose.
|
|
33
|
+
|
|
34
|
+
## A program
|
|
35
|
+
|
|
36
|
+
[`photo-booth.hsx`](./examples/02-imports-and-archetypes/photo-booth.hsx), a
|
|
37
|
+
booth rental company, whole apart from its comments:
|
|
38
|
+
|
|
39
|
+
```hsx
|
|
40
|
+
program photo_booth "Photo booth rentals"
|
|
41
|
+
|
|
42
|
+
import { held_payment } from "settlement"
|
|
43
|
+
|
|
44
|
+
party renter: person
|
|
45
|
+
party company: business
|
|
46
|
+
|
|
47
|
+
asset booth: good { title_transfer: off_platform }
|
|
48
|
+
|
|
49
|
+
settlement booking = held_payment {
|
|
50
|
+
payer: renter
|
|
51
|
+
payee: company
|
|
52
|
+
amount: bookingFee: money(SAR)
|
|
53
|
+
fees { renter: 1%, company: 3% }
|
|
54
|
+
release: port confirm_delivery
|
|
55
|
+
on_cancel(funded) { renter: 90%, company: 10% }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
port confirm_delivery {
|
|
59
|
+
allowed: [company]
|
|
60
|
+
shape {
|
|
61
|
+
boothId: id(booth)
|
|
62
|
+
deliveredOn: date
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { compile } from "@hyperscale0/hsx";
|
|
69
|
+
|
|
70
|
+
const result = compile(await Bun.file("photo-booth.hsx").text());
|
|
71
|
+
|
|
72
|
+
result.verdict; // "valid" | "warning" | "invalid"
|
|
73
|
+
result.diagnostics; // [{ line, column, severity, stage, message }]
|
|
74
|
+
result.artifacts; // present unless the verdict is "invalid"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`result.artifacts.document` is the HSX-JSON IR. Those 20 lines compile to one
|
|
78
|
+
escrow noun, `booking`, carrying:
|
|
79
|
+
|
|
80
|
+
- **five money fields**: `bookingFee`, the three pieces it partitions into
|
|
81
|
+
(90%, 7%, 3%: the finest split that every exit agrees on, since release pays
|
|
82
|
+
97/3 to company and platform while cancellation pays 90/10 to renter and
|
|
83
|
+
company), and `serviceFeeAmount` for the renter's 1% charged on top;
|
|
84
|
+
- **a `partitions` clause** proving those pieces sum to `bookingFee` exactly,
|
|
85
|
+
checked at create admission before any money moves;
|
|
86
|
+
- **fifteen verbs**: the funding chain, the fee collection, the port itself,
|
|
87
|
+
the release payout, the cancellation unwind, and the abandonment refunds,
|
|
88
|
+
each with its `from` states, its `to` state, and its ledger moves.
|
|
89
|
+
|
|
90
|
+
`result.artifacts.frame` is the congruent Business Frame: the same product as
|
|
91
|
+
actors, money events, rules, and fees, for the surfaces people read rather
|
|
92
|
+
than the runtime that executes.
|
|
93
|
+
|
|
94
|
+
Both shapes are specified in
|
|
95
|
+
[`spec/hsx-ir.schema.json`](./spec/hsx-ir.schema.json) (JSON Schema 2020-12),
|
|
96
|
+
and every file under `examples/` and `test/fixtures/` is validated against it
|
|
97
|
+
in CI.
|
|
98
|
+
|
|
99
|
+
## The command
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
hsx check photo-booth.hsx # diagnostics, nothing else
|
|
103
|
+
hsx check photo-booth.hsx --strict # warnings fail too
|
|
104
|
+
hsx build photo-booth.hsx # artifacts to stdout
|
|
105
|
+
hsx build photo-booth.hsx --out ir.json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Exit codes: `0` the program compiled, `1` it was refused, `2` the command line
|
|
109
|
+
or the input file could not be used. A refused program and a mistyped command
|
|
110
|
+
are different failures, so they get different codes.
|
|
111
|
+
|
|
112
|
+
There is no `hsx fmt`. This package ships no formatter, and shipping a bad one
|
|
113
|
+
is worse than shipping none.
|
|
114
|
+
|
|
115
|
+
## Learn it
|
|
116
|
+
|
|
117
|
+
- [`examples/`](./examples/) has four programs, in order: the smallest one that
|
|
118
|
+
moves money, archetypes and ports, a walk through the diagnostics, and a
|
|
119
|
+
complete small product. Each has its own README, and each is compiled by the
|
|
120
|
+
test suite so they cannot rot.
|
|
121
|
+
- [`docs/reference.md`](./docs/reference.md) is the language reference: lexical
|
|
122
|
+
grammar, EBNF, what each stage does, the diagnostic model, and every
|
|
123
|
+
archetype in the `settlement` standard library with its parameters and
|
|
124
|
+
constraints.
|
|
125
|
+
- [`editors/vscode/`](./editors/vscode/) carries the syntax highlighting.
|
|
126
|
+
|
|
127
|
+
## Versioning
|
|
128
|
+
|
|
129
|
+
Two numbers move independently.
|
|
130
|
+
|
|
131
|
+
**IR version** is the literal `"hsx": 1` stamped into every compiled document,
|
|
132
|
+
exported as `HSX_IR_VERSION`. A consumer reads that one integer to decide
|
|
133
|
+
whether it understands the document. It moves only when the emitted IR shape
|
|
134
|
+
changes in a way a consumer must notice.
|
|
135
|
+
|
|
136
|
+
**Package version** is this package's semver, currently `1.0.0-alpha.1`,
|
|
137
|
+
published only under the `alpha` dist-tag. It moves whenever the compiler
|
|
138
|
+
changes, including changes that only affect a diagnostic's wording.
|
|
139
|
+
|
|
140
|
+
IR version 1 is unstable until the package reaches 1.0.0. Until then an alpha
|
|
141
|
+
release may change what the compiler emits, and every such change is listed in
|
|
142
|
+
[`CHANGELOG.md`](./CHANGELOG.md). After 1.0.0, an incompatible IR change bumps
|
|
143
|
+
the literal to `2`.
|
|
144
|
+
|
|
145
|
+
## Status
|
|
146
|
+
|
|
147
|
+
Alpha. Nine settlement archetypes ship and all nine lower. The compiler is in
|
|
148
|
+
production use; the surface is settled enough to build on and the version
|
|
149
|
+
number is honest about the rest. What is most likely to move: diagnostic
|
|
150
|
+
wording (there are no stable diagnostic codes yet), and the archetype
|
|
151
|
+
parameter surfaces as more products land.
|
|
152
|
+
|
|
153
|
+
## Contributing
|
|
154
|
+
|
|
155
|
+
Issues only. Hyperscale makes the changes to the language and the compiler; you
|
|
156
|
+
propose them in an issue carrying the program you were trying to write and the
|
|
157
|
+
fixture the change would add. [`CONTRIBUTING.md`](./CONTRIBUTING.md) has that
|
|
158
|
+
model in full, plus the setup, the test commands, and the one hard rule: a
|
|
159
|
+
grammar change without a fixture is not a grammar change. Conduct:
|
|
160
|
+
[`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md). Vulnerabilities:
|
|
161
|
+
[`SECURITY.md`](./SECURITY.md).
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
AGPL-3.0-only, with a commercial license available from Hyperscale LLC for
|
|
166
|
+
organisations that cannot accept the AGPL. See [`LICENSE`](./LICENSE) for the
|
|
167
|
+
text and [`LICENSING.md`](./LICENSING.md) for which one you want and how to ask
|
|
168
|
+
for the commercial one. The marks are not covered by either; see
|
|
169
|
+
[`TRADEMARKS.md`](./TRADEMARKS.md), which also carries the rule for claiming
|
|
170
|
+
HSX compatibility.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Reporting a vulnerability
|
|
4
|
+
|
|
5
|
+
Report privately through GitHub, using this repository's
|
|
6
|
+
[private vulnerability reporting form](https://github.com/hyperscale0/hyperscale-hsx/security/advisories/new).
|
|
7
|
+
That is the only intake. There is no security email address, and nothing
|
|
8
|
+
security-sensitive belongs in an issue, a pull request, a discussion, or a
|
|
9
|
+
commit message.
|
|
10
|
+
|
|
11
|
+
A report we can act on names the affected version and gives us something to
|
|
12
|
+
run: the `.hsx` source, and what you expected the compiler to do with it. If
|
|
13
|
+
you can shape it as a fixture under `test/fixtures/`, do that; it goes straight
|
|
14
|
+
into the fix.
|
|
15
|
+
|
|
16
|
+
## What counts
|
|
17
|
+
|
|
18
|
+
This compiler reads untrusted source and emits a document a runtime then
|
|
19
|
+
executes, so the interesting failures are the ones a source file can cause:
|
|
20
|
+
|
|
21
|
+
- **A program that compiles but should not**, especially one whose emitted
|
|
22
|
+
pieces do not partition their total, whose exits do not drain custody, or
|
|
23
|
+
whose fees move money the source did not authorise. A `valid` verdict on an
|
|
24
|
+
unsound program is the worst bug this package can have.
|
|
25
|
+
- **A program that makes the lexer, parser, checker, or lowering burn
|
|
26
|
+
unbounded time or memory.** Every stage is meant to be linear or near it in
|
|
27
|
+
the size of the input, and the schedule, split, and money-event limits exist
|
|
28
|
+
to bound the output.
|
|
29
|
+
- **A crash.** Parsing and checking are total by design: they return
|
|
30
|
+
diagnostics, they never throw. A source file that throws out of `compile()`
|
|
31
|
+
is a bug even when the program is nonsense.
|
|
32
|
+
- **A diagnostic that reports the wrong source coordinates**, which sends an
|
|
33
|
+
author to fix the wrong line.
|
|
34
|
+
|
|
35
|
+
Out of scope: the `hsx` command reading a file you told it to read, and
|
|
36
|
+
anything that requires already controlling the machine running it.
|
|
37
|
+
|
|
38
|
+
## Supported versions
|
|
39
|
+
|
|
40
|
+
Alpha releases are supported at the newest published `alpha` version only.
|
|
41
|
+
Fixes land there; there is no backport branch before 1.0.0.
|
|
42
|
+
|
|
43
|
+
## Disclosure
|
|
44
|
+
|
|
45
|
+
We will confirm receipt, tell you what we found, and agree a disclosure date
|
|
46
|
+
with you before publishing an advisory. If a fix is not straightforward we will
|
|
47
|
+
say so rather than go quiet.
|
package/TRADEMARKS.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Trademarks
|
|
2
|
+
|
|
3
|
+
"Hyperscale" and "HSX" are trademarks of Hyperscale LLC.
|
|
4
|
+
|
|
5
|
+
The AGPL covers the code in this repository and nothing else. It grants no
|
|
6
|
+
rights to the marks, and it never mentions them: a copyright license says
|
|
7
|
+
nothing about trademarks either way. This file draws that boundary so nobody
|
|
8
|
+
has to guess where it sits.
|
|
9
|
+
|
|
10
|
+
What that means in practice:
|
|
11
|
+
|
|
12
|
+
- **Yes.** Say your project uses HSX, compiles HSX, or reads the HSX-JSON IR.
|
|
13
|
+
Say it in your README, your docs, your talk, and your package description.
|
|
14
|
+
Fork this repository and keep the notices intact.
|
|
15
|
+
- **Yes.** Publish an HSX implementation or tool in another language, and name
|
|
16
|
+
it in a way that describes what it does: `hsx-rs`, `hsx-lsp`, `tree-sitter-hsx`.
|
|
17
|
+
- **No.** Name your project, company, or product in a way that suggests
|
|
18
|
+
Hyperscale LLC published it or endorses it. `@hyperscale0/*` on npm and the
|
|
19
|
+
`hyperscale0` GitHub organisation are ours.
|
|
20
|
+
- **No.** Use the marks or our logo in a way that implies affiliation,
|
|
21
|
+
sponsorship, or certification we have not given.
|
|
22
|
+
|
|
23
|
+
## Claiming compatibility
|
|
24
|
+
|
|
25
|
+
An independent implementation may say it "implements HSX IR version X" only
|
|
26
|
+
while it emits IR that validates against the published schema for that version,
|
|
27
|
+
from the published example programs, unmodified. The schema in
|
|
28
|
+
[`spec/`](./spec) and the programs in [`examples/`](./examples) are the whole
|
|
29
|
+
test: no edited fixture, no local relaxation of the schema.
|
|
30
|
+
|
|
31
|
+
That claim is a statement about your implementation, so keep the marks out of
|
|
32
|
+
its name and off its logo, and do not present it as endorsement or
|
|
33
|
+
certification by Hyperscale LLC. We certify nothing; the schema does.
|
|
34
|
+
|
|
35
|
+
If you are unsure, open an issue and ask. Nobody has ever regretted asking.
|
package/bin/hsx.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `hsx` executable. Everything it does lives in `runCli`; this file only
|
|
4
|
+
* binds that function to the real filesystem and the real streams.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
8
|
+
import { runCli } from "../src/cli.ts";
|
|
9
|
+
|
|
10
|
+
process.exitCode = await runCli(process.argv.slice(2), {
|
|
11
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
12
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
13
|
+
readFile: (path) => readFile(path, "utf8"),
|
|
14
|
+
writeFile: (path, contents) => writeFile(path, contents, "utf8"),
|
|
15
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsx.d.ts","sourceRoot":"","sources":["../../bin/hsx.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/bin/hsx.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `hsx` executable. Everything it does lives in `runCli`; this file only
|
|
4
|
+
* binds that function to the real filesystem and the real streams.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
7
|
+
import { runCli } from "../src/cli.js";
|
|
8
|
+
process.exitCode = await runCli(process.argv.slice(2), {
|
|
9
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
10
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
11
|
+
readFile: (path) => readFile(path, "utf8"),
|
|
12
|
+
writeFile: (path, contents) => writeFile(path, contents, "utf8"),
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=hsx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsx.js","sourceRoot":"","sources":["../../bin/hsx.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACrD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;IAChD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;IAChD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC1C,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;CACjE,CAAC,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
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
|
+
export interface Span {
|
|
10
|
+
/** Inclusive start byte offset into the source text. */
|
|
11
|
+
readonly start: number;
|
|
12
|
+
/** Exclusive end byte offset into the source text. */
|
|
13
|
+
readonly end: number;
|
|
14
|
+
}
|
|
15
|
+
export interface LineCol {
|
|
16
|
+
/** 1-indexed line. */
|
|
17
|
+
readonly line: number;
|
|
18
|
+
/** 1-indexed column, counted in UTF-16 code units. */
|
|
19
|
+
readonly column: number;
|
|
20
|
+
}
|
|
21
|
+
/** Convert a byte offset to a 1-indexed line/column position. */
|
|
22
|
+
export declare function lineColAt(source: string, offset: number): LineCol;
|
|
23
|
+
export interface IdentExpr {
|
|
24
|
+
readonly kind: "ident";
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly span: Span;
|
|
27
|
+
}
|
|
28
|
+
export interface StringExpr {
|
|
29
|
+
readonly kind: "string";
|
|
30
|
+
readonly span: Span;
|
|
31
|
+
readonly value: string;
|
|
32
|
+
}
|
|
33
|
+
interface NumberExpr {
|
|
34
|
+
readonly kind: "number";
|
|
35
|
+
/** The literal exactly as written, e.g. "99.5". Interpretation is typed later. */
|
|
36
|
+
readonly raw: string;
|
|
37
|
+
readonly span: Span;
|
|
38
|
+
}
|
|
39
|
+
export interface PercentExpr {
|
|
40
|
+
/** Exact basis points: 99.5% is 9950. Percents never round. */
|
|
41
|
+
readonly bps: number;
|
|
42
|
+
readonly kind: "percent";
|
|
43
|
+
readonly raw: string;
|
|
44
|
+
readonly span: Span;
|
|
45
|
+
}
|
|
46
|
+
/** A type or constructor application: `money(SAR)`, `id(vehicle)`. */
|
|
47
|
+
export interface CallExpr {
|
|
48
|
+
readonly args: readonly Expr[];
|
|
49
|
+
readonly callee: IdentExpr;
|
|
50
|
+
readonly kind: "call";
|
|
51
|
+
readonly span: Span;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A reference to a decision port, optionally bounded (`port dispute within
|
|
55
|
+
* P14D`) or carrying the date that decides when the port has not
|
|
56
|
+
* (`port approve_release | at(releaseDueAt)`).
|
|
57
|
+
*/
|
|
58
|
+
export interface PortRefExpr {
|
|
59
|
+
/** `| at(<field>)`, the stored date field that resolves an undecided hold. */
|
|
60
|
+
readonly deadline?: IdentExpr;
|
|
61
|
+
readonly kind: "port_ref";
|
|
62
|
+
readonly name: IdentExpr;
|
|
63
|
+
readonly span: Span;
|
|
64
|
+
readonly within?: IdentExpr;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* `retention.release`, one settlement naming another settlement's exit. The
|
|
68
|
+
* only cross-settlement reference the language has: it is resolved wholly at
|
|
69
|
+
* check time, never by a caller at runtime.
|
|
70
|
+
*/
|
|
71
|
+
export interface SettlementRefExpr {
|
|
72
|
+
readonly kind: "settlement_ref";
|
|
73
|
+
/** The exit named on the owner, e.g. `release`. */
|
|
74
|
+
readonly member: IdentExpr;
|
|
75
|
+
/** The settlement being referenced. */
|
|
76
|
+
readonly owner: IdentExpr;
|
|
77
|
+
readonly span: Span;
|
|
78
|
+
}
|
|
79
|
+
export interface ListExpr {
|
|
80
|
+
readonly items: readonly Expr[];
|
|
81
|
+
readonly kind: "list";
|
|
82
|
+
readonly span: Span;
|
|
83
|
+
}
|
|
84
|
+
/** A brace block of entries: `{ buyer: 1%, seller: 2% }`. */
|
|
85
|
+
export interface BlockExpr {
|
|
86
|
+
readonly entries: readonly Entry[];
|
|
87
|
+
readonly kind: "block";
|
|
88
|
+
readonly span: Span;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A named typed binding inside an expression position:
|
|
92
|
+
* `amount: price: money(SAR)` binds the field name `price` to type
|
|
93
|
+
* `money(SAR)`: the entry key is `amount`, the value is this binding.
|
|
94
|
+
*/
|
|
95
|
+
interface BindingExpr {
|
|
96
|
+
readonly kind: "binding";
|
|
97
|
+
readonly name: IdentExpr;
|
|
98
|
+
readonly span: Span;
|
|
99
|
+
readonly type: Expr;
|
|
100
|
+
}
|
|
101
|
+
export type Expr = BindingExpr | BlockExpr | CallExpr | IdentExpr | ListExpr | NumberExpr | PercentExpr | PortRefExpr | SettlementRefExpr | StringExpr;
|
|
102
|
+
/**
|
|
103
|
+
* One keyed entry inside a declaration body. Three surface shapes normalize
|
|
104
|
+
* here: `payer: buyer` (key + value), `fees { ... }` (key + block value),
|
|
105
|
+
* and `on_cancel(funded) { ... }` (key + qualifiers + block value).
|
|
106
|
+
*/
|
|
107
|
+
export interface Entry {
|
|
108
|
+
readonly key: IdentExpr;
|
|
109
|
+
readonly qualifiers: readonly IdentExpr[];
|
|
110
|
+
readonly span: Span;
|
|
111
|
+
readonly value: Expr;
|
|
112
|
+
}
|
|
113
|
+
/** `program used_car_escrow "Used-car escrow"` names the company program. */
|
|
114
|
+
export interface ProgramDecl {
|
|
115
|
+
readonly kind: "program";
|
|
116
|
+
readonly name: IdentExpr;
|
|
117
|
+
readonly span: Span;
|
|
118
|
+
readonly title?: StringExpr;
|
|
119
|
+
}
|
|
120
|
+
/** `import { held_payment } from "settlement"`. */
|
|
121
|
+
export interface ImportDecl {
|
|
122
|
+
readonly from: StringExpr;
|
|
123
|
+
readonly kind: "import";
|
|
124
|
+
readonly names: readonly IdentExpr[];
|
|
125
|
+
readonly span: Span;
|
|
126
|
+
}
|
|
127
|
+
/** `party buyer: person` with an optional attribute block. */
|
|
128
|
+
export interface PartyDecl {
|
|
129
|
+
readonly attrs?: BlockExpr;
|
|
130
|
+
readonly kind: "party";
|
|
131
|
+
readonly name: IdentExpr;
|
|
132
|
+
readonly partyKind: IdentExpr;
|
|
133
|
+
readonly span: Span;
|
|
134
|
+
}
|
|
135
|
+
/** `asset vehicle: good { title_transfer: off_platform }`. */
|
|
136
|
+
export interface AssetDecl {
|
|
137
|
+
readonly assetKind: IdentExpr;
|
|
138
|
+
readonly attrs?: BlockExpr;
|
|
139
|
+
readonly kind: "asset";
|
|
140
|
+
readonly name: IdentExpr;
|
|
141
|
+
readonly span: Span;
|
|
142
|
+
}
|
|
143
|
+
/** `settlement sale = held_payment { ... }`, an archetype instantiation. */
|
|
144
|
+
export interface SettlementDecl {
|
|
145
|
+
readonly archetype: IdentExpr;
|
|
146
|
+
readonly body: BlockExpr;
|
|
147
|
+
readonly kind: "settlement";
|
|
148
|
+
readonly name: IdentExpr;
|
|
149
|
+
readonly span: Span;
|
|
150
|
+
}
|
|
151
|
+
/** `port confirm_handover { allowed: [buyer], ... }`. */
|
|
152
|
+
export interface PortDecl {
|
|
153
|
+
readonly body: BlockExpr;
|
|
154
|
+
readonly kind: "port";
|
|
155
|
+
readonly name: IdentExpr;
|
|
156
|
+
readonly span: Span;
|
|
157
|
+
}
|
|
158
|
+
export type Decl = AssetDecl | ImportDecl | PartyDecl | PortDecl | ProgramDecl | SettlementDecl;
|
|
159
|
+
export interface Program {
|
|
160
|
+
readonly decls: readonly Decl[];
|
|
161
|
+
readonly span: Span;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A parse-stage problem, worded for the program's author. Parsing is total:
|
|
165
|
+
* it never throws, it returns the best-effort tree plus these.
|
|
166
|
+
*/
|
|
167
|
+
export interface Diagnostic {
|
|
168
|
+
readonly message: string;
|
|
169
|
+
readonly span: Span;
|
|
170
|
+
}
|
|
171
|
+
export {};
|
|
172
|
+
//# sourceMappingURL=ast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"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"}
|
package/dist/src/ast.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
/** Convert a byte offset to a 1-indexed line/column position. */
|
|
10
|
+
export function lineColAt(source, offset) {
|
|
11
|
+
let line = 1;
|
|
12
|
+
let lineStart = 0;
|
|
13
|
+
const clamped = Math.max(0, Math.min(offset, source.length));
|
|
14
|
+
for (let index = 0; index < clamped; index += 1) {
|
|
15
|
+
if (source.charCodeAt(index) === 10) {
|
|
16
|
+
line += 1;
|
|
17
|
+
lineStart = index + 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return { column: clamped - lineStart + 1, line };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH,iEAAiE;AACjE,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,MAAc;IACtD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,CAAC;YACV,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HSX typechecker. Takes the parsed AST, resolves every name, validates
|
|
3
|
+
* each archetype's parameter surface, and produces the checked program model
|
|
4
|
+
* the lowering consumes. Total: always returns diagnostics; returns the model
|
|
5
|
+
* exactly when nothing error-severity was found. Warnings are the compiler's
|
|
6
|
+
* lint voice and never block.
|
|
7
|
+
*/
|
|
8
|
+
import type { Program } from "./ast.ts";
|
|
9
|
+
import { type CheckResult } from "./model.ts";
|
|
10
|
+
export declare function checkProgram(program: Program): CheckResult;
|
|
11
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/check.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAKV,OAAO,EAER,MAAM,UAAU,CAAC;AAClB,OAAO,EAOL,KAAK,WAAW,EAcjB,MAAM,YAAY,CAAC;AAiFpB,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAshD1D"}
|