Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,16 @@ source dependency-closure rule as any other migrated file: its relative runtime
imports and JSDoc type references may target `.f.mjs` modules only. This is a
JavaScript/JSDoc and dependency-readiness rule, not a FunctionalScript compiler
feature gate. A proof that still imports an unmigrated helper such as
`fjs/asserts/module.f.ts` remains `proof.f.ts` until that helper migrates. See
`fjs/types/list/module.f.ts` remains `proof.f.ts` until that helper migrates. See
[`fjs/fsc/README.md`](./fjs/fsc/README.md) for the migration order and the
module-import policy it implies.

### 3.3 Use `assert` / `assertEq`, never a hand-written `if`/`throw`

Assert results in `proof` code with `assert`/`assertEq` from the current authored
`fjs/asserts/module.f.*` source, not a hand-written `if (cond) { throw ... }`.
During Stage 1 that helper is `.f.ts` until it migrates to `.f.mjs`; a
`proof.f.mjs` that needs it must wait for that dependency migration.
That helper has already migrated, so the current source is
`fjs/asserts/module.f.mjs` and a `proof.f.mjs` may import it directly.

A local `if`/`throw` in a test is itself a new branch for the coverage tool to
track, and its failure side is normally never exercised (the test is expected to
Expand All @@ -202,7 +202,7 @@ new uncovered branch.

To prove that a type resolves to what you claim, write
`type _Name = Assert<Equal<Actual, Expected>>` — `Assert` from
`fjs/asserts/module.f.ts`, `Equal` from `fjs/types/ts/module.f.ts`. A wrong
`fjs/asserts/module.f.mjs`, `Equal` from `fjs/types/ts/module.f.mjs`. A wrong
claim is then a compile error (TS2344, "Type 'false' does not satisfy the
constraint 'true'"), and the check costs nothing at runtime.

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ history.

## Unreleased

- **BREAKING CHANGES:** `fjs/types/function/compare` and
`fjs/types/function/operator` migrate from authored TypeScript (`.f.ts`) to
JSDoc-typed JavaScript (`.f.mjs`) under the stage-1 TypeScript-to-mjs
migration — importers must use the `.f.mjs` specifier
Comment on lines +24 to +26

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fix the stale operator source references

After this rename, a repo-wide search still finds todo/flow.md:241 linking to the deleted fjs/types/function/operator/module.f.ts and fjs/types/function/todo/uncurry-accumulator-types.md:13 directing readers to that old path. Following the canonical todo documentation now produces a broken link or points contributors at a nonexistent source file, so these references should be updated to .f.mjs with the other importers.

AGENTS.md reference: AGENTS.md:L10-L11

Useful? React with 👍 / 👎.

[#1456](https://github.com/functionalscript/functionalscript/pull/1456)
- **BREAKING CHANGES:** `fjs/types/array`, `fjs/types/function`,
`fjs/types/nullable`, and `fjs/types/option` migrate from authored
TypeScript (`.f.ts`) to JSDoc-typed JavaScript (`.f.mjs`) under the stage-1
Expand Down
2 changes: 1 addition & 1 deletion fjs/asn.1/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
type Vec
} from "../types/bit_vec/module.f.ts"
import { identity } from "../types/function/module.f.mjs"
import { max } from "../types/function/compare/module.f.ts"
import { max } from "../types/function/compare/module.f.mjs"
import { encode as b128encode, decode as b128decode } from "../basen/base128/module.f.ts"

const { popFront: pop, listToVec } = msb
Expand Down
2 changes: 1 addition & 1 deletion fjs/bnf/ll1/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @module
*/
import { type CodePoint } from '../../text/utf16/module.f.ts'
import { strictEqual } from '../../types/function/operator/module.f.ts'
import { strictEqual } from '../../types/function/operator/module.f.mjs'
import { toArray } from '../../types/list/module.f.ts'
import { rangeMap, type RangeMapArray } from '../../types/range_map/module.f.ts'
import { contains, set, type StringSet } from '../../types/string_set/module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/common/monoid/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* @module
*/
import type { Fold, Reduce } from '../../types/function/operator/module.f.ts'
import type { Fold, Reduce } from '../../types/function/operator/module.f.mjs'
import { reduce, type List } from '../../types/list/module.f.ts'
import { flip } from '../../types/function/module.f.mjs'

Expand Down
2 changes: 1 addition & 1 deletion fjs/crypto/secp/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* @module
*/
import type { Equal, Fold, Reduce } from '../../types/function/operator/module.f.ts'
import type { Equal, Fold, Reduce } from '../../types/function/operator/module.f.mjs'
import { prime_field, sqrt, type PrimeField } from '../../types/prime_field/module.f.ts'
import { repeat } from '../../common/monoid/module.f.ts'

Expand Down
2 changes: 1 addition & 1 deletion fjs/crypto/sha2/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
uint,
type Vec
} from '../../types/bit_vec/module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.mjs'
import { fold, type List } from '../../types/list/module.f.ts'

const { concat, front } = msb
Expand Down
2 changes: 1 addition & 1 deletion fjs/djs/parser/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { error, ok, type Result } from '../../types/result/module.f.ts'
import { fold, next, toArray, length, concat, type List } from '../../types/list/module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.mjs'
import type { DjsToken, DjsTokenWithMetadata } from '../tokenizer/module.f.ts'
import { setReplace, at, type OrderedMap } from '../../types/ordered_map/module.f.ts'
import { fromMap } from '../../types/object/module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/djs/serializer/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @module
*/
import type { Unknown, Object } from '../module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.ts'
import type { Fold } from '../../types/function/operator/module.f.mjs'
import type { Entry as ObjectEntry } from '../../types/object/module.f.ts'
import { fold } from '../../types/list/module.f.ts'
import { concat } from '../../types/string/module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/djs/tokenizer/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import {
range as asciiRange,
} from "../../text/ascii/module.f.ts"
import { type CodePoint, codePointListToString, stringToCodePointList } from "../../text/utf16/module.f.ts"
import type { StateScan } from "../../types/function/operator/module.f.ts"
import type { StateScan } from "../../types/function/operator/module.f.mjs"
import { contains } from "../../types/range/module.f.ts"
import { concat, empty, filter, flat, flatMap, fold, map, stateScan, toArray, type List } from "../../types/list/module.f.ts"
import { stringifyAsTree } from "../serializer/module.f.ts"
Expand Down
2 changes: 1 addition & 1 deletion fjs/emergent_testing/todo/f-mjs-test-and-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ may migrate from `proof.f.ts` to `proof.f.mjs` as soon as it can be expressed as
JavaScript with JSDoc and its authored runtime and declaration-retained type
dependencies are already `.f.mjs`; current FunctionalScript compiler support is
not a migration gate. A proof that still depends on an unmigrated `.f.ts` helper,
such as `fjs/asserts/module.f.ts`, remains `proof.f.ts` until that dependency
such as `fjs/types/list/module.f.ts`, remains `proof.f.ts` until that dependency
moves.

