functionalscript
Advanced tools
Comparing version 0.3.11 to 0.3.12
@@ -26,3 +26,4 @@ import { entries, fold } from "../../types/list/module.f.js"; | ||
state = state0; | ||
if (s === 'error') { | ||
// Usual tests throw on error, but if the function name is 'throw', then the test passes if it throws. | ||
if ((s === 'error') === (v.name !== 'throw')) { | ||
ts = addFail(delta)(ts); | ||
@@ -29,0 +30,0 @@ if (isGitHub) { |
@@ -24,2 +24,3 @@ import { strictEqual } from "../types/function/operator/module.f.js"; | ||
equal: strictEqual, | ||
def, | ||
}); | ||
@@ -26,0 +27,0 @@ return toArray(listReduce(merge)(empty)(a)); |
@@ -20,3 +20,3 @@ import { equal, isEmpty, fold, toArray, scan, foldScan, empty as emptyList } from "../types/list/module.f.js"; | ||
}; | ||
const mergeOp = { union: sortedSetUnion(unsafeCmp), equal: equal(strictEqual) }; | ||
const mergeOp = { union: sortedSetUnion(unsafeCmp), equal: equal(strictEqual), def: [] }; | ||
const hasState = s => set => !isEmpty(intersect(unsafeCmp)([s])(set)); | ||
@@ -23,0 +23,0 @@ const foldOp = set => ([ruleIn, bs, ruleOut]) => rm => { |
@@ -110,2 +110,3 @@ import * as operator from "../../types/function/operator/module.f.js"; | ||
equal: operator.strictEqual, | ||
def, | ||
}); | ||
@@ -130,3 +131,7 @@ const rangeFunc = r => f => def => fromRange(def)(r)(f); | ||
const startNumber = digit => ({ s: 1n, m: digitToBigInt(digit), f: 0, es: 1, e: 0 }); | ||
const startNegativeNumber = { s: -1n, m: 0n, f: 0, es: 1, e: 0 }; | ||
/* | ||
const startNegativeNumber | ||
: ParseNumberBuffer | ||
= { s: -1n, m: 0n, f: 0, es: 1, e: 0 } | ||
*/ | ||
const addIntDigit = digit => b => ({ ...b, m: b.m * 10n + digitToBigInt(digit) }); | ||
@@ -133,0 +138,0 @@ const addFracDigit = digit => b => ({ ...b, m: b.m * 10n + digitToBigInt(digit), f: b.f - 1 }); |
@@ -44,2 +44,5 @@ declare const _default: { | ||
}; | ||
bigint: { | ||
throw: () => number; | ||
}; | ||
array: { | ||
@@ -54,4 +57,5 @@ empty: () => void; | ||
}; | ||
function: () => void; | ||
}; | ||
}; | ||
export default _default; |
@@ -111,7 +111,5 @@ const e = a => b => { | ||
}, | ||
// TODO: bigint - handle TypeError exception for bigint. The test below (that follows | ||
// current Rust implementation) is incorrect. | ||
// bigint: { | ||
// nan: () => u_p_nan(0n) | ||
// } | ||
bigint: { | ||
throw: () => op(0n), | ||
}, | ||
array: { | ||
@@ -126,6 +124,6 @@ empty: () => e(op([]))(0), | ||
// TODO: test objects with valueOf, toString functions - when Rust logic is implemented | ||
} | ||
// TODO: test Function - when Rust logic is implemented | ||
}, | ||
function: () => nan(op(() => { })) | ||
}; | ||
} | ||
}; |
{ | ||
"name": "functionalscript", | ||
"version": "0.3.11", | ||
"version": "0.3.12", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "files": [ |
import { msb, u8List, u8ListToVec } from "../types/bit_vec/module.f.js"; | ||
import { flatMap } from "../types/list/module.f.js"; | ||
import * as utf8 from "./utf8/module.f.js"; | ||
import * as utf16 from "./utf16/module.f.js"; | ||
import { stringToCodePointList, codePointListToString } from "./utf16/module.f.js"; | ||
export const flat = (indent) => { | ||
@@ -19,3 +19,3 @@ const f = (prefix) => { | ||
*/ | ||
export const msbUtf8 = (s) => u8ListToVec(msb)(utf8.fromCodePointList(utf16.toCodePointList(utf16.stringToList(s)))); | ||
export const msbUtf8 = (s) => u8ListToVec(msb)(utf8.fromCodePointList(stringToCodePointList(s))); | ||
/** | ||
@@ -27,2 +27,2 @@ * Converts a UTF-8 bit vector with MSB first encoding to a string. | ||
*/ | ||
export const msbUtf8ToString = (msbV) => utf16.listToString(utf16.fromCodePointList(utf8.toCodePointList(u8List(msb)(msbV)))); | ||
export const msbUtf8ToString = (msbV) => codePointListToString(utf8.toCodePointList(u8List(msb)(msbV))); |
import { type List, type Thunk } from '../../types/list/module.f.ts'; | ||
type U16 = number; | ||
type I32 = number; | ||
export declare const fromCodePointList: (input: List<number>) => Thunk<number>; | ||
export declare const toCodePointList: (input: List<U16>) => List<I32>; | ||
export type U16 = number; | ||
/** | ||
* [0, 0x10_FFFF]: 16+5 = 21 bits | ||
* | ||
* 121_0000_0000: 16+16+9 = 41 bits | ||
*/ | ||
export type CodePoint = number; | ||
export declare const fromCodePointList: (input: List<CodePoint>) => Thunk<U16>; | ||
export declare const toCodePointList: (input: List<U16>) => List<CodePoint>; | ||
export declare const stringToList: (s: string) => List<U16>; | ||
export declare const stringToCodePointList: (input: string) => List<CodePoint>; | ||
export declare const listToString: (input: List<U16>) => string; | ||
export {}; | ||
export declare const codePointListToString: (input: List<CodePoint>) => string; |
@@ -63,4 +63,6 @@ import { map, flat, stateScan, reduce, flatMap, empty, } from "../../types/list/module.f.js"; | ||
}; | ||
export const stringToCodePointList = (input) => toCodePointList(stringToList(input)); | ||
export const listToString = fn(map(String.fromCharCode)) | ||
.then(reduce(concat)('')) | ||
.result; | ||
export const codePointListToString = (input) => listToString(fromCodePointList(input)); |
@@ -1,2 +0,2 @@ | ||
import { toCodePointList, fromCodePointList, stringToList, listToString } from "./module.f.js"; | ||
import { toCodePointList, fromCodePointList, stringToList, listToString, stringToCodePointList, codePointListToString } from "./module.f.js"; | ||
import * as json from "../../json/module.f.js"; | ||
@@ -134,2 +134,9 @@ import { sort } from "../../types/object/module.f.js"; | ||
() => { | ||
const cpList = stringToCodePointList("Hello world!😂🚜🚲"); | ||
const result = codePointListToString(cpList); | ||
if (result !== "Hello world!😂🚜🚲") { | ||
throw result; | ||
} | ||
}, | ||
() => { | ||
const a = stringToList("Hello world!😂🚜🚲"); | ||
@@ -136,0 +143,0 @@ const b = toCodePointList(a); |
@@ -0,1 +1,37 @@ | ||
/** | ||
* Utility functions and types for managing and merging range maps. | ||
* | ||
* @module | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const rmOps = rangeMap({ | ||
* union: a => b => a | b, | ||
* equal: a => b => a === b, | ||
* def: 0, | ||
* }) | ||
* | ||
* // Create range maps | ||
* const range1 = rmOps.fromRange([0, 10])(2) | ||
* const range2 = rmOps.fromRange([5, 15])(5) | ||
* | ||
* // Merge range maps | ||
* const merged = toArray(rmOps.merge(range1)(range2)) | ||
* | ||
* // Retrieve values from the merged range map | ||
* // | ||
* if (rmOps.get(-1)(merged) !== 0) { throw 'error' } | ||
* // | ||
* if (rmOps.get(0)(merged) !== 2) { throw 'error' } | ||
* if (rmOps.get(2)(merged) !== 2) { throw 'error' } | ||
* // overlapped: 2 | 5 = 7 | ||
* if (rmOps.get(7)(merged) !== 7) { throw 'error' } | ||
* // | ||
* if (rmOps.get(12)(merged) !== 5) { throw 'error' } | ||
* if (rmOps.get(15)(merged) !== 5) { throw 'error' } | ||
* // | ||
* if (rmOps.get(16)(merged) !== 0) { throw 'error' } | ||
* ``` | ||
*/ | ||
import { type SortedList } from '../sorted_list/module.f.ts'; | ||
@@ -5,11 +41,52 @@ import type { Reduce, Equal } from '../function/operator/module.f.ts'; | ||
export type Entry<T> = [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<T> = SortedList<Entry<T>>; | ||
export type RangeMapArray<T> = readonly Entry<T>[]; | ||
export type Operators<T> = { | ||
/** | ||
* Defines the properties and operations required for managing range maps. | ||
*/ | ||
export type Properties<T> = { | ||
/** | ||
* A function to merge two values of type `T`. This defines how overlapping ranges are combined. | ||
*/ | ||
readonly union: Reduce<T>; | ||
/** | ||
* A function to check equality between two values of type `T`. | ||
*/ | ||
readonly equal: Equal<T>; | ||
/** | ||
* The default value used when no range matches or for initializing ranges. | ||
*/ | ||
readonly def: T; | ||
}; | ||
export type RangeMerge<T> = Reduce<RangeMap<T>>; | ||
export declare const merge: <T>(op: Operators<T>) => RangeMerge<T>; | ||
export declare const merge: <T>(op: Properties<T>) => RangeMerge<T>; | ||
export declare const get: <T>(def: T) => (value: number) => (rm: RangeMapArray<T>) => T; | ||
export declare const fromRange: <T>(def: T) => (r: Range) => (value: T) => RangeMapArray<T>; | ||
/** | ||
* Represents a set of operations for managing range maps. | ||
*/ | ||
export type RangeMapOp<T> = { | ||
/** | ||
* Merges two range maps into a single range map. | ||
*/ | ||
readonly merge: RangeMerge<T>; | ||
/** | ||
* Retrieves the value associated with a given numeric range. | ||
*/ | ||
readonly get: (value: number) => (rm: RangeMapArray<T>) => T; | ||
/** | ||
* Constructs a range map for a single numeric range and value. | ||
*/ | ||
readonly fromRange: (r: Range) => (value: T) => RangeMapArray<T>; | ||
}; | ||
/** | ||
* Creates a set of operations for managing range maps using the specified properties. | ||
* | ||
* @param op - The properties defining union and equality operations and the default value. | ||
* @returns An object containing operations for merging, retrieving, and constructing range maps. | ||
*/ | ||
export declare const rangeMap: <T>(op: Properties<T>) => RangeMapOp<T>; |
@@ -0,5 +1,41 @@ | ||
/** | ||
* Utility functions and types for managing and merging range maps. | ||
* | ||
* @module | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const rmOps = rangeMap({ | ||
* union: a => b => a | b, | ||
* equal: a => b => a === b, | ||
* def: 0, | ||
* }) | ||
* | ||
* // Create range maps | ||
* const range1 = rmOps.fromRange([0, 10])(2) | ||
* const range2 = rmOps.fromRange([5, 15])(5) | ||
* | ||
* // Merge range maps | ||
* const merged = toArray(rmOps.merge(range1)(range2)) | ||
* | ||
* // Retrieve values from the merged range map | ||
* // | ||
* if (rmOps.get(-1)(merged) !== 0) { throw 'error' } | ||
* // | ||
* if (rmOps.get(0)(merged) !== 2) { throw 'error' } | ||
* if (rmOps.get(2)(merged) !== 2) { throw 'error' } | ||
* // overlapped: 2 | 5 = 7 | ||
* if (rmOps.get(7)(merged) !== 7) { throw 'error' } | ||
* // | ||
* if (rmOps.get(12)(merged) !== 5) { throw 'error' } | ||
* if (rmOps.get(15)(merged) !== 5) { throw 'error' } | ||
* // | ||
* if (rmOps.get(16)(merged) !== 0) { throw 'error' } | ||
* ``` | ||
*/ | ||
import { genericMerge } from "../sorted_list/module.f.js"; | ||
import { next } from "../list/module.f.js"; | ||
import { cmp } from "../number/module.f.js"; | ||
const reduceOp = union => equal => state => ([aItem, aMax]) => ([bItem, bMax]) => { | ||
const reduceOp = ({ union, equal }) => state => ([aItem, aMax]) => ([bItem, bMax]) => { | ||
const sign = cmp(aMax)(bMax); | ||
@@ -24,3 +60,3 @@ const min = sign === 1 ? bMax : aMax; | ||
}; | ||
export const merge = ({ union, equal }) => genericMerge({ reduceOp: reduceOp(union)(equal), tailReduce: tailReduce(equal) })(null); | ||
export const merge = op => genericMerge({ reduceOp: reduceOp(op), tailReduce: tailReduce(op.equal) })(null); | ||
export const get = def => value => rm => { | ||
@@ -47,1 +83,12 @@ const len = rm.length; | ||
export const fromRange = def => ([a, b]) => v => [[def, a - 1], [v, b]]; | ||
/** | ||
* Creates a set of operations for managing range maps using the specified properties. | ||
* | ||
* @param op - The properties defining union and equality operations and the default value. | ||
* @returns An object containing operations for merging, retrieving, and constructing range maps. | ||
*/ | ||
export const rangeMap = (op) => ({ | ||
merge: merge(op), | ||
get: get(op.def), | ||
fromRange: fromRange(op.def), | ||
}); |
declare const _default: { | ||
example: () => void; | ||
merge: (() => void)[]; | ||
@@ -3,0 +4,0 @@ get: () => (() => void)[]; |
@@ -1,11 +0,54 @@ | ||
import { get, merge, fromRange } from "./module.f.js"; | ||
import { get, merge, fromRange, rangeMap } from "./module.f.js"; | ||
import { unsafeCmp } from "../function/compare/module.f.js"; | ||
import * as json from "../../json/module.f.js"; | ||
import { sort } from "../object/module.f.js"; | ||
import * as sortedSet from "../sorted_set/module.f.js"; | ||
import * as list from "../list/module.f.js"; | ||
import { union } from "../sorted_set/module.f.js"; | ||
import { equal, toArray } from "../list/module.f.js"; | ||
import * as operator from "../function/operator/module.f.js"; | ||
const stringify = json.stringify(sort); | ||
const op = { union: sortedSet.union(unsafeCmp), equal: list.equal(operator.strictEqual) }; | ||
const op = { | ||
union: union(unsafeCmp), | ||
equal: equal(operator.strictEqual), | ||
def: [] | ||
}; | ||
export default { | ||
example: () => { | ||
const rmOps = rangeMap({ | ||
union: a => b => a | b, | ||
equal: a => b => a === b, | ||
def: 0, | ||
}); | ||
// Create range maps | ||
const range1 = rmOps.fromRange([0, 10])(2); | ||
const range2 = rmOps.fromRange([5, 15])(5); | ||
// Merge range maps | ||
const merged = toArray(rmOps.merge(range1)(range2)); | ||
// Retrieve values from the merged range map | ||
// | ||
if (rmOps.get(-1)(merged) !== 0) { | ||
throw 'error'; | ||
} | ||
// | ||
if (rmOps.get(0)(merged) !== 2) { | ||
throw 'error'; | ||
} | ||
if (rmOps.get(2)(merged) !== 2) { | ||
throw 'error'; | ||
} | ||
// 2 | 5 = 7 | ||
if (rmOps.get(7)(merged) !== 7) { | ||
throw 'error'; | ||
} | ||
// | ||
if (rmOps.get(12)(merged) !== 5) { | ||
throw 'error'; | ||
} | ||
if (rmOps.get(15)(merged) !== 5) { | ||
throw 'error'; | ||
} | ||
// | ||
if (rmOps.get(16)(merged) !== 0) { | ||
throw 'error'; | ||
} | ||
}, | ||
merge: [ | ||
@@ -16,3 +59,3 @@ () => { | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a"],1],[["b"],2]]') { | ||
@@ -26,3 +69,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a"],1],[["b"],2]]') { | ||
@@ -36,3 +79,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a"],1],[["b"],2]]') { | ||
@@ -46,3 +89,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a","b"],1],[["b","c"],2],[["c","d"],3],[["d"],4]]') { | ||
@@ -56,3 +99,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a","b"],1],[["b","d"],2],[["c","d"],3],[["d"],4]]') { | ||
@@ -66,3 +109,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a","b"],2]]') { | ||
@@ -76,3 +119,3 @@ throw result; | ||
const merged = merge(op)(a)(b); | ||
const result = stringify(list.toArray(merged)); | ||
const result = stringify(toArray(merged)); | ||
if (result !== '[[["a"],1],[["a","b"],2],[["a"],5]]') { | ||
@@ -79,0 +122,0 @@ throw result; |
@@ -0,6 +1,53 @@ | ||
/** | ||
* A module for representing and handling operations that can succeed or fail. | ||
* | ||
* @module | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* import { error, ok, unwrap, type Result } from './module.f.ts' | ||
* | ||
* const success: Result<number, string> = ok(42) | ||
* const failure: Result<number, string> = error('Something went wrong') | ||
* | ||
* if (unwrap(success) !== 42) { throw 'error' } | ||
* const [kind, v] = failure | ||
* if (kind !== 'error') { throw 'error' } | ||
* // `v` is inferred as `string` here | ||
* if (v !== 'Something went wrong') { throw 'error' } | ||
* ``` | ||
*/ | ||
/** | ||
* Represents a successful result. | ||
*/ | ||
export type Ok<T> = readonly ['ok', T]; | ||
/** | ||
* Represents a failed result. | ||
*/ | ||
export type Error<E> = readonly ['error', E]; | ||
/** | ||
* Represents a result that can be either successful or failed. | ||
*/ | ||
export type Result<T, E> = Ok<T> | Error<E>; | ||
/** | ||
* Creates a successful result. | ||
* | ||
* @param value - The value to wrap. | ||
* @returns A successful result containing the value. | ||
*/ | ||
export declare const ok: <T>(value: T) => Ok<T>; | ||
/** | ||
* Creates a failed result. | ||
* | ||
* @param e - The error to wrap. | ||
* @returns A failed result containing the error. | ||
*/ | ||
export declare const error: <E>(e: E) => Error<E>; | ||
export declare const unwrap: <T, E>(r: Result<T, E>) => T; | ||
/** | ||
* Unwraps a result, returning the value if successful or throwing the error if failed. | ||
* | ||
* @param param0 - The result to unwrap. | ||
* @returns The value if the result is successful. Otherwise, throws the error. | ||
*/ | ||
export declare const unwrap: <T, E>([kind, v]: Result<T, E>) => T; |
@@ -1,3 +0,41 @@ | ||
export const ok = value => ['ok', value]; | ||
export const error = e => ['error', e]; | ||
/** | ||
* A module for representing and handling operations that can succeed or fail. | ||
* | ||
* @module | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* import { error, ok, unwrap, type Result } from './module.f.ts' | ||
* | ||
* const success: Result<number, string> = ok(42) | ||
* const failure: Result<number, string> = error('Something went wrong') | ||
* | ||
* if (unwrap(success) !== 42) { throw 'error' } | ||
* const [kind, v] = failure | ||
* if (kind !== 'error') { throw 'error' } | ||
* // `v` is inferred as `string` here | ||
* if (v !== 'Something went wrong') { throw 'error' } | ||
* ``` | ||
*/ | ||
/** | ||
* Creates a successful result. | ||
* | ||
* @param value - The value to wrap. | ||
* @returns A successful result containing the value. | ||
*/ | ||
export const ok = (value) => ['ok', value]; | ||
/** | ||
* Creates a failed result. | ||
* | ||
* @param e - The error to wrap. | ||
* @returns A failed result containing the error. | ||
*/ | ||
export const error = (e) => ['error', e]; | ||
/** | ||
* Unwraps a result, returning the value if successful or throwing the error if failed. | ||
* | ||
* @param param0 - The result to unwrap. | ||
* @returns The value if the result is successful. Otherwise, throws the error. | ||
*/ | ||
export const unwrap = ([kind, v]) => { | ||
@@ -4,0 +42,0 @@ if (kind === 'error') { |
@@ -31,10 +31,11 @@ import { next } from "../list/module.f.js"; | ||
export const find = (cmp) => (value) => (array) => { | ||
const cmpValue = cmp(value); | ||
let b = 0; | ||
let e = array.length - 1; | ||
while (true) { | ||
if (e - b < 0) | ||
const d = e - b; | ||
if (d < 0) | ||
return null; | ||
const mid = b + (e - b >> 1); | ||
const sign = cmp(value)(array[mid]); | ||
switch (sign) { | ||
const mid = b + (d >> 1); | ||
switch (cmpValue(array[mid])) { | ||
case -1: { | ||
@@ -41,0 +42,0 @@ e = mid - 1; |
586132
257
16280