diff --git a/AGENTS.md b/AGENTS.md index 7d5ba8a94..9fe210800 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -212,7 +212,7 @@ new uncovered branch. To prove that a type resolves to what you claim, write `type _Name = Assert>` — `Assert` from -`fjs/asserts/module.f.mjs`, `Equal` from `fjs/types/ts/module.f.mjs`. A wrong +`fjs/asserts/types.ts`, `Equal` from `fjs/types/ts/types.ts`. A wrong claim is then a compile error (TS2344, "Type 'false' does not satisfy the constraint 'true'"), and the check costs nothing at runtime. diff --git a/CHANGELOG.md b/CHANGELOG.md index 16ac1818b..69bea2846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,12 @@ history. ## Unreleased +- **BREAKING CHANGES:** every public type exported by an authored `.f.mjs` + module moves to a sibling `types.ts` (31 modules, including `asserts`, + `types/list`, `types/bit_vec`, `types/result`, `text`, `crypto/sha2`) — + importers of these types must use the `types.ts` specifier. The runtime-empty + `fjs/types/option/module.f.mjs` becomes `fjs/types/option/types.ts` + [#1483](https://github.com/functionalscript/functionalscript/pull/1483) - `fjs/types/nullable/proof.f.ts`, `fjs/types/range/proof.f.ts`, `fjs/types/function/proof.f.ts`, `fjs/types/result/proof.f.ts`, and `fjs/types/function/compare/proof.f.ts` migrate to `proof.f.mjs` under diff --git a/fjs/asn.1/module.f.mjs b/fjs/asn.1/module.f.mjs index b73c6bee7..3b7316f0f 100644 --- a/fjs/asn.1/module.f.mjs +++ b/fjs/asn.1/module.f.mjs @@ -18,7 +18,13 @@ import { vec8, } from '../types/bit_vec/module.f.mjs' -/** @import { Unpacked, Vec } from '../types/bit_vec/module.f.mjs' */ +/** @import { Unpacked, Vec } from '../types/bit_vec/types.ts' */ + +/** + * @import { + * ObjectIdentifier, Raw, Record, Sequence, SupportedRecord, _Tag, + * } from './types.ts' + */ import { identity } from '../types/function/module.f.mjs' @@ -57,12 +63,6 @@ const tagNumberMask = 0b000_11111n * @typedef {readonly[_ClassPc, bigint]} _ParsedTag */ -/** - * ASN.1 tag number. - * - * @typedef {bigint} _Tag - */ - /** @type {([classPc, number]: _ParsedTag) => Vec} */ const parsedTagEncode = ([classPc, number]) => { const [firstByteNumber, rest] = number < tagNumberMask @@ -179,12 +179,6 @@ const lenDecode = v => { // raw -/** - * Raw ASN.1 TLV tuple. - * - * @typedef {readonly [_Tag, Vec]} Raw - */ - /** * Encodes a raw ASN.1 TLV tuple into a bit vector. * @@ -265,12 +259,6 @@ export const decodeOctetString = v => v // object identifier -/** - * ASN.1 OBJECT IDENTIFIER components. - * - * @typedef {readonly bigint[]} ObjectIdentifier - */ - /** * Encodes an OBJECT IDENTIFIER value. * @@ -313,12 +301,6 @@ export const decodeObjectIdentifier = v => { // sequence -/** - * ASN.1 ordered collection of records. - * - * @typedef {readonly Record[]} Sequence - */ - /** * @param {(vec: readonly Vec[]) => readonly Vec[]} map * @return {(...records: Sequence) => Vec} @@ -343,12 +325,6 @@ export const decodeSequence = v => decodeAll(decode)(v) // set -/** - * ASN.1 SET represented as a sequence of records. - * - * @typedef {Sequence} Set - */ - /** * Encodes a SET payload with canonical byte ordering. * @@ -364,43 +340,6 @@ export const encodeSet = */ export const decodeSet = decodeSequence -// Record - -/** - * Supported ASN.1 record variants. - * - * @typedef {| - * readonly[typeof boolean, boolean] | - * readonly[typeof integer, bigint] | - * readonly[typeof octetString, Vec] | - * readonly[typeof objectIdentifier, ObjectIdentifier] | - * readonly[typeof constructedSequence, Sequence] | - * readonly[typeof constructedSet, Set] - * } SupportedRecord - */ - -// Alternative: -// -// export type SupportedRecord = -// | boolean -// | bigint // integer -// | { tag: typeof octetString, value: Vec } -// | { tag: typeof objectIdentifier, value: ObjectIdentifier } -// | readonly Record[] // sequence -// | { tag: typeof constructedSet, value: readonly Record[] } -// -// export type UnsupportedRecord = -// | { tag: null, value: Vec } - -/** - * For unsupported tags, we just store the raw value including the tag and length, - * so that it can be re-encoded without loss of information. - * - * @typedef {Vec} UnsupportedRecord - */ - -/** @typedef {SupportedRecord | UnsupportedRecord} Record */ - // encode /** @type {(_: SupportedRecord) => Vec} */ diff --git a/fjs/asn.1/proof.f.mjs b/fjs/asn.1/proof.f.mjs index 8f75a410a..b60271924 100644 --- a/fjs/asn.1/proof.f.mjs +++ b/fjs/asn.1/proof.f.mjs @@ -1,5 +1,5 @@ import { empty, isVec, length, msb, uint, unpack, vec, vec8 } from '../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../types/bit_vec/types.ts' */ import { asBase } from '../types/nominal/module.f.mjs' @@ -18,7 +18,7 @@ import { encodeObjectIdentifier, decodeObjectIdentifier, } from './module.f.mjs' -/** @import { SupportedRecord, ObjectIdentifier } from './module.f.mjs' */ +/** @import { SupportedRecord, ObjectIdentifier } from './types.ts' */ import { assert, assertEq } from '../asserts/module.f.mjs' diff --git a/fjs/asn.1/todo/65z-asn1-tag-codec-table.md b/fjs/asn.1/todo/65z-asn1-tag-codec-table.md index e78b9d1cc..86d811bb1 100644 --- a/fjs/asn.1/todo/65z-asn1-tag-codec-table.md +++ b/fjs/asn.1/todo/65z-asn1-tag-codec-table.md @@ -82,7 +82,7 @@ declaration site per (tag, encode, decode) triple. ### Caveats -- `SupportedRecord` is a discriminated union keyed by tag (`fjs/asn.1/module.f.mjs:272-278`), +- `SupportedRecord` is a discriminated union keyed by tag (`fjs/asn.1/types.ts:45-51`), so the codec values are heterogeneously typed. The table approach loses the per-branch payload typing that the switch currently gives `recordToRaw`. A small per-tag helper that types `encode` against the union branch may be diff --git a/fjs/asn.1/types.ts b/fjs/asn.1/types.ts new file mode 100644 index 000000000..98bed3594 --- /dev/null +++ b/fjs/asn.1/types.ts @@ -0,0 +1,72 @@ +/** + * Types for ASN.1 BER/DER encoding and decoding over bit vectors. + * + * @module + */ + +import type { Vec } from '../types/bit_vec/types.ts' +import type { + boolean as booleanTag, + constructedSequence, + constructedSet, + integer, + objectIdentifier, + octetString, +} from './module.f.mjs' + +/** + * ASN.1 tag number. + */ +export type _Tag = bigint + +/** + * Raw ASN.1 TLV tuple. + */ +export type Raw = readonly [_Tag, Vec] + +/** + * ASN.1 OBJECT IDENTIFIER components. + */ +export type ObjectIdentifier = readonly bigint[] + +/** + * ASN.1 ordered collection of records. + */ +export type Sequence = readonly Record[] + +/** + * ASN.1 SET represented as a sequence of records. + */ +export type Set = Sequence + +/** + * Supported ASN.1 record variants. + */ +export type SupportedRecord = + | readonly [typeof booleanTag, boolean] + | readonly [typeof integer, bigint] + | readonly [typeof octetString, Vec] + | readonly [typeof objectIdentifier, ObjectIdentifier] + | readonly [typeof constructedSequence, Sequence] + | readonly [typeof constructedSet, Set] + +// Alternative: +// +// export type SupportedRecord = +// | boolean +// | bigint // integer +// | { tag: typeof octetString, value: Vec } +// | { tag: typeof objectIdentifier, value: ObjectIdentifier } +// | readonly Record[] // sequence +// | { tag: typeof constructedSet, value: readonly Record[] } +// +// export type UnsupportedRecord = +// | { tag: null, value: Vec } + +/** + * For unsupported tags, we just store the raw value including the tag and + * length, so that it can be re-encoded without loss of information. + */ +export type UnsupportedRecord = Vec + +export type Record = SupportedRecord | UnsupportedRecord diff --git a/fjs/asserts/module.f.mjs b/fjs/asserts/module.f.mjs index 2e2ec4f81..83f0599bf 100644 --- a/fjs/asserts/module.f.mjs +++ b/fjs/asserts/module.f.mjs @@ -33,15 +33,6 @@ export const assertEq = (...x) => { assert(a === b, x) } -/** - * Compile-time-only check: a type resolves only if it is exactly `true`. - * Used to assert type-level properties without any runtime cost, e.g. - * `type _ = Assert>`. - * - * @template {true} T - * @typedef {T} Assert - */ - /** * Asserts that `a` is neither `null` nor `undefined` and returns it, * narrowed to `T`. diff --git a/fjs/asserts/types.ts b/fjs/asserts/types.ts new file mode 100644 index 000000000..6cfbcb354 --- /dev/null +++ b/fjs/asserts/types.ts @@ -0,0 +1,12 @@ +/** + * Type-level assertion helpers. + * + * @module + */ + +/** + * Compile-time-only check: a type resolves only if it is exactly `true`. + * Used to assert type-level properties without any runtime cost, e.g. + * `type _ = Assert>`. + */ +export type Assert = T diff --git a/fjs/basen/base128/module.f.mjs b/fjs/basen/base128/module.f.mjs index 6bfb85007..0d59fcb5b 100644 --- a/fjs/basen/base128/module.f.mjs +++ b/fjs/basen/base128/module.f.mjs @@ -5,7 +5,7 @@ */ import { vec8, msb, empty } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ const { concat, popFront } = msb diff --git a/fjs/basen/base128/proof.f.mjs b/fjs/basen/base128/proof.f.mjs index 83bb830f1..0e1a7d3a6 100644 --- a/fjs/basen/base128/proof.f.mjs +++ b/fjs/basen/base128/proof.f.mjs @@ -1,5 +1,5 @@ import { empty, vec, vec8 } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ import { asBase } from '../../types/nominal/module.f.mjs' diff --git a/fjs/basen/base64/module.f.mjs b/fjs/basen/base64/module.f.mjs index 65341ed95..37d79fe4e 100644 --- a/fjs/basen/base64/module.f.mjs +++ b/fjs/basen/base64/module.f.mjs @@ -5,9 +5,9 @@ */ import { msb, length, vec, maxLength } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ -/** @import { Nullable } from '../../types/nullable/module.f.mjs' */ +/** @import { Nullable } from '../../types/nullable/types.ts' */ import { baseN } from "../module.f.mjs" diff --git a/fjs/basen/base64/proof.f.mjs b/fjs/basen/base64/proof.f.mjs index 3f5ac37ef..c71534f12 100644 --- a/fjs/basen/base64/proof.f.mjs +++ b/fjs/basen/base64/proof.f.mjs @@ -1,7 +1,7 @@ import { assertEq } from '../../asserts/module.f.mjs' import { empty, vec, repeat, vec8, maxLength } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ import { encode, decode } from './module.f.mjs' diff --git a/fjs/basen/cbase32/module.f.mjs b/fjs/basen/cbase32/module.f.mjs index c934b1664..172593cd9 100644 --- a/fjs/basen/cbase32/module.f.mjs +++ b/fjs/basen/cbase32/module.f.mjs @@ -5,9 +5,9 @@ */ import { msb, lsb, length, vec, empty } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ -/** @import { Nullable } from '../../types/nullable/module.f.mjs' */ +/** @import { Nullable } from '../../types/nullable/types.ts' */ import { baseN } from '../module.f.mjs' diff --git a/fjs/basen/cbase32/proof.f.mjs b/fjs/basen/cbase32/proof.f.mjs index ca43ef7b7..8aa1aeabb 100644 --- a/fjs/basen/cbase32/proof.f.mjs +++ b/fjs/basen/cbase32/proof.f.mjs @@ -1,5 +1,5 @@ import { empty, vec } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ import { cBase32ToVec, cBase32ToVec5x, vec5xToCBase32, vecToCBase32 } from './module.f.mjs' diff --git a/fjs/basen/module.f.mjs b/fjs/basen/module.f.mjs index ac81bdbb7..166ea3e48 100644 --- a/fjs/basen/module.f.mjs +++ b/fjs/basen/module.f.mjs @@ -13,14 +13,14 @@ */ import { msb, lsb, vec, chunkList, unpack } from '../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../types/bit_vec/types.ts' */ import { fold } from '../types/list/module.f.mjs' -/** @import { List } from '../types/list/module.f.mjs' */ +/** @import { List } from '../types/list/types.ts' */ import { compose } from '../types/function/module.f.mjs' -/** @import { Nullable } from '../types/nullable/module.f.mjs' */ +/** @import { BaseN } from './types.ts' */ const { unpackSplit } = msb @@ -30,15 +30,6 @@ const { tryListToVec: reversedListToVec } = lsb // `baseN(...)` codec (base64, cbase32, ...). const chunkListMsb = chunkList(msb) -/** - * The encode/decode pair returned by {@link baseN}. - * - * @typedef {{ - * readonly vecToString: (v: Vec) => string - * readonly stringToVec: (s: string) => Nullable - * }} BaseN - */ - /** * Builds a {@link BaseN} codec for a fixed chunk width and alphabet. * diff --git a/fjs/basen/types.ts b/fjs/basen/types.ts new file mode 100644 index 000000000..a7dc081f4 --- /dev/null +++ b/fjs/basen/types.ts @@ -0,0 +1,16 @@ +/** + * Types for the shared bit-codec factory. + * + * @module + */ + +import type { Vec } from '../types/bit_vec/types.ts' +import type { Nullable } from '../types/nullable/types.ts' + +/** + * The encode/decode pair returned by `baseN` in `./module.f.mjs`. + */ +export type BaseN = { + readonly vecToString: (v: Vec) => string + readonly stringToVec: (s: string) => Nullable +} diff --git a/fjs/bnf/descent/module.f.ts b/fjs/bnf/descent/module.f.ts index a55d7be69..85d38a2e1 100644 --- a/fjs/bnf/descent/module.f.ts +++ b/fjs/bnf/descent/module.f.ts @@ -13,7 +13,7 @@ * * @module */ -import { type CodePoint } from '../../text/utf16/module.f.mjs' +import type { CodePoint } from '../../text/utf16/types.ts' import { rangeDecode, type TerminalRange } from '../module.f.ts' import { contains as rangeContains } from '../../types/range/module.f.mjs' import { definedEntries } from '../../types/object/module.f.ts' diff --git a/fjs/bnf/descent/proof.f.ts b/fjs/bnf/descent/proof.f.ts index 2022a8643..de3c3a5e5 100644 --- a/fjs/bnf/descent/proof.f.ts +++ b/fjs/bnf/descent/proof.f.ts @@ -1,4 +1,5 @@ -import { type CodePoint, stringToCodePointList } from '../../text/utf16/module.f.mjs' +import type { CodePoint } from '../../text/utf16/types.ts' +import { stringToCodePointList } from '../../text/utf16/module.f.mjs' import { map, toArray } from '../../types/list/module.f.mjs' import { commaJoin0Plus, option, range, repeat0Plus, set } from '../module.f.ts' import { deterministic } from '../testlib.f.ts' diff --git a/fjs/bnf/ll1/module.f.ts b/fjs/bnf/ll1/module.f.ts index eaf63007c..f2436d759 100644 --- a/fjs/bnf/ll1/module.f.ts +++ b/fjs/bnf/ll1/module.f.ts @@ -10,10 +10,11 @@ * * @module */ -import { type CodePoint } from '../../text/utf16/module.f.mjs' +import type { CodePoint } from '../../text/utf16/types.ts' import { strictEqual } from '../../types/function/operator/module.f.mjs' import { toArray } from '../../types/list/module.f.mjs' -import { rangeMap, type RangeMapArray } from '../../types/range_map/module.f.mjs' +import type { RangeMapArray } from '../../types/range_map/types.ts' +import { rangeMap } from '../../types/range_map/module.f.mjs' import { contains, set, type StringSet } from '../../types/string_set/module.f.ts' import { rangeDecode } from '../module.f.ts' import { definedEntries, type StringMap } from '../../types/object/module.f.ts' diff --git a/fjs/bnf/module.f.ts b/fjs/bnf/module.f.ts index e73b61c0e..a80d2489a 100644 --- a/fjs/bnf/module.f.ts +++ b/fjs/bnf/module.f.ts @@ -6,9 +6,12 @@ * * @module */ + +import type { Tuple } from '../types/array/types.ts' + import { codePointListToString, stringToCodePointList } from '../text/utf16/module.f.mjs' import { definedValues, type StringMap } from '../types/object/module.f.ts' -import { isTuple, type Tuple } from '../types/array/module.f.mjs' +import { isTuple } from '../types/array/module.f.mjs' import { map, toArray, repeat as listRepeat } from '../types/list/module.f.mjs' import { contains } from '../types/range/module.f.mjs' import { assert } from '../asserts/module.f.mjs' diff --git a/fjs/bnf/token_symbol/module.f.ts b/fjs/bnf/token_symbol/module.f.ts index 4a04edd7a..3a54c6bac 100644 --- a/fjs/bnf/token_symbol/module.f.ts +++ b/fjs/bnf/token_symbol/module.f.ts @@ -9,7 +9,8 @@ * @module */ import { assert } from '../../asserts/module.f.mjs' -import { fromUndefined, type Nullable } from '../../types/nullable/module.f.mjs' +import type { Nullable } from '../../types/nullable/types.ts' +import { fromUndefined } from '../../types/nullable/module.f.mjs' import { eof, rangeDecode, unicodeRange } from '../module.f.ts' const [, unicodeLast] = rangeDecode(unicodeRange) diff --git a/fjs/cas/evo/module.f.ts b/fjs/cas/evo/module.f.ts index 4d7b8e7d9..e80d5b83f 100644 --- a/fjs/cas/evo/module.f.ts +++ b/fjs/cas/evo/module.f.ts @@ -50,11 +50,12 @@ import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.mjs' import { fromVec } from '../../text/utf8/module.f.mjs' import { tryUtf8 } from '../../text/module.f.mjs' import { decodeText, encodeText, dialect, checkReferences, isHash, type LockMap, type Revision } from '../../media/revision/module.f.ts' -import { ok, error, type Ok, type Result } from '../../types/result/module.f.mjs' +import type { Ok, Result } from '../../types/result/types.ts' +import { ok, error } from '../../types/result/module.f.mjs' import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.ts' import { at, definedEntries, type StringMap } from '../../types/object/module.f.ts' import { unwrap } from '../../types/nullable/module.f.mjs' -import type { Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' import { isNotFound, type IoResult } from '../../effects/node/module.f.ts' /** A cBase32 content hash, as accepted/returned by `Cas`. */ diff --git a/fjs/cas/evo/proof.f.ts b/fjs/cas/evo/proof.f.ts index 40b2f073b..d06810337 100644 --- a/fjs/cas/evo/proof.f.ts +++ b/fjs/cas/evo/proof.f.ts @@ -3,10 +3,12 @@ import { pure } from '../../effects/module.f.ts' import { fileCas, type Cas } from '../module.f.ts' import { sha256 } from '../../crypto/sha2/module.f.mjs' import { emptyState, virtual } from '../../effects/node/virtual/module.f.ts' -import { vec, vec8, type Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { vec, vec8 } from '../../types/bit_vec/module.f.mjs' import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.mjs' import { unwrap } from '../../types/nullable/module.f.mjs' -import { ok, error, type Ok } from '../../types/result/module.f.mjs' +import type { Ok } from '../../types/result/types.ts' +import { ok, error } from '../../types/result/module.f.mjs' import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.ts' import type { IoResult } from '../../effects/node/module.f.ts' import { tryUtf8 } from '../../text/module.f.mjs' diff --git a/fjs/cas/module.f.ts b/fjs/cas/module.f.ts index 72ba62ecb..11433ea51 100644 --- a/fjs/cas/module.f.ts +++ b/fjs/cas/module.f.ts @@ -3,9 +3,11 @@ * * @module */ -import { sha256, type Sha2, type State as Sha2State } from '../crypto/sha2/module.f.mjs' +import type { Sha2, State as Sha2State } from '../crypto/sha2/types.ts' +import { sha256 } from '../crypto/sha2/module.f.mjs' import { join, normalize, parse } from '../path/module.f.ts' -import { empty, length, maxLength, maxLengthBytes, msb, vec, type Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' +import { empty, length, maxLength, maxLengthBytes, msb, vec } from '../types/bit_vec/module.f.mjs' import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.mjs' import { foldStep, forEachStep, history, historyStep, okStep, pure, step, type Effect, type Operation } from '../effects/module.f.ts' import { eff } from '../effects/eff/module.f.ts' @@ -37,7 +39,7 @@ import { } from '../effects/node/module.f.ts' import { toOption } from '../types/nullable/module.f.mjs' import { error, ok, unwrap } from '../types/result/module.f.mjs' -import { splitAt } from '../types/string/module.f.ts' +import { splitAt } from '../types/string/module.f.mjs' import { nonEmpty, empty as elEmpty, type List } from '../effects/list/module.f.ts' const split2 = splitAt(2) diff --git a/fjs/cas/proof.f.ts b/fjs/cas/proof.f.ts index 3945149e6..026282639 100644 --- a/fjs/cas/proof.f.ts +++ b/fjs/cas/proof.f.ts @@ -1,10 +1,12 @@ -import { length, maxLength, msb, vec, vec8, type Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' +import { length, maxLength, msb, vec, vec8 } from '../types/bit_vec/module.f.mjs' import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.mjs' import { computeSync, sha256 } from '../crypto/sha2/module.f.mjs' import { fileCas, casAddFile, collectRead, type FileCasOperation, casUpload } from './module.f.ts' import { match, pure, runPure, step, type Effect } from '../effects/module.f.ts' import { mkdir, writeFile, rm, readFile, type ReadFile, type WriteFile, type Rm, type Mkdir, type IoResult, access } from '../effects/node/module.f.ts' -import { error, ok, type Ok } from '../types/result/module.f.mjs' +import type { Ok } from '../types/result/types.ts' +import { error, ok } from '../types/result/module.f.mjs' import { emptyState, virtual } from '../effects/node/virtual/module.f.ts' import { join } from '../path/module.f.ts' import { nonEmpty, empty, type List } from '../effects/list/module.f.ts' diff --git a/fjs/common/monoid/module.f.mjs b/fjs/common/monoid/module.f.mjs index 7cabb8d5d..f22d4637f 100644 --- a/fjs/common/monoid/module.f.mjs +++ b/fjs/common/monoid/module.f.mjs @@ -6,57 +6,11 @@ * * @module */ -/** @import { Fold, Reduce } from '../../types/function/operator/module.f.mjs' */ +/** @import { Fold } from '../../types/function/operator/types.ts' */ import { reduce } from '../../types/list/module.f.mjs' -/** @import { List } from '../../types/list/module.f.mjs' */ +/** @import { List } from '../../types/list/types.ts' */ import { flip } from '../../types/function/module.f.mjs' - -/** - * Represents a monoid, an algebraic structure with a binary operation - * and an identity (neutral) element. - * - * A monoid satisfies the following properties: - * 1. **Associativity**: The operation must be associative. - * For all `a`, `b`, and `c` in the set, `(a operation b) operation c = a operation (b operation c)`. - * {@link https://en.wikipedia.org/wiki/Associative_property Learn more about associativity}. - * 2. **Identity Element**: There exists an element (called the identity) such that, - * when combined with any other element under the operation, it leaves the other element unchanged. - * {@link https://en.wikipedia.org/wiki/Identity_element Learn more about identity elements}. - * - * Learn more about monoids: {@link https://en.wikipedia.org/wiki/Monoid}. - * - * @template T The type of the elements in the monoid. - * @typedef {{ - * readonly identity: T - * readonly operation: Reduce - * }} Monoid - * - * @property identity - * - * The identity (neutral) element for the monoid. - * When combined with any value under the `operation`, it leaves the other value unchanged. - * - * Examples: - * - `0` for addition - * - `1` for multiplication - * - `""` for string concatenation - * - `[]` for array concatenation - * - * Learn more: {@link https://en.wikipedia.org/wiki/Identity_element} - * - * @property operation - * - * The associative binary operation of the monoid. - * Takes one value of type `T` and returns a function that takes another value of type `T`, - * producing a result of type `T`. - * - * Examples: - * - `(a, b) => a + b` for addition - * - `(a, b) => a * b` for multiplication - * - `(a, b) => a.concat(b)` for arrays or strings - * - * Learn more: {@link https://en.wikipedia.org/wiki/Binary_operation} - */ +/** @import { Monoid } from './types.ts' */ /** * Repeats a monoid operation `n` times on the given element `a`. diff --git a/fjs/common/monoid/proof.f.ts b/fjs/common/monoid/proof.f.ts index 4ef43d7a2..6685432ae 100644 --- a/fjs/common/monoid/proof.f.ts +++ b/fjs/common/monoid/proof.f.ts @@ -1,4 +1,5 @@ -import { repeat, fold, type Monoid } from "./module.f.mjs"; +import type { Monoid } from "./types.ts" +import { repeat, fold } from "./module.f.mjs"; import { assertEq } from '../../asserts/module.f.mjs' export const proof = { diff --git a/fjs/common/monoid/types.ts b/fjs/common/monoid/types.ts new file mode 100644 index 000000000..169ed5717 --- /dev/null +++ b/fjs/common/monoid/types.ts @@ -0,0 +1,52 @@ +/** + * The `Monoid` algebraic structure. + * + * @module + */ + +import type { Reduce } from '../../types/function/operator/types.ts' + +/** + * Represents a monoid, an algebraic structure with a binary operation + * and an identity (neutral) element. + * + * A monoid satisfies the following properties: + * 1. **Associativity**: The operation must be associative. + * For all `a`, `b`, and `c` in the set, `(a operation b) operation c = a operation (b operation c)`. + * {@link https://en.wikipedia.org/wiki/Associative_property Learn more about associativity}. + * 2. **Identity Element**: There exists an element (called the identity) such that, + * when combined with any other element under the operation, it leaves the other element unchanged. + * {@link https://en.wikipedia.org/wiki/Identity_element Learn more about identity elements}. + * + * Learn more about monoids: {@link https://en.wikipedia.org/wiki/Monoid}. + * + * @property identity + * + * The identity (neutral) element for the monoid. + * When combined with any value under the `operation`, it leaves the other value unchanged. + * + * Examples: + * - `0` for addition + * - `1` for multiplication + * - `""` for string concatenation + * - `[]` for array concatenation + * + * Learn more: {@link https://en.wikipedia.org/wiki/Identity_element} + * + * @property operation + * + * The associative binary operation of the monoid. + * Takes one value of type `T` and returns a function that takes another value of type `T`, + * producing a result of type `T`. + * + * Examples: + * - `(a, b) => a + b` for addition + * - `(a, b) => a * b` for multiplication + * - `(a, b) => a.concat(b)` for arrays or strings + * + * Learn more: {@link https://en.wikipedia.org/wiki/Binary_operation} + */ +export type Monoid = { + readonly identity: T + readonly operation: Reduce +} diff --git a/fjs/crypto/hmac/module.f.ts b/fjs/crypto/hmac/module.f.ts index 5c88daed7..dc2e51cf3 100644 --- a/fjs/crypto/hmac/module.f.ts +++ b/fjs/crypto/hmac/module.f.ts @@ -18,8 +18,10 @@ * ``` */ -import { length, type Vec, msb, vec, vec8, type Reduce, repeat } from '../../types/bit_vec/module.f.mjs' -import { computeSync, type Sha2 } from '../sha2/module.f.mjs' +import type { Vec, Reduce } from '../../types/bit_vec/types.ts' +import { length, msb, vec, vec8, repeat } from '../../types/bit_vec/module.f.mjs' +import type { Sha2 } from '../sha2/types.ts' +import { computeSync } from '../sha2/module.f.mjs' const { concat, xor } = msb diff --git a/fjs/crypto/pow/module.f.mjs b/fjs/crypto/pow/module.f.mjs index b6e2acd5e..690c7709d 100644 --- a/fjs/crypto/pow/module.f.mjs +++ b/fjs/crypto/pow/module.f.mjs @@ -7,10 +7,11 @@ import { mask } from '../../types/bigint/module.f.mjs' import { uint } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ -/** @import { Nullable } from '../../types/nullable/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ +/** @import { Nullable } from '../../types/nullable/types.ts' */ import { computeSync, sha256 } from '../sha2/module.f.mjs' -/** @import { Sha2 } from '../sha2/module.f.mjs' */ +/** @import { Sha2 } from '../sha2/types.ts' */ +/** @import { Pow } from './types.ts' */ const nBitsMantissa = mask(24n) const mantissaSign = 0x00800000n @@ -66,21 +67,6 @@ export const targetFromNBits = nBits => { return target } -/** - * @typedef {{ - * readonly hashInt: (data: Vec) => bigint - * readonly meets: (nBits: bigint) => (data: Vec) => boolean - * }} Pow - * - * @property hashInt - * - * Hash `data` with the configured `Sha2`; digest as big-endian uint256. - * - * @property meets - * - * Whether `hashInt(data) <= targetFromNBits(nBits)`; `false` when **nBits** is invalid. - */ - /** * Builds PoW helpers for a hash function (typical consumer: {@link sha256}). * diff --git a/fjs/crypto/pow/types.ts b/fjs/crypto/pow/types.ts new file mode 100644 index 000000000..7de8b37f0 --- /dev/null +++ b/fjs/crypto/pow/types.ts @@ -0,0 +1,21 @@ +/** + * Types for Bitcoin-style proof-of-work verification. + * + * @module + */ + +import type { Vec } from '../../types/bit_vec/types.ts' + +/** + * @property hashInt + * + * Hash `data` with the configured `Sha2`; digest as big-endian uint256. + * + * @property meets + * + * Whether `hashInt(data) <= targetFromNBits(nBits)`; `false` when **nBits** is invalid. + */ +export type Pow = { + readonly hashInt: (data: Vec) => bigint + readonly meets: (nBits: bigint) => (data: Vec) => boolean +} diff --git a/fjs/crypto/secp/module.f.mjs b/fjs/crypto/secp/module.f.mjs index 9d8cb63ee..c28fee3a2 100644 --- a/fjs/crypto/secp/module.f.mjs +++ b/fjs/crypto/secp/module.f.mjs @@ -6,45 +6,10 @@ * @module */ -/** @import { Equal, Fold, Reduce } from '../../types/function/operator/module.f.mjs' */ +/** @import { Equal, Fold, Reduce } from '../../types/function/operator/types.ts' */ import { prime_field, sqrt } from '../../types/prime_field/module.f.mjs' -/** @import { PrimeField } from '../../types/prime_field/module.f.mjs' */ import { repeat } from '../../common/monoid/module.f.mjs' - -/** A 2D point represented as a pair of `bigint` values `[x, y]`. @typedef {readonly [bigint, bigint]} Point2D */ - -/** - * A 2D point on an elliptic curve, represented as a pair of `bigint` values. - * `null` represents the point at infinity (`O`). - * - * @typedef {Point2D | null} Point - */ - -/** - * Initialization parameters for an elliptic curve. - * - * @typedef {{ - * readonly p: bigint - * readonly a: readonly [bigint, bigint] - * readonly g: readonly [bigint, bigint] - * readonly n: bigint - * }} Init - */ - -/** - * Represents an elliptic curve and its associated operations. - * - * @typedef {{ - * readonly pf: PrimeField - * readonly nf: PrimeField - * readonly g: Point - * readonly y2: (x: bigint) => bigint - * readonly y: (x: bigint) => bigint | null - * readonly neg: (a: Point) => Point - * readonly add: Reduce - * readonly mul: Fold - * }} Curve - */ +/** @import { Curve, Init, Point, Point2D } from './types.ts' */ /** * Constructs an elliptic curve with the given initialization parameters. diff --git a/fjs/crypto/secp/proof.f.mjs b/fjs/crypto/secp/proof.f.mjs index 67481e8dc..22ca728c1 100644 --- a/fjs/crypto/secp/proof.f.mjs +++ b/fjs/crypto/secp/proof.f.mjs @@ -1,7 +1,7 @@ import { assert, assertEq, assertNotNullish } from '../../asserts/module.f.mjs' import { prime_field } from '../../types/prime_field/module.f.mjs' import { curve, secp256k1, secp192r1, secp256r1, eq, secp384r1, secp521r1 } from './module.f.mjs' -/** @import { Point, Curve, Init } from './module.f.mjs' */ +/** @import { Point, Curve, Init } from './types.ts' */ /** @type {(param: Curve) => () => void} */ const poker = param => () => { diff --git a/fjs/crypto/secp/todo/init-named-coefficients.md b/fjs/crypto/secp/todo/init-named-coefficients.md index 29111cbcd..b0ce6cbef 100644 --- a/fjs/crypto/secp/todo/init-named-coefficients.md +++ b/fjs/crypto/secp/todo/init-named-coefficients.md @@ -5,29 +5,27 @@ ### Problem -`Init` (`fjs/crypto/secp/module.f.mjs:26-31`) stores the curve-equation +`Init` (`fjs/crypto/secp/types.ts:22-27`) stores the curve-equation coefficients as a pair under the name `a`: -```js -/** - * @typedef {{ - * readonly p: bigint - * readonly a: readonly [bigint, bigint] - * readonly g: readonly [bigint, bigint] - * readonly n: bigint - * }} Init - */ +```ts +export type Init = { + readonly p: bigint + readonly a: readonly [bigint, bigint] + readonly g: readonly [bigint, bigint] + readonly n: bigint +} ``` The pair's convention is index = power of `x`: `curve` unpacks -`({ a: [a0, a1] })` (`:72`) and builds the equation (`:86`) as +`({ a: [a0, a1] })` (`:37`) and builds the equation (`:51`) as `x³ + a1·x¹ + a0·x⁰`. The indexed scheme itself is good — the index states the coefficient's defining property (its power) — but the letter `a` is a bad fit: in the standard Weierstrass notation `y² = x³ + a·x + b`, `a` is specifically the *linear* coefficient, so a field named `a` whose slot `a0` holds Weierstrass `b` invites misreading. That's why every non-trivial curve -literal needs prose comments to decode it (`secp256r1` `:198-199`, -`secp384r1` `:214-215`, `secp521r1` `:230-231`): +literal needs prose comments to decode it (`secp256r1` `:163-164`, +`secp384r1` `:179-180`, `secp521r1` `:195-196`): ```ts a: [ @@ -82,9 +80,9 @@ c: [ and add the same comments to `secp192r1` and `secp256k1`, which have none today. Update all **five** active curve literals in -`fjs/crypto/secp/module.f.mjs` (`secp192r1` `:146`, `secp256k1` `:181`, -`secp256r1` `:195`, `secp384r1` `:211`, `secp521r1` `:227`), the -commented-out `secp224r1` block (`:164-175`, so it doesn't rot on the old +`fjs/crypto/secp/module.f.mjs` (`secp192r1` `:111`, `secp256k1` `:146`, +`secp256r1` `:160`, `secp384r1` `:176`, `secp521r1` `:192`), the +commented-out `secp224r1` block (`:129-140`, so it doesn't rot on the old shape), and the `example` init in `fjs/crypto/secp/proof.f.mjs:63-68`. This is a breaking change to an exported type — update every importer in the same PR per @@ -103,9 +101,9 @@ AGENTS.md; `curve`'s behavior and all curve constants are unchanged. ### Related -- `fjs/crypto/secp/module.f.mjs:14` (`Point2D`), `:26-31` (`Init`), `:72-86` - (`curve`/`y2`), `:146-238` (curve literals, including the commented-out - `secp224r1`). +- `fjs/crypto/secp/types.ts:11` (`Point2D`), `:22-27` (`Init`). +- `fjs/crypto/secp/module.f.mjs:37-51` (`curve`/`y2`), `:111-203` (curve + literals, including the commented-out `secp224r1`). - `fjs/crypto/todo/666-crypto-sign-fromcurve.md` — reshapes the `sign`→`curve` boundary; independent of this record cleanup, but land whichever goes first and rebase the other. diff --git a/fjs/crypto/secp/types.ts b/fjs/crypto/secp/types.ts new file mode 100644 index 000000000..33e5aaff4 --- /dev/null +++ b/fjs/crypto/secp/types.ts @@ -0,0 +1,41 @@ +/** + * Types for short Weierstrass elliptic-curve arithmetic over a prime field. + * + * @module + */ + +import type { Fold, Reduce } from '../../types/function/operator/types.ts' +import type { PrimeField } from '../../types/prime_field/types.ts' + +/** A 2D point represented as a pair of `bigint` values `[x, y]`. */ +export type Point2D = readonly [bigint, bigint] + +/** + * A 2D point on an elliptic curve, represented as a pair of `bigint` values. + * `null` represents the point at infinity (`O`). + */ +export type Point = Point2D | null + +/** + * Initialization parameters for an elliptic curve. + */ +export type Init = { + readonly p: bigint + readonly a: readonly [bigint, bigint] + readonly g: readonly [bigint, bigint] + readonly n: bigint +} + +/** + * Represents an elliptic curve and its associated operations. + */ +export type Curve = { + readonly pf: PrimeField + readonly nf: PrimeField + readonly g: Point + readonly y2: (x: bigint) => bigint + readonly y: (x: bigint) => bigint | null + readonly neg: (a: Point) => Point + readonly add: Reduce + readonly mul: Fold +} diff --git a/fjs/crypto/sha2/module.f.mjs b/fjs/crypto/sha2/module.f.mjs index 9736a5e2c..f8145ecb0 100644 --- a/fjs/crypto/sha2/module.f.mjs +++ b/fjs/crypto/sha2/module.f.mjs @@ -4,9 +4,9 @@ * @module */ -/** @import { Tuple } from '../../types/array/module.f.mjs' */ +/** @import { Tuple } from '../../types/array/types.ts' */ import { mask } from '../../types/bigint/module.f.mjs' -/** @import { Reduce } from '../../types/bigint/module.f.mjs' */ +/** @import { Reduce } from '../../types/bigint/types.ts' */ import { vec, length, @@ -15,10 +15,11 @@ import { chunkList, uint, } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ -/** @import { Fold } from '../../types/function/operator/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ +/** @import { Fold } from '../../types/function/operator/types.ts' */ import { fold } from '../../types/list/module.f.mjs' -/** @import { List } from '../../types/list/module.f.mjs' */ +/** @import { List } from '../../types/list/types.ts' */ +/** @import { Base, Sha2, State, V16, V8 } from './types.ts' */ const { concat, front } = msb @@ -30,41 +31,6 @@ const chunkListMsb = chunkList(msb) /** @typedef {Tuple<4, bigint>} _V4 */ -/** - * 8-word SHA-2 state vector. - * - * @typedef {Tuple<8, bigint>} V8 - */ - -/** - * 16-word SHA-2 message schedule chunk. - * - * @typedef {Tuple<16, bigint>} V16 - */ - -/** - * State of the SHA-2 algorithm: `hash` is the current hash value, `len` the - * length of the data processed so far, and `remainder` the data that has not - * yet been processed. - * - * @typedef {{ - * readonly hash: V8, - * readonly len: bigint, - * readonly remainder: Vec, - * }} State - */ - -/** - * @typedef {{ - * readonly bitLength: bigint, - * readonly chunkLength: bigint, - * readonly compress: (i: V8) => (u: bigint) => V8, - * readonly fromV8: (a: V8) => bigint, - * readonly append: Fold, - * readonly end: (hashLength: bigint) => (state: State) => Vec, - * }} Base - */ - /** * @typedef {{ * readonly logBitLen: bigint, @@ -284,14 +250,6 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => { * state = sha224.append(state)(s) * const h = sha224.end(state) // 0x1_619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn * ``` - * - * @typedef {{ - * readonly hashLength: bigint, - * readonly blockLength: bigint, - * readonly init: State, - * readonly append: Fold, - * readonly end: (state: State) => Vec, - * }} Sha2 */ /** @type {(base: Base, hash: V8, hashLength: bigint) => Sha2} */ diff --git a/fjs/crypto/sha2/proof.f.ts b/fjs/crypto/sha2/proof.f.ts index 35f9b682d..d6d929a0f 100644 --- a/fjs/crypto/sha2/proof.f.ts +++ b/fjs/crypto/sha2/proof.f.ts @@ -3,18 +3,8 @@ import { repeat, uint, vec } from '../../types/bit_vec/module.f.mjs' import { flip } from '../../types/function/module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' import { map } from '../../types/list/module.f.mjs' -import { - base32, - base64, - computeSync, - type Sha2, - sha224, - sha256, - sha384, - sha512, - sha512x224, - sha512x256, -} from './module.f.mjs' +import type { Sha2 } from './types.ts' +import { base32, base64, computeSync, sha224, sha256, sha384, sha512, sha512x224, sha512x256 } from './module.f.mjs' const checkEmpty = ({ init, end, hashLength }: Sha2) => (x: bigint) => { const result = end(init) diff --git a/fjs/crypto/sha2/types.ts b/fjs/crypto/sha2/types.ts new file mode 100644 index 000000000..f4b94adf3 --- /dev/null +++ b/fjs/crypto/sha2/types.ts @@ -0,0 +1,63 @@ +/** + * Types for the SHA-2 family of hash functions. + * + * @module + */ + +import type { Tuple } from '../../types/array/types.ts' +import type { Vec } from '../../types/bit_vec/types.ts' +import type { Fold } from '../../types/function/operator/types.ts' + +/** + * 8-word SHA-2 state vector. + */ +export type V8 = Tuple<8, bigint> + +/** + * 16-word SHA-2 message schedule chunk. + */ +export type V16 = Tuple<16, bigint> + +/** + * State of the SHA-2 algorithm: `hash` is the current hash value, `len` the + * length of the data processed so far, and `remainder` the data that has not + * yet been processed. + */ +export type State = { + readonly hash: V8 + readonly len: bigint + readonly remainder: Vec +} + +export type Base = { + readonly bitLength: bigint + readonly chunkLength: bigint + readonly compress: (i: V8) => (u: bigint) => V8 + readonly fromV8: (a: V8) => bigint + readonly append: Fold + readonly end: (hashLength: bigint) => (state: State) => Vec +} + +/** + * SHA2. See https://en.wikipedia.org/wiki/SHA-2 + * + * `hashLength` is a hash length, `blockLength` an internal block length, + * `init` the initial state of the SHA-2 algorithm, `append` adds data to a + * state and returns the new state, and `end` finalizes the hash of a state. + * + * @example + * + * ```js + * const s = msbUtf8("The quick brown fox jumps over the lazy dog.") + * let state = sha224.init + * state = sha224.append(state)(s) + * const h = sha224.end(state) // 0x1_619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn + * ``` + */ +export type Sha2 = { + readonly hashLength: bigint + readonly blockLength: bigint + readonly init: State + readonly append: Fold + readonly end: (state: State) => Vec +} diff --git a/fjs/crypto/sign/module.f.ts b/fjs/crypto/sign/module.f.ts index 45e7f00aa..4abb1e064 100644 --- a/fjs/crypto/sign/module.f.ts +++ b/fjs/crypto/sign/module.f.ts @@ -4,12 +4,14 @@ * @module */ import { assertNotNullish } from '../../asserts/module.f.mjs' -import type { Tuple } from '../../types/array/module.f.mjs' +import type { Tuple } from '../../types/array/types.ts' import { bitLength, divUp8, roundUp8 } from '../../types/bigint/module.f.mjs' -import { empty, length, msb, repeat, unpack, vec, vec8, type Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { empty, length, msb, repeat, unpack, vec, vec8 } from '../../types/bit_vec/module.f.mjs' import { hmac } from '../hmac/module.f.ts' -import type { Curve } from '../secp/module.f.mjs' -import { computeSync, type Sha2 } from '../sha2/module.f.mjs' +import type { Curve } from '../secp/types.ts' +import type { Sha2 } from '../sha2/types.ts' +import { computeSync } from '../sha2/module.f.mjs' export type All = { readonly q: bigint diff --git a/fjs/crypto/sign/proof.f.ts b/fjs/crypto/sign/proof.f.ts index 676893938..ba26f5c1e 100644 --- a/fjs/crypto/sign/proof.f.ts +++ b/fjs/crypto/sign/proof.f.ts @@ -1,9 +1,12 @@ import { utf8 } from "../../text/module.f.mjs" -import type { Tuple } from "../../types/array/module.f.mjs" -import { empty, msb, repeat, vec, vec8, type Vec } from "../../types/bit_vec/module.f.mjs" +import type { Tuple } from "../../types/array/types.ts" +import type { Vec } from "../../types/bit_vec/types.ts" +import { empty, msb, repeat, vec, vec8 } from "../../types/bit_vec/module.f.mjs" import { hmac } from "../hmac/module.f.ts" -import { secp192r1, secp256r1, secp384r1, secp521r1, type Curve } from "../secp/module.f.mjs" -import { computeSync, sha224, sha256, sha384, sha512, type Sha2 } from "../sha2/module.f.mjs" +import type { Curve } from "../secp/types.ts" +import { secp192r1, secp256r1, secp384r1, secp521r1 } from "../secp/module.f.mjs" +import type { Sha2 } from "../sha2/types.ts" +import { computeSync, sha224, sha256, sha384, sha512 } from "../sha2/module.f.mjs" import { all, concat, computeK, fromCurve, sign } from "./module.f.ts" import { assertEq } from '../../asserts/module.f.mjs' diff --git a/fjs/crypto/vdf/module.f.ts b/fjs/crypto/vdf/module.f.ts index 38c6eefb2..82562ee64 100644 --- a/fjs/crypto/vdf/module.f.ts +++ b/fjs/crypto/vdf/module.f.ts @@ -14,9 +14,10 @@ * if (y === null || !sloth.verify(steps)(x)(y)) { throw y } * ``` */ -import { modSqrt, prime_field, type PrimeField } from '../../types/prime_field/module.f.mjs' -import type { Nullable } from '../../types/nullable/module.f.mjs' -import type { Unary } from '../../types/bigint/module.f.mjs' +import type { PrimeField } from '../../types/prime_field/types.ts' +import { modSqrt, prime_field } from '../../types/prime_field/module.f.mjs' +import type { Nullable } from '../../types/nullable/types.ts' +import type { Unary } from '../../types/bigint/types.ts' /** Sloth VDF modulus (3072-bit safe prime, same as reference implementations). */ export const p = diff --git a/fjs/crypto/vdf/todo/iterate-combinator.md b/fjs/crypto/vdf/todo/iterate-combinator.md index ccc67cce9..4dbaa074d 100644 --- a/fjs/crypto/vdf/todo/iterate-combinator.md +++ b/fjs/crypto/vdf/todo/iterate-combinator.md @@ -51,7 +51,7 @@ export const iterate = (n: bigint) => (f: (v: T) => T) => (value: T): T => { (keeping the internal `let`/`while` — a recursive form would overflow the stack for the large step counts VDFs use). `squareLoop`/`modSqrtLoop` call `iterate`; the local `repeatSeq` is deleted. Alternative home: a -bigint-typed form next to `Unary` in `fjs/types/bigint/module.f.mjs`, but the +bigint-typed form next to `Unary` in `fjs/types/bigint/types.ts`, but the combinator is not bigint-specific in `T` — only the counter is — so `fjs/types/function` is the natural owner. diff --git a/fjs/dev/module.f.ts b/fjs/dev/module.f.ts index a13d1f21e..80ea5265b 100644 --- a/fjs/dev/module.f.ts +++ b/fjs/dev/module.f.ts @@ -13,7 +13,7 @@ import { type Import, type Readdir } from '../effects/node/module.f.ts' -import { cmp as strCmp } from '../types/string/module.f.ts' +import { cmp as strCmp } from '../types/string/module.f.mjs' import type { StringMap } from '../types/object/module.f.ts' import { unwrap } from '../types/result/module.f.mjs' import { pure, step, type Effect } from '../effects/module.f.ts' diff --git a/fjs/dev/package_json/module.f.ts b/fjs/dev/package_json/module.f.ts index 4642d4ea2..955c364cc 100644 --- a/fjs/dev/package_json/module.f.ts +++ b/fjs/dev/package_json/module.f.ts @@ -9,7 +9,8 @@ import { option, record, string } from '../../types/rtti/module.f.ts' import { validate as rttiValidate } from '../../types/rtti/validate/module.f.ts' import type { ValidationError } from '../../types/rtti/validate/module.f.ts' import type { Ts } from '../../types/rtti/ts/module.f.ts' -import { error, ok, type Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { error, ok } from '../../types/result/module.f.mjs' export const packageJsonSchema = { name: option(string), diff --git a/fjs/djs/ast/module.f.ts b/fjs/djs/ast/module.f.ts index 42b68206d..1c4b26e06 100644 --- a/fjs/djs/ast/module.f.ts +++ b/fjs/djs/ast/module.f.ts @@ -4,9 +4,11 @@ * @module */ import type { Primitive, Array, Unknown } from '../module.f.ts' -import { type List, concat, fold, last, map, take, toArray } from '../../types/list/module.f.mjs' -import type { Entry } from '../../types/ordered_map/module.f.ts' +import type { List } from '../../types/list/types.ts' +import { concat, fold, last, map, take, toArray } from '../../types/list/module.f.mjs' +import type { Entry } from '../../types/ordered_map/types.ts' import { fromEntries } from '../../types/object/module.f.ts' + const { entries } = Object /** diff --git a/fjs/djs/parser/module.f.ts b/fjs/djs/parser/module.f.ts index 08acf5d83..08d8a09a7 100644 --- a/fjs/djs/parser/module.f.ts +++ b/fjs/djs/parser/module.f.ts @@ -3,11 +3,14 @@ * * @module */ -import { error, ok, type Result } from '../../types/result/module.f.mjs' -import { fold, next, toArray, length, concat, type List } from '../../types/list/module.f.mjs' -import type { Fold } from '../../types/function/operator/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { error, ok } from '../../types/result/module.f.mjs' +import type { List } from '../../types/list/types.ts' +import { fold, next, toArray, length, concat } from '../../types/list/module.f.mjs' +import type { Fold } from '../../types/function/operator/types.ts' import type { DjsToken, DjsTokenWithMetadata } from '../tokenizer/module.f.ts' -import { setReplace, at, type OrderedMap } from '../../types/ordered_map/module.f.ts' +import { setReplace, at } from '../../types/ordered_map/module.f.mjs' +import type { OrderedMap } from '../../types/ordered_map/types.ts' import { fromMap } from '../../types/object/module.f.ts' import type { AstArray, AstConst, AstModule, AstModuleRef } from '../ast/module.f.ts' import type { TokenMetadata } from '../../js/tokenizer/module.f.ts' diff --git a/fjs/djs/proof.f.ts b/fjs/djs/proof.f.ts index b34c6e1ea..63d6c7aa7 100644 --- a/fjs/djs/proof.f.ts +++ b/fjs/djs/proof.f.ts @@ -1,7 +1,7 @@ import { compile } from './module.f.ts' import { virtual, emptyState } from '../effects/node/virtual/module.f.ts' import { utf8, utf8ToString } from '../text/module.f.mjs' -import type { Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' import { assert, assertEq } from '../asserts/module.f.mjs' const readOutput = (root: typeof emptyState.root, path: string): string => { diff --git a/fjs/djs/serializer/module.f.ts b/fjs/djs/serializer/module.f.ts index 22669e284..4ff61cbfd 100644 --- a/fjs/djs/serializer/module.f.ts +++ b/fjs/djs/serializer/module.f.ts @@ -4,11 +4,12 @@ * @module */ import type { Unknown, Object } from '../module.f.ts' -import type { Fold } from '../../types/function/operator/module.f.mjs' +import type { Fold } from '../../types/function/operator/types.ts' import type { Entry as ObjectEntry } from '../../types/object/module.f.ts' import { fold } from '../../types/list/module.f.mjs' -import { concat } from '../../types/string/module.f.ts' -import { type List, flat, flatMap, map, concat as listConcat } from '../../types/list/module.f.mjs' +import { concat } from '../../types/string/module.f.mjs' +import type { List } from '../../types/list/types.ts' +import { flat, flatMap, map, concat as listConcat } from '../../types/list/module.f.mjs' const { entries } = Object import { compose, fn } from '../../types/function/module.f.mjs' import { serialize as bigintSerialize } from '../../types/bigint/module.f.mjs' diff --git a/fjs/djs/tokenizer/module.f.ts b/fjs/djs/tokenizer/module.f.ts index 7923fce92..35bd44bee 100644 --- a/fjs/djs/tokenizer/module.f.ts +++ b/fjs/djs/tokenizer/module.f.ts @@ -52,10 +52,12 @@ import { latinSmallLetterN, latinSmallLetterR, latinSmallLetterT, latinSmallLetterU, range as asciiRange, } from "../../text/ascii/module.f.mjs" -import { type CodePoint, codePointListToString, stringToCodePointList } from "../../text/utf16/module.f.mjs" -import type { StateScan } from "../../types/function/operator/module.f.mjs" +import type { CodePoint } from "../../text/utf16/types.ts" +import { codePointListToString, stringToCodePointList } from "../../text/utf16/module.f.mjs" +import type { StateScan } from "../../types/function/operator/types.ts" import { contains } from "../../types/range/module.f.mjs" -import { concat, empty, filter, flat, flatMap, fold, map, stateScan, toArray, type List } from "../../types/list/module.f.mjs" +import type { List } from "../../types/list/types.ts" +import { concat, empty, filter, flat, flatMap, fold, map, stateScan, toArray } from "../../types/list/module.f.mjs" import { stringifyAsTree } from "../serializer/module.f.ts" import { sort } from "../../types/object/module.f.ts" import type { Unknown } from "../module.f.ts" diff --git a/fjs/djs/transpiler/module.f.ts b/fjs/djs/transpiler/module.f.ts index 3fabb7228..d3fc00cd1 100644 --- a/fjs/djs/transpiler/module.f.ts +++ b/fjs/djs/transpiler/module.f.ts @@ -4,10 +4,13 @@ * @module */ import { type Unknown } from '../module.f.ts' -import { type Result, error, ok } from '../../types/result/module.f.mjs' -import { drop, map as listMap, type List, toArray, includes } from '../../types/list/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { error, ok } from '../../types/result/module.f.mjs' +import type { List } from '../../types/list/types.ts' +import { drop, map as listMap, toArray, includes } from '../../types/list/module.f.mjs' import { tokenize } from '../tokenizer/module.f.ts' -import { setReplace, at, type OrderedMap } from '../../types/ordered_map/module.f.ts' +import { setReplace, at } from '../../types/ordered_map/module.f.mjs' +import type { OrderedMap } from '../../types/ordered_map/types.ts' import { stringToList } from '../../text/utf16/module.f.mjs' import { concat as pathConcat } from '../../path/module.f.ts' import { type ParseError, parseFromTokens } from '../parser/module.f.ts' diff --git a/fjs/effects/memory/module.f.ts b/fjs/effects/memory/module.f.ts index 592e34151..1973d76db 100644 --- a/fjs/effects/memory/module.f.ts +++ b/fjs/effects/memory/module.f.ts @@ -13,8 +13,9 @@ * @module */ -import type { Phantom } from '../../types/phantom/module.f.ts' -import { type Nominal, asBase as nominalAsBase, asNominal as nominalAsNominal } from '../../types/nominal/module.f.mjs' +import type { Phantom } from '../../types/phantom/types.ts' +import type { Nominal } from '../../types/nominal/types.ts' +import { asBase as nominalAsBase, asNominal as nominalAsNominal } from '../../types/nominal/module.f.mjs' import { do_, type Effect } from '../module.f.ts' /** Nominal brand version for memory keys. */ diff --git a/fjs/effects/module.f.ts b/fjs/effects/module.f.ts index 5c523f3c4..5ddece098 100644 --- a/fjs/effects/module.f.ts +++ b/fjs/effects/module.f.ts @@ -96,10 +96,11 @@ */ import { assert } from '../asserts/module.f.mjs' -import { fold, type List } from '../types/list/module.f.mjs' +import type { List } from '../types/list/types.ts' +import { fold } from '../types/list/module.f.mjs' import { at } from '../types/object/module.f.ts' -import type { Option } from '../types/option/module.f.mjs' -import type { Result } from '../types/result/module.f.mjs' +import type { Option } from '../types/option/types.ts' +import type { Result } from '../types/result/types.ts' export type Operation = readonly[string, (..._: readonly never[]) => unknown] diff --git a/fjs/effects/node/module.f.ts b/fjs/effects/node/module.f.ts index bd9912794..cbf3e280a 100644 --- a/fjs/effects/node/module.f.ts +++ b/fjs/effects/node/module.f.ts @@ -11,11 +11,14 @@ import { utf8, utf8ToString } from '../../text/module.f.mjs' import { toCodePointList } from '../../text/utf8/module.f.mjs' import { codePointListToString } from '../../text/utf16/module.f.mjs' -import { reverse, type List as EffectList } from '../../types/list/module.f.mjs' -import { length, type Vec } from '../../types/bit_vec/module.f.mjs' +import type { List as EffectList } from '../../types/list/types.ts' +import { reverse } from '../../types/list/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { length } from '../../types/bit_vec/module.f.mjs' import type { MemOp } from '../memory/module.f.ts' -import type { Nominal } from '../../types/nominal/module.f.mjs' -import { ok, error as resultError, mapOk, type Result } from '../../types/result/module.f.mjs' +import type { Nominal } from '../../types/nominal/types.ts' +import type { Result } from '../../types/result/types.ts' +import { ok, error as resultError, mapOk } from '../../types/result/module.f.mjs' import type { StringMap } from '../../types/object/module.f.ts' import { type Effect, type Func, type Operation, type ToAsyncOperationMap, do_, mapStep, okStep, pure, step } from '../module.f.ts' import type { List } from '../list/module.f.ts' diff --git a/fjs/effects/node/module.ts b/fjs/effects/node/module.ts index 7ae382ddc..7d7512688 100644 --- a/fjs/effects/node/module.ts +++ b/fjs/effects/node/module.ts @@ -39,7 +39,8 @@ import { usesInlineTestContext, } from './module.f.ts' import { asBase, asNominal } from '../../types/nominal/module.f.mjs' -import { error, ok, type Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { error, ok } from '../../types/result/module.f.mjs' import { asyncTryCatch } from '../../types/result/module.ts' import { fromVec, listToVec, toVec } from '../../types/uint8array/module.f.mjs' import type { StringMap } from '../../types/object/module.f.ts' diff --git a/fjs/effects/node/proof.f.ts b/fjs/effects/node/proof.f.ts index 62ac1bcfe..bd1480de4 100644 --- a/fjs/effects/node/proof.f.ts +++ b/fjs/effects/node/proof.f.ts @@ -1,4 +1,5 @@ -import { empty, isVec, uint, vec, vec8, type Vec } from "../../types/bit_vec/module.f.mjs" +import type { Vec } from "../../types/bit_vec/types.ts" +import { empty, isVec, uint, vec, vec8 } from "../../types/bit_vec/module.f.mjs" import { utf8, utf8ToString } from "../../text/module.f.mjs" import { match, pure, step } from "../module.f.ts" import { both, fetch, mkdir, now, readdir, readFile, readUtf8File, rm, sandbox, writeFile, writeUtf8File, rename, readBytes, randomInt, writeFromStream, usesInlineTestContext, versionLessThan, type IoResult, type ReadFile } from "./module.f.ts" diff --git a/fjs/effects/node/virtual/module.f.ts b/fjs/effects/node/virtual/module.f.ts index 48ff0e058..1e1b921a5 100644 --- a/fjs/effects/node/virtual/module.f.ts +++ b/fjs/effects/node/virtual/module.f.ts @@ -6,7 +6,8 @@ import { todo } from '../../../asserts/module.f.mjs' import { isProperPrefix, join, parse } from '../../../path/module.f.ts' import { utf8ToString } from '../../../text/module.f.mjs' -import { empty, length, maxLengthBytes, msb, vec, type Vec } from '../../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../../types/bit_vec/types.ts' +import { empty, length, maxLengthBytes, msb, vec } from '../../../types/bit_vec/module.f.mjs' import { error, ok } from '../../../types/result/module.f.mjs' import { run, type MemOperationMap, type RunInstance } from '../../mock/module.f.ts' import { asBase, asNominal, type Key } from '../../memory/module.f.ts' diff --git a/fjs/effects/todo/fold-stream-combinator.md b/fjs/effects/todo/fold-stream-combinator.md index 78b9bbebc..addb4f11f 100644 --- a/fjs/effects/todo/fold-stream-combinator.md +++ b/fjs/effects/todo/fold-stream-combinator.md @@ -66,7 +66,7 @@ so write the signature in terms of `Result` — call sites that hold `IoResult` values type-check unchanged: ```ts -import type { Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' export const foldStream = (step: (acc: A) => (chunk: Vec) => Effect>) => diff --git a/fjs/fsc/module.f.mjs b/fjs/fsc/module.f.mjs index d8cf4731f..0964eda1d 100644 --- a/fjs/fsc/module.f.mjs +++ b/fjs/fsc/module.f.mjs @@ -5,13 +5,13 @@ */ import { strictEqual } from '../types/function/operator/module.f.mjs' import { merge as rangeMapMerge, fromRange, get } from '../types/range_map/module.f.mjs' -/** @import { RangeMapArray, RangeMerge } from '../types/range_map/module.f.mjs' */ +/** @import { RangeMapArray, RangeMerge } from '../types/range_map/types.ts' */ import { reduce as listReduce, toArray, map } from '../types/list/module.f.mjs' -/** @import { List } from '../types/list/module.f.mjs' */ +/** @import { List } from '../types/list/types.ts' */ import { range as asciiRange } from '../text/ascii/module.f.mjs' import { flip, fn } from '../types/function/module.f.mjs' import { one } from '../types/range/module.f.mjs' -/** @import { Range } from '../types/range/module.f.mjs' */ +/** @import { Range } from '../types/range/types.ts' */ import { assertEq } from '../asserts/module.f.mjs' const fromCharCode = String.fromCharCode diff --git a/fjs/fsm/module.f.ts b/fjs/fsm/module.f.ts index f9c5fc6a4..0541c795c 100644 --- a/fjs/fsm/module.f.ts +++ b/fjs/fsm/module.f.ts @@ -3,23 +3,19 @@ * * @module */ -import { equal, isEmpty, fold, toArray, scan, foldScan, empty as emptyList, type List } from '../types/list/module.f.mjs' +import type { List } from '../types/list/types.ts' +import { equal, isEmpty, fold, toArray, scan, foldScan, empty as emptyList } from '../types/list/module.f.mjs' import type { StringMap } from '../types/object/module.f.ts' import { toRangeMap, union as byteSetUnion, one, empty, range, type ByteSet } from '../types/byte_set/module.f.ts' import { intersect, type SortedSet, union as sortedSetUnion } from '../types/sorted_set/module.f.ts' -import { - merge, - get as rangeMapGet, - type RangeMap, - type Properties, - type RangeMapArray, - type Entry -} from '../types/range_map/module.f.mjs' -import { type Fold, type Scan, strictEqual } from '../types/function/operator/module.f.mjs' +import type { RangeMap, Properties, RangeMapArray, Entry } from '../types/range_map/types.ts' +import { merge, get as rangeMapGet } from '../types/range_map/module.f.mjs' +import type { Fold, Scan } from '../types/function/operator/types.ts' +import { strictEqual } from '../types/function/operator/module.f.mjs' import { stringify } from '../media/json/module.f.ts' import { identity } from '../types/function/module.f.mjs' import { stringToList } from '../text/utf16/module.f.mjs' -import { cmp } from '../types/string/module.f.ts' +import { cmp } from '../types/string/module.f.mjs' type Rule = readonly [string, ByteSet, string] diff --git a/fjs/fsm/todo/scan-as-map.md b/fjs/fsm/todo/scan-as-map.md index 174180395..c111f639f 100644 --- a/fjs/fsm/todo/scan-as-map.md +++ b/fjs/fsm/todo/scan-as-map.md @@ -39,9 +39,9 @@ const scanFetch = map(([item]: Entry>) => item) ``` Note the explicit `Entry` return annotation instead of `as const`: -`Entry` (`fjs/types/range_map/module.f.mjs:48`) is the *mutable* tuple +`Entry` (`fjs/types/range_map/types.ts:11`) is the *mutable* tuple `[T, number]`, and `Dfa` stores `RangeMapArray = readonly -Entry[]` (`:58`), so a `readonly [string, number]` produced by +Entry[]` (`:19`), so a `readonly [string, number]` produced by `as const` would not be assignable where `toArray(scanStringify(setMap))` lands in `newDfa`. The annotation pins the tuple type without widening and matches what `stringifyOp` returns today. diff --git a/fjs/js/tokenizer/module.f.ts b/fjs/js/tokenizer/module.f.ts index 471a133e4..50fdc9891 100644 --- a/fjs/js/tokenizer/module.f.ts +++ b/fjs/js/tokenizer/module.f.ts @@ -5,12 +5,17 @@ * * @module */ -import { strictEqual, type Scan, type StateScan } from '../../types/function/operator/module.f.mjs' -import { merge, fromRange, get, type RangeMapArray, type RangeMerge } from '../../types/range_map/module.f.mjs' -import { empty, stateScan, flat, toArray, reduce as listReduce, scan, map as listMap, type List } from '../../types/list/module.f.mjs' -import { at, fromEntries, type Entry } from '../../types/ordered_map/module.f.ts' -import { one, type Range as NumberRange } from '../../types/range/module.f.mjs' -import type { BigFloat } from '../../types/bigfloat/module.f.mjs' +import type { Scan, StateScan } from '../../types/function/operator/types.ts' +import { strictEqual } from '../../types/function/operator/module.f.mjs' +import type { RangeMapArray, RangeMerge } from '../../types/range_map/types.ts' +import { merge, fromRange, get } from '../../types/range_map/module.f.mjs' +import type { List } from '../../types/list/types.ts' +import { empty, stateScan, flat, toArray, reduce as listReduce, scan, map as listMap } from '../../types/list/module.f.mjs' +import { at, fromEntries } from '../../types/ordered_map/module.f.mjs' +import type { Entry } from '../../types/ordered_map/types.ts' +import type { Range as NumberRange } from '../../types/range/types.ts' +import { one } from '../../types/range/module.f.mjs' +import type { BigFloat } from '../../types/bigfloat/types.ts' import { range, // diff --git a/fjs/mcp/cas/module.f.ts b/fjs/mcp/cas/module.f.ts index f816c0922..1d967ae3e 100644 --- a/fjs/mcp/cas/module.f.ts +++ b/fjs/mcp/cas/module.f.ts @@ -111,8 +111,10 @@ import { tryUtf8 } from '../../text/module.f.mjs' import { detectStream } from '../../media/type/module.f.ts' import { detect } from '../../media/module.f.ts' import { revisionDialect } from '../../media/revision/module.f.ts' -import { maxLengthBytes, type Vec } from '../../types/bit_vec/module.f.mjs' -import { ok, type Ok } from '../../types/result/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { maxLengthBytes } from '../../types/bit_vec/module.f.mjs' +import type { Ok } from '../../types/result/types.ts' +import { ok } from '../../types/result/module.f.mjs' import { toolEntry, errorResult, okResult, type ToolEntry, type ToolsCallResult, diff --git a/fjs/mcp/proof.f.ts b/fjs/mcp/proof.f.ts index bc0d13b0e..df44c0087 100644 --- a/fjs/mcp/proof.f.ts +++ b/fjs/mcp/proof.f.ts @@ -5,7 +5,8 @@ import { parse as parseJson, type Unknown } from '../media/json/module.f.ts' import { number as rttiNumber, option, string as rttiString } from '../types/rtti/module.f.ts' import { parse as rttiParse } from '../types/rtti/parse/module.f.ts' import type { Response } from '../protocol/json_rpc/module.f.ts' -import { msb, u8ListToVec, vec8, repeat, length, type Vec, maxLengthBytes } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' +import { msb, u8ListToVec, vec8, repeat, length, maxLengthBytes } from '../types/bit_vec/module.f.mjs' import { vecToCBase32 } from '../basen/cbase32/module.f.mjs' import { encode as base64Encode } from '../basen/base64/module.f.mjs' import { utf8 } from '../text/module.f.mjs' diff --git a/fjs/media/html/module.f.ts b/fjs/media/html/module.f.ts index 3924ca663..42b6f6307 100644 --- a/fjs/media/html/module.f.ts +++ b/fjs/media/html/module.f.ts @@ -4,13 +4,14 @@ * * @module */ -import { map, flatMap, flat, concat as listConcat, type List } from '../../types/list/module.f.mjs' -import { concat, concat as stringConcat } from '../../types/string/module.f.ts' +import type { List } from '../../types/list/types.ts' +import { map, flatMap, flat, concat as listConcat } from '../../types/list/module.f.mjs' +import { concat, concat as stringConcat } from '../../types/string/module.f.mjs' import { definedEntries, type Entry, type StringMap } from '../../types/object/module.f.ts' import { compose } from '../../types/function/module.f.mjs' import { stringToList } from '../../text/utf16/module.f.mjs' import { includes } from '../../types/array/module.f.mjs' -import { type Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' import { utf8 } from '../../text/module.f.mjs' import { quotationMark, ampersand, lessThanSign, greaterThanSign } from '../../text/ascii/module.f.mjs' diff --git a/fjs/media/json/module.f.ts b/fjs/media/json/module.f.ts index 4da406224..ea5adfcd9 100644 --- a/fjs/media/json/module.f.ts +++ b/fjs/media/json/module.f.ts @@ -11,10 +11,11 @@ * * @module */ -import { next, flat, map, type List } from '../../types/list/module.f.mjs' -import { concat } from '../../types/string/module.f.ts' +import type { List } from '../../types/list/types.ts' +import { next, flat, map } from '../../types/list/module.f.mjs' +import { concat } from '../../types/string/module.f.mjs' import { stringToList } from '../../text/utf16/module.f.mjs' -import type { Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' import { parse as parseTokens } from './parser/module.f.ts' import { tokenize } from './tokenizer/module.f.ts' import { at, definedEntries, type Entry as ObjectEntry } from '../../types/object/module.f.ts' @@ -22,8 +23,8 @@ import { compose, fn } from '../../types/function/module.f.mjs' import { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from './serializer/module.f.ts' import { boolean as rttiBoolean, number as rttiNumber, string as rttiString, or, record, array as rttiArray } from '../../types/rtti/module.f.ts' import type { Ts } from '../../types/rtti/ts/module.f.ts' -import type { Assert } from '../../asserts/module.f.mjs' -import type { Equal } from '../../types/ts/module.f.mjs' +import type { Assert } from '../../asserts/types.ts' +import type { Equal } from '../../types/ts/types.ts' // ── rtti schemas ────────────────────────────────────────────────────────────── diff --git a/fjs/media/json/parser/module.f.ts b/fjs/media/json/parser/module.f.ts index 4dc65064e..0a9f238fd 100644 --- a/fjs/media/json/parser/module.f.ts +++ b/fjs/media/json/parser/module.f.ts @@ -3,11 +3,14 @@ * * @module */ -import { error, ok, type Result } from '../../../types/result/module.f.mjs' -import { type List, fold, next, toArray, concat } from '../../../types/list/module.f.mjs' -import { type Fold } from '../../../types/function/operator/module.f.mjs' +import type { Result } from '../../../types/result/types.ts' +import { error, ok } from '../../../types/result/module.f.mjs' +import type { List } from '../../../types/list/types.ts' +import { fold, next, toArray, concat } from '../../../types/list/module.f.mjs' +import type { Fold } from '../../../types/function/operator/types.ts' import { type JsonToken } from '../tokenizer/module.f.ts' -import { setReplace, type OrderedMap } from '../../../types/ordered_map/module.f.ts' +import { setReplace } from '../../../types/ordered_map/module.f.mjs' +import type { OrderedMap } from '../../../types/ordered_map/types.ts' import { type Unknown } from '../module.f.ts' import { fromMap } from '../../../types/object/module.f.ts' import { assertEq } from '../../../asserts/module.f.mjs' diff --git a/fjs/media/json/schema/module.f.ts b/fjs/media/json/schema/module.f.ts index 849b126bc..156068965 100644 --- a/fjs/media/json/schema/module.f.ts +++ b/fjs/media/json/schema/module.f.ts @@ -10,7 +10,7 @@ import { type Struct, type Tuple, type Type as RttiType, array, option, or, reco import { visit, type Visitor } from '../../../types/rtti/common/module.f.ts' import type { Primitive } from '../../../djs/module.f.ts' import type { Ts } from '../../../types/rtti/ts/module.f.ts' -import type { Phantom } from '../../../types/phantom/module.f.ts' +import type { Phantom } from '../../../types/phantom/types.ts' import { unknown as jsonUnknown } from '../module.f.ts' const unknownThunk = () => ['const', unknownConst] as const diff --git a/fjs/media/json/serializer/module.f.ts b/fjs/media/json/serializer/module.f.ts index 63943dcae..c87ae0659 100644 --- a/fjs/media/json/serializer/module.f.ts +++ b/fjs/media/json/serializer/module.f.ts @@ -7,14 +7,12 @@ * * @module */ -import { flat, map, reduce, empty, type List } from '../../../types/list/module.f.mjs' -import { type Reduce } from '../../../types/function/operator/module.f.mjs' -import { concat } from '../../../types/string/module.f.ts' -import { - codePointToString, - stringToCodePointList, - type CodePoint, -} from '../../../text/utf16/module.f.mjs' +import type { List } from '../../../types/list/types.ts' +import { flat, map, reduce, empty } from '../../../types/list/module.f.mjs' +import type { Reduce } from '../../../types/function/operator/types.ts' +import { concat } from '../../../types/string/module.f.mjs' +import type { CodePoint } from '../../../text/utf16/types.ts' +import { codePointToString, stringToCodePointList } from '../../../text/utf16/module.f.mjs' import { errorMask } from '../../../text/code_point/module.f.mjs' import { backspace, diff --git a/fjs/media/json/serializer/proof.f.ts b/fjs/media/json/serializer/proof.f.ts index 77db1773d..52751da23 100644 --- a/fjs/media/json/serializer/proof.f.ts +++ b/fjs/media/json/serializer/proof.f.ts @@ -1,6 +1,6 @@ import { arrayWrap, boolSerialize, numberSerialize, objectWrap, stringSerialize } from './module.f.ts' import * as list from '../../../types/list/module.f.mjs' -import { concat } from '../../../types/string/module.f.ts' +import { concat } from '../../../types/string/module.f.mjs' import { assertEq } from '../../../asserts/module.f.mjs' const { toArray } = list diff --git a/fjs/media/json/tokenizer/module.f.ts b/fjs/media/json/tokenizer/module.f.ts index 891be1c04..be2c57049 100644 --- a/fjs/media/json/tokenizer/module.f.ts +++ b/fjs/media/json/tokenizer/module.f.ts @@ -3,8 +3,9 @@ * * @module */ -import { type StateScan } from '../../../types/function/operator/module.f.mjs' -import { concat, empty, flat, stateScan, type List } from '../../../types/list/module.f.mjs' +import type { StateScan } from '../../../types/function/operator/types.ts' +import type { List } from '../../../types/list/types.ts' +import { concat, empty, flat, stateScan } from '../../../types/list/module.f.mjs' import { multiply } from '../../../types/bigfloat/module.f.mjs' import { tokenize as jsTokenize, diff --git a/fjs/media/module.f.ts b/fjs/media/module.f.ts index 87a8f2b85..a3c26d611 100644 --- a/fjs/media/module.f.ts +++ b/fjs/media/module.f.ts @@ -41,7 +41,7 @@ * * @module */ -import type { Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' import { fromVec } from '../text/utf8/module.f.mjs' import { detectVec, type DetectMeta } from './type/module.f.ts' import { parse } from './json/module.f.ts' diff --git a/fjs/media/nix/module.f.ts b/fjs/media/nix/module.f.ts index 402c266f9..8aa671622 100644 --- a/fjs/media/nix/module.f.ts +++ b/fjs/media/nix/module.f.ts @@ -7,8 +7,9 @@ * * @module */ -import { toArray, type List as ChunkList } from '../../types/list/module.f.mjs' -import { concat } from '../../types/string/module.f.ts' +import type { List as ChunkList } from '../../types/list/types.ts' +import { toArray } from '../../types/list/module.f.mjs' +import { concat } from '../../types/string/module.f.mjs' import { includes } from '../../types/array/module.f.mjs' import { digitRange, diff --git a/fjs/media/proof.f.ts b/fjs/media/proof.f.ts index 6cdb4de87..b92e89538 100644 --- a/fjs/media/proof.f.ts +++ b/fjs/media/proof.f.ts @@ -1,5 +1,6 @@ import { assertEq } from '../asserts/module.f.mjs' -import { msb, u8ListToVec, repeat, vec8, type Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' +import { msb, u8ListToVec, repeat, vec8 } from '../types/bit_vec/module.f.mjs' import { detect, dialectEntry, type DialectEntry } from './module.f.ts' import { dialect, revisionDialect } from './revision/module.f.ts' import { number, string } from '../types/rtti/module.f.ts' diff --git a/fjs/media/revision/module.f.ts b/fjs/media/revision/module.f.ts index 36d074bc7..f5b0c19e0 100644 --- a/fjs/media/revision/module.f.ts +++ b/fjs/media/revision/module.f.ts @@ -19,7 +19,8 @@ import { validate as rttiValidate, type ValidationError } from '../../types/rtti import type { Ts } from '../../types/rtti/ts/module.f.ts' import { parse as parseJson, type Unknown } from '../json/module.f.ts' import { cBase32ToVec } from '../../basen/cbase32/module.f.mjs' -import { error, ok, type Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { error, ok } from '../../types/result/module.f.mjs' import { dialectEntry, type DialectEntry } from '../module.f.ts' import { definedEntries, sort } from '../../types/object/module.f.ts' import { stringify } from '../json/module.f.ts' diff --git a/fjs/media/type/module.f.ts b/fjs/media/type/module.f.ts index 6984d082d..193bdafcf 100644 --- a/fjs/media/type/module.f.ts +++ b/fjs/media/type/module.f.ts @@ -32,15 +32,17 @@ * * @module */ -import { msb, fromSentinel, length, u8List, type Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { msb, fromSentinel, length, u8List } from '../../types/bit_vec/module.f.mjs' import { iterable } from '../../types/list/module.f.mjs' -import type { Nullable } from '../../types/nullable/module.f.mjs' +import type { Nullable } from '../../types/nullable/types.ts' import { pure, step, type Effect, type Operation } from '../../effects/module.f.ts' import type { List } from '../../effects/list/module.f.ts' import type { IoResult } from '../../effects/node/module.f.ts' import { ok, error } from '../../types/result/module.f.mjs' import { isValidCodePoint, isTextCodePoint } from '../../text/code_point/module.f.mjs' -import { utf8ByteToCodePointOp, type Utf8State } from '../../text/utf8/module.f.mjs' +import type { Utf8State } from '../../text/utf8/types.ts' +import { utf8ByteToCodePointOp } from '../../text/utf8/module.f.mjs' const { startsWith, removeFront } = msb diff --git a/fjs/media/type/proof.f.ts b/fjs/media/type/proof.f.ts index 99f9fa44a..e4d227eb0 100644 --- a/fjs/media/type/proof.f.ts +++ b/fjs/media/type/proof.f.ts @@ -1,8 +1,10 @@ import { assert, assertEq } from '../../asserts/module.f.mjs' -import { msb, u8ListToVec, vec8, repeat, empty, type Vec } from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { msb, u8ListToVec, vec8, repeat, empty } from '../../types/bit_vec/module.f.mjs' import { runPure } from '../../effects/module.f.ts' import { nonEmpty, empty as emptyList, type List } from '../../effects/list/module.f.ts' -import { ok, type Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' +import { ok } from '../../types/result/module.f.mjs' import { detect, detectStream, detectVec, type DetectMeta } from './module.f.ts' // Builds a big-endian `Vec` from a list of byte values — mirrors how the CAS diff --git a/fjs/path/module.f.ts b/fjs/path/module.f.ts index 97a9baf8b..d48ce5542 100644 --- a/fjs/path/module.f.ts +++ b/fjs/path/module.f.ts @@ -3,9 +3,10 @@ * * @module */ -import type { Fold, Reduce, Unary } from '../types/function/operator/module.f.mjs' -import { type List, fold, last, take, length, concat as listConcat, toArray } from '../types/list/module.f.mjs' -import { join as listJoin, concat as stringConcat } from '../types/string/module.f.ts' +import type { Fold, Reduce, Unary } from '../types/function/operator/types.ts' +import type { List } from '../types/list/types.ts' +import { fold, last, take, length, concat as listConcat, toArray } from '../types/list/module.f.mjs' +import { join as listJoin, concat as stringConcat } from '../types/string/module.f.mjs' const foldNormalizeOp: Fold> = input => state => { diff --git a/fjs/protocol/json_rpc/module.f.ts b/fjs/protocol/json_rpc/module.f.ts index 4fbcf84bb..8c1c227db 100644 --- a/fjs/protocol/json_rpc/module.f.ts +++ b/fjs/protocol/json_rpc/module.f.ts @@ -17,7 +17,7 @@ import { number, string, or, option } from '../../types/rtti/module.f.ts' import type { Ts } from '../../types/rtti/ts/module.f.ts' import { validate } from '../../types/rtti/validate/module.f.ts' -import type { Result } from '../../types/result/module.f.mjs' +import type { Result } from '../../types/result/types.ts' import { unknown, type Unknown } from '../../media/json/module.f.ts' export const jsonrpc = '2.0' as const diff --git a/fjs/sul/id/module.f.ts b/fjs/sul/id/module.f.ts index 6a1896d30..4bc0cb2c8 100644 --- a/fjs/sul/id/module.f.ts +++ b/fjs/sul/id/module.f.ts @@ -7,22 +7,18 @@ */ import { toArray } from '../../types/list/module.f.mjs' -import { - length, - msb, - uint, - uintChunkList, - unpack, - vec, - type Vec -} from '../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../types/bit_vec/types.ts' +import { length, msb, uint, uintChunkList, unpack, vec } from '../../types/bit_vec/module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' import { utf8 } from '../../text/module.f.mjs' -import { secp256r1, type Point2D } from '../../crypto/secp/module.f.mjs' -import { base32, type V8 } from '../../crypto/sha2/module.f.mjs' +import type { Point2D } from '../../crypto/secp/types.ts' +import { secp256r1 } from '../../crypto/secp/module.f.mjs' +import type { V8 } from '../../crypto/sha2/types.ts' +import { base32 } from '../../crypto/sha2/module.f.mjs' import { literal3ToVec } from '../level/literal/module.f.ts' import { log2 } from '../../types/bigint/module.f.mjs' -import { asBase, asNominal, type Nominal } from '../../types/nominal/module.f.mjs' +import type { Nominal } from '../../types/nominal/types.ts' +import { asBase, asNominal } from '../../types/nominal/module.f.mjs' /** A 256-bit SUL identifier. One of three variants: level-3 literal, raw bit vector, or SHA2 hash. */ export type Id = Nominal< diff --git a/fjs/sul/level/hash/module.f.ts b/fjs/sul/level/hash/module.f.ts index c1b96af5c..55be612d2 100644 --- a/fjs/sul/level/hash/module.f.ts +++ b/fjs/sul/level/hash/module.f.ts @@ -4,7 +4,8 @@ * @module */ -import { emptyState, patriciaTrie, type Create, type State } from '../../../types/patricia_trie/module.f.mjs' +import type { Create, State } from '../../../types/patricia_trie/types.ts' +import { emptyState, patriciaTrie } from '../../../types/patricia_trie/module.f.mjs' import { compress, type Id } from '../../id/module.f.ts' import { asBase } from '../../../types/nominal/module.f.mjs' diff --git a/fjs/sul/level/literal/module.f.ts b/fjs/sul/level/literal/module.f.ts index a6b8bc3a3..4f2395100 100644 --- a/fjs/sul/level/literal/module.f.ts +++ b/fjs/sul/level/literal/module.f.ts @@ -6,11 +6,14 @@ */ import { log2 } from '../../../types/bigint/module.f.mjs' -import { msb, vec, type Vec } from '../../../types/bit_vec/module.f.mjs' -import type { Func } from '../../../types/function/module.f.mjs' -import { strictEqual, type Equal, type StateScan } from '../../../types/function/operator/module.f.mjs' -import { equal, map, type List } from '../../../types/list/module.f.mjs' -import { join } from '../../../types/string/module.f.ts' +import type { Vec } from '../../../types/bit_vec/types.ts' +import { msb, vec } from '../../../types/bit_vec/module.f.mjs' +import type { Func } from '../../../types/function/types.ts' +import type { Equal, StateScan } from '../../../types/function/operator/types.ts' +import { strictEqual } from '../../../types/function/operator/module.f.mjs' +import type { List } from '../../../types/list/types.ts' +import { equal, map } from '../../../types/list/module.f.mjs' +import { join } from '../../../types/string/module.f.mjs' export const symbolToString = (s: bigint): string => s.toString(16) diff --git a/fjs/sul/level/literal/proof.f.ts b/fjs/sul/level/literal/proof.f.ts index 36709b43d..753405664 100644 --- a/fjs/sul/level/literal/proof.f.ts +++ b/fjs/sul/level/literal/proof.f.ts @@ -1,4 +1,5 @@ -import { chunkList, msb, vec, type Vec } from '../../../types/bit_vec/module.f.mjs' +import type { Vec } from '../../../types/bit_vec/types.ts' +import { chunkList, msb, vec } from '../../../types/bit_vec/module.f.mjs' import { assert, assertEq } from '../../../asserts/module.f.mjs' import { map, stateScan, toArray } from '../../../types/list/module.f.mjs' import { diff --git a/fjs/sul/module.f.ts b/fjs/sul/module.f.ts index 762605fa9..4834d008d 100644 --- a/fjs/sul/module.f.ts +++ b/fjs/sul/module.f.ts @@ -8,7 +8,7 @@ import { emptyPipelineState, pipelineStep, type PipelineState } from './level/literal/module.f.ts' import { encode as hashEncode, type Add } from './level/hash/module.f.ts' import { level3Id, type Id } from './id/module.f.ts' -import type { InternalState } from '../types/patricia_trie/module.f.mjs' +import type { InternalState } from '../types/patricia_trie/types.ts' type HashState = InternalState diff --git a/fjs/text/ascii/module.f.mjs b/fjs/text/ascii/module.f.mjs index fbfb5e023..f1f5d6947 100644 --- a/fjs/text/ascii/module.f.mjs +++ b/fjs/text/ascii/module.f.mjs @@ -4,7 +4,7 @@ * @module */ -/** @import { Range } from '../../types/range/module.f.mjs' */ +/** @import { Range } from '../../types/range/types.ts' */ /** @type {(s: string) => (i: number) => number} */ const at = s => i => { diff --git a/fjs/text/code_point/module.f.mjs b/fjs/text/code_point/module.f.mjs index bde8229e9..1c7c3ac7b 100644 --- a/fjs/text/code_point/module.f.mjs +++ b/fjs/text/code_point/module.f.mjs @@ -10,9 +10,9 @@ */ import { flat, stateScan } from '../../types/list/module.f.mjs' -/** @import { List } from '../../types/list/module.f.mjs' */ +/** @import { List } from '../../types/list/types.ts' */ -/** @import { StateScan } from '../../types/function/operator/module.f.mjs' */ +/** @import { StateScan } from '../../types/function/operator/types.ts' */ import { contains } from '../../types/range/module.f.mjs' diff --git a/fjs/text/module.f.mjs b/fjs/text/module.f.mjs index 536282849..2119c8e6c 100644 --- a/fjs/text/module.f.mjs +++ b/fjs/text/module.f.mjs @@ -7,21 +7,13 @@ */ import { msb, tryU8ListToVec, u8List } from '../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../types/bit_vec/module.f.mjs' */ import { flatMap } from '../types/list/module.f.mjs' -/** @import { List } from '../types/list/module.f.mjs' */ +/** @import { List } from '../types/list/types.ts' */ import { fromCodePointList, toCodePointList } from './utf8/module.f.mjs' import { stringToCodePointList, codePointListToString } from './utf16/module.f.mjs' import { mapUnwrap } from '../types/nullable/module.f.mjs' -/** @import { Nullable } from '../types/nullable/module.f.mjs' */ - -/** @typedef {_ItemThunk | _ItemArray} Block */ - -/** @typedef {readonly Item[]} _ItemArray */ - -/** @typedef {() => List} _ItemThunk */ - -/** @typedef {string | _ItemArray | _ItemThunk} Item */ +/** @import { Nullable } from '../types/nullable/types.ts' */ +/** @import { Block, Item, Utf8 } from './types.ts' */ /** @type {(indent: string) => (text: Block) => List} */ export const flat = indent => { @@ -37,8 +29,6 @@ export const flat = indent => { const tryU8ListToVecMsb = tryU8ListToVec(msb) -/** @typedef {Vec} Utf8 */ - /** * Converts a string to an UTF-8, represented as an MSB first bit vector, * returning `null` instead of throwing if the result would exceed diff --git a/fjs/text/proof.f.ts b/fjs/text/proof.f.ts index 9bca741e0..2b34b35bc 100644 --- a/fjs/text/proof.f.ts +++ b/fjs/text/proof.f.ts @@ -1,6 +1,7 @@ import { assertEq, assertNotNullish } from '../asserts/module.f.mjs' -import { flat, utf8, utf8ToString, tryUtf8, type Block } from './module.f.mjs' -import { join } from '../types/string/module.f.ts' +import type { Block } from './types.ts' +import { flat, utf8, utf8ToString, tryUtf8 } from './module.f.mjs' +import { join } from '../types/string/module.f.mjs' import { empty, maxLengthBytes } from '../types/bit_vec/module.f.mjs' const overflowStr = 'a'.repeat(Number(maxLengthBytes) + 1) diff --git a/fjs/text/types.ts b/fjs/text/types.ts new file mode 100644 index 000000000..43e126b26 --- /dev/null +++ b/fjs/text/types.ts @@ -0,0 +1,18 @@ +/** + * Types for indented text blocks and UTF-8 bit vectors. + * + * @module + */ + +import type { Vec } from '../types/bit_vec/types.ts' +import type { List } from '../types/list/types.ts' + +type _ItemArray = readonly Item[] + +type _ItemThunk = () => List + +export type Block = _ItemThunk | _ItemArray + +export type Item = string | _ItemArray | _ItemThunk + +export type Utf8 = Vec diff --git a/fjs/text/utf16/module.f.mjs b/fjs/text/utf16/module.f.mjs index 38f2e2120..7f44253e3 100644 --- a/fjs/text/utf16/module.f.mjs +++ b/fjs/text/utf16/module.f.mjs @@ -12,10 +12,10 @@ import { flatMap, empty, } from '../../types/list/module.f.mjs' -/** @import { List, Result, Thunk } from '../../types/list/module.f.mjs' */ +/** @import { List, Result, Thunk } from '../../types/list/types.ts' */ import { concat } from '../../types/function/operator/module.f.mjs' -/** @import { StateScan } from '../../types/function/operator/module.f.mjs' */ +/** @import { StateScan } from '../../types/function/operator/types.ts' */ import { contains } from '../../types/range/module.f.mjs' @@ -37,24 +37,7 @@ import { * @typedef {number | null} _Utf16State */ -/** - * Represent an unsigned UTF16, used to store one word UTF-16 (code unit). - * - * @typedef {number} U16 - */ - -/** - * [0, 0x10_FFFF]: 16+5 = 21 bits - * - * 121_0000_0000: 16+16+9 = 41 bits - */ - -/** - * Represent an Unicode code point. - * Has range: from 0x0000 to 0x10_FFFF (21 bits). - * - * @typedef {number} CodePoint - */ +/** @import { CodePoint, U16 } from './types.ts' */ /** * The BMP / surrogate / supplementary-plane predicates used below live in diff --git a/fjs/text/utf16/types.ts b/fjs/text/utf16/types.ts new file mode 100644 index 000000000..5ca45fdbd --- /dev/null +++ b/fjs/text/utf16/types.ts @@ -0,0 +1,22 @@ +/** + * Types for UTF-16 code units and Unicode code points. + * + * @module + */ + +/** + * Represent an unsigned UTF16, used to store one word UTF-16 (code unit). + */ +export type U16 = number + +/** + * [0, 0x10_FFFF]: 16+5 = 21 bits + * + * 121_0000_0000: 16+16+9 = 41 bits + */ + +/** + * Represent an Unicode code point. + * Has range: from 0x0000 to 0x10_FFFF (21 bits). + */ +export type CodePoint = number diff --git a/fjs/text/utf8/module.f.mjs b/fjs/text/utf8/module.f.mjs index 4fc6b673f..7b15a40af 100644 --- a/fjs/text/utf8/module.f.mjs +++ b/fjs/text/utf8/module.f.mjs @@ -5,36 +5,16 @@ */ import { flatMap, toArray } from '../../types/list/module.f.mjs' -/** @import { List, Thunk } from '../../types/list/module.f.mjs' */ -/** @import { StateScan } from '../../types/function/operator/module.f.mjs' */ -/** @import { Tuple } from '../../types/array/module.f.mjs' */ +/** @import { List, Thunk } from '../../types/list/types.ts' */ +/** @import { StateScan } from '../../types/function/operator/types.ts' */ import { decoder, errorMask, isValidCodePoint } from '../code_point/module.f.mjs' import { msb, u8List, length } from '../../types/bit_vec/module.f.mjs' -/** @import { Vec } from '../../types/bit_vec/module.f.mjs' */ +/** @import { Vec } from '../../types/bit_vec/types.ts' */ import { codePointListToString } from '../utf16/module.f.mjs' - -/** An unsigned 8-bit integer, represents a single byte. @typedef {number} U8 */ - -/** A singed 32-bit integer. @typedef {number} I32 */ - -/** - * Represents an unsigned 8-bit type - U8 or the end-of-file indicator. - * The U8 represents the byte itself, and null indicates that reading does not return anything else. - * - * @typedef {U8 | null} ByteOrEof - */ - -/** - * Represents the state of a UTF-8 decoding operation that contains at least one byte. - * - * @typedef {Tuple<1, number> | Tuple<2, number> | Tuple<3, number>} Utf8NonEmptyState - */ - /** - * Represents the state of a UTF-8 decoding operation, which can be either `null` (no state) - * or a non-empty state containing one or more bytes. - * - * @typedef {null | Utf8NonEmptyState} Utf8State + * @import { + * ByteOrEof, I32, U8, Utf8NonEmptyState, Utf8State, + * } from './types.ts' */ /** diff --git a/fjs/text/utf8/types.ts b/fjs/text/utf8/types.ts new file mode 100644 index 000000000..5767645b3 --- /dev/null +++ b/fjs/text/utf8/types.ts @@ -0,0 +1,33 @@ +/** + * Types for UTF-8 byte-level encoding and decoding. + * + * @module + */ + +import type { Tuple } from '../../types/array/types.ts' + +/** An unsigned 8-bit integer, represents a single byte. */ +export type U8 = number + +/** A singed 32-bit integer. */ +export type I32 = number + +/** + * Represents an unsigned 8-bit type - U8 or the end-of-file indicator. + * The U8 represents the byte itself, and null indicates that reading does not + * return anything else. + */ +export type ByteOrEof = U8 | null + +/** + * Represents the state of a UTF-8 decoding operation that contains at least one + * byte. + */ +export type Utf8NonEmptyState = + Tuple<1, number> | Tuple<2, number> | Tuple<3, number> + +/** + * Represents the state of a UTF-8 decoding operation, which can be either + * `null` (no state) or a non-empty state containing one or more bytes. + */ +export type Utf8State = null | Utf8NonEmptyState diff --git a/fjs/types/array/module.f.mjs b/fjs/types/array/module.f.mjs index 159446ec3..f24e5d493 100644 --- a/fjs/types/array/module.f.mjs +++ b/fjs/types/array/module.f.mjs @@ -6,49 +6,13 @@ import { fromUndefined, map } from '../nullable/module.f.mjs' -/** @import { Assert } from '../../asserts/module.f.mjs' */ -/** @import { Equal } from '../ts/module.f.mjs' */ +/** @import { Tuple } from './types.ts' */ /** * @type {(value: unknown) => value is readonly unknown[]} */ export const isArray = value => value instanceof Array -/** - * @template {number} N - * @template T - * @template {readonly T[]} R - * @typedef {N extends R['length'] ? R : _Tuple} _Tuple -*/ - -/** - * @template {number} N - * @template {readonly unknown[]} R - * @typedef {R['length'] extends N ? never : R['length'] | _Index} _Index - */ - -/** - * @template {number} N - * @typedef {number extends N ? number : N extends number ? _Index : never} Index - */ - -/** - * @template {number} N - * @template T - * @typedef {_Tuple} Tuple - */ - -/** - * @template {readonly unknown[]} T - * @typedef {Index} KeyOf - */ - -/** - * @typedef {Assert, number>>} _X0 - * @typedef {Assert, 0>>} _X1 - * @typedef {Assert, 0 | 1>>} _X2 - */ - /** * Currently, TypeScript can't narrow the type of `readonly T[]` to `Array2` * only by checking `a.length === 2`, so we need a user-defined type guard. @@ -67,11 +31,6 @@ export const isTuple = a => a.length === n -/** - * @template T - * @typedef {Tuple<1, T> | Tuple<2, T> | Tuple<3, T> | Tuple<4, T> | Tuple<5, T>} Array1_5 - */ - /** * @type {(a: readonly T[]) => readonly T[]} */ @@ -127,12 +86,6 @@ export const splitLast = a => { */ export const empty = /** @type {const} */([]) -/** - * @template I - * @template {readonly I[]} T - * @typedef {(v: I) => v is T[number]} Includes - */ - export const includes = /** * @template I diff --git a/fjs/types/array/types.ts b/fjs/types/array/types.ts new file mode 100644 index 000000000..368cd9b14 --- /dev/null +++ b/fjs/types/array/types.ts @@ -0,0 +1,32 @@ +/** + * Types for JavaScript immutable arrays. + * + * @module + */ + +import type { Assert } from '../../asserts/types.ts' +import type { Equal } from '../ts/types.ts' + +type _Tuple = + N extends R['length'] ? R : _Tuple + +type _Index = + R['length'] extends N + ? never + : R['length'] | _Index + +export type Index = + number extends N ? number : N extends number ? _Index : never + +export type Tuple = _Tuple + +export type KeyOf = Index + +type _X0 = Assert, number>> +type _X1 = Assert, 0>> +type _X2 = Assert, 0 | 1>> + +export type Array1_5 = + Tuple<1, T> | Tuple<2, T> | Tuple<3, T> | Tuple<4, T> | Tuple<5, T> + +export type Includes = (v: I) => v is T[number] diff --git a/fjs/types/bigfloat/module.f.mjs b/fjs/types/bigfloat/module.f.mjs index f2d54d8f5..dd590dcd8 100644 --- a/fjs/types/bigfloat/module.f.mjs +++ b/fjs/types/bigfloat/module.f.mjs @@ -5,8 +5,7 @@ */ import { abs, sign } from '../bigint/module.f.mjs' - -/** @typedef {readonly [bigint, number]} BigFloat */ +/** @import { BigFloat } from './types.ts' */ /** @typedef {readonly [BigFloat, bigint]} _BigFloatWithRemainder */ diff --git a/fjs/types/bigfloat/types.ts b/fjs/types/bigfloat/types.ts new file mode 100644 index 000000000..8e8217629 --- /dev/null +++ b/fjs/types/bigfloat/types.ts @@ -0,0 +1,7 @@ +/** + * Types for big-floats built from bigint mantissa and exponent parts. + * + * @module + */ + +export type BigFloat = readonly [bigint, number] diff --git a/fjs/types/bigint/module.f.mjs b/fjs/types/bigint/module.f.mjs index f085899c1..3c05792a2 100644 --- a/fjs/types/bigint/module.f.mjs +++ b/fjs/types/bigint/module.f.mjs @@ -18,23 +18,11 @@ */ import { cmp } from '../function/compare/module.f.mjs' -/** @import { Sign } from '../function/compare/module.f.mjs' */ -/** @import { Unary as OpUnary, Reduce as OpReduce } from '../function/operator/module.f.mjs' */ -/** @import { List } from '../list/module.f.mjs' */ +/** @import { Sign } from '../function/compare/types.ts' */ +/** @import { List } from '../list/types.ts' */ +/** @import { Reduce, Unary } from './types.ts' */ import { fold } from '../../common/monoid/module.f.mjs' -/** - * Type representing a unary operation on `bigint`. - * - * @typedef {OpUnary} Unary - */ - -/** - * Type representing a reduction operation on `bigint` values. - * - * @typedef {OpReduce} Reduce - */ - /** * Adds two `bigint` values. * TODO: should be combined with `addition` for `number`. diff --git a/fjs/types/bigint/types.ts b/fjs/types/bigint/types.ts new file mode 100644 index 000000000..359da1f23 --- /dev/null +++ b/fjs/types/bigint/types.ts @@ -0,0 +1,20 @@ +/** + * Operator types specialized to `bigint`. + * + * @module + */ + +import type { + Unary as OpUnary, + Reduce as OpReduce, +} from '../function/operator/types.ts' + +/** + * Type representing a unary operation on `bigint`. + */ +export type Unary = OpUnary + +/** + * Type representing a reduction operation on `bigint` values. + */ +export type Reduce = OpReduce diff --git a/fjs/types/bit_vec/module.f.mjs b/fjs/types/bit_vec/module.f.mjs index bd54b837f..5baea7f94 100644 --- a/fjs/types/bit_vec/module.f.mjs +++ b/fjs/types/bit_vec/module.f.mjs @@ -23,32 +23,30 @@ */ import { bitLength, divUp, mask, maxLength, xor } from '../bigint/module.f.mjs' -/** @import { Reduce as BigintReduce } from '../bigint/module.f.mjs' */ +/** @import { Reduce as BigintReduce } from '../bigint/types.ts' */ import { flip, identity } from '../function/module.f.mjs' -/** @import { Binary, Fold, Reduce as OpReduce } from '../function/operator/module.f.mjs' */ +/** @import { Fold } from '../function/operator/types.ts' */ import { map, tryFold } from '../list/module.f.mjs' -/** @import { Accumulator, List, Thunk } from '../list/module.f.mjs' */ +/** @import { Accumulator, List, Thunk } from '../list/types.ts' */ import { asBase, asNominal } from '../nominal/module.f.mjs' -/** @import { Nominal } from '../nominal/module.f.mjs' */ import { repeat as mRepeat } from '../../common/monoid/module.f.mjs' import { cmp, max, min } from '../function/compare/module.f.mjs' -/** @import { Sign } from '../function/compare/module.f.mjs' */ +/** @import { Sign } from '../function/compare/types.ts' */ import { mapUnwrap } from '../nullable/module.f.mjs' -/** @import { Nullable } from '../nullable/module.f.mjs' */ - -/** @typedef {'1a23a4336197e6158b6936cad34e90d146cd84b9b40ff7ab75a17c6d79e31d89'} _Revision */ +/** @import { Nullable } from '../nullable/types.ts' */ /** - * A vector of bits represented as a signed `bigint`. - * - * @typedef {Nominal<'bit_vec', _Revision, bigint>} Vec + * @import { + * BitOrder, PopFront, Reduce, Unpacked, Vec, + * _NormOp, _UnpackConcat, + * } from './types.ts' */ /** @@ -150,14 +148,6 @@ export const uint = v => { return u ^ (1n << (len - 1n)) } -/** - * Structure describing the unpacked view of a vector. - * @typedef {{ - * readonly length: bigint - * readonly uint: bigint - * }} Unpacked - */ - /** * Extracts the logical length and unsigned integer from the vector. * @@ -178,17 +168,6 @@ export const pack = ({ length, uint }) => vec(length)(uint) /** @type {({ uint }: Unpacked) => bigint} */ export const unpackedUint = ({ uint }) => uint -/** - * @typedef {(len: bigint) => { - * readonly a: bigint - * readonly b: bigint - * }} _Norm - */ - -/** @typedef {Binary} _NormOp */ - -/** @typedef {OpReduce} Reduce */ - /** * Normalizes two vectors to the same length before applying a bigint reducer. * @@ -202,33 +181,6 @@ const op = norm => op => ap => bp => { return vec(len)(op(a)(b)) } -/** - * @template T - * @typedef {(len: bigint) => (u: T) => readonly [bigint, T]} PopFront - */ - -/** - * Represents operations for handling bit vectors with a specific bit order. - * - * https://en.wikipedia.org/wiki/Bit_numbering - * - * @typedef {{ - * readonly front: (len: bigint) => (v: Vec) => bigint - * readonly removeFront: (len: bigint) => (v: Vec) => Vec - * readonly popFront: PopFront - * readonly concat: Reduce - * readonly tryListToVec: (list: List) => Nullable - * readonly listToVec: (list: List) => Vec - * readonly xor: Reduce - * readonly unpackPopFront: PopFront - * readonly norm: _NormOp - * readonly cmp: (a: Vec) => (b: Vec) => Sign - * readonly unpackSplit: (len: bigint) => (u: Unpacked) => readonly[bigint, bigint] - * readonly unpackConcat: _UnpackConcat - * readonly startsWith: (prefix: Vec) => (v: Vec) => boolean - * }} BitOrder - */ - /** * @typedef {{ * readonly front: (len: bigint) => (v: Vec) => bigint @@ -242,8 +194,6 @@ const op = norm => op => ap => bp => { const unpackEmpty = /** @type {const} */{ length: 0n, uint: 0n } -/** @typedef {(a: Unpacked) => (b: Unpacked) => Unpacked} _UnpackConcat */ - /** * @typedef {{ * readonly len: bigint diff --git a/fjs/types/bit_vec/proof.f.ts b/fjs/types/bit_vec/proof.f.ts index 41c2209c4..ce8f06ca5 100644 --- a/fjs/types/bit_vec/proof.f.ts +++ b/fjs/types/bit_vec/proof.f.ts @@ -1,9 +1,11 @@ import { assert, assertEq } from '../../asserts/module.f.mjs' import { mask } from '../bigint/module.f.mjs' -import type { Sign } from '../function/compare/module.f.mjs' +import type { Sign } from '../function/compare/types.ts' import { asBase, asNominal } from '../nominal/module.f.mjs' -import { length, empty, uint, type Vec, vec, lsb, msb, type BitOrder, repeat, vec8, maxLength, u8ListToVec, tryU8ListToVec, u8List, chunkList, fromSentinel } from './module.f.mjs' -import { repeat as listRepeat, toArray, type List } from '../list/module.f.mjs' +import type { Vec, BitOrder } from './types.ts' +import { length, empty, uint, vec, lsb, msb, repeat, vec8, maxLength, u8ListToVec, tryU8ListToVec, u8List, chunkList, fromSentinel } from './module.f.mjs' +import type { List } from '../list/types.ts' +import { repeat as listRepeat, toArray } from '../list/module.f.mjs' const unsafeVec = (a: bigint): Vec => asNominal(a) diff --git a/fjs/types/bit_vec/types.ts b/fjs/types/bit_vec/types.ts new file mode 100644 index 000000000..93b1d7bed --- /dev/null +++ b/fjs/types/bit_vec/types.ts @@ -0,0 +1,64 @@ +/** + * Types for bit vectors normalized on the most-significant bit. + * + * @module + */ + +import type { Sign } from '../function/compare/types.ts' +import type { + Binary, + Reduce as OpReduce, +} from '../function/operator/types.ts' +import type { List } from '../list/types.ts' +import type { Nominal } from '../nominal/types.ts' +import type { Nullable } from '../nullable/types.ts' + +type _Revision = + '1a23a4336197e6158b6936cad34e90d146cd84b9b40ff7ab75a17c6d79e31d89' + +/** + * A vector of bits represented as a signed `bigint`. + */ +export type Vec = Nominal<'bit_vec', _Revision, bigint> + +/** + * Structure describing the unpacked view of a vector. + */ +export type Unpacked = { + readonly length: bigint + readonly uint: bigint +} + +export type _Norm = (len: bigint) => { + readonly a: bigint + readonly b: bigint +} + +export type _NormOp = Binary + +export type _UnpackConcat = (a: Unpacked) => (b: Unpacked) => Unpacked + +export type Reduce = OpReduce + +export type PopFront = (len: bigint) => (u: T) => readonly [bigint, T] + +/** + * Represents operations for handling bit vectors with a specific bit order. + * + * https://en.wikipedia.org/wiki/Bit_numbering + */ +export type BitOrder = { + readonly front: (len: bigint) => (v: Vec) => bigint + readonly removeFront: (len: bigint) => (v: Vec) => Vec + readonly popFront: PopFront + readonly concat: Reduce + readonly tryListToVec: (list: List) => Nullable + readonly listToVec: (list: List) => Vec + readonly xor: Reduce + readonly unpackPopFront: PopFront + readonly norm: _NormOp + readonly cmp: (a: Vec) => (b: Vec) => Sign + readonly unpackSplit: (len: bigint) => (u: Unpacked) => readonly [bigint, bigint] + readonly unpackConcat: _UnpackConcat + readonly startsWith: (prefix: Vec) => (v: Vec) => boolean +} diff --git a/fjs/types/btree/find/module.f.mjs b/fjs/types/btree/find/module.f.mjs index a9c61f5c2..d8ab53db2 100644 --- a/fjs/types/btree/find/module.f.mjs +++ b/fjs/types/btree/find/module.f.mjs @@ -3,53 +3,13 @@ * * @module */ -/** @import { Leaf1, Leaf2, Branch3, Branch5, TNode } from '../types/module.f.mjs' */ -/** @import { List } from '../../list/module.f.mjs' */ +/** @import { TNode } from '../types/types.ts' */ import { index3, index5 } from '../../function/compare/module.f.mjs' -/** @import { Compare } from '../../function/compare/module.f.mjs' */ +/** @import { Compare } from '../../function/compare/types.ts' */ -/** @import { KeyOf, Index } from '../../array/module.f.mjs' */ - -/** - * @template T - * @typedef {readonly[Index<3>, Leaf1]} _FirstLeaf1 - */ - -/** - * @template T - * @typedef {readonly[1, Branch3]} _FirstBranch3 - */ - -/** - * @template T - * @typedef {readonly[Index<5>, Leaf2]} _FirstLeaf2 - */ - -/** - * @template T - * @typedef {readonly[1|3, Branch5]} _FirstBranch5 - */ - -/** - * @template T - * @typedef {_FirstLeaf1 | _FirstBranch3 | _FirstLeaf2 | _FirstBranch5} First - */ - -/** - * @template T - * @typedef {readonly[0|2, Branch3]} _PathItem3 - */ - -/** - * @template T - * @typedef {readonly[0|2|4, Branch5]} _PathItem5 - */ - -/** - * @template T - * @typedef {_PathItem3 | _PathItem5} PathItem - */ +/** @import { KeyOf } from '../../array/types.ts' */ +/** @import { First, Path, PathItem, Result } from './types.ts' */ /** @type {(item: PathItem) => TNode} */ const child = item => { @@ -57,19 +17,6 @@ const child = item => { return /** @type {TNode} */ (item[1][item[0]]) } -/** - * @template T - * @typedef {List>} Path - */ - -/** - * @template T - * @typedef {{ - * readonly first: First, - * readonly tail: Path - * }} Result - */ - /** @type {(c: Compare) => (node: TNode) => Result} */ export const find = c => { /** @typedef {typeof c extends Compare ? T : never} T */ diff --git a/fjs/types/btree/find/proof.f.ts b/fjs/types/btree/find/proof.f.ts index c9cba85f9..52e6ebfcb 100644 --- a/fjs/types/btree/find/proof.f.ts +++ b/fjs/types/btree/find/proof.f.ts @@ -1,9 +1,10 @@ -import { type Result, find as btreeFind } from './module.f.mjs' +import type { Result } from './types.ts' +import { find as btreeFind } from './module.f.mjs' import { map, toArray } from '../../list/module.f.mjs' import { stringify, type Unknown } from '../../../media/json/module.f.ts' import { sort } from '../../object/module.f.ts' -import { type TNode } from '../types/module.f.mjs' -import { cmp } from '../../string/module.f.ts' +import type { TNode } from '../types/types.ts' +import { cmp } from '../../string/module.f.mjs' import { set as setSet } from '../set/module.f.mjs' import { assertEq } from '../../../asserts/module.f.mjs' diff --git a/fjs/types/btree/find/types.ts b/fjs/types/btree/find/types.ts new file mode 100644 index 000000000..e688e5cd1 --- /dev/null +++ b/fjs/types/btree/find/types.ts @@ -0,0 +1,33 @@ +/** + * Types for B-tree lookup results and paths. + * + * @module + */ + +import type { Index } from '../../array/types.ts' +import type { List } from '../../list/types.ts' +import type { Branch3, Branch5, Leaf1, Leaf2 } from '../types/types.ts' + +type _FirstLeaf1 = readonly [Index<3>, Leaf1] + +type _FirstBranch3 = readonly [1, Branch3] + +type _FirstLeaf2 = readonly [Index<5>, Leaf2] + +type _FirstBranch5 = readonly [1 | 3, Branch5] + +export type First = + _FirstLeaf1 | _FirstBranch3 | _FirstLeaf2 | _FirstBranch5 + +type _PathItem3 = readonly [0 | 2, Branch3] + +type _PathItem5 = readonly [0 | 2 | 4, Branch5] + +export type PathItem = _PathItem3 | _PathItem5 + +export type Path = List> + +export type Result = { + readonly first: First + readonly tail: Path +} diff --git a/fjs/types/btree/module.f.mjs b/fjs/types/btree/module.f.mjs index e087a1631..de9b9d852 100644 --- a/fjs/types/btree/module.f.mjs +++ b/fjs/types/btree/module.f.mjs @@ -5,9 +5,9 @@ */ import { flat } from '../list/module.f.mjs' -/** @import { List, Thunk } from '../list/module.f.mjs' */ +/** @import { List, Thunk } from '../list/types.ts' */ import { map } from '../nullable/module.f.mjs' -/** @import { TNode, Tree } from './types/module.f.mjs' */ +/** @import { TNode, Tree } from './types/types.ts' */ /** @type {(node: TNode) => Thunk} */ const nodeValues diff --git a/fjs/types/btree/proof.f.ts b/fjs/types/btree/proof.f.ts index a66df1752..66a5b1c25 100644 --- a/fjs/types/btree/proof.f.ts +++ b/fjs/types/btree/proof.f.ts @@ -1,9 +1,10 @@ -import type { TNode } from './types/module.f.mjs' +import type { TNode } from './types/types.ts' import { values } from './module.f.mjs' import { stringify as jsonStringify, type Unknown } from '../../media/json/module.f.ts' import { sort } from '../object/module.f.ts' -import { cmp } from '../string/module.f.ts' -import { next, toArray, type List, type Result } from '../list/module.f.mjs' +import { cmp } from '../string/module.f.mjs' +import type { List, Result } from '../list/types.ts' +import { next, toArray } from '../list/module.f.mjs' import { set as setSet } from './set/module.f.mjs' import { value, find as findFind } from './find/module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' diff --git a/fjs/types/btree/remove/module.f.mjs b/fjs/types/btree/remove/module.f.mjs index 77600dd73..3b1a24cf6 100644 --- a/fjs/types/btree/remove/module.f.mjs +++ b/fjs/types/btree/remove/module.f.mjs @@ -4,16 +4,16 @@ * @module */ import { collapseRoot } from '../types/module.f.mjs' -/** @import { Leaf1, TNode, Branch1, Branch3, Branch5, Tree } from '../types/module.f.mjs' */ +/** @import { Leaf1, TNode, Branch1, Branch3, Branch5, Tree } from '../types/types.ts' */ -/** @import { Compare } from '../../function/compare/module.f.mjs' */ +/** @import { Compare } from '../../function/compare/types.ts' */ import { find } from '../find/module.f.mjs' -/** @import { Path, PathItem } from '../find/module.f.mjs' */ +/** @import { Path, PathItem } from '../find/types.ts' */ import { fold, concat, next } from '../../list/module.f.mjs' -/** @import { Tuple } from '../../array/module.f.mjs' */ +/** @import { Tuple } from '../../array/types.ts' */ import { map } from '../../nullable/module.f.mjs' diff --git a/fjs/types/btree/remove/proof.f.ts b/fjs/types/btree/remove/proof.f.ts index 8edbd60d5..7f03924b2 100644 --- a/fjs/types/btree/remove/proof.f.ts +++ b/fjs/types/btree/remove/proof.f.ts @@ -1,7 +1,7 @@ import { nodeRemove } from './module.f.mjs' -import type { TNode } from '../types/module.f.mjs' +import type { TNode } from '../types/types.ts' import { set as setSet } from '../set/module.f.mjs' -import { cmp } from '../../string/module.f.ts' +import { cmp } from '../../string/module.f.mjs' import { stringify } from '../../../media/json/module.f.ts' import { sort } from '../../object/module.f.ts' import { assertEq, assertNotNullish } from '../../../asserts/module.f.mjs' diff --git a/fjs/types/btree/set/module.f.mjs b/fjs/types/btree/set/module.f.mjs index 1f2a8b8c0..9337a6d9a 100644 --- a/fjs/types/btree/set/module.f.mjs +++ b/fjs/types/btree/set/module.f.mjs @@ -4,12 +4,12 @@ * @module */ import { collapseRoot } from '../types/module.f.mjs' -/** @import { Branch1, Branch3, Branch5, Branch7, TNode, Tree } from '../types/module.f.mjs' */ +/** @import { Branch1, Branch3, Branch5, Branch7, TNode, Tree } from '../types/types.ts' */ import { find } from '../find/module.f.mjs' -/** @import { First, PathItem, Result } from '../find/module.f.mjs' */ +/** @import { First, PathItem, Result } from '../find/types.ts' */ -/** @import { Compare } from '../../function/compare/module.f.mjs' */ +/** @import { Compare } from '../../function/compare/types.ts' */ import { fold } from '../../list/module.f.mjs' diff --git a/fjs/types/btree/set/proof.f.ts b/fjs/types/btree/set/proof.f.ts index d4e80cca8..57148260f 100644 --- a/fjs/types/btree/set/proof.f.ts +++ b/fjs/types/btree/set/proof.f.ts @@ -1,6 +1,6 @@ import { set as setSet } from './module.f.mjs' -import type { TNode } from '../types/module.f.mjs' -import { cmp } from '../../string/module.f.ts' +import type { TNode } from '../types/types.ts' +import { cmp } from '../../string/module.f.mjs' import { stringify } from '../../../media/json/module.f.ts' import { sort } from '../../object/module.f.ts' import { assertEq } from '../../../asserts/module.f.mjs' diff --git a/fjs/types/btree/types/module.f.mjs b/fjs/types/btree/types/module.f.mjs index bb3a559f2..0f9e798c7 100644 --- a/fjs/types/btree/types/module.f.mjs +++ b/fjs/types/btree/types/module.f.mjs @@ -1,49 +1,10 @@ /** - * Shared type definitions for persistent B-tree modules. + * Node helpers shared by the persistent B-tree modules. The node types + * themselves live in `./types.ts`. * * @module */ -/** @import { Tuple } from '../../array/module.f.mjs' */ - -/** - * @template T - * @typedef {Tuple<1, T>} Leaf1 - */ - -/** - * @template T - * @typedef {Tuple<2, T>} Leaf2 - */ - -/** - * @template T - * @typedef {readonly[TNode, T, TNode]} Branch3 - */ - -/** - * @template T - * @typedef {readonly[TNode, T, TNode, T, TNode]} Branch5 - */ - -/** - * @template T - * @typedef {Leaf1 | Leaf2 | Branch3 | Branch5} TNode - */ - -/** - * @template T - * @typedef {TNode | null} Tree - */ - -/** - * @template T - * @typedef {readonly[TNode]} Branch1 - */ - -/** - * @template T - * @typedef {readonly[...Branch5, T, TNode]} Branch7 - */ +/** @import { Branch1, Branch3, Branch5, TNode } from './types.ts' */ /** * Demotes a single-child branch root to its only child. diff --git a/fjs/types/btree/types/types.ts b/fjs/types/btree/types/types.ts new file mode 100644 index 000000000..d16c93e71 --- /dev/null +++ b/fjs/types/btree/types/types.ts @@ -0,0 +1,23 @@ +/** + * Shared type definitions for persistent B-tree modules. + * + * @module + */ + +import type { Tuple } from '../../array/types.ts' + +export type Leaf1 = Tuple<1, T> + +export type Leaf2 = Tuple<2, T> + +export type Branch3 = readonly [TNode, T, TNode] + +export type Branch5 = readonly [TNode, T, TNode, T, TNode] + +export type TNode = Leaf1 | Leaf2 | Branch3 | Branch5 + +export type Tree = TNode | null + +export type Branch1 = readonly [TNode] + +export type Branch7 = readonly [...Branch5, T, TNode] diff --git a/fjs/types/byte_set/module.f.ts b/fjs/types/byte_set/module.f.ts index 7c8bc6688..4c0fbf5e0 100644 --- a/fjs/types/byte_set/module.f.ts +++ b/fjs/types/byte_set/module.f.ts @@ -4,7 +4,7 @@ * @module */ import { compose } from '../function/module.f.mjs' -import type { RangeMap } from '../range_map/module.f.mjs' +import type { RangeMap } from '../range_map/types.ts' import type { SortedSet } from '../sorted_set/module.f.ts' import { reverse, countdown, flat, map } from '../list/module.f.mjs' diff --git a/fjs/types/function/compare/module.f.mjs b/fjs/types/function/compare/module.f.mjs index 2cab3d8ac..e2c5d1a25 100644 --- a/fjs/types/function/compare/module.f.mjs +++ b/fjs/types/function/compare/module.f.mjs @@ -3,19 +3,8 @@ * * @module */ -/** @import { Index, Tuple } from '../../array/module.f.mjs' */ - -/** @typedef {-1 | 0 | 1} Sign */ - -/** - * @template T - * @typedef {(_: T) => Sign} Compare - */ - -/** - * @template T - * @typedef {(a: T) => Compare} Cmp - */ +/** @import { Index, Tuple } from '../../array/types.ts' */ +/** @import { Cmp1, Cmp2, Compare, Sign } from './types.ts' */ /** @type {(cmp: Compare) => (value: T) => Index<3>} */ export const index3 @@ -27,19 +16,6 @@ export const index5 = cmp => ([v0, v1]) => { return /** @type {Index<5>} */(_0 <= 0 ? _0 + 1 : cmp(v1) + 3) } -/** @typedef {boolean | string | number | bigint} Cmp1 */ - -/** - * @template A - * @template B - * @typedef {[A, B] extends [boolean, boolean] ? boolean : - * [A, B] extends [string, string] ? string : - * [A, B] extends [number, number] ? number : - * [A, B] extends [bigint, bigint] ? bigint : - * never - * } Cmp2 - */ - /** @type {(a: A) => >(b: B) => Sign} */ export const cmp = a => b => /** @type {any} */(a) < b ? -1 : /** @type {any} */(a) > b ? 1 : 0 diff --git a/fjs/types/function/compare/types.ts b/fjs/types/function/compare/types.ts new file mode 100644 index 000000000..dec10fca7 --- /dev/null +++ b/fjs/types/function/compare/types.ts @@ -0,0 +1,20 @@ +/** + * Comparison function types. + * + * @module + */ + +export type Sign = -1 | 0 | 1 + +export type Compare = (_: T) => Sign + +export type Cmp = (a: T) => Compare + +export type Cmp1 = boolean | string | number | bigint + +export type Cmp2 = + [A, B] extends [boolean, boolean] ? boolean : + [A, B] extends [string, string] ? string : + [A, B] extends [number, number] ? number : + [A, B] extends [bigint, bigint] ? bigint : + never diff --git a/fjs/types/function/module.f.mjs b/fjs/types/function/module.f.mjs index 92682f2bf..974e4f509 100644 --- a/fjs/types/function/module.f.mjs +++ b/fjs/types/function/module.f.mjs @@ -1,9 +1,4 @@ -/** - * A generic function type. - * - * @template I, O - * @typedef {(_: I) => O} Func - */ +/** @import { Func, Fn } from './types.ts' */ /** * A postfix compose function. @@ -26,16 +21,6 @@ export const identity = value => value */ export const flip = f => b => a => f(a)(b) -/** - * A functional utility type that enables seamless chaining of transformations. - * - * @template I, O - * @typedef {{ - * readonly result: Func - * readonly map: (g: Func) => Fn - * }} Fn - */ - /** * Creates an `Fn` instance from a function, enabling chaining of transformations. * diff --git a/fjs/types/function/operator/module.f.mjs b/fjs/types/function/operator/module.f.mjs index 67d4e9018..aec7e66eb 100644 --- a/fjs/types/function/operator/module.f.mjs +++ b/fjs/types/function/operator/module.f.mjs @@ -4,23 +4,7 @@ * @module */ -/** - * @template A - * @template B - * @template R - * @typedef {(a: A) => (b: B) => R} Binary - */ - -/** - * @template I - * @template O - * @typedef {Binary} Fold - */ - -/** - * @template T - * @typedef {Fold} Reduce - */ +/** @import { Fold, Reduce, Scan, StateScan, Unary } from './types.ts' */ /** @type {(separator: string) => Reduce} */ export const join = separator => value => prior => @@ -29,20 +13,9 @@ export const join = separator => value => prior => /** @type {Reduce} */ export const concat = i => acc => `${acc}${i}` -/** - * @template T - * @template R - * @typedef {(value: T) => R} Unary - */ - /** @type {Unary} */ export const logicalNot = v => !v -/** - * @template T - * @typedef {Binary} Equal - */ - /** * See also `Object.is` which should be used for deep comparison instead of the `structEqual`. * TODO: add `binaryEqual = a => b => Object.is(a, b)`. @@ -51,44 +24,6 @@ export const logicalNot = v => !v */ export const strictEqual = a => b => a === b -/** - * @template I - * @template O - * @typedef {(input: I) => readonly[O, Scan]} Scan - */ - -/** - * One step of a stream transducer: given an `input` symbol and the `prior` - * state, produce an `output` and the next state. It both maps an input stream - * to an output stream and threads state, so it models tokenizers, decoders, and - * other stream-to-stream stages. - * - * This is the *shape* of a [Mealy machine](https://en.wikipedia.org/wiki/Mealy_machine) - * — a [finite-state transducer](https://en.wikipedia.org/wiki/Finite-state_transducer) - * — but only its signature. The state `S` (and `I`, `O`) is an arbitrary type, - * not a finite set, so a `StateScan` is strictly more expressive than a Mealy - * machine — its power is the power of `S`: - * - a finite `S`/`I`/`O` recovers the classical finite-state machine (e.g. the - * DFA states in `../../../fsm/module.f.ts`); - * - an `S` that is a stack makes it a - * [pushdown / stack machine](https://en.wikipedia.org/wiki/Pushdown_automaton) - * (context-free power — balanced brackets, nested structure, the AST tier); - * - an unbounded `S` like `bigint` can count, which no finite automaton can. - * - * And `O` may be a list (0+ symbols per input), not the single symbol strict - * Mealy emits. (Functional/coalgebraic usage still calls this `(input, state) - * => [output, state]` shape a "Mealy machine", finiteness aside.) - * - * A {@link Fold} is the output-less special case (state only); driving a - * `StateScan` over a `List` is `stateScan` in `../../list/module.f.ts`, and - * {@link stateScanToScan} hides the state to recover a {@link Scan}. - * - * @template I - * @template S - * @template O - * @typedef {(input: I, prior: S) => readonly[O, S]} StateScan - */ - /** @type {(op: StateScan) => (prior: S) => Scan} */ export const stateScanToScan = op => prior => i => { const [o, s] = op(i, prior) diff --git a/fjs/types/function/operator/types.ts b/fjs/types/function/operator/types.ts new file mode 100644 index 000000000..e69365564 --- /dev/null +++ b/fjs/types/function/operator/types.ts @@ -0,0 +1,46 @@ +/** + * Common higher-order operator type aliases. + * + * @module + */ + +export type Binary = (a: A) => (b: B) => R + +export type Fold = Binary + +export type Reduce = Fold + +export type Unary = (value: T) => R + +export type Equal = Binary + +export type Scan = (input: I) => readonly [O, Scan] + +/** + * One step of a stream transducer: given an `input` symbol and the `prior` + * state, produce an `output` and the next state. It both maps an input stream + * to an output stream and threads state, so it models tokenizers, decoders, and + * other stream-to-stream stages. + * + * This is the *shape* of a [Mealy machine](https://en.wikipedia.org/wiki/Mealy_machine) + * — a [finite-state transducer](https://en.wikipedia.org/wiki/Finite-state_transducer) + * — but only its signature. The state `S` (and `I`, `O`) is an arbitrary type, + * not a finite set, so a `StateScan` is strictly more expressive than a Mealy + * machine — its power is the power of `S`: + * - a finite `S`/`I`/`O` recovers the classical finite-state machine (e.g. the + * DFA states in `../../../fsm/module.f.ts`); + * - an `S` that is a stack makes it a + * [pushdown / stack machine](https://en.wikipedia.org/wiki/Pushdown_automaton) + * (context-free power — balanced brackets, nested structure, the AST tier); + * - an unbounded `S` like `bigint` can count, which no finite automaton can. + * + * And `O` may be a list (0+ symbols per input), not the single symbol strict + * Mealy emits. (Functional/coalgebraic usage still calls this `(input, state) + * => [output, state]` shape a "Mealy machine", finiteness aside.) + * + * A {@link Fold} is the output-less special case (state only); driving a + * `StateScan` over a `List` is `stateScan` in `../../list/module.f.mjs`, and + * {@link ./module.f.mjs | `stateScanToScan`} hides the state to recover a + * {@link Scan}. + */ +export type StateScan = (input: I, prior: S) => readonly [O, S] diff --git a/fjs/types/function/types.ts b/fjs/types/function/types.ts new file mode 100644 index 000000000..652102337 --- /dev/null +++ b/fjs/types/function/types.ts @@ -0,0 +1,18 @@ +/** + * Types for function composition. + * + * @module + */ + +/** + * A generic function type. + */ +export type Func = (_: I) => O + +/** + * A functional utility type that enables seamless chaining of transformations. + */ +export type Fn = { + readonly result: Func + readonly map: (g: Func) => Fn +} diff --git a/fjs/types/list/module.f.mjs b/fjs/types/list/module.f.mjs index fd5a7cfa6..8571e85a6 100644 --- a/fjs/types/list/module.f.mjs +++ b/fjs/types/list/module.f.mjs @@ -4,7 +4,7 @@ * @module */ import { identity, fn, compose } from '../function/module.f.mjs' -/** @import { Nullable } from '../nullable/module.f.mjs' */ +/** @import { Nullable } from '../nullable/types.ts' */ import { addition, logicalNot, @@ -13,50 +13,8 @@ import { foldToScan, reduceToScan, } from '../function/operator/module.f.mjs' -/** @import {Scan, StateScan, Fold, Reduce, Equal} from '../function/operator/module.f.mjs' */ - -/** - * @template T - * @typedef {NotLazy | Thunk} List - */ - -/** - * @template T - * @typedef {Result | - * Concat | - * readonly T[] - * } NotLazy - */ - -/** @typedef {null} Empty */ - -/** - * @template T - * @typedef {Empty | NonEmpty} Result - */ - -/** - * @template T - * @typedef {() => List} Thunk - */ - -/** - * See also https://en.wikipedia.org/wiki/Cons#Lists - * - * @template T - * @typedef {{ - * readonly first: T - * readonly tail: List - * }} NonEmpty - */ - -/** - * @template T - * @typedef {{ - * readonly head: List - * readonly tail: List - * }} Concat - */ +/** @import {Scan, StateScan, Fold, Reduce, Equal} from '../function/operator/types.ts' */ +/** @import { Accumulator, Concat, Entry, List, NonEmpty, NotLazy, Result, Thunk } from './types.ts' */ export const fromArrayLike = /** @@ -274,24 +232,6 @@ export const fold = op => init => compose(foldScan(op)(init))(last(init)) /** @type {(op: Reduce) => (def: D) => (input: List) => D | T} */ export const reduce = op => def => compose(scan(reduceToScan(op)))(last(def)) -/** - * A fold that can bail out early, packaged as plain data. - * - * `init` is the starting state, `update` advances the state by one item and - * returns `null` to abort the whole fold, and `end` finalizes the surviving - * state into a result. Keeping the three parts together lets `tryFold` drive - * any short-circuiting accumulation without knowing its domain. - * - * @template I - * @template T - * @template R - * @typedef {{ - * readonly init: T - * readonly update: (i: I, state: T) => Nullable - * readonly end: (state: T) => R - * }} Accumulator - */ - /** * Folds `input` with an {@link Accumulator}, short-circuiting to `null` the * moment `update` rejects an item; otherwise finalizes with `end`. This is the @@ -327,11 +267,6 @@ const sum = reduce(addition)(0) /** @type {(input: List) => number} */ export const length = input => sum(lengthList(input)) -/** - * @template T - * @typedef {readonly [number, T]} Entry - */ - /** @type {(value: T, index: number) => readonly [Entry, number]} */ const entryOperator = (value, index) => [[index, value], index + 1] diff --git a/fjs/types/list/proof.f.ts b/fjs/types/list/proof.f.ts index 6cca9eb4e..ba60716c3 100644 --- a/fjs/types/list/proof.f.ts +++ b/fjs/types/list/proof.f.ts @@ -1,33 +1,5 @@ -import { - length, - concat, - countdown, - cycle, - drop, - dropWhile, - entries, - every, - filter, - find, - flat, - flatMap, - map, - next, - reduce, - reverse, - scan, - some, - take, - takeWhile, - toArray, - zip, - type List, - first, - filterMap, - isEmpty, - equal, - tryFold -} from './module.f.mjs' +import type { List } from './types.ts' +import { length, concat, countdown, cycle, drop, dropWhile, entries, every, filter, find, flat, flatMap, map, next, reduce, reverse, scan, some, take, takeWhile, toArray, zip, first, filterMap, isEmpty, equal, tryFold } from './module.f.mjs' import { stringify, type Unknown } from '../../media/json/module.f.ts' import { sort } from '../object/module.f.ts' import { addition, strictEqual, reduceToScan } from '../function/operator/module.f.mjs' diff --git a/fjs/types/list/todo/simplify-list-type.md b/fjs/types/list/todo/simplify-list-type.md index bd586b224..ceb984241 100644 --- a/fjs/types/list/todo/simplify-list-type.md +++ b/fjs/types/list/todo/simplify-list-type.md @@ -5,7 +5,7 @@ ### Problem -`List` (`fjs/types/list/module.f.mjs`) currently has four shapes behind two +`List` (`fjs/types/list/types.ts`) currently has four shapes behind two type aliases: ```ts diff --git a/fjs/types/list/types.ts b/fjs/types/list/types.ts new file mode 100644 index 000000000..a564eca58 --- /dev/null +++ b/fjs/types/list/types.ts @@ -0,0 +1,46 @@ +/** + * Types for the immutable list data structure. + * + * @module + */ + +import type { Nullable } from '../nullable/types.ts' + +export type List = NotLazy | Thunk + +export type NotLazy = Result | Concat | readonly T[] + +export type Empty = null + +export type Result = Empty | NonEmpty + +export type Thunk = () => List + +/** + * See also https://en.wikipedia.org/wiki/Cons#Lists + */ +export type NonEmpty = { + readonly first: T + readonly tail: List +} + +export type Concat = { + readonly head: List + readonly tail: List +} + +/** + * A fold that can bail out early, packaged as plain data. + * + * `init` is the starting state, `update` advances the state by one item and + * returns `null` to abort the whole fold, and `end` finalizes the surviving + * state into a result. Keeping the three parts together lets `tryFold` drive + * any short-circuiting accumulation without knowing its domain. + */ +export type Accumulator = { + readonly init: T + readonly update: (i: I, state: T) => Nullable + readonly end: (state: T) => R +} + +export type Entry = readonly [number, T] diff --git a/fjs/types/nibble_set/module.f.mjs b/fjs/types/nibble_set/module.f.mjs index f09d563ed..e0f1706d0 100644 --- a/fjs/types/nibble_set/module.f.mjs +++ b/fjs/types/nibble_set/module.f.mjs @@ -15,9 +15,7 @@ * @module */ -/** A set of nibbles as a 16-bit mask. JSON-serializable. @typedef {number} NibbleSet */ - -/** A 4-bit value, `0..15`. @typedef {number} Nibble */ +/** @import { Nibble, NibbleSet } from './types.ts' */ export const empty = 0 diff --git a/fjs/types/nibble_set/types.ts b/fjs/types/nibble_set/types.ts new file mode 100644 index 000000000..e83e40de7 --- /dev/null +++ b/fjs/types/nibble_set/types.ts @@ -0,0 +1,11 @@ +/** + * Types for compact 4-bit membership tracking. + * + * @module + */ + +/** A set of nibbles as a 16-bit mask. JSON-serializable. */ +export type NibbleSet = number + +/** A 4-bit value, `0..15`. */ +export type Nibble = number diff --git a/fjs/types/nominal/module.f.mjs b/fjs/types/nominal/module.f.mjs index d87162d59..331e9108c 100644 --- a/fjs/types/nominal/module.f.mjs +++ b/fjs/types/nominal/module.f.mjs @@ -5,18 +5,7 @@ */ import { identity } from "../function/module.f.mjs" - -/** - * Nominal type. - * - * It doesn't allow `===` between different nominal types. - * It doesn't allow `<`, `>`, `<=`, `>=` comparisons at all. - * - * @template {string} N - * @template {string} R - * @template B - * @typedef {symbol & {[k in N]: readonly[R, B]}} Nominal - */ +/** @import { Nominal } from './types.ts' */ export const asNominal = /** @type {(b: B) => Nominal} */ diff --git a/fjs/types/nominal/proof.f.ts b/fjs/types/nominal/proof.f.ts index 126214038..ed35f2982 100644 --- a/fjs/types/nominal/proof.f.ts +++ b/fjs/types/nominal/proof.f.ts @@ -1,4 +1,5 @@ -import { asBase, asNominal, type Nominal } from "./module.f.mjs" +import type { Nominal } from "./types.ts" +import { asBase, asNominal } from "./module.f.mjs" import { assert } from '../../asserts/module.f.mjs' declare const noCompareBrand: unique symbol diff --git a/fjs/types/nominal/types.ts b/fjs/types/nominal/types.ts new file mode 100644 index 000000000..8e335e462 --- /dev/null +++ b/fjs/types/nominal/types.ts @@ -0,0 +1,14 @@ +/** + * Types for nominal typing (branded TypeScript types). + * + * @module + */ + +/** + * Nominal type. + * + * It doesn't allow `===` between different nominal types. + * It doesn't allow `<`, `>`, `<=`, `>=` comparisons at all. + */ +export type Nominal = + symbol & { [k in N]: readonly [R, B] } diff --git a/fjs/types/nullable/module.f.mjs b/fjs/types/nullable/module.f.mjs index c7e72c03f..797323181 100644 --- a/fjs/types/nullable/module.f.mjs +++ b/fjs/types/nullable/module.f.mjs @@ -5,12 +5,8 @@ */ import { assert } from '../../asserts/module.f.mjs' import { fn } from '../function/module.f.mjs' -/** @import { Option } from '../option/module.f.mjs' */ - -/** - * @template T - * @typedef {T | null} Nullable - */ +/** @import { Option } from '../option/types.ts' */ +/** @import { Nullable } from './types.ts' */ /** * @type {(f: (value: T) => R) => (value: Nullable) => Nullable} diff --git a/fjs/types/nullable/types.ts b/fjs/types/nullable/types.ts new file mode 100644 index 000000000..81b3ce6a2 --- /dev/null +++ b/fjs/types/nullable/types.ts @@ -0,0 +1,7 @@ +/** + * Types for nullable (`null`) value handling. + * + * @module + */ + +export type Nullable = T | null diff --git a/fjs/types/number/module.f.mjs b/fjs/types/number/module.f.mjs index 8acb209d1..1f9191a96 100644 --- a/fjs/types/number/module.f.mjs +++ b/fjs/types/number/module.f.mjs @@ -6,11 +6,11 @@ */ import { reduce } from '../list/module.f.mjs' -/** @import { List } from '../list/module.f.mjs' */ +/** @import { List } from '../list/types.ts' */ import { addition } from '../function/operator/module.f.mjs' -/** @import { Reduce } from '../function/operator/module.f.mjs' */ +/** @import { Reduce } from '../function/operator/types.ts' */ import { cmp as uCmp, min as uMin, max as uMax } from '../function/compare/module.f.mjs' -/** @import { Sign } from '../function/compare/module.f.mjs' */ +/** @import { Sign } from '../function/compare/types.ts' */ import { fold } from '../../common/monoid/module.f.mjs' /** @type {(input: List) => number} */ diff --git a/fjs/types/object/module.f.ts b/fjs/types/object/module.f.ts index fa7f32864..dc6f21414 100644 --- a/fjs/types/object/module.f.ts +++ b/fjs/types/object/module.f.ts @@ -6,10 +6,15 @@ * * @module */ + +import type { List } from '../list/types.ts' +import type { Nullable } from '../nullable/types.ts' +import type { OrderedMap } from '../ordered_map/types.ts' + import { isArray } from '../array/module.f.mjs' -import { iterable, type List } from '../list/module.f.mjs' -import { fromUndefined, type Nullable } from '../nullable/module.f.mjs' -import { entries as mapEntries, fromEntries as mapFromEntries, type OrderedMap } from '../ordered_map/module.f.ts' +import { iterable } from '../list/module.f.mjs' +import { fromUndefined } from '../nullable/module.f.mjs' +import { entries as mapEntries, fromEntries as mapFromEntries } from '../ordered_map/module.f.mjs' const { getOwnPropertyDescriptor, fromEntries: objectFromEntries } = Object diff --git a/fjs/types/object/proof.f.ts b/fjs/types/object/proof.f.ts index 0d082a950..b37859392 100644 --- a/fjs/types/object/proof.f.ts +++ b/fjs/types/object/proof.f.ts @@ -1,7 +1,8 @@ import { at } from './module.f.ts' import type { OptionalMap, RequiredMap, StringMap } from './module.f.ts' -import { assertEq, type Assert } from '../../asserts/module.f.mjs' -import type { Equal } from '../ts/module.f.mjs' +import { assertEq } from '../../asserts/module.f.mjs' +import type { Assert } from '../../asserts/types.ts' +import type { Equal } from '../ts/types.ts' type _StringMapIsOptional = Assert, diff --git a/fjs/types/option/module.f.mjs b/fjs/types/option/types.ts similarity index 70% rename from fjs/types/option/module.f.mjs rename to fjs/types/option/types.ts index 70a8cf301..fc7937afb 100644 --- a/fjs/types/option/module.f.mjs +++ b/fjs/types/option/types.ts @@ -6,7 +6,5 @@ /** * Represents an optional value as an empty tuple or a tuple with one value. - * - * @template T - * @typedef {readonly [T] | readonly []} Option */ +export type Option = readonly [T] | readonly [] diff --git a/fjs/types/ordered_map/module.f.mjs b/fjs/types/ordered_map/module.f.mjs new file mode 100644 index 000000000..ac6d8d52b --- /dev/null +++ b/fjs/types/ordered_map/module.f.mjs @@ -0,0 +1,54 @@ +/** + * Ordered map operations with deterministic key traversal. + * + * @module + */ + +import { value, find } from '../btree/find/module.f.mjs' +import { set } from '../btree/set/module.f.mjs' +import { remove as btreeRemove } from '../btree/remove/module.f.mjs' +import { values } from '../btree/module.f.mjs' +/** @import { Sign } from '../function/compare/types.ts' */ +import { cmp } from '../string/module.f.mjs' +/** @import { List } from '../list/types.ts' */ +import { fold } from '../list/module.f.mjs' +/** @import { Reduce } from '../function/operator/types.ts' */ +/** @import { Entry, OrderedMap } from './types.ts' */ + +/** @type {(a: string) => (b: Entry) => Sign} */ +const keyCmp = a => ([b]) => cmp(a)(b) + +/** @type {(name: string) => (map: OrderedMap) => T | null} */ +export const at = name => map => { + if (map === null) { return null } + const result = value(find(keyCmp(name))(map).first) + return result === null ? null : result[1] +} + +/** @type {(reduce: Reduce) => (entry: Entry) => (map: OrderedMap) => OrderedMap} */ +const setReduceEntry = reduce => entry => + set(keyCmp(entry[0]))(old => old === null ? entry : [old[0], reduce(old[1])(entry[1])]) + +/** @type {(reduce: Reduce) => (name: string) => (value: T) => (map: OrderedMap) => OrderedMap} */ +export const setReduce = + reduce => name => value => setReduceEntry(reduce)([name, value]) + +/** @type {(a: T) => (b: T) => T} */ +const replace = () => b => b + +/** @type {(name: string) => (value: T) => (map: OrderedMap) => OrderedMap} */ +export const setReplace = + name => value => setReduceEntry(replace)([name, value]) + +/** @type {(map: OrderedMap) => List>} */ +export const entries = values + +/** @type {(entries: List>) => OrderedMap} */ +export const fromEntries = + fold(setReduceEntry(replace))(null) + +/** @type {(name: string) => (map: OrderedMap) => OrderedMap} */ +export const remove = + name => btreeRemove(keyCmp(name)) + +export const empty = null diff --git a/fjs/types/ordered_map/module.f.ts b/fjs/types/ordered_map/module.f.ts deleted file mode 100644 index c16516b58..000000000 --- a/fjs/types/ordered_map/module.f.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Ordered map operations with deterministic key traversal. - * - * @module - */ -import type { Tree } from '../btree/types/module.f.mjs' -import { value, find } from '../btree/find/module.f.mjs' -import { set } from '../btree/set/module.f.mjs' -import { remove as btreeRemove } from '../btree/remove/module.f.mjs' -import { values } from '../btree/module.f.mjs' -import type { Sign } from '../function/compare/module.f.mjs' -import { cmp } from '../string/module.f.ts' -import { fold, type List } from '../list/module.f.mjs' -import type { Reduce } from '../function/operator/module.f.mjs' - -export type Entry = readonly [string, T] - -export type OrderedMap = Tree> - -const keyCmp: (a: string) => (b: Entry) => Sign - = a => ([b]) => cmp(a)(b) - -export const at - = (name: string) => (map: OrderedMap): T | null => { - if (map === null) { return null } - const result = value(find(keyCmp(name))(map).first) - return result === null ? null : result[1] - } - -const setReduceEntry - : (reduce: Reduce) => (entry: Entry) => (map: OrderedMap) => OrderedMap - = reduce => entry => - set(keyCmp(entry[0]))(old => old === null ? entry : [old[0], reduce(old[1])(entry[1])]) - -export const setReduce - : (reduce: Reduce) => (name: string) => (value: T) => (map: OrderedMap) => OrderedMap - = reduce => name => value => setReduceEntry(reduce)([name, value]) - -const replace - : (a: T) => (b: T) => T - = () => b => b - -export const setReplace - : (name: string) => (value: T) => (map: OrderedMap) => OrderedMap - = name => value => setReduceEntry(replace)([name, value]) - -export const entries - : (map: OrderedMap) => List> - = values - -export const fromEntries - : (entries: List>) => OrderedMap - = fold(setReduceEntry(replace))(null) - -export const remove - : (name: string) => (map: OrderedMap) => OrderedMap - = name => btreeRemove(keyCmp(name)) - -export const empty = null diff --git a/fjs/types/ordered_map/proof.f.ts b/fjs/types/ordered_map/proof.f.mjs similarity index 84% rename from fjs/types/ordered_map/proof.f.ts rename to fjs/types/ordered_map/proof.f.mjs index 8a2eb79a9..27e90be1a 100644 --- a/fjs/types/ordered_map/proof.f.ts +++ b/fjs/types/ordered_map/proof.f.mjs @@ -1,4 +1,5 @@ -import { at, setReplace, setReduce, empty, entries, remove, fromEntries, type OrderedMap } from './module.f.ts' +import { at, setReplace, setReduce, empty, entries, remove, fromEntries } from './module.f.mjs' +/** @import { OrderedMap } from './types.ts' */ import { toArray } from '../list/module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' @@ -44,7 +45,7 @@ export const proof = { m = remove('Hello world!')(m) assertEq(at('Hello world!')(m), null) - m = setReduce((a: number) => (b: number) => a + b)('a')(43)(m) + m = setReduce((/** @type {number} */a) => (/** @type {number} */b) => a + b)('a')(43)(m) assertEq(at('a')(m), 44) }, () => { @@ -58,18 +59,20 @@ export const proof = { }, ], fromEntries: () => { - const list: readonly (readonly [string, number])[] = [['a', 1], ['b', 2], ['c', 3]] + /** @type {readonly (readonly [string, number])[]} */ + const list = [['a', 1], ['b', 2], ['c', 3]] const m = fromEntries(list) assertEq(at('a')(m), 1) assertEq(at('b')(m), 2) assertEq(at('c')(m), 3) assertEq(at('d')(m), null) // duplicate key: last one wins - const m2 = fromEntries([['x', 10], ['x', 20]] as const) + const m2 = fromEntries(/** @type {const} */([['x', 10], ['x', 20]])) assertEq(at('x')(m2), 20) }, stress: () => { - let m: OrderedMap = empty + /** @type {OrderedMap} */ + let m = empty for (let i = 0; i < 100_000; ++i) { m = setReplace((i * i).toString())(i)(m) /* diff --git a/fjs/types/ordered_map/types.ts b/fjs/types/ordered_map/types.ts new file mode 100644 index 000000000..22e15922e --- /dev/null +++ b/fjs/types/ordered_map/types.ts @@ -0,0 +1,11 @@ +/** + * Types for the ordered map data structure. + * + * @module + */ + +import type { Tree } from '../btree/types/types.ts' + +export type Entry = readonly [string, T] + +export type OrderedMap = Tree> diff --git a/fjs/types/patricia_trie/module.f.mjs b/fjs/types/patricia_trie/module.f.mjs index 27d08894b..5e529b3b8 100644 --- a/fjs/types/patricia_trie/module.f.mjs +++ b/fjs/types/patricia_trie/module.f.mjs @@ -4,51 +4,7 @@ * @module */ -/** - * Merges two child identities into a parent. Values first, storage last in both params and return. - * - * @template S - * @template T - * @typedef {(a: T, b: T, storage: S) => readonly [T, S]} Create - */ - -/** - * A leaf entry: `[sortKey, identity]`. The sort key is used only for XOR comparisons. - * - * @template T - * @typedef {readonly [bigint, T]} Candidate - */ - -/** - * @template T - * @typedef {readonly Candidate[]} InternalState - */ - -/** - * Streaming state: `[storage, right-spine stack]`. - * - * @template S - * @template T - * @typedef {readonly [S, InternalState]} State - */ - -/** - * @template S - * @template T - * @typedef {{ - * readonly push: (c: Candidate, state: State) => State - * readonly end: (state: State) => readonly [T | undefined, S] - * }} PatriciaTrie - * - * @property push - * - * Add one leaf. Merges any tightly-coupled stack candidates before pushing. - * - * @property end - * - * Drain the stack right-to-left, returning the root identity and final storage. - * Returns `undefined` as the root if no leaves were pushed. - */ +/** @import { Candidate, Create, PatriciaTrie } from './types.ts' */ /** * Creates a Patricia trie whose node merging is delegated to `create`. diff --git a/fjs/types/patricia_trie/proof.f.mjs b/fjs/types/patricia_trie/proof.f.mjs index 8031eaa5a..415376d6a 100644 --- a/fjs/types/patricia_trie/proof.f.mjs +++ b/fjs/types/patricia_trie/proof.f.mjs @@ -1,6 +1,6 @@ import { assert, assertEq } from '../../asserts/module.f.mjs' import { emptyState, patriciaTrie } from './module.f.mjs' -/** @import { State } from './module.f.mjs' */ +/** @import { State } from './types.ts' */ /** @typedef {readonly [bigint, bigint, bigint][]} _NodeList */ diff --git a/fjs/types/patricia_trie/types.ts b/fjs/types/patricia_trie/types.ts new file mode 100644 index 000000000..cb36cf4e1 --- /dev/null +++ b/fjs/types/patricia_trie/types.ts @@ -0,0 +1,39 @@ +/** + * Types for the streaming Patricia trie. + * + * @module + */ + +/** + * Merges two child identities into a parent. Values first, storage last in both + * params and return. + */ +export type Create = (a: T, b: T, storage: S) => readonly [T, S] + +/** + * A leaf entry: `[sortKey, identity]`. The sort key is used only for XOR + * comparisons. + */ +export type Candidate = readonly [bigint, T] + +export type InternalState = readonly Candidate[] + +/** + * Streaming state: `[storage, right-spine stack]`. + */ +export type State = readonly [S, InternalState] + +/** + * @property push + * + * Add one leaf. Merges any tightly-coupled stack candidates before pushing. + * + * @property end + * + * Drain the stack right-to-left, returning the root identity and final storage. + * Returns `undefined` as the root if no leaves were pushed. + */ +export type PatriciaTrie = { + readonly push: (c: Candidate, state: State) => State + readonly end: (state: State) => readonly [T | undefined, S] +} diff --git a/fjs/types/phantom/module.f.ts b/fjs/types/phantom/types.ts similarity index 100% rename from fjs/types/phantom/module.f.ts rename to fjs/types/phantom/types.ts diff --git a/fjs/types/prime_field/module.f.mjs b/fjs/types/prime_field/module.f.mjs index ce3d3ea81..1ab5d3ce8 100644 --- a/fjs/types/prime_field/module.f.mjs +++ b/fjs/types/prime_field/module.f.mjs @@ -7,43 +7,10 @@ * @module */ -/** @import { Unary, Reduce } from '../bigint/module.f.mjs' */ +/** @import { Reduce, Unary } from '../bigint/types.ts' */ import { repeat } from '../../common/monoid/module.f.mjs' import { assertNotNullish } from '../../asserts/module.f.mjs' - -/** - * A type representing a prime field and its associated operations. - * - * @typedef {{ - * readonly p: bigint - * readonly middle: bigint - * readonly max: bigint - * readonly neg: Unary - * readonly sub: Reduce - * readonly add: Reduce - * readonly abs: Unary - * readonly mul: Reduce - * readonly reciprocal: Unary - * readonly div: Reduce - * readonly pow: Reduce - * readonly pow2: Unary - * readonly pow3: Unary - * readonly reduce: Unary - * readonly quadRes: (x: bigint) => boolean - * }} PrimeField - * - * @property reduce - * - * Reduces an arbitrary `bigint` into `[0, p)`. - * - * @property quadRes - * - * `true` when `x` is a square modulo `p`, including `0`. - * - * Nonzero values are tested with Euler's criterion: - * `x^((p - 1) / 2) === 1 (mod p)`. - * For `p === 2n`, both field elements are squares. - */ +/** @import { PrimeField } from './types.ts' */ /** * Creates a prime field with the specified prime modulus and associated operations. diff --git a/fjs/types/prime_field/types.ts b/fjs/types/prime_field/types.ts new file mode 100644 index 000000000..e09c3b81b --- /dev/null +++ b/fjs/types/prime_field/types.ts @@ -0,0 +1,40 @@ +/** + * Types for prime field arithmetic over `bigint`. + * + * @module + */ + +import type { Reduce, Unary } from '../bigint/types.ts' + +/** + * A type representing a prime field and its associated operations. + * + * @property reduce + * + * Reduces an arbitrary `bigint` into `[0, p)`. + * + * @property quadRes + * + * `true` when `x` is a square modulo `p`, including `0`. + * + * Nonzero values are tested with Euler's criterion: + * `x^((p - 1) / 2) === 1 (mod p)`. + * For `p === 2n`, both field elements are squares. + */ +export type PrimeField = { + readonly p: bigint + readonly middle: bigint + readonly max: bigint + readonly neg: Unary + readonly sub: Reduce + readonly add: Reduce + readonly abs: Unary + readonly mul: Reduce + readonly reciprocal: Unary + readonly div: Reduce + readonly pow: Reduce + readonly pow2: Unary + readonly pow3: Unary + readonly reduce: Unary + readonly quadRes: (x: bigint) => boolean +} diff --git a/fjs/types/range/module.f.mjs b/fjs/types/range/module.f.mjs index 9fc941f7f..a5b0735fc 100644 --- a/fjs/types/range/module.f.mjs +++ b/fjs/types/range/module.f.mjs @@ -4,7 +4,7 @@ * @module */ -/** @typedef { readonly [number, number]} Range */ +/** @import { Range } from './types.ts' */ /** @type {(...range: Range) => (i: number) => boolean} */ export const contains = (b, e) => i => b <= i && i <= e diff --git a/fjs/types/range/types.ts b/fjs/types/range/types.ts new file mode 100644 index 000000000..cc0da8f6c --- /dev/null +++ b/fjs/types/range/types.ts @@ -0,0 +1,7 @@ +/** + * Range and interval types for numeric boundaries. + * + * @module + */ + +export type Range = readonly [number, number] diff --git a/fjs/types/range_map/module.f.mjs b/fjs/types/range_map/module.f.mjs index cb410de27..548076f0d 100644 --- a/fjs/types/range_map/module.f.mjs +++ b/fjs/types/range_map/module.f.mjs @@ -37,53 +37,21 @@ */ import { genericMerge } from '../sorted_list/module.f.mjs' -/** @import { TailReduce, ReduceOp, SortedList } from '../sorted_list/module.f.mjs' */ +/** @import { TailReduce, ReduceOp } from '../sorted_list/types.ts' */ import { next } from '../list/module.f.mjs' -/** @import { Nullable } from '../nullable/module.f.mjs' */ +/** @import { Nullable } from '../nullable/types.ts' */ import { cmp } from '../number/module.f.mjs' import { bsearch } from '../function/compare/module.f.mjs' -/** @import { Reduce, Equal } from '../function/operator/module.f.mjs' */ -/** @import { Range } from '../range/module.f.mjs' */ - -/** @template T @typedef {[T, number]} Entry */ - -/** - * A sorted list of entries, where each entry is a tuple `[T, number]` that maps a value of type `T` to an upper boundary - * of a numeric range. - * - * @template T - * @typedef {SortedList>} RangeMap - */ - -/** @template T @typedef {readonly Entry[]} RangeMapArray */ - +/** @import { Equal } from '../function/operator/types.ts' */ +/** @import { Range } from '../range/types.ts' */ /** - * Defines the properties and operations required for managing range maps. - * - * @template T - * @typedef {{ - * readonly union: Reduce - * readonly equal: Equal - * readonly def: T - * }} Properties - * - * @property union - * - * A function to merge two values of type `T`. This defines how overlapping ranges are combined. - * - * @property equal - * - * A function to check equality between two values of type `T`. - * - * @property def - * - * The default value used when no range matches or for initializing ranges. + * @import { + * Entry, Properties, RangeMapArray, RangeMapOp, RangeMerge, + * } from './types.ts' */ /** @template T @typedef {Nullable>} _RangeState */ -/** @template T @typedef {Reduce>} RangeMerge */ - const reduceOp = /** * @template T @@ -148,29 +116,6 @@ export const fromRange = /** @param {Range} r */ ([a, b]) => /** @type {RangeMapArray} */([[def, a - 1], [v, b]]) -/** - * Represents a set of operations for managing range maps. - * - * @template T - * @typedef {{ - * readonly merge: RangeMerge - * readonly get: (rm: RangeMapArray) => (value: number) => T - * readonly fromRange: (value: T) => (r: Range) => RangeMapArray - * }} RangeMapOp - * - * @property merge - * - * Merges two range maps into a single range map. - * - * @property get - * - * Retrieves the value associated with a given numeric range. - * - * @property fromRange - * - * Constructs a range map for a single numeric range and value. - */ - /** * Creates a set of operations for managing range maps using the specified properties. * diff --git a/fjs/types/range_map/proof.f.ts b/fjs/types/range_map/proof.f.ts index a821193c4..13c3aa268 100644 --- a/fjs/types/range_map/proof.f.ts +++ b/fjs/types/range_map/proof.f.ts @@ -1,10 +1,11 @@ -import { get, merge, type RangeMapArray, type Properties, type RangeMap, fromRange, rangeMap } from './module.f.mjs' +import type { RangeMapArray, Properties, RangeMap } from './types.ts' +import { get, merge, fromRange, rangeMap } from './module.f.mjs' import { stringify, type Unknown } from '../../media/json/module.f.ts' import { sort } from '../object/module.f.ts' import { union, type SortedSet } from '../sorted_set/module.f.ts' import { equal, toArray } from '../list/module.f.mjs' import { strictEqual } from '../function/operator/module.f.mjs' -import { cmp } from '../string/module.f.ts' +import { cmp } from '../string/module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' const str diff --git a/fjs/types/range_map/types.ts b/fjs/types/range_map/types.ts new file mode 100644 index 000000000..d60b59b24 --- /dev/null +++ b/fjs/types/range_map/types.ts @@ -0,0 +1,63 @@ +/** + * Types for managing and merging range maps. + * + * @module + */ + +import type { Equal, Reduce } from '../function/operator/types.ts' +import type { Range } from '../range/types.ts' +import type { SortedList } from '../sorted_list/types.ts' + +export type Entry = [T, number] + +/** + * A sorted list of entries, where each entry is a tuple `[T, number]` that maps + * a value of type `T` to an upper boundary of a numeric range. + */ +export type RangeMap = SortedList> + +export type RangeMapArray = readonly Entry[] + +/** + * Defines the properties and operations required for managing range maps. + * + * @property union + * + * A function to merge two values of type `T`. This defines how overlapping ranges are combined. + * + * @property equal + * + * A function to check equality between two values of type `T`. + * + * @property def + * + * The default value used when no range matches or for initializing ranges. + */ +export type Properties = { + readonly union: Reduce + readonly equal: Equal + readonly def: T +} + +export type RangeMerge = Reduce> + +/** + * Represents a set of operations for managing range maps. + * + * @property merge + * + * Merges two range maps into a single range map. + * + * @property get + * + * Retrieves the value associated with a given numeric range. + * + * @property fromRange + * + * Constructs a range map for a single numeric range and value. + */ +export type RangeMapOp = { + readonly merge: RangeMerge + readonly get: (rm: RangeMapArray) => (value: number) => T + readonly fromRange: (value: T) => (r: Range) => RangeMapArray +} diff --git a/fjs/types/range_set/proof.f.mjs b/fjs/types/range_set/proof.f.mjs index e7e208501..ed46c7539 100644 --- a/fjs/types/range_set/proof.f.mjs +++ b/fjs/types/range_set/proof.f.mjs @@ -1,7 +1,7 @@ import { assert } from '../../asserts/module.f.mjs' import { toArray } from '../list/module.f.mjs' import { fromRange, merge, get } from './module.f.mjs' -/** @import { Range } from '../range/module.f.mjs' */ +/** @import { Range } from '../range/types.ts' */ /** @type {(a: string) => number} */ const c = a => a.charCodeAt(0) diff --git a/fjs/types/result/module.f.mjs b/fjs/types/result/module.f.mjs index db49cb6bd..8974c1567 100644 --- a/fjs/types/result/module.f.mjs +++ b/fjs/types/result/module.f.mjs @@ -19,27 +19,7 @@ * ``` */ -/** - * Represents a successful result. - * - * @template T - * @typedef {readonly ['ok', T]} Ok - */ - -/** - * Represents a failed result. - * - * @template E - * @typedef {readonly ['error', E]} Error - */ - -/** - * Represents a result that can be either successful or failed. - * - * @template T - * @template E - * @typedef {Ok | Error} Result - */ +/** @import { Ok, Error, Result } from './types.ts' */ /** * Creates a successful result. diff --git a/fjs/types/result/module.ts b/fjs/types/result/module.ts index 740f04d97..6e532bfdb 100644 --- a/fjs/types/result/module.ts +++ b/fjs/types/result/module.ts @@ -1,4 +1,5 @@ -import { ok, error, type Result } from './module.f.mjs' +import type { Result } from './types.ts' +import { ok, error } from './module.f.mjs' export const tryCatch : (f: () => T) => Result diff --git a/fjs/types/result/proof.f.mjs b/fjs/types/result/proof.f.mjs index be3ad6c2d..e64196e56 100644 --- a/fjs/types/result/proof.f.mjs +++ b/fjs/types/result/proof.f.mjs @@ -1,5 +1,5 @@ import { error, ok, unwrap, invert, mapOk } from './module.f.mjs' -/** @import { Result } from './module.f.mjs' */ +/** @import { Result } from './types.ts' */ import { assert, assertEq } from '../../asserts/module.f.mjs' const example = () => { diff --git a/fjs/types/result/types.ts b/fjs/types/result/types.ts new file mode 100644 index 000000000..3a03999b8 --- /dev/null +++ b/fjs/types/result/types.ts @@ -0,0 +1,20 @@ +/** + * Types for representing operations that can succeed or fail. + * + * @module + */ + +/** + * Represents a successful result. + */ +export type Ok = readonly ['ok', T] + +/** + * Represents a failed result. + */ +export type Error = readonly ['error', E] + +/** + * Represents a result that can be either successful or failed. + */ +export type Result = Ok | Error diff --git a/fjs/types/rtti/common/module.f.ts b/fjs/types/rtti/common/module.f.ts index 90456fa6e..6f337e2b0 100644 --- a/fjs/types/rtti/common/module.f.ts +++ b/fjs/types/rtti/common/module.f.ts @@ -37,7 +37,8 @@ import { type Tuple, type Type, } from '../module.f.ts' -import { error, ok, type Error, type Result as CommonResult } from '../../result/module.f.mjs' +import type { Error, Result as CommonResult } from '../../result/types.ts' +import { error, ok } from '../../result/module.f.mjs' import type { Ts } from '../ts/module.f.ts' import { isArray as commonIsArray } from '../../array/module.f.mjs' import { isObject as commonIsObject, type StringMap } from '../../object/module.f.ts' diff --git a/fjs/types/rtti/common/proof.f.ts b/fjs/types/rtti/common/proof.f.ts index e102a14ec..a66b94c8a 100644 --- a/fjs/types/rtti/common/proof.f.ts +++ b/fjs/types/rtti/common/proof.f.ts @@ -1,5 +1,6 @@ import { eachEntry } from './module.f.ts' -import { error, ok, type Result } from '../../result/module.f.mjs' +import type { Result } from '../../result/types.ts' +import { error, ok } from '../../result/module.f.mjs' import type { ValidationError } from './module.f.ts' import { assert, assertEq } from '../../../asserts/module.f.mjs' diff --git a/fjs/types/rtti/module.f.ts b/fjs/types/rtti/module.f.ts index 5e0f8cf31..4c7998ee1 100644 --- a/fjs/types/rtti/module.f.ts +++ b/fjs/types/rtti/module.f.ts @@ -36,9 +36,10 @@ * * See `./ts/module.f.ts` for `Ts` and the `*Ts` transformer types. */ -import type { Assert } from '../../asserts/module.f.mjs' -import { includes, type Includes } from '../array/module.f.mjs' -import type { Equal } from '../ts/module.f.mjs' +import type { Assert } from '../../asserts/types.ts' +import type { Includes } from '../array/types.ts' +import { includes } from '../array/module.f.mjs' +import type { Equal } from '../ts/types.ts' import type { StringMap } from '../object/module.f.ts' /** A constant schema: a primitive literal, a struct object, or a tuple. */ diff --git a/fjs/types/rtti/parse/module.f.ts b/fjs/types/rtti/parse/module.f.ts index 575916159..a3df0b961 100644 --- a/fjs/types/rtti/parse/module.f.ts +++ b/fjs/types/rtti/parse/module.f.ts @@ -33,9 +33,11 @@ import { type Tuple, type Type, } from '../module.f.ts' -import { ok, type Result as CommonResult } from '../../result/module.f.mjs' +import type { Result as CommonResult } from '../../result/types.ts' +import { ok } from '../../result/module.f.mjs' import type { StringMap } from '../../object/module.f.ts' -import { reverse, toArray, type List } from '../../list/module.f.mjs' +import type { List } from '../../list/types.ts' +import { reverse, toArray } from '../../list/module.f.mjs' import { constPrimitiveValidate, eachEntry, diff --git a/fjs/types/rtti/parse/proof.f.ts b/fjs/types/rtti/parse/proof.f.ts index a832379d6..f05d923c6 100644 --- a/fjs/types/rtti/parse/proof.f.ts +++ b/fjs/types/rtti/parse/proof.f.ts @@ -1,9 +1,9 @@ import { parse, type ValidationError } from './module.f.ts' import { boolean, number, string, bigint, unknown, array, record, or, option } from '../module.f.ts' -import type { Equal } from '../../ts/module.f.mjs' +import type { Equal } from '../../ts/types.ts' import type { Ts } from '../ts/module.f.ts' import type { Unknown as DjsUnknown } from '../../../djs/module.f.ts' -import type { Assert } from '../../../asserts/module.f.mjs' +import type { Assert } from '../../../asserts/types.ts' import { assert, assertEq } from '../../../asserts/module.f.mjs' const assertOk = ([k]: readonly [string, unknown]) => { assertEq(k, 'ok', 'expected ok') } diff --git a/fjs/types/rtti/ts/module.f.ts b/fjs/types/rtti/ts/module.f.ts index a6a60bb15..23a0b86ce 100644 --- a/fjs/types/rtti/ts/module.f.ts +++ b/fjs/types/rtti/ts/module.f.ts @@ -7,10 +7,11 @@ * The runtime `toTs` function mirrors `Ts` at value level, returning a TypeScript * type expression string for a given RTTI schema. */ -import { type Equal, primitive, union, printer as tsPrinter } from '../../ts/module.f.mjs' +import type { Equal } from '../../ts/types.ts' +import { primitive, union, printer as tsPrinter } from '../../ts/module.f.mjs' import type { Tag0, Tag1, Const, Or, String as RttiString, Struct, Tuple, Type, ConstObject } from '../module.f.ts' -import type { Assert } from '../../../asserts/module.f.mjs' -import type { phantomKey } from '../../phantom/module.f.ts' +import type { Assert } from '../../../asserts/types.ts' +import type { phantomKey } from '../../phantom/types.ts' import type { StringMap } from '../../object/module.f.ts' /** @@ -96,11 +97,11 @@ export type StructTs = * * **Recursive schemas and TS2589:** when a schema is self-referential, `StructTs` would * expand infinitely and TypeScript raises TS2589. Break the cycle by annotating the - * schema value with `Phantom` from `fjs/types/phantom/module.f.ts`. + * schema value with `Phantom` from `fjs/types/phantom/types.ts`. * `Ts<>` detects the phantom key and returns `MyType` directly without recursing: * * ```ts - * import { type Phantom } from '../types/phantom/module.f.ts' + * import { type Phantom } from '../../phantom/types.ts' * * type MyType = { readonly self?: MyType } * const myThunk = () => ['const', myConst] as const diff --git a/fjs/types/rtti/validate/proof.f.ts b/fjs/types/rtti/validate/proof.f.ts index b84326b68..93619f698 100644 --- a/fjs/types/rtti/validate/proof.f.ts +++ b/fjs/types/rtti/validate/proof.f.ts @@ -1,9 +1,9 @@ import { validate, type ValidationError } from './module.f.ts' import { boolean, number, string, bigint, unknown, array, record, or, option } from '../module.f.ts' -import type { Equal } from '../../ts/module.f.mjs' +import type { Equal } from '../../ts/types.ts' import type { Ts } from '../ts/module.f.ts' import type { Unknown as DjsUnknown } from '../../../djs/module.f.ts' -import type { Assert } from '../../../asserts/module.f.mjs' +import type { Assert } from '../../../asserts/types.ts' import { assert, assertEq } from '../../../asserts/module.f.mjs' const assertOk = ([k]: readonly [string, unknown]) => { assertEq(k, 'ok', 'expected ok') } diff --git a/fjs/types/sorted_list/module.f.mjs b/fjs/types/sorted_list/module.f.mjs index 02535f4a6..092eb8e41 100644 --- a/fjs/types/sorted_list/module.f.mjs +++ b/fjs/types/sorted_list/module.f.mjs @@ -5,37 +5,14 @@ */ import { bsearch } from '../function/compare/module.f.mjs' -/** @import { Sign, Cmp } from '../function/compare/module.f.mjs' */ +/** @import { Cmp } from '../function/compare/types.ts' */ import { next } from '../list/module.f.mjs' -/** @import { List } from '../list/module.f.mjs' */ -/** @import { Nullable } from '../nullable/module.f.mjs' */ +/** @import { List } from '../list/types.ts' */ import { identity } from '../function/module.f.mjs' - -/** @template T @typedef {List} SortedList */ +/** @import { ReduceOp, SortedList, TailReduce, _MergeReduce } from './types.ts' */ /** @template T @typedef {readonly T[]} _SortedArray */ -/** - * @template T - * @template S - * @typedef {(state: S) => (a: T) => (b: T) => readonly [Nullable, Sign, S]} ReduceOp - */ - -/** - * @template T - * @template S - * @typedef {(state: S) => (tail: List) => List} TailReduce - */ - -/** - * @template T - * @template S - * @typedef {{ - * readonly reduceOp: ReduceOp - * readonly tailReduce: TailReduce - * }} _MergeReduce - */ - /** * Two-way sorted-list merge. * `reduceOp` returns `[output, sign, nextState]` where sign `-1` advances `a`, `1` advances `b`, `0` advances both; `null` output skips emission. diff --git a/fjs/types/sorted_list/types.ts b/fjs/types/sorted_list/types.ts new file mode 100644 index 000000000..bad600921 --- /dev/null +++ b/fjs/types/sorted_list/types.ts @@ -0,0 +1,21 @@ +/** + * Types for sorted immutable lists and their merge operations. + * + * @module + */ + +import type { Sign } from '../function/compare/types.ts' +import type { List } from '../list/types.ts' +import type { Nullable } from '../nullable/types.ts' + +export type SortedList = List + +export type ReduceOp = + (state: S) => (a: T) => (b: T) => readonly [Nullable, Sign, S] + +export type TailReduce = (state: S) => (tail: List) => List + +export type _MergeReduce = { + readonly reduceOp: ReduceOp + readonly tailReduce: TailReduce +} diff --git a/fjs/types/sorted_set/module.f.ts b/fjs/types/sorted_set/module.f.ts index 2c070ce45..d24dbd55f 100644 --- a/fjs/types/sorted_set/module.f.ts +++ b/fjs/types/sorted_set/module.f.ts @@ -26,7 +26,7 @@ * has(cmp)(2)(setA) // false * ``` */ -import type { Cmp } from '../function/compare/module.f.mjs' +import type { Cmp } from '../function/compare/types.ts' import { toArray } from "../list/module.f.mjs" import { merge, intersect as listIntersect, find } from '../sorted_list/module.f.mjs' diff --git a/fjs/types/string/module.f.mjs b/fjs/types/string/module.f.mjs new file mode 100644 index 000000000..faa24be31 --- /dev/null +++ b/fjs/types/string/module.f.mjs @@ -0,0 +1,58 @@ +/** + * Utility functions for working with strings and lists of strings. + * + * @module + * + * @example + * + * ```js + * import { join, concat, repeat, cmp } from './module.f.mjs' + * + * const words = ['hello', 'world'] + * join(' ')(words) // 'hello world' + * concat(words) // 'helloworld' + * repeat('abc')(3) // 'abcabcabc' + * cmp('apple')('banana') // -1 + * ``` + */ + +/** @import { List } from '../list/types.ts' */ +import { reduce as listReduce, repeat as listRepeat } from '../list/module.f.mjs' +import { compose } from '../function/module.f.mjs' +/** @import { Sign } from '../function/compare/types.ts' */ +import { cmp as uCmp } from '../function/compare/module.f.mjs' +/** @import { Reduce } from '../function/operator/types.ts' */ +import { join as joinOp } from '../function/operator/module.f.mjs' +import { fold } from '../../common/monoid/module.f.mjs' + +/** + * `join`'s per-separator reduction is seeded at `''` but is *not* a monoid fold: + * `joinOp(sep)` has no identity (`joinOp(sep)('')(x)` prepends a separator), so + * it stays a hand-seeded `reduce` rather than going through `monoid.fold`. + * + * @type {(o: Reduce) => (input: List) => string} + */ +const reduce = o => listReduce(o)('') + +/** @type {(_: string) => (input: List) => string} */ +export const join = compose(joinOp)(reduce) + +/** + * String concatenation with identity `''` is a lawful monoid, so `concat` is a + * monoid fold. The operation is accumulator-first (`a` on the left), matching + * `monoid.fold`'s convention — unlike the element-first `concat` in + * `function/operator`, which is written for `list.reduce`. + * + * @type {(input: List) => string} + */ +export const concat = fold({ identity: '', operation: a => b => a + b }) + +/** @type {(n: string) => (v: number) => string} */ +export const repeat = v => compose(listRepeat(v))(concat) + +/** @type {(a: string) => (b: string) => Sign} */ +export const cmp = uCmp + +/** @type {(p: number) => (v: string) => readonly[string, string]} */ +export const splitAt = p => v => + [v.substring(0, p), v.substring(p)] diff --git a/fjs/types/string/module.f.ts b/fjs/types/string/module.f.ts deleted file mode 100644 index 5cc884bbc..000000000 --- a/fjs/types/string/module.f.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Utility functions for working with strings and lists of strings. - * - * @module - * - * @example - * - * ```js - * import { join, concat, repeat, cmp } from './module.f.ts' - * - * const words = ['hello', 'world'] - * join(' ')(words) // 'hello world' - * concat(words) // 'helloworld' - * repeat('abc')(3) // 'abcabcabc' - * cmp('apple')('banana') // -1 - * ``` - */ -import { type List, reduce as listReduce, repeat as listRepeat } from '../list/module.f.mjs' -import { compose } from '../function/module.f.mjs' -import { type Sign, cmp as uCmp } from '../function/compare/module.f.mjs' -import { join as joinOp, type Reduce } from '../function/operator/module.f.mjs' -import { fold } from '../../common/monoid/module.f.mjs' - -// `join`'s per-separator reduction is seeded at `''` but is *not* a monoid fold: -// `joinOp(sep)` has no identity (`joinOp(sep)('')(x)` prepends a separator), so -// it stays a hand-seeded `reduce` rather than going through `monoid.fold`. -const reduce: (o: Reduce) => (input: List) => string - = o => listReduce(o)('') - -export const join: (_: string) => (input: List) => string - = compose(joinOp)(reduce) - -// String concatenation with identity `''` is a lawful monoid, so `concat` is a -// monoid fold. The operation is accumulator-first (`a` on the left), matching -// `monoid.fold`'s convention — unlike the element-first `concat` in -// `function/operator`, which is written for `list.reduce`. -export const concat: (input: List) => string - = fold({ identity: '', operation: a => b => a + b }) - -export const repeat: (n: string) => (v: number) => string - = v => compose(listRepeat(v))(concat) - -export const cmp: (a: string) => (b: string) => Sign - = uCmp - -export const splitAt = (p: number) => (v: string): readonly[string, string] => - [v.substring(0, p), v.substring(p)] diff --git a/fjs/types/string/proof.f.ts b/fjs/types/string/proof.f.mjs similarity index 96% rename from fjs/types/string/proof.f.ts rename to fjs/types/string/proof.f.mjs index 49548d9c9..69d2ab6e7 100644 --- a/fjs/types/string/proof.f.ts +++ b/fjs/types/string/proof.f.mjs @@ -1,4 +1,4 @@ -import { join, concat, repeat, cmp, splitAt } from './module.f.ts' +import { join, concat, repeat, cmp, splitAt } from './module.f.mjs' import { repeat as repeatList } from '../list/module.f.mjs' import { assert, assertEq } from '../../asserts/module.f.mjs' diff --git a/fjs/types/string_set/module.f.ts b/fjs/types/string_set/module.f.ts index 2b4fd019a..1efec81cb 100644 --- a/fjs/types/string_set/module.f.ts +++ b/fjs/types/string_set/module.f.ts @@ -20,13 +20,14 @@ * ``` */ -import type { Tree } from '../btree/types/module.f.mjs' +import type { Tree } from '../btree/types/types.ts' import { empty as btEmpty, values as btValues } from '../btree/module.f.mjs' import { find, isFound } from '../btree/find/module.f.mjs' import { remove as btreeRemove } from '../btree/remove/module.f.mjs' import { set as btreeSet } from '../btree/set/module.f.mjs' -import { cmp } from "../string/module.f.ts" -import { fold, type List } from '../list/module.f.mjs' +import { cmp } from "../string/module.f.mjs" +import type { List } from '../list/types.ts' +import { fold } from '../list/module.f.mjs' import { compose } from '../function/module.f.mjs' export const values: (s: StringSet) => List = btValues diff --git a/fjs/types/todo/bit-set-factory.md b/fjs/types/todo/bit-set-factory.md index d1e7fceba..1df2109e5 100644 --- a/fjs/types/todo/bit-set-factory.md +++ b/fjs/types/todo/bit-set-factory.md @@ -54,7 +54,7 @@ AGENTS.md). `byte_set`'s `toRangeMap` stays local — it is genuinely byte-specific. Rider: both modules inline `readonly [number, number]` for `range`'s -parameter; the factory should use `Range` from `fjs/types/range/module.f.mjs`. +parameter; the factory should use `Range` from `fjs/types/range/types.ts`. `has` on a `bigint` set may deserve a domain-specific override if the generic form costs (see [185](./185.md) for the mask-based direction) — diff --git a/fjs/types/ts/module.f.mjs b/fjs/types/ts/module.f.mjs index ec0d2fd5a..176d43f76 100644 --- a/fjs/types/ts/module.f.mjs +++ b/fjs/types/ts/module.f.mjs @@ -6,10 +6,7 @@ * @module */ -/** - * @template A, B - * @typedef {(() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false} Equal - */ +/** @import { Printer } from './types.ts' */ /** @type {(open: string, close: string) => (i: readonly string[]) => string} */ const complex = (open, close) => i => @@ -17,17 +14,6 @@ const complex = (open, close) => i => const structX = complex('{', '}') -/** - * Functions for emitting TypeScript type expression strings. - * - * @typedef {{ - * readonly tuple: (types: readonly string[]) => string - * readonly struct: (fields: readonly (readonly[string, string])[]) => string - * readonly array: (type: string) => string - * readonly record: (type: string) => string - * }} Printer - */ - /** * Creates a `Printer`. Pass `true` to emit mutable (non-`readonly`) types. * diff --git a/fjs/types/ts/proof.f.ts b/fjs/types/ts/proof.f.ts index d864307db..9269da2b9 100644 --- a/fjs/types/ts/proof.f.ts +++ b/fjs/types/ts/proof.f.ts @@ -1,5 +1,6 @@ -import type { Assert } from '../../asserts/module.f.mjs' -import { printer, primitive, union, type Equal } from './module.f.mjs' +import type { Assert } from '../../asserts/types.ts' +import type { Equal } from './types.ts' +import { printer, primitive, union } from './module.f.mjs' import { assertEq } from '../../asserts/module.f.mjs' const ro = printer() diff --git a/fjs/types/ts/types.ts b/fjs/types/ts/types.ts new file mode 100644 index 000000000..82407c8fd --- /dev/null +++ b/fjs/types/ts/types.ts @@ -0,0 +1,21 @@ +/** + * Types for the TypeScript source emitter: the `Equal` compile-time predicate + * and the `Printer` interface. + * + * @module + */ + +export type Equal = + (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) + ? true + : false + +/** + * Functions for emitting TypeScript type expression strings. + */ +export type Printer = { + readonly tuple: (types: readonly string[]) => string + readonly struct: (fields: readonly (readonly [string, string])[]) => string + readonly array: (type: string) => string + readonly record: (type: string) => string +} diff --git a/fjs/types/uint8array/module.f.mjs b/fjs/types/uint8array/module.f.mjs index 5f5899393..718304789 100644 --- a/fjs/types/uint8array/module.f.mjs +++ b/fjs/types/uint8array/module.f.mjs @@ -13,10 +13,10 @@ import { assert, assertNotNullish } from '../../asserts/module.f.mjs' import { utf8, utf8ToString } from '../../text/module.f.mjs' import { maxLengthBytes, msb, tryU8ListToVec, u8List, u8ListToVec } from '../bit_vec/module.f.mjs' -/** @import { Vec } from '../bit_vec/module.f.mjs' */ +/** @import { Vec } from '../bit_vec/types.ts' */ import { compose } from '../function/module.f.mjs' import { flat, fromArrayLike, iterable, map } from '../list/module.f.mjs' -/** @import { List } from '../list/module.f.mjs' */ +/** @import { List } from '../list/types.ts' */ const u8ListToVecMsb = u8ListToVec(msb) const tryU8ListToVecMsb = tryU8ListToVec(msb) diff --git a/fjs/website/module.f.ts b/fjs/website/module.f.ts index 67030cbbb..bed1b4a02 100644 --- a/fjs/website/module.f.ts +++ b/fjs/website/module.f.ts @@ -6,7 +6,7 @@ import { htmlUtf8 } from '../media/html/module.f.ts' import { writeFile, type WriteFile } from '../effects/node/module.f.ts' import { pure, step, type Effect } from '../effects/module.f.ts' -import type { Vec } from '../types/bit_vec/module.f.mjs' +import type { Vec } from '../types/bit_vec/types.ts' const html: Vec = htmlUtf8()( ['a',