@typesol/cli 0.16.0 → 0.18.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 +121 -0
- package/README.md +4 -4
- package/dist/clientgen.js +39 -0
- package/dist/compiler/analyze.d.ts +16 -1
- package/dist/compiler/analyze.js +355 -43
- package/dist/compiler/emit/base.d.ts +36 -1
- package/dist/compiler/emit/base.js +135 -4
- package/dist/compiler/emit/borsh.d.ts +13 -0
- package/dist/compiler/emit/borsh.js +298 -0
- package/dist/compiler/emit/calls.d.ts +2 -3
- package/dist/compiler/emit/calls.js +135 -29
- package/dist/compiler/emit/cpi.d.ts +62 -8
- package/dist/compiler/emit/cpi.js +1458 -40
- package/dist/compiler/emit/expressions.d.ts +5 -0
- package/dist/compiler/emit/expressions.js +85 -5
- package/dist/compiler/emit/function.js +82 -14
- package/dist/compiler/emit/program.js +24 -6
- package/dist/compiler/emit/shared.d.ts +20 -0
- package/dist/compiler/emit/shared.js +23 -3
- package/dist/compiler/emit/statements.d.ts +21 -0
- package/dist/compiler/emit/statements.js +380 -19
- package/dist/compiler/emit/storage.d.ts +6 -0
- package/dist/compiler/emit/storage.js +88 -16
- package/dist/compiler/idl.js +37 -5
- package/dist/compiler/model.d.ts +70 -4
- package/dist/compiler/model.js +8 -2
- package/dist/portgen.js +90 -4
- package/docs/errors.md +6 -4
- package/docs/language.md +32 -20
- package/docs/migrate-from-anchor.md +24 -7
- package/docs/test-your-program.md +1 -1
- package/lib/typesol.d.ts +652 -21
- package/package.json +1 -1
- package/runtime/typesol_rt.h +230 -7
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,127 @@ until 1.0, a minor version may change the language, the IDL layout or error code
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.18.0 — 2026-10-28
|
|
9
|
+
|
|
10
|
+
The remaining Anchor differences, closed: Anchor's argument structs (Strings, Vecs, Options and enums in Borsh),
|
|
11
|
+
keypair `init` with `space`, `init` of mints with Token-2022 extensions and of token accounts, `Vec<String>`
|
|
12
|
+
arguments, `SystemAccount`, string return values, and the Token-2022 and Token Metadata instructions programs call.
|
|
13
|
+
Closures, list callbacks and more everyday TypeScript; the rest of Bubblegum and Core. 26 of the 46 official
|
|
14
|
+
examples are now full ports. Existing programs keep their layouts and error codes (2018 and 3011 are new, raised only
|
|
15
|
+
by the new `Init<Mint>` and `SystemAccount` checks). Not externally audited (see SECURITY.md).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
Anchor accounts and arguments:
|
|
19
|
+
- `@layout borsh` structs as whole instruction arguments, return values and events, in Anchor's Borsh bytes (a
|
|
20
|
+
FixedString is a String, a FixedVec a Vec, an Option one byte when empty). Arguments are checked as Borsh
|
|
21
|
+
deserialization does, UTF-8 included (102 otherwise). `return vault` returns a whole struct account.
|
|
22
|
+
- `@layout borsh` structs used as arguments, return values or events may hold `string` fields and data enums (with or
|
|
23
|
+
without strings), as Anchor argument structs do; Borsh accounts may hold data enums without strings.
|
|
24
|
+
- `acct.create(payer, null)` on `Init<T>`: Anchor's `init` of a keypair account (it must sign; 3010 otherwise), and an
|
|
25
|
+
optional third argument for Anchor's `space = …` on `create` / `createIfNeeded`.
|
|
26
|
+
- Mint extensions on `Init<Mint>`: `mint.create(payer, seeds | null, decimals, authority, freeze, { … })` with
|
|
27
|
+
transferFee, closeAuthority, defaultAccountState, nonTransferable, interestBearing, permanentDelegate, transferHook,
|
|
28
|
+
metadataPointer, groupPointer and groupMemberPointer (Anchor's `extensions::…`).
|
|
29
|
+
- `Init<Mint>` / `InitIfNeeded<Mint>` with `mint.create(payer, seeds | null, decimals, mintAuthority, freezeAuthority)`
|
|
30
|
+
and `Init<TokenAccount>` / `InitIfNeeded<TokenAccount>` (without `Ata<…>`) with `vault.create(payer, seeds | null,
|
|
31
|
+
mint, authority)`: Anchor's `init` with `mint::` / `token::` constraints, at a PDA of this program or (with `null`) a
|
|
32
|
+
new keypair account that signs, under SPL Token or Token-2022 (token accounts sized with GetAccountDataSize). The
|
|
33
|
+
`createIfNeeded` forms check an existing account like Anchor's `init_if_needed` (2014 / 2015 / 2016 / 2017 and the
|
|
34
|
+
new 2018 ConstraintMintDecimals). The IDL marks keypair-created accounts as signers.
|
|
35
|
+
- `SystemAccount` / `Mut<SystemAccount>`: Anchor's `SystemAccount`, refused with 3011 (AccountNotSystemOwned) when
|
|
36
|
+
another program owns it.
|
|
37
|
+
- `Vec<string>` instruction arguments (Anchor's `Vec<String>`): `.get(i)`, `.length`, `for … of`, list callbacks,
|
|
38
|
+
helper parameters, storing into `FixedVec<FixedString<N>, M>`, and re-encoding through `invoke`; each string is
|
|
39
|
+
checked as UTF-8 on entry (102).
|
|
40
|
+
- Helpers and instructions can return `string` (an instruction's is Borsh String return data).
|
|
41
|
+
- `acct.key` of an `Init<…>` account before it is created (the address is known; Anchor seeds use it that way).
|
|
42
|
+
- `mint.create(…, tokenProgram)` / `vault.create(…, tokenProgram)`: an explicit token program, for instructions that
|
|
43
|
+
take more than one.
|
|
44
|
+
|
|
45
|
+
Language:
|
|
46
|
+
- Closures: a local function that reads or writes the enclosing function's variables is expanded where it is called,
|
|
47
|
+
with the names it was declared with (a block at the call that declares the same name does not change it), struct
|
|
48
|
+
parameters by reference and `return` leaving the closure. Recursion and storing / returning closures are refused.
|
|
49
|
+
- List callbacks on Vec, FixedArray, FixedVec and Vec arguments: `forEach`, `some`, `every`, `find`, `findIndex`,
|
|
50
|
+
`reduce`, `includes`, `indexOf`, expanded into loops with the arrow written at the call.
|
|
51
|
+
- Helpers can take function parameters (`f: (x: u64) => u64`): compiled once per named function passed.
|
|
52
|
+
- `do … while` loops (`continue` goes to the test).
|
|
53
|
+
- `x **= n` (the target must not call a function: it is read and written).
|
|
54
|
+
- `switch` on 128-bit integers (the case is picked with comparisons, then switched on as usual, fallthrough included).
|
|
55
|
+
- `?.` on optional accounts (`acct?.field`) and on `Option<struct>` fields (`x.home?.field`): an Option, empty when the
|
|
56
|
+
account was left out or the option is empty; use it with `??`.
|
|
57
|
+
- `acct!` on optional accounts (fails with 5115 when it was left out), Pubkeys / Hashes in template strings (base58),
|
|
58
|
+
and data-enum arguments whose variants carry fixed-size structs or arrays.
|
|
59
|
+
- Type parameters standing for fixed-size structs (`pick<Point>(…)`, or taken from struct arguments), and `cond ? a : b`
|
|
60
|
+
for struct values (places, literals or calls).
|
|
61
|
+
- Growable `Vec<T>` `push` / `pop` / `clear` inside helpers that take the account as `Mut<T>` (with its payer and
|
|
62
|
+
SystemProgram, as in instructions).
|
|
63
|
+
- `mulDiv` / `mulDivCeil` on u128 through a 256-bit product (all three u128; literals take that type).
|
|
64
|
+
|
|
65
|
+
CPI:
|
|
66
|
+
- Token-2022 extension instructions: `updateDefaultAccountState`, `updateTransferHook`, `enableRequiredMemoTransfers` /
|
|
67
|
+
`disableRequiredMemoTransfers`, `updateInterestRate`, `transferCheckedWithFee`, `harvestWithheldTokensToMint`,
|
|
68
|
+
`withdrawWithheldTokensFromMint`, `setTransferFee`; the Token Metadata interface: `updateMetadataField`,
|
|
69
|
+
`removeMetadataKey`, `updateMetadataAuthority`, `emitMetadata`; `closeAccount` of a mint; `mintTo` /
|
|
70
|
+
`initializeMetadata` on a mint created earlier in the instruction; `isTransferring(tokenAccount)` and
|
|
71
|
+
`transferHookAuthority(mint)`.
|
|
72
|
+
- Metaplex Core plugin values: MasterEdition, VerifiedCreators, Autograph, FreezeExecute, PermanentFreezeExecute, and
|
|
73
|
+
royalty rule sets (`ruleSet: { programAllowList | programDenyList }`).
|
|
74
|
+
- Bubblegum: `delegateV2`, `freezeV2`, `thawV2`, `setNonTransferableV2`, `updateMetadataV2`, `verifyCreatorV2`,
|
|
75
|
+
`unverifyCreatorV2`, `setCollectionV2`, and the V1 `transfer`, `burn`, `delegate`. Checked on the real programs with
|
|
76
|
+
every leaf recomputed: verify → delegate → freeze (a frozen leaf is refused) → thaw → rename, unverify, moving a leaf
|
|
77
|
+
into a collection, soulbinding a collection's leaf, and a V1 transfer signed by a PDA owner, delegate and burn.
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
- Bubblegum leaf fields that may be null at run time (`assetDataHash: Hash | null`, `flags`) are sent as Borsh Options;
|
|
81
|
+
a null aborted the instruction before.
|
|
82
|
+
|
|
83
|
+
## 0.17.0 — 2026-10-28
|
|
84
|
+
|
|
85
|
+
Anchor's account bytes on request (`@layout borsh`, so a TypeSOL program can take over an Anchor program's accounts
|
|
86
|
+
without a migration), lists with a fixed capacity anywhere in account data (`FixedVec`), arrow functions and generic
|
|
87
|
+
helpers, Metaplex collection verification, Core plugins and Bubblegum V2, and a faster UTF-8 check. Existing programs
|
|
88
|
+
keep their layouts and error codes (3004 is new, raised only by `@layout borsh` accounts). Not externally audited (see
|
|
89
|
+
SECURITY.md).
|
|
90
|
+
|
|
91
|
+
### Added
|
|
92
|
+
- `/** @layout borsh */` on an account struct stores it with Anchor's bytes (Borsh String / Vec / Option for
|
|
93
|
+
`FixedString` / `FixedVec` / `Option`), so a TypeSOL program can take over an Anchor program's accounts without a
|
|
94
|
+
migration; its IDL lists Anchor's own types. An instruction unpacks the account into the fixed layout when it starts
|
|
95
|
+
and packs it back when it returns (3003 for bytes that are not a valid value, 3004 when the account is too small).
|
|
96
|
+
Checked byte for byte against an Anchor twin, including switching programs in the middle of a sequence.
|
|
97
|
+
`typesol port` marks Anchor account structs that need it.
|
|
98
|
+
- `FixedVec<T, N>`: a list with room for N elements (u32 length + N slots, like `FixedString<N>`) as any account field,
|
|
99
|
+
several per struct and in nested structs, with `get` / `set` / `push` / `pop` / `clear` / `.length` / `for … of`;
|
|
100
|
+
`push` on a full one fails with 5104, `fixedVec([…])` writes a whole one. The IDL describes each as a
|
|
101
|
+
`FixedVec<N>_<T>` struct `{ len, items }`; the generated client reads and writes them as arrays. The
|
|
102
|
+
basics/favorites port uses one.
|
|
103
|
+
- Bubblegum V2: `createTreeV2`, `mintV2` (optionally into a Metaplex Core collection), `transferV2` and `burnV2`, which
|
|
104
|
+
take the leaf (root, data and creator hashes, nonce, index) and pass its Merkle proof on from the remaining accounts;
|
|
105
|
+
the Core `BubblegumV2` collection plugin. Checked against Bubblegum, mpl-account-compression, mpl-noop and Core
|
|
106
|
+
(`pnpm fetch:programs` now fetches the mpl-account-compression pair too).
|
|
107
|
+
- Metaplex Core plugins: a literal plugin list in `createAsset` / `createCollection` (Royalties, freeze / burn / transfer /
|
|
108
|
+
update delegates and their permanent forms, Attributes, Edition, AddBlocker, ImmutableMetadata, each with an optional
|
|
109
|
+
authority), and `addPlugin`, `updatePlugin`, `removePlugin` with their collection forms, checked against the real Core
|
|
110
|
+
program (a frozen asset cannot move until it is thawed).
|
|
111
|
+
- Arrow functions: `const f = (x: u64): u64 => …` (and `const f = function (…) {…}`) at the top level or inside a
|
|
112
|
+
function is a helper. Local ones capture nothing (a closure over the enclosing function's variables is refused with
|
|
113
|
+
the name it reads); functions are called, not passed around.
|
|
114
|
+
- Generic helpers: `function max<T extends bigint>(a: T, b: T): T` compiles once per set of types it is called with,
|
|
115
|
+
inferred from the arguments or written out (`max<u128>(x, 1n)`); type parameters stand for integers, booleans,
|
|
116
|
+
Pubkeys or enums.
|
|
117
|
+
- `x as T` (and `satisfies`): names a type the value already has, never a conversion; mainly `return (a + b) as T`
|
|
118
|
+
in a generic helper.
|
|
119
|
+
- Metaplex collections: `createV3`'s `isCollection: true` (CollectionDetails::V1), `createMasterEditionV3(…, maxSupply | null)`,
|
|
120
|
+
`verifyCollection(…)` (Verify with CollectionV1) and `masterEditionAddress(mint)`. The tokens/nft-operations port now
|
|
121
|
+
uses them instead of hand-encoded `invoke`s, checked against the real Token Metadata program.
|
|
122
|
+
|
|
123
|
+
### Changed
|
|
124
|
+
- IDLs no longer list `FixedString*` / `FixedOption_*` / `FixedVec*` helper types that nothing in them refers to
|
|
125
|
+
(for example an `Option` used only as an instruction argument, which is Borsh there).
|
|
126
|
+
- UTF-8 checks of strings run eight ASCII bytes at a time: every official-example instruction with a string argument
|
|
127
|
+
gets cheaper (create_token_mint 40,919 → 39,828 CU, set_favorites 4,282 → 4,195).
|
|
128
|
+
|
|
8
129
|
## 0.16.0 — 2026-10-28
|
|
9
130
|
|
|
10
131
|
Everyday TypeScript that Anchor developers reach for (`for … of`, `??`, destructuring, `**`, structs returned from
|
package/README.md
CHANGED
|
@@ -189,10 +189,10 @@ Runtime failures point back to your source: `Error 6000 Unauthorized (counter.ts
|
|
|
189
189
|
|
|
190
190
|
| | |
|
|
191
191
|
| --- | --- |
|
|
192
|
-
| **Accounts** | `Signer`, `Account<T>`, `Mut<T>`, `Init<T>`, `InitIfNeeded<T>` (PDAs and associated token accounts), `Zeroed<T>` (up to 10 MiB), optional accounts (`A \| null`), token accounts and mints, programs, sysvars |
|
|
192
|
+
| **Accounts** | `Signer`, `Account<T>`, `Mut<T>`, `Init<T>`, `InitIfNeeded<T>` (PDAs or keypair accounts, with Anchor's `space`; mints, token accounts and associated token accounts), `Zeroed<T>` (up to 10 MiB), optional accounts (`A \| null`), token accounts and mints, `SystemAccount`, programs, sysvars |
|
|
193
193
|
| **Constraints** | `HasOne`, `Seeds` (also from account fields and under another program; `pdaBump` like `ctx.bumps`), `CloseTo`, `Ata`, `Address`, `Owner`, `Executable`. They are checked before the body runs and recorded in the IDL |
|
|
194
|
-
| **Data** | `u8`…`u128`, `i8`…`i128`, `boolean`, `Pubkey`, `Hash`, nested structs, `FixedArray`, `FixedString`, `Option`, unit enums, data enums (discriminated unions), `Vec` that resizes its account |
|
|
195
|
-
| **Control flow** | `if`, `for`, `for … of`, `while`, `switch` (with narrowing on data enums), ternaries, `??`, destructuring, helper functions (returning structs too) across multiple files |
|
|
194
|
+
| **Data** | `u8`…`u128`, `i8`…`i128`, `boolean`, `Pubkey`, `Hash`, nested structs, `FixedArray`, `FixedString`, `Option`, unit enums, data enums (discriminated unions), `Vec` that resizes its account, `FixedVec` lists anywhere, and Anchor's own byte layout (`@layout borsh`) to take over existing Anchor accounts and to pass, return and emit structs with String / Vec / Option fields as Anchor does |
|
|
195
|
+
| **Control flow** | `if`, `for`, `for … of`, `while`, `switch` (with narrowing on data enums), ternaries, `??`, destructuring, helper functions (returning structs too, arrow functions, closures, function arguments, generics), list callbacks (`some`, `find`, `reduce`, …) across multiple files |
|
|
196
196
|
| **CPIs** | System, SPL Token, Token-2022 (including extension reads and metadata), ATA, Metaplex Token Metadata, Core, Bubblegum. Generic `invoke` with PDA signing, return data, and typed bindings generated from any Anchor IDL (`typesol cpi`) |
|
|
197
197
|
| **Events** | `emit` (log-based) and `emitCpi` (Anchor `emit_cpi!`, through a self-CPI) |
|
|
198
198
|
| **Crypto & oracles** | `sha256`, `keccak256`, Merkle proofs, Ed25519 and secp256k1 signature checks, Pyth pull oracle, Switchboard |
|
|
@@ -306,7 +306,7 @@ Details are in [docs/testing.md](docs/testing.md).
|
|
|
306
306
|
|
|
307
307
|
## Status
|
|
308
308
|
|
|
309
|
-
**TypeSOL is pre-1.0 (0.
|
|
309
|
+
**TypeSOL is pre-1.0 (0.18).** Releases follow the organization's
|
|
310
310
|
[versioning policy](https://github.com/typesol/.github/blob/main/VERSIONING.md); [CHANGELOG.md](CHANGELOG.md) lists every
|
|
311
311
|
change.
|
|
312
312
|
- The compiler, runtime and tooling have been through internal security reviews and are covered by the tests above.
|
package/dist/clientgen.js
CHANGED
|
@@ -39,16 +39,19 @@ export const TYPESOL_ERRORS = {
|
|
|
39
39
|
2015: "ConstraintTokenOwner",
|
|
40
40
|
2016: "ConstraintMintMintAuthority",
|
|
41
41
|
2017: "ConstraintMintFreezeAuthority",
|
|
42
|
+
2018: "ConstraintMintDecimals",
|
|
42
43
|
2040: "ConstraintDuplicateMutableAccount",
|
|
43
44
|
3000: "AccountDiscriminatorAlreadySet",
|
|
44
45
|
3002: "AccountDiscriminatorMismatch",
|
|
45
46
|
3003: "AccountDidNotDeserialize",
|
|
47
|
+
3004: "AccountDidNotSerialize",
|
|
46
48
|
3005: "AccountNotEnoughKeys",
|
|
47
49
|
3006: "AccountNotMutable",
|
|
48
50
|
3007: "AccountOwnedByWrongProgram",
|
|
49
51
|
3008: "InvalidProgramId",
|
|
50
52
|
3009: "InvalidProgramExecutable",
|
|
51
53
|
3010: "AccountNotSigner",
|
|
54
|
+
3011: "AccountNotSystemOwned",
|
|
52
55
|
3012: "AccountNotInitialized",
|
|
53
56
|
3016: "AccountReallocExceedsLimit",
|
|
54
57
|
4102: "InvalidNumericConversion",
|
|
@@ -383,6 +386,8 @@ export function generateClient(idl, opts = {}) {
|
|
|
383
386
|
const arrayLen = (t) => (typeof t === "object" && t.array ? Number(t.array[1]) : NaN);
|
|
384
387
|
if (/^FixedString\d+$/.test(n) && f[0].name === "len" && Number.isInteger(arrayLen(f[1].type)))
|
|
385
388
|
return { kind: "fstring", cap: arrayLen(f[1].type) };
|
|
389
|
+
if (/^FixedVec\d+_/.test(n) && f[0].name === "len" && f[1].name === "items" && Number.isInteger(arrayLen(f[1].type)))
|
|
390
|
+
return { kind: "fvec", elem: f[1].type.array[0], cap: arrayLen(f[1].type) };
|
|
386
391
|
if (n.startsWith("FixedOption_") && f[0].name === "is_some")
|
|
387
392
|
return { kind: "foption", inner: f[1].type };
|
|
388
393
|
if (n.startsWith("FixedEnum_") && f[0].name === "tag" && defs.has(n.slice("FixedEnum_".length)) && Number.isInteger(arrayLen(f[1].type)))
|
|
@@ -476,6 +481,8 @@ export function generateClient(idl, opts = {}) {
|
|
|
476
481
|
const s = special(n);
|
|
477
482
|
if (s?.kind === "fstring")
|
|
478
483
|
return "string";
|
|
484
|
+
if (s?.kind === "fvec")
|
|
485
|
+
return `Array<${tsType(s.elem, dir)}>`;
|
|
479
486
|
if (s?.kind === "foption")
|
|
480
487
|
return `${tsType(s.inner, dir)} | null`;
|
|
481
488
|
if (s?.kind === "fenum")
|
|
@@ -484,6 +491,7 @@ export function generateClient(idl, opts = {}) {
|
|
|
484
491
|
}
|
|
485
492
|
let needsFixedString = false;
|
|
486
493
|
let needsFixedOption = false;
|
|
494
|
+
let needsFixedVec = false;
|
|
487
495
|
let needsUnitEnum = false;
|
|
488
496
|
function codec(t) {
|
|
489
497
|
if (typeof t === "string") {
|
|
@@ -525,6 +533,11 @@ export function generateClient(idl, opts = {}) {
|
|
|
525
533
|
const s = special(n);
|
|
526
534
|
if (s?.kind === "fstring")
|
|
527
535
|
return ((needsFixedString = true), `fixedString(${s.cap})`);
|
|
536
|
+
if (s?.kind === "fvec") {
|
|
537
|
+
if (idlSize(s.elem) === undefined)
|
|
538
|
+
throw new ClientIdlError(`${n}: the elements have no fixed size`);
|
|
539
|
+
return ((needsFixedVec = true), `fixedVec(${codec(s.elem)}, ${idlSize(s.elem)}, ${s.cap})`);
|
|
540
|
+
}
|
|
528
541
|
if (s?.kind === "foption") {
|
|
529
542
|
const size = idlSize(s.inner);
|
|
530
543
|
if (size === undefined)
|
|
@@ -560,6 +573,10 @@ export function generateClient(idl, opts = {}) {
|
|
|
560
573
|
const sp = special(n);
|
|
561
574
|
if (sp?.kind === "fstring")
|
|
562
575
|
return 4 + sp.cap;
|
|
576
|
+
if (sp?.kind === "fvec") {
|
|
577
|
+
const e = idlSize(sp.elem);
|
|
578
|
+
return e === undefined ? undefined : 4 + e * sp.cap;
|
|
579
|
+
}
|
|
563
580
|
if (sp?.kind === "fenum")
|
|
564
581
|
return sp.size;
|
|
565
582
|
if (sp?.kind === "foption") {
|
|
@@ -982,6 +999,28 @@ export function generateClient(idl, opts = {}) {
|
|
|
982
999
|
` });`,
|
|
983
1000
|
],
|
|
984
1001
|
});
|
|
1002
|
+
if (needsFixedVec)
|
|
1003
|
+
helperDefs.push({
|
|
1004
|
+
name: "fixedVec",
|
|
1005
|
+
lines: [
|
|
1006
|
+
`/** TypeSOL FixedVec<T, N> in account data: u32 length, then room for N elements (unused ones zero). */`,
|
|
1007
|
+
`const fixedVec = <From, To extends From>(item: Codec<From, To>, size: number, cap: number): Codec<From[], To[]> =>`,
|
|
1008
|
+
` createCodec<From[], To[]>({`,
|
|
1009
|
+
` fixedSize: 4 + size * cap,`,
|
|
1010
|
+
` write: (value, bytes, offset) => {`,
|
|
1011
|
+
` if (value.length > cap) throw new Error(value.length + " elements; the field holds " + cap);`,
|
|
1012
|
+
` bytes.fill(0, offset, offset + 4 + size * cap);`,
|
|
1013
|
+
` getU32Codec().write(value.length, bytes, offset);`,
|
|
1014
|
+
` value.forEach((v, i) => item.write(v, bytes, offset + 4 + i * size));`,
|
|
1015
|
+
` return offset + 4 + size * cap;`,
|
|
1016
|
+
` },`,
|
|
1017
|
+
` read: (bytes, offset) => {`,
|
|
1018
|
+
` const n = Math.min(getU32Codec().read(bytes, offset)[0], cap);`,
|
|
1019
|
+
` return [Array.from({ length: n }, (_, i) => item.read(bytes, offset + 4 + i * size)[0]), offset + 4 + size * cap];`,
|
|
1020
|
+
` },`,
|
|
1021
|
+
` });`,
|
|
1022
|
+
],
|
|
1023
|
+
});
|
|
985
1024
|
if (needsUnitEnum)
|
|
986
1025
|
helperDefs.push({
|
|
987
1026
|
name: "unitEnum",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { Reporter } from "./diagnostics.js";
|
|
3
|
-
import { type DataEnumDef, type EnumDef, type ProgramModel, type ScalarType, type StructDef, type ValueType, isScalar } from "./model.js";
|
|
3
|
+
import { type DataEnumDef, type EnumDef, type GenericHelper, type Helper, type ProgramModel, type ScalarType, type StructDef, type ValueType, isScalar } from "./model.js";
|
|
4
4
|
export declare const LIB_PATH: string;
|
|
5
5
|
/** Why a name cannot be used as a C member, or undefined when it can. */
|
|
6
6
|
export declare function cNameProblem(name: string): string | undefined;
|
|
@@ -11,6 +11,8 @@ export declare const MAX_RETURN_DATA = 1024;
|
|
|
11
11
|
export declare const MAX_CPI_ALLOCATION: number;
|
|
12
12
|
export interface Analysis {
|
|
13
13
|
model: ProgramModel;
|
|
14
|
+
/** A generic helper's instance for these type arguments (analyzed once, then kept in `model.helpers`). */
|
|
15
|
+
instantiate(g: GenericHelper, typeArgs: TypeArg[], fnArgs?: string[]): Helper;
|
|
14
16
|
/** TypeScript's checker: used for narrowing (which variant a data-enum value is in a branch). */
|
|
15
17
|
checker: ts.TypeChecker;
|
|
16
18
|
sourceFile: ts.SourceFile;
|
|
@@ -20,9 +22,20 @@ export interface Analysis {
|
|
|
20
22
|
imports: Map<string, string>;
|
|
21
23
|
reporter: Reporter;
|
|
22
24
|
}
|
|
25
|
+
/** What a generic helper's type parameter stands for: a scalar, or a fixed-size struct. */
|
|
26
|
+
export type TypeArg = ScalarType | {
|
|
27
|
+
kind: "struct";
|
|
28
|
+
name: string;
|
|
29
|
+
};
|
|
30
|
+
/** A struct named by a type reference, through the type parameters of a generic helper's instance. */
|
|
31
|
+
export declare function structNameOf(node: ts.TypeNode, scope: Pick<TypeScope, "structArgs">): string | undefined;
|
|
23
32
|
/** What type resolution needs: imports, unit enums, and where to record Option<T> uses. */
|
|
24
33
|
export interface TypeScope {
|
|
25
34
|
imports: Map<string, string>;
|
|
35
|
+
/** Inside a generic helper's instance: type parameter -> the type it stands for. */
|
|
36
|
+
typeArgs?: Map<string, ScalarType>;
|
|
37
|
+
/** Inside a generic helper's instance: type parameter -> the struct it stands for. */
|
|
38
|
+
structArgs?: Map<string, string>;
|
|
26
39
|
enums: Map<string, EnumDef>;
|
|
27
40
|
dataEnums?: Map<string, DataEnumDef>;
|
|
28
41
|
options: Map<string, ScalarType | {
|
|
@@ -49,4 +62,6 @@ export declare function resolveOptionType(node: ts.TypeNode, scope: TypeScope):
|
|
|
49
62
|
}) | undefined;
|
|
50
63
|
/** Values a local, argument or helper parameter can hold. */
|
|
51
64
|
export declare function resolveValueType(node: ts.TypeNode, scope: TypeScope, allowVec?: boolean): ValueType | undefined;
|
|
65
|
+
/** The helper (or generic) a call's callee names: a local function by its declaration, others by name. */
|
|
66
|
+
export declare function calleeName(callee: ts.Identifier, decls: Map<ts.Node, string>, checker: ts.TypeChecker): string | undefined;
|
|
52
67
|
export { isScalar };
|