### Proposal
Expand Down
2 changes: 1 addition & 1 deletion fjs/fsc/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @module
*/
import { strictEqual } from '../types/function/operator/module.f.ts'
import { strictEqual } from '../types/function/operator/module.f.mjs'
import {
merge as rangeMapMerge,
fromRange,
Expand Down
2 changes: 1 addition & 1 deletion fjs/fsm/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
type RangeMapArray,
type Entry
} from '../types/range_map/module.f.ts'
import { type Fold, type Scan, strictEqual } from '../types/function/operator/module.f.ts'
import { type Fold, type Scan, 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.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/js/tokenizer/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* @module
*/
import { strictEqual, type Scan, type StateScan } from '../../types/function/operator/module.f.ts'
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.ts'
import { empty, stateScan, flat, toArray, reduce as listReduce, scan, map as listMap, type List } from '../../types/list/module.f.ts'
import { at, fromEntries, type Entry } from '../../types/ordered_map/module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/media/json/parser/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { error, ok, type Result } from '../../../types/result/module.f.ts'
import { type List, fold, next, toArray, concat } from '../../../types/list/module.f.ts'
import { type Fold } from '../../../types/function/operator/module.f.ts'
import { type Fold } from '../../../types/function/operator/module.f.mjs'
import { type JsonToken } from '../tokenizer/module.f.ts'
import { setReplace, type OrderedMap } from '../../../types/ordered_map/module.f.ts'
import { type Unknown } from '../module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/media/json/serializer/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @module
*/
import { flat, map, reduce, empty, type List } from '../../../types/list/module.f.ts'
import { type Reduce } from '../../../types/function/operator/module.f.ts'
import { type Reduce } from '../../../types/function/operator/module.f.mjs'
import { concat } from '../../../types/string/module.f.ts'
import {
codePointToString,
Expand Down
2 changes: 1 addition & 1 deletion fjs/media/json/tokenizer/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @module
*/
import { type StateScan } from '../../../types/function/operator/module.f.ts'
import { type StateScan } from '../../../types/function/operator/module.f.mjs'
import { concat, empty, flat, stateScan, type List } from '../../../types/list/module.f.ts'
import { multiply } from '../../../types/bigfloat/module.f.ts'
import {
Expand Down
2 changes: 1 addition & 1 deletion fjs/path/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @module
*/
import type { Fold, Reduce, Unary } from '../types/function/operator/module.f.ts'
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.ts'
import { join as listJoin, concat as stringConcat } from '../types/string/module.f.ts'

Expand Down
2 changes: 1 addition & 1 deletion fjs/sul/level/literal/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { log2 } from '../../../types/bigint/module.f.ts'
import { msb, vec, type Vec } from '../../../types/bit_vec/module.f.ts'
import type { Func } from '../../../types/function/module.f.mjs'
import { strictEqual, type Equal, type StateScan } from '../../../types/function/operator/module.f.ts'
import { strictEqual, type Equal, type StateScan } from '../../../types/function/operator/module.f.mjs'
import { equal, map, type List } from '../../../types/list/module.f.ts'
import { join } from '../../../types/string/module.f.ts'

Expand Down
2 changes: 1 addition & 1 deletion fjs/text/code_point/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @module
*/
import { flat, type List, stateScan } from '../../types/list/module.f.ts'
import type { StateScan } from '../../types/function/operator/module.f.ts'
import type { StateScan } from '../../types/function/operator/module.f.mjs'
import { contains } from '../../types/range/module.f.ts'

/**
Expand Down
2 changes: 1 addition & 1 deletion fjs/text/utf16/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
type Result,
type Thunk,
} from '../../types/list/module.f.ts'
import { concat, type StateScan } from '../../types/function/operator/module.f.ts'
import { concat, type StateScan } from '../../types/function/operator/module.f.mjs'
import { contains } from '../../types/range/module.f.ts'
import { fn } from '../../types/function/module.f.mjs'
import {
Expand Down
2 changes: 1 addition & 1 deletion fjs/text/utf8/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @module
*/
import { flatMap, toArray, type List, type Thunk } from '../../types/list/module.f.ts'
import type { StateScan } from '../../types/function/operator/module.f.ts'
import type { StateScan } from '../../types/function/operator/module.f.mjs'
import type { Tuple } from '../../types/array/module.f.mjs'
import { decoder, errorMask, isValidCodePoint } from '../code_point/module.f.ts'
import { msb, u8List, length, type Vec } from '../../types/bit_vec/module.f.ts'
Expand Down
4 changes: 2 additions & 2 deletions fjs/types/bigint/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* ```
*/

import { cmp, type Sign } from '../function/compare/module.f.ts'
import type { Unary as OpUnary, Reduce as OpReduce } from '../function/operator/module.f.ts'
import { cmp, type Sign } from '../function/compare/module.f.mjs'
import type { Unary as OpUnary, Reduce as OpReduce } from '../function/operator/module.f.mjs'
import { type List } from '../list/module.f.ts'
import { fold } from '../../common/monoid/module.f.ts'

Expand Down
2 changes: 1 addition & 1 deletion fjs/types/bigint/proof.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
roundUp8
} from './module.f.ts'
import { assert, assertEq } from '../../asserts/module.f.mjs'
import { min } from '../function/compare/module.f.ts'
import { min } from '../function/compare/module.f.mjs'

const oldLog2 = (v: bigint): bigint => {
if (v <= 0n) { return -1n }
Expand Down
4 changes: 2 additions & 2 deletions fjs/types/bit_vec/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
*/
import { bitLength, divUp, mask, maxLength, xor, type Reduce as BigintReduce } from '../bigint/module.f.ts'
import { flip, identity } from '../function/module.f.mjs'
import type { Binary, Fold, Reduce as OpReduce } from '../function/operator/module.f.ts'
import type { Binary, Fold, Reduce as OpReduce } from '../function/operator/module.f.mjs'
import { map, tryFold, type Accumulator, type List, type Thunk } from '../list/module.f.ts'
import { asBase, asNominal, type Nominal } from '../nominal/module.f.ts'
import { repeat as mRepeat } from '../../common/monoid/module.f.ts'
import { cmp, max, min, type Sign } from '../function/compare/module.f.ts'
import { cmp, max, min, type Sign } from '../function/compare/module.f.mjs'
import { mapUnwrap, type Nullable } from '../nullable/module.f.mjs'

/**
Expand Down
2 changes: 1 addition & 1 deletion fjs/types/bit_vec/proof.f.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert, assertEq } from '../../asserts/module.f.mjs'
import { mask } from '../bigint/module.f.ts'
import type { Sign } from '../function/compare/module.f.ts'
import type { Sign } from '../function/compare/module.f.mjs'
import { asBase, asNominal } from '../nominal/module.f.ts'
import { length, empty, uint, type Vec, vec, lsb, msb, type BitOrder, repeat, vec8, maxLength, u8ListToVec, tryU8ListToVec, u8List, chunkList, fromSentinel } from './module.f.ts'
import { repeat as listRepeat, toArray, type List } from '../list/module.f.ts'
Expand Down
2 changes: 1 addition & 1 deletion fjs/types/btree/find/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import type { Leaf1, Leaf2, Branch3, Branch5, TNode } from '../types/module.f.ts'
import type { List } from '../../list/module.f.ts'
import { index3, index5, type Compare } from '../../function/compare/module.f.ts'
import { index3, index5, type Compare } from '../../function/compare/module.f.mjs'
import type { KeyOf, Index, Tuple } from "../../array/module.f.mjs";

export type FirstLeaf1<T> = readonly[Index<3>, Leaf1<T>]
Expand Down
2 changes: 1 addition & 1 deletion fjs/types/btree/remove/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @module
*/
import { collapseRoot, type Leaf1, type TNode, type Branch1, type Branch3, type Branch5, type Tree } from '../types/module.f.ts'
import type { Compare } from '../../function/compare/module.f.ts'
import type { Compare } from '../../function/compare/module.f.mjs'
import { type Path, type PathItem, find } from '../find/module.f.ts'
import { fold, concat, next } from '../../list/module.f.ts'
import type { Tuple } from '../../array/module.f.mjs'
Expand Down
2 changes: 1 addition & 1 deletion fjs/types/btree/set/module.f.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { collapseRoot, type Branch1, type Branch3, type Branch5, type Branch7, type TNode, type Tree } from '../types/module.f.ts'
import { find, type First, type PathItem, type Result } from '../find/module.f.ts'
import type { Compare } from '../../function/compare/module.f.ts'
import type { Compare } from '../../function/compare/module.f.mjs'
import { fold } from '../../list/module.f.ts'

type Branch1To3<T> = Branch1<T> | Branch3<T>
Expand Down
95 changes: 95 additions & 0 deletions fjs/types/function/compare/module.f.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Comparison function types and helpers.
*
* @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<T>} Cmp
*/

/** @type {<T>(cmp: Compare<T>) => (value: T) => Index<3>} */
export const index3
= cmp => value => /** @type {Index<3>} */(cmp(value) + 1)

/** @type {<T>(cmp: Compare<T>) => (v2: Tuple<2, T>) => Index<5>} */
export const index5 = cmp => ([v0, v1]) => {
const _0 = cmp(v0)
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 extends Cmp1>(a: A) => <B extends Cmp2<A, B>>(b: B) => Sign} */
export const cmp = a => b =>
/** @type {any} */(a) < b ? -1 : /** @type {any} */(a) > b ? 1 : 0

/**
* Returns the smaller of two comparable values. The `Cmp2<A, B>` constraint
* is the same one `cmp` uses: it rejects calls that mix incompatible primitive
* types (e.g. `min(1)("a")`) at compile time.
*
* @type {<A extends Cmp1>(a: A) => <B extends Cmp2<A, B>>(b: B) => A | B}
*/
export const min = a => b => cmp(a)(b) < 0 ? a : b

/**
* Returns the larger of two comparable values. The `Cmp2<A, B>` constraint
* is the same one `cmp` uses: it rejects calls that mix incompatible primitive
* types (e.g. `max(1)("a")`) at compile time.
*
* @type {<A extends Cmp1>(a: A) => <B extends Cmp2<A, B>>(b: B) => A | B}
*/
export const max = a => b => cmp(a)(b) > 0 ? a : b

/**
* Binary search over `[0, len)`. `probe(mid)` returns the sign of the search
* key relative to the element at `mid` (`-1` before, `0` at, `1` after). On a
* hit it returns the matching index; on a miss it returns the converged lower
* bound `b` (the insertion point), which may equal `len`.
*
* `probe` must be monotonic over `[0, len)`: scanning indices left to right its
* result is non-increasing — a run of `1`s, then `0`s, then `-1`s. A
* non-monotonic probe yields an undefined position.
*
* @type {(len: number) => (probe: (mid: number) => Sign) => number}
*/
export const bsearch = len => probe => {
let b = 0
let e = len - 1
while (true) {
if (e < b) { return b }
const mid = b + (e - b >> 1)
switch (probe(mid)) {
case -1: {
e = mid - 1
break
}
case 0: { return mid }
case 1: {
b = mid + 1
break
}
}
}
}
Loading
Loading