functionalscript
Advanced tools
Comparing version
@@ -68,2 +68,10 @@ import type { Reduce } from '../../types/function/operator/module.f.ts'; | ||
export declare const secp256r1: Init; | ||
/** | ||
* https://neuromancer.sk/std/secg/secp384r1 | ||
*/ | ||
export declare const secp384r1: Init; | ||
/** | ||
* https://neuromancer.sk/std/secg/secp521r1 | ||
*/ | ||
export declare const secp521r1: Init; | ||
export {}; |
@@ -127,1 +127,31 @@ import { prime_field, sqrt } from "../prime_field/module.f.js"; | ||
}; | ||
/** | ||
* https://neuromancer.sk/std/secg/secp384r1 | ||
*/ | ||
export const secp384r1 = { | ||
p: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffn, | ||
a: [ | ||
0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aefn, //< b | ||
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffcn, //< a | ||
], | ||
g: [ | ||
0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7n, //< x | ||
0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5fn, //< y | ||
], | ||
n: 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973n, | ||
}; | ||
/** | ||
* https://neuromancer.sk/std/secg/secp521r1 | ||
*/ | ||
export const secp521r1 = { | ||
p: 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn, | ||
a: [ | ||
0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00n, //< b | ||
0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcn, //< a | ||
], | ||
g: [ | ||
0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66n, | ||
0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650n, | ||
], | ||
n: 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409n | ||
}; |
declare const _default: { | ||
example: () => void; | ||
test: () => void; | ||
poker: () => { | ||
[k: string]: () => void; | ||
}; | ||
}; | ||
export default _default; |
@@ -1,2 +0,56 @@ | ||
import { curve, secp256k1, secp192r1, secp256r1, eq } from "./module.f.js"; | ||
import { prime_field } from "../prime_field/module.f.js"; | ||
import { curve, secp256k1, secp192r1, secp256r1, eq, secp384r1, secp521r1 } from "./module.f.js"; | ||
const poker = (param) => () => { | ||
// (c ^ x) ^ y = c ^ (x * y) | ||
// c ^ ((x * y) * (1/x * 1/y)) = c | ||
const { g, n } = param; | ||
const { mul, y } = curve(param); | ||
const f = (m) => (pList) => pList.map(i => mul(i)(m)); | ||
// | ||
const pf = prime_field(n); | ||
// 0 1 2 3 4 5 6 7 | ||
const sA = 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefn % n; | ||
const sB = 0xfedcba98fedcba98fedcba98fedcba98fedcba98fedcba98fedcba98fedcba98n % n; | ||
// "22d3ad011aec6aabdb3d3d47636f3e2859de02298c87a496" | ||
// "2b359de5cfb5937a5610d565dceaef2a760ceeaec96e68140757f0c8371534e0" | ||
// "1359162ede91207ccaea1de94afc63c1db5a967c1e6e21f91ef9f077f20a46b6" | ||
const rA = pf.reciprocal(sA); | ||
// "e1e768c7427cf5bafd58756df9b54b9ec2558201f129f4ab" | ||
// "edaf7ede285c3da723c54fcdaa3b631f626681f884d8f41fae55c4f552bb551e" | ||
// "6ca248e88c124478975b57c4c3ca682bd8be0f0d9f11593d01273d9ceebdb735" | ||
const rB = pf.reciprocal(sB); | ||
// | ||
let d = []; | ||
for (let i = 0n; i < 52n; ++i) { | ||
let nonce = 0n; // can be a random number in a range [`0`, `p >> 6n`). | ||
let x = 0n; | ||
let yi; | ||
while (true) { | ||
x = i | (nonce << 6n); | ||
yi = y(x); | ||
if (yi !== null) { | ||
break; | ||
} | ||
++nonce; | ||
} | ||
d = [...d, [x, yi]]; | ||
} | ||
// | ||
const dA = f(sA)(d); | ||
const dAB = f(sB)(dA); | ||
const dB = f(rA)(dAB); | ||
const dN = f(rB)(dB); | ||
// | ||
let m = 0n; | ||
for (const p of dN) { | ||
if (p === null) { | ||
throw 'null'; | ||
} | ||
const x = p[0] & 0x3fn; | ||
if (x !== m) { | ||
throw [p[0], x, m]; | ||
} | ||
++m; | ||
} | ||
}; | ||
export default { | ||
@@ -20,3 +74,3 @@ example: () => { | ||
const { mul, neg, pf: { abs }, y: yf, nf: { p: n } } = curve(c); | ||
const point_check = p => { | ||
const point_check = (p) => { | ||
if (p === null) { | ||
@@ -36,3 +90,3 @@ throw 'p === null'; | ||
point_check(neg(g)); | ||
const test_mul = p => { | ||
const test_mul = (p) => { | ||
if (mul(p)(0n) !== null) { | ||
@@ -73,3 +127,13 @@ throw 'O'; | ||
test_curve(secp256r1); | ||
test_curve(secp384r1); | ||
test_curve(secp521r1); | ||
}, | ||
poker: () => { | ||
const c = { | ||
secp192r1, | ||
//secp256k1, | ||
//secp256r1, | ||
}; | ||
return Object.fromEntries(Object.entries(c).map(([k, v]) => [k, poker(v)])); | ||
} | ||
}; |
@@ -1,17 +0,7 @@ | ||
import * as list from '../types/list/module.f.ts'; | ||
import type * as O from '../types/object/module.f.ts'; | ||
type Object = { | ||
import type { Primitive as JsonPrimitive } from '../json/module.f.ts'; | ||
export type Object = { | ||
readonly [k in string]: Unknown; | ||
}; | ||
type Array = readonly Unknown[]; | ||
type Unknown = Object | boolean | string | number | null | Array | bigint | undefined; | ||
type Entry = O.Entry<Unknown>; | ||
type Entries = list.List<Entry>; | ||
type MapEntries = (entries: Entries) => Entries; | ||
export declare const serialize: (mapEntries: MapEntries) => (value: Unknown) => list.List<string>; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export declare const stringify: (mapEntries: MapEntries) => (value: Unknown) => string; | ||
export {}; | ||
export type Array = readonly Unknown[]; | ||
export type Primitive = JsonPrimitive | bigint | undefined; | ||
export type Unknown = Primitive | Object | Array; |
@@ -1,62 +0,1 @@ | ||
import * as list from "../types/list/module.f.js"; | ||
const { flat, map } = list; | ||
import * as string from "../types/string/module.f.js"; | ||
const { concat } = string; | ||
import * as f from "../types/function/module.f.js"; | ||
const { compose, fn } = f; | ||
const { entries } = Object; | ||
import * as bi from "../types/bigint/module.f.js"; | ||
const { serialize: bigintSerialize } = bi; | ||
import * as j from "../json/serializer/module.f.js"; | ||
const { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } = j; | ||
import * as djs from "./serializer/module.f.js"; | ||
const { undefinedSerialize } = djs; | ||
const colon = [':']; | ||
export const serialize = sort => { | ||
const propertySerialize = ([k, v]) => flat([ | ||
stringSerialize(k), | ||
colon, | ||
f(v) | ||
]); | ||
const mapPropertySerialize = map(propertySerialize); | ||
const objectSerialize = fn(entries) | ||
.then(sort) | ||
.then(mapPropertySerialize) | ||
.then(objectWrap) | ||
.result; | ||
const f = value => { | ||
switch (typeof value) { | ||
case 'boolean': { | ||
return boolSerialize(value); | ||
} | ||
case 'number': { | ||
return numberSerialize(value); | ||
} | ||
case 'string': { | ||
return stringSerialize(value); | ||
} | ||
case 'bigint': { | ||
return [bigintSerialize(value)]; | ||
} | ||
default: { | ||
if (value === null) { | ||
return nullSerialize; | ||
} | ||
if (value === undefined) { | ||
return undefinedSerialize; | ||
} | ||
if (value instanceof Array) { | ||
return arraySerialize(value); | ||
} | ||
return objectSerialize(value); | ||
} | ||
} | ||
}; | ||
const arraySerialize = compose(map(f))(arrayWrap); | ||
return f; | ||
}; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export const stringify = sort => compose(serialize(sort))(concat); | ||
export {}; |
import * as result from '../../types/result/module.f.ts'; | ||
import { type List } from '../../types/list/module.f.ts'; | ||
import type * as tokenizerT from '../tokenizer/module.f.ts'; | ||
export type DjsModule = [readonly string[], readonly DjsConst[]]; | ||
export type DjsConst = boolean | string | number | null | bigint | undefined | DjsModuleRef | DjsArray | DjsObject; | ||
type DjsModuleRef = ['aref' | 'cref', number]; | ||
type DjsArray = ['array', readonly DjsConst[]]; | ||
export type DjsObject = { | ||
readonly [k in string]: DjsConst; | ||
import type { DjsToken } from '../tokenizer/module.f.ts'; | ||
import { type Map } from '../../types/map/module.f.ts'; | ||
import type { Fs } from '../../io/module.f.ts'; | ||
import type { AstModule } from '../ast/module.f.ts'; | ||
export type ParseContext = { | ||
readonly fs: Fs; | ||
readonly complete: Map<result.Result<AstModule, string>>; | ||
readonly stack: List<string>; | ||
}; | ||
export declare const parse: (tokenList: List<tokenizerT.DjsToken>) => result.Result<DjsModule, string>; | ||
export {}; | ||
export declare const parseFromTokens: (tokenList: List<DjsToken>) => result.Result<AstModule, string>; |
import * as result from "../../types/result/module.f.js"; | ||
import { fold, first, drop, toArray, length, concat } from "../../types/list/module.f.js"; | ||
import { setReplace, at } from "../../types/map/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
const { fromMap } = o; | ||
import { fromMap } from "../../types/object/module.f.js"; | ||
const parseInitialOp = token => state => { | ||
@@ -62,4 +61,4 @@ switch (token.kind) { | ||
return { state: 'error', message: 'duplicate id' }; | ||
let cref = ['cref', length(state.module.consts)]; | ||
let refs = setReplace(token.value)(cref)(state.module.refs); | ||
const cref = ['cref', length(state.module.consts)]; | ||
const refs = setReplace(token.value)(cref)(state.module.refs); | ||
return { ...state, state: 'const+name', module: { ...state.module, refs: refs } }; | ||
@@ -90,4 +89,4 @@ } | ||
} | ||
let aref = ['aref', length(state.module.modules)]; | ||
let refs = setReplace(token.value)(aref)(state.module.refs); | ||
const aref = ['aref', length(state.module.modules)]; | ||
const refs = setReplace(token.value)(aref)(state.module.refs); | ||
return { ...state, state: 'import+name', module: { ...state.module, refs: refs } }; | ||
@@ -135,3 +134,3 @@ } | ||
if (state.top === null) { | ||
let consts = concat(state.module.consts)([value]); | ||
const consts = concat(state.module.consts)([value]); | ||
switch (state.state) { | ||
@@ -327,3 +326,3 @@ case 'exportValue': return { ...state, state: 'result', module: { ...state.module, consts: consts } }; | ||
}; | ||
export const parse = (tokenList) => { | ||
export const parseFromTokens = (tokenList) => { | ||
const state = fold(foldOp)({ state: '', module: { refs: null, modules: null, consts: null } })(tokenList); | ||
@@ -330,0 +329,0 @@ switch (state.state) { |
@@ -6,5 +6,5 @@ import * as parser from "./module.f.js"; | ||
import * as encoding from "../../text/utf16/module.f.js"; | ||
import { djsModuleStringify } from "../serializer/module.f.js"; | ||
import { stringify } from "../serializer/module.f.js"; | ||
const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))); | ||
const stringifyDjsModule = djsModuleStringify(sort); | ||
const stringifyDjsModule = stringify(sort); | ||
export default { | ||
@@ -14,3 +14,3 @@ valid: [ | ||
const tokenList = tokenizeString('export default null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -20,3 +20,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default null') { | ||
if (result !== '[[],[null]]') { | ||
throw result; | ||
@@ -27,3 +27,3 @@ } | ||
const tokenList = tokenizeString('export default true'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -33,3 +33,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default true') { | ||
if (result !== '[[],[true]]') { | ||
throw result; | ||
@@ -40,3 +40,3 @@ } | ||
const tokenList = tokenizeString('export default false'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -46,3 +46,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default false') { | ||
if (result !== '[[],[false]]') { | ||
throw result; | ||
@@ -53,3 +53,3 @@ } | ||
const tokenList = tokenizeString('export default undefined'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -59,3 +59,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default undefined') { | ||
if (result !== '[[],[undefined]]') { | ||
throw result; | ||
@@ -66,3 +66,3 @@ } | ||
const tokenList = tokenizeString('export default 0.1'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -72,3 +72,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default 0.1') { | ||
if (result !== '[[],[0.1]]') { | ||
throw result; | ||
@@ -79,3 +79,3 @@ } | ||
const tokenList = tokenizeString('export default 1.1e+2'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -85,3 +85,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default 110') { | ||
if (result !== '[[],[110]]') { | ||
throw result; | ||
@@ -92,3 +92,3 @@ } | ||
const tokenList = tokenizeString('export default "abc"'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -98,3 +98,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default "abc"') { | ||
if (result !== '[[],["abc"]]') { | ||
throw result; | ||
@@ -105,3 +105,3 @@ } | ||
const tokenList = tokenizeString('export default []'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -111,3 +111,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default []') { | ||
if (result !== '[[],[["array",[]]]]') { | ||
throw result; | ||
@@ -118,3 +118,3 @@ } | ||
const tokenList = tokenizeString('export default [1]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -124,3 +124,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [1]') { | ||
if (result !== '[[],[["array",[1]]]]') { | ||
throw result; | ||
@@ -131,3 +131,3 @@ } | ||
const tokenList = tokenizeString('export default [[]]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -137,3 +137,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [[]]') { | ||
if (result !== '[[],[["array",[["array",[]]]]]]') { | ||
throw result; | ||
@@ -144,3 +144,3 @@ } | ||
const tokenList = tokenizeString('export default [0,[1,[2,[]]],3]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -150,3 +150,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [0,[1,[2,[]]],3]') { | ||
if (result !== '[[],[["array",[0,["array",[1,["array",[2,["array",[]]]]]],3]]]]') { | ||
throw result; | ||
@@ -157,3 +157,3 @@ } | ||
const tokenList = tokenizeString('export default {}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -163,3 +163,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default {}') { | ||
if (result !== '[[],[{}]]') { | ||
throw result; | ||
@@ -170,3 +170,3 @@ } | ||
const tokenList = tokenizeString('export default [{}]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -176,3 +176,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [{}]') { | ||
if (result !== '[[],[["array",[{}]]]]') { | ||
throw result; | ||
@@ -183,3 +183,3 @@ } | ||
const tokenList = tokenizeString('export default {"a":true,"b":false,"c":null,"d":undefined}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -189,3 +189,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default {"a":true,"b":false,"c":null,"d":undefined}') { | ||
if (result !== '[[],[{"a":true,"b":false,"c":null,"d":undefined}]]') { | ||
throw result; | ||
@@ -196,3 +196,3 @@ } | ||
const tokenList = tokenizeString('export default {"a":{"b":{"c":["d"]}}}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -202,3 +202,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default {"a":{"b":{"c":["d"]}}}') { | ||
if (result !== '[[],[{"a":{"b":{"c":["array",["d"]]}}}]]') { | ||
throw result; | ||
@@ -209,3 +209,3 @@ } | ||
const tokenList = tokenizeString('export default 1234567890n'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -215,3 +215,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default 1234567890n') { | ||
if (result !== '[[],[1234567890n]]') { | ||
throw result; | ||
@@ -222,3 +222,3 @@ } | ||
const tokenList = tokenizeString('export default [1234567890n]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -228,3 +228,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [1234567890n]') { | ||
if (result !== '[[],[["array",[1234567890n]]]]') { | ||
throw result; | ||
@@ -237,3 +237,3 @@ } | ||
const tokenList = tokenizeString('export default'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -248,3 +248,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default "123'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -259,3 +259,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [,]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -270,3 +270,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [1 2]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -281,3 +281,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [1,,2]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -292,3 +292,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default []]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -303,3 +303,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default ["a"'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -314,3 +314,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [1,]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -325,3 +325,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [,1]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -336,3 +336,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [:]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -347,3 +347,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default ]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -358,3 +358,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {,}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -369,3 +369,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {1:2}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -380,3 +380,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {"1"2}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -391,3 +391,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {"1"::2}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -402,3 +402,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {"1":2,,"3":4'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -413,3 +413,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {}}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -424,3 +424,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {"1":2'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -435,3 +435,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {"1":2,}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -446,3 +446,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {,"1":2}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -457,3 +457,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default }'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -468,3 +468,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default [{]}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -479,3 +479,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default {[}]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -490,3 +490,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default 10-5'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -503,3 +503,3 @@ throw obj; | ||
const tokenList = tokenizeString(' export default [ 0 , 1 , 2 ] '); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -509,3 +509,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [0,1,2]') { | ||
if (result !== '[[],[["array",[0,1,2]]]]') { | ||
throw result; | ||
@@ -516,3 +516,3 @@ } | ||
const tokenList = tokenizeString(' export default { "a" : 0 , "b" : 1 } '); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -522,3 +522,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default {"a":0,"b":1}') { | ||
if (result !== '[[],[{"a":0,"b":1}]]') { | ||
throw result; | ||
@@ -529,3 +529,3 @@ } | ||
const tokenList = tokenizeString('\nexport\ndefault\n[\n0\n,\n1\n,\n2\n]\n'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -535,3 +535,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default [0,1,2]') { | ||
if (result !== '[[],[["array",[0,1,2]]]]') { | ||
throw result; | ||
@@ -542,3 +542,3 @@ } | ||
const tokenList = tokenizeString('\rexport\rdefault\r{\r"a"\r:\r0\r,\r"b"\r:\r1\r}\r'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -548,3 +548,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default {"a":0,"b":1}') { | ||
if (result !== '[[],[{"a":0,"b":1}]]') { | ||
throw result; | ||
@@ -557,3 +557,3 @@ } | ||
const tokenList = tokenizeString('null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -568,3 +568,3 @@ throw obj; | ||
const tokenList = tokenizeString('module=null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -579,3 +579,3 @@ throw obj; | ||
const tokenList = tokenizeString('export null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -590,3 +590,3 @@ throw obj; | ||
const tokenList = tokenizeString('export default = null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -603,3 +603,3 @@ throw obj; | ||
const tokenList = tokenizeString('const a = 1 \n const b = 2 \n export default 3'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -609,3 +609,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'const c0 = 1\nconst c1 = 2\nexport default 3') { | ||
if (result !== '[[],[1,2,3]]') { | ||
throw result; | ||
@@ -616,3 +616,3 @@ } | ||
const tokenList = tokenizeString('const a = 1 \n const b = 2 \n export default b'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -622,3 +622,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'const c0 = 1\nconst c1 = 2\nexport default c1') { | ||
if (result !== '[[],[1,2,["cref",1]]]') { | ||
throw result; | ||
@@ -629,3 +629,3 @@ } | ||
const tokenList = tokenizeString('const a = 1 \n const b = 2 \n export default [b,a,b]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -635,3 +635,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'const c0 = 1\nconst c1 = 2\nexport default [c1,c0,c1]') { | ||
if (result !== '[[],[1,2,["array",[["cref",1],["cref",0],["cref",1]]]]]') { | ||
throw result; | ||
@@ -642,3 +642,3 @@ } | ||
const tokenList = tokenizeString('const a = 1 \n const b = 2 \n export default {"1st":b,"2nd":a,"3rd":b}'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -648,3 +648,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'const c0 = 1\nconst c1 = 2\nexport default {"1st":c1,"2nd":c0,"3rd":c1}') { | ||
if (result !== '[[],[1,2,{"1st":["cref",1],"2nd":["cref",0],"3rd":["cref",1]}]]') { | ||
throw result; | ||
@@ -657,3 +657,3 @@ } | ||
const tokenList = tokenizeString('const a = 1 const b = 2 export default 3'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -668,3 +668,3 @@ throw obj; | ||
const tokenList = tokenizeString('const = 1 \n const b = 2 \n export default 3'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -679,3 +679,3 @@ throw obj; | ||
const tokenList = tokenizeString('const a = 1 \n const a = 2 \n export default 3'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -692,3 +692,3 @@ throw obj; | ||
const tokenList = tokenizeString('import a from "test/test.f.mjs" \n export default a'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -698,3 +698,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'import a0 from "test/test.f.mjs"\nexport default a0') { | ||
if (result !== '[["test/test.f.mjs"],[["aref",0]]]') { | ||
throw result; | ||
@@ -705,3 +705,3 @@ } | ||
const tokenList = tokenizeString('import a from "first/test.f.mjs" \n import b from "second/test.f.mjs" \n export default [b, a, b]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -711,3 +711,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'import a0 from "first/test.f.mjs"\nimport a1 from "second/test.f.mjs"\nexport default [a1,a0,a1]') { | ||
if (result !== '[["first/test.f.mjs","second/test.f.mjs"],[["array",[["aref",1],["aref",0],["aref",1]]]]]') { | ||
throw result; | ||
@@ -718,3 +718,3 @@ } | ||
const tokenList = tokenizeString('import a from "test/test.f.mjs" \n const b = null \n export default [b, a, b]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -724,3 +724,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'import a0 from "test/test.f.mjs"\nconst c0 = null\nexport default [c0,a0,c0]') { | ||
if (result !== '[["test/test.f.mjs"],[null,["array",[["cref",0],["aref",0],["cref",0]]]]]') { | ||
throw result; | ||
@@ -733,3 +733,3 @@ } | ||
const tokenList = tokenizeString('import a from "test/test.f.mjs" export default a'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -744,3 +744,3 @@ throw obj; | ||
const tokenList = tokenizeString('import a from \n export default a'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -755,3 +755,3 @@ throw obj; | ||
const tokenList = tokenizeString('import a "test/test.f.mjs" \n export default a'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -766,3 +766,3 @@ throw obj; | ||
const tokenList = tokenizeString('import from "test/test.f.mjs" \n export default a'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -777,3 +777,3 @@ throw obj; | ||
const tokenList = tokenizeString('import a from "first/test.f.mjs" \n import a from "second/test.f.mjs" \n export default [b, a, b]'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -788,3 +788,3 @@ throw obj; | ||
const tokenList = tokenizeString('import a from "test/test.f.mjs" \n const a = null \n export default null'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'error') { | ||
@@ -801,3 +801,3 @@ throw obj; | ||
const tokenList = tokenizeString('export //comment \n default /* comment */ null //comment'); | ||
const obj = parser.parse(tokenList); | ||
const obj = parser.parseFromTokens(tokenList); | ||
if (obj[0] !== 'ok') { | ||
@@ -807,3 +807,3 @@ throw obj; | ||
const result = stringifyDjsModule(obj[1]); | ||
if (result !== 'export default null') { | ||
if (result !== '[[],[null]]') { | ||
throw result; | ||
@@ -810,0 +810,0 @@ } |
import * as list from '../../types/list/module.f.ts'; | ||
import type * as O from '../../types/object/module.f.ts'; | ||
import type * as DjsParser from '../parser/module.f.ts'; | ||
export declare const undefinedSerialize: string[]; | ||
type Entry = O.Entry<DjsParser.DjsConst>; | ||
import type { Unknown } from '../module.f.ts'; | ||
type Entry = O.Entry<Unknown>; | ||
type Entries = list.List<Entry>; | ||
type MapEntries = (entries: Entries) => Entries; | ||
export declare const djsModuleStringify: (mapEntries: MapEntries) => (djsModule: DjsParser.DjsModule) => string; | ||
export declare const serialize: (mapEntries: MapEntries) => (value: Unknown) => list.List<string>; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export declare const stringify: (mapEntries: MapEntries) => (value: Unknown) => string; | ||
export {}; |
import * as list from "../../types/list/module.f.js"; | ||
const { flat, map, entries: listEntries, concat: listConcat, flatMap } = list; | ||
const { flat, map } = list; | ||
import * as string from "../../types/string/module.f.js"; | ||
@@ -13,4 +13,4 @@ const { concat } = string; | ||
const colon = [':']; | ||
export const undefinedSerialize = ['undefined']; | ||
const djsConstSerialize = sort => { | ||
const undefinedSerialize = ['undefined']; | ||
export const serialize = sort => { | ||
const propertySerialize = ([k, v]) => flat([ | ||
@@ -49,13 +49,3 @@ stringSerialize(k), | ||
if (value instanceof Array) { | ||
switch (value[0]) { | ||
case 'aref': { | ||
return [`a${value[1]}`]; | ||
} | ||
case 'cref': { | ||
return [`c${value[1]}`]; | ||
} | ||
case 'array': { | ||
return arraySerialize(value[1]); | ||
} | ||
} | ||
return arraySerialize(value); | ||
} | ||
@@ -69,14 +59,6 @@ return objectSerialize(value); | ||
}; | ||
export const djsModuleStringify = sort => djsModule => { | ||
const importEntries = listEntries(djsModule[0]); | ||
const importSerialize = entry => flat([['import a'], numberSerialize(entry[0]), [' from "', entry[1], '"\n']]); | ||
const len = djsModule[1].length; | ||
const constEntries = listEntries(djsModule[1]); | ||
const moduleEntrySerialize = entry => { | ||
if (entry[0] === len - 1) { | ||
return listConcat(['export default '])(djsConstSerialize(sort)(entry[1])); | ||
} | ||
return flat([['const c'], numberSerialize(entry[0]), [' = '], djsConstSerialize(sort)(entry[1]), ['\n']]); | ||
}; | ||
return concat(listConcat(flatMap(importSerialize)(importEntries))(flatMap(moduleEntrySerialize)(constEntries))); | ||
}; | ||
/** | ||
* The standard `JSON.stringify` rules determined by | ||
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys | ||
*/ | ||
export const stringify = sort => compose(serialize(sort))(concat); |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as djs from "../module.f.js"; | ||
import * as serializer from "../serializer/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -9,3 +9,3 @@ const { sort } = o; | ||
const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))); | ||
const stringify = djs.stringify(sort); | ||
const stringify = serializer.stringify(sort); | ||
export default { | ||
@@ -12,0 +12,0 @@ djs: [ |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as djs from "../../djs/module.f.js"; | ||
import * as serializer from "../../djs/serializer/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -9,3 +9,3 @@ const { sort } = o; | ||
const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))); | ||
const stringify = djs.stringify(sort); | ||
const stringify = serializer.stringify(sort); | ||
export default { | ||
@@ -12,0 +12,0 @@ djs: [ |
@@ -7,3 +7,4 @@ import * as list from '../types/list/module.f.ts'; | ||
type Array = readonly Unknown[]; | ||
export type Unknown = Object | boolean | string | number | null | Array; | ||
export type Primitive = boolean | string | number | null; | ||
export type Unknown = Primitive | Object | Array; | ||
export declare const setProperty: (value: Unknown) => (path: list.List<string>) => (src: Unknown) => Unknown; | ||
@@ -10,0 +11,0 @@ export type Entry = object.Entry<Unknown>; |
import * as tokenizer from "./module.f.js"; | ||
import * as list from "../../types/list/module.f.js"; | ||
const { toArray } = list; | ||
import * as djs from "../../djs/module.f.js"; | ||
import * as serializer from "../../djs/serializer/module.f.js"; | ||
import * as o from "../../types/object/module.f.js"; | ||
@@ -9,3 +9,3 @@ const { sort } = o; | ||
const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))); | ||
const stringify = djs.stringify(sort); | ||
const stringify = serializer.stringify(sort); | ||
export default { | ||
@@ -12,0 +12,0 @@ json: [ |
@@ -1,2 +0,2 @@ | ||
const e = a => b => { | ||
const e = (a) => (b) => { | ||
if (a === b) { } | ||
@@ -7,3 +7,3 @@ else { | ||
}; | ||
const n = a => b => { | ||
const n = (a) => (b) => { | ||
if (a !== b) { } | ||
@@ -14,4 +14,4 @@ else { | ||
}; | ||
const nan_res = op => n => { | ||
let result = op(n); | ||
const nan_res = (op) => (n) => { | ||
const result = op(n); | ||
if (!Number.isNaN(result)) { | ||
@@ -18,0 +18,0 @@ throw result; |
{ | ||
"name": "functionalscript", | ||
"version": "0.4.3", | ||
"version": "0.4.4", | ||
"type": "module", | ||
@@ -41,5 +41,5 @@ "files": [ | ||
"devDependencies": { | ||
"@types/node": "^22.10.5", | ||
"@types/node": "^22.13.4", | ||
"typescript": "^5.7.3" | ||
} | ||
} |
@@ -22,3 +22,3 @@ # FunctionalScript | ||
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and distributted under under [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html#license-text). Let us know if you need another license by sending an [email](mailto:sergey.oss@proton.me). | ||
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and distributted under [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html#license-text). Let us know if you need another license by sending an [email](mailto:sergey.oss@proton.me). | ||
@@ -25,0 +25,0 @@ ## Vision |
@@ -0,5 +1,17 @@ | ||
export declare const backspace: string; | ||
type End = 'm'; | ||
type Csi = (code: number | string) => string; | ||
/** | ||
* Control Sequence Introducer (CSI) escape sequence. | ||
* https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands | ||
* | ||
* @param end - The final character that indicates the type of sequence. | ||
* @returns A function that takes a code (number or string) and returns the complete ANSI escape sequence. | ||
*/ | ||
export declare const csi: (end: End) => Csi; | ||
/** | ||
* Specialization of CSI for Select Graphic Rendition (SGR) sequences. | ||
* https://en.wikipedia.org/wiki/ANSI_escape_code#SGR | ||
*/ | ||
export declare const sgr: (c: number) => string; | ||
export declare const sgr: Csi; | ||
export declare const reset: string; | ||
@@ -9,1 +21,7 @@ export declare const bold: string; | ||
export declare const fgGreen: string; | ||
export type Stdout = { | ||
readonly write: (s: string) => void; | ||
}; | ||
export type WriteText = (text: string) => WriteText; | ||
export declare const createConsoleText: (stdout: Stdout) => WriteText; | ||
export {}; |
@@ -0,5 +1,17 @@ | ||
// Co control codes | ||
// https://en.wikipedia.org/wiki/ANSI_escape_code#C0_control_codes | ||
export const backspace = '\x08'; | ||
/** | ||
* Control Sequence Introducer (CSI) escape sequence. | ||
* https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands | ||
* | ||
* @param end - The final character that indicates the type of sequence. | ||
* @returns A function that takes a code (number or string) and returns the complete ANSI escape sequence. | ||
*/ | ||
export const csi = (end) => code => `\x1b[${code.toString()}${end}`; | ||
/** | ||
* Specialization of CSI for Select Graphic Rendition (SGR) sequences. | ||
* https://en.wikipedia.org/wiki/ANSI_escape_code#SGR | ||
*/ | ||
export const sgr = (c) => `\x1b[${c.toString()}m`; | ||
export const sgr = csi('m'); | ||
export const reset = sgr(0); | ||
@@ -9,1 +21,14 @@ export const bold = sgr(1); | ||
export const fgGreen = sgr(32); | ||
const { max } = Math; | ||
const replace = (old) => (text) => { | ||
const len = old.length; | ||
const suffixLength = max(0, len - text.length); | ||
return backspace.repeat(len) + text + " ".repeat(suffixLength) + backspace.repeat(suffixLength); | ||
}; | ||
export const createConsoleText = (stdout) => { | ||
const f = (old) => (text) => { | ||
stdout.write(replace(old)(text)); | ||
return f(text); | ||
}; | ||
return f(''); | ||
}; |
import { type List, type Thunk } from '../../types/list/module.f.ts'; | ||
/** | ||
* Represent an unsigned UTF16, used to store one word UTF-16 (code unit). | ||
*/ | ||
export type U16 = number; | ||
@@ -8,8 +11,121 @@ /** | ||
*/ | ||
/** | ||
* Represent an Unicode code point. | ||
* Has range: from 0x0000 to 0x10_FFFF (21 bits). | ||
*/ | ||
export type CodePoint = number; | ||
/** | ||
* Converts a UTF-16 sequence to its corresponding Unicode code points. | ||
* | ||
* This function handles: | ||
* 1. Single U16 values in the Basic Multilingual Plane (BMP) [0x0000β0xFFFF]. | ||
* 2. Surrogate pairs representing code points in the Supplementary Plane [0x10000β0x10FFFF]. | ||
* 3. Invalid input sequences by applying an error mask to the resulting code point. | ||
* | ||
* @param utf16 - A list of UTF-16 code units (U16) to convert. | ||
* @returns A list of Unicode code points. Each code point corresponds to one or more U16 | ||
* values in the input. Invalid sequences are marked with the `errorMask`. | ||
* @example | ||
* | ||
* ```ts | ||
* const exampleUtf16: List<U16> = [ | ||
* 0x0041, // 'A' (BMP, single U16) | ||
* 0xD83D, 0xDE00, // π (Emoji, surrogate pair) | ||
* 0xD800, // Unpaired high surrogate | ||
* 0xDC00, // Unpaired low surrogate | ||
* ] | ||
* | ||
* const codePoints = toCodePointList(exampleUtf16) | ||
* codePoints.forEach((codePoint) => { | ||
* if (codePoint & errorMask) { | ||
* console.log(`Invalid sequence detected: ${codePoint.toString(16).toUpperCase()}`) | ||
* } else { | ||
* console.log(`Code Point: U+${codePoint.toString(16).toUpperCase()}`) | ||
* } | ||
* }) | ||
* ``` | ||
*/ | ||
export declare const fromCodePointList: (input: List<CodePoint>) => Thunk<U16>; | ||
/** | ||
* Converts a list of UTF-16 code units to a list of Unicode code points (CodePoint). | ||
* This function processes each UTF-16 code unit, decoding them into their corresponding Unicode code points. | ||
* The input list of `U16` values may represent characters in the Basic Multilingual Plane (BMP) or supplementary planes, | ||
* with surrogate pairs handled correctly. The function also handles EOF (`null`). | ||
* @param input - A list of UTF-16 code units (`U16`), possibly containing surrogate pairs. | ||
* @returns A list of Unicode code points (`CodePoint`), one for each valid code unit or surrogate pair. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const utf16List: List<U16> = [0x0041, 0xD83D, 0xDE00] // 'A' and π (surrogate pair) | ||
* const codePoints = toCodePointList(utf16List) | ||
* ``` | ||
*/ | ||
export declare const toCodePointList: (input: List<U16>) => List<CodePoint>; | ||
/** | ||
* Converts a string to a list of UTF-16 code units (U16). | ||
* | ||
* This function processes each character in the input string and converts it to its corresponding UTF-16 code unit(s). | ||
* Characters in the Basic Multilingual Plane (BMP) will produce a single `U16`, while supplementary plane characters | ||
* (those requiring surrogate pairs) will produce two `U16` values. | ||
* @param s - The input string to convert to UTF-16 code units. | ||
* @returns A list of UTF-16 code units (`U16`) representing the string. | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const inputString = "Hello, π" | ||
* const utf16List = stringToList(inputString) | ||
* ``` | ||
*/ | ||
export declare const stringToList: (s: string) => List<U16>; | ||
/** | ||
* Converts a string to a list of Unicode code points (CodePoint). | ||
* This function first converts the string to a list of UTF-16 code units (U16) using `stringToList`, | ||
* then it converts the UTF-16 code units to Unicode code points using `toCodePointList`. This is useful for handling | ||
* Unicode characters, including supplementary characters represented by surrogate pairs in UTF-16. | ||
* | ||
* @param input - The input string to convert. | ||
* @returns A list of Unicode code points (`CodePoint`) corresponding to the characters in the string. | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const inputString = "Hello, π" | ||
* const codePoints = stringToCodePointList(inputString) | ||
* ``` | ||
*/ | ||
export declare const stringToCodePointList: (input: string) => List<CodePoint>; | ||
/** | ||
* Converts a list of UTF-16 code units (U16) to a string. | ||
* This function takes a list of `U16` values (UTF-16 code units) and reconstructs the original string by mapping | ||
* each code unit back to its character using `String.fromCharCode`. The resulting characters are concatenated | ||
* to form the final string. | ||
* | ||
* @param input - A list of UTF-16 code units (`U16`). | ||
* @returns A string representing the characters encoded by the input UTF-16 code units. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const utf16List: List<U16> = [0x0041, 0x0042, 0x0043] // 'ABC' | ||
* const outputString = listToString(utf16List) | ||
* ``` | ||
*/ | ||
export declare const listToString: (input: List<U16>) => string; | ||
/** | ||
* Converts a list of Unicode code points (CodePoint) to a string. | ||
* This function first converts the list of Unicode code points to a list of UTF-16 code units using `fromCodePointList`, | ||
* then it uses `listToString` to reconstruct the string from the UTF-16 code units. | ||
* | ||
* @param input - A list of Unicode code points (`CodePoint`). | ||
* @returns A string representing the characters encoded by the input code points. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const codePoints: List<CodePoint> = [0x48, 0x65, 0x6C, 0x6C, 0x6F] | ||
* const outputString = codePointListToString(codePoints) | ||
* ``` | ||
*/ | ||
export declare const codePointListToString: (input: List<CodePoint>) => string; |
@@ -5,9 +5,63 @@ import { map, flat, stateScan, reduce, flatMap, empty, } from "../../types/list/module.f.js"; | ||
import { fn } from "../../types/function/module.f.js"; | ||
/** | ||
* Ranges of code points for the lower (Low) and higher (High) parts of the BMP (Basic Multilingual Plane) plane. | ||
*/ | ||
const lowBmp = contains([0x0000, 0xd7ff]); | ||
const highBmp = contains([0xe000, 0xffff]); | ||
/** | ||
* Checks whether the code point is in the BMP range. | ||
* BMP is the main multi-plane Unicode plane that covers code points 0x0000 - 0xFFFF, except for the range of surrogates. | ||
*/ | ||
const isBmpCodePoint = (codePoint) => lowBmp(codePoint) || highBmp(codePoint); | ||
/** | ||
* Checks whether the 16-bit word (U16) is a surrogate of the high part. | ||
* Range: 0xD800 - 0xDBFF. | ||
*/ | ||
const isHighSurrogate = contains([0xd800, 0xdbff]); | ||
/** | ||
* Checks whether the 16-bit word (U16) is a substitute for the low part. | ||
* Range: 0xDC00 β 0xDFFF. | ||
*/ | ||
const isLowSurrogate = contains([0xdc00, 0xdfff]); | ||
/** | ||
* Mask of mistakes. Used to indicate invalid code points or coding errors | ||
*/ | ||
const errorMask = 0b1000_0000_0000_0000_0000_0000_0000_0000; | ||
/** | ||
* Checks whether the code point belongs to the additional (Supplementary) plane of Unicode. | ||
* Additional planes include code points from 0x010000 to 0x10FFFF. | ||
*/ | ||
const isSupplementaryPlane = contains([0x01_0000, 0x10_ffff]); | ||
/** | ||
* Converts a Unicode code point to its corresponding UTF-16 representation. | ||
* | ||
* This function handles: | ||
* 1. Code points in the Basic Multilingual Plane (BMP) [0x0000β0xFFFF], | ||
* which map directly to a single 16-bit value (U16). | ||
* 2. Supplementary Plane code points [0x10000β0x10FFFF], | ||
* which are represented as surrogate pairs in UTF-16. | ||
* | ||
* @param codePoint - A valid Unicode code point. | ||
* @returns A list of 16-bit unsigned integers (U16) representing the UTF-16 encoding | ||
* of the input code point. If the code point is in the BMP range, a single U16 | ||
* value is returned. For code points in the supplementary planes, two U16 | ||
* values (a high and a low surrogate) are returned. | ||
* @example | ||
* | ||
* ```ts | ||
* const exampleCodePoints: List<CodePoint> = [ | ||
* 0x0041, // 'A' (BMP, single U16) | ||
* 0x1F600, // π (Emoji, supplementary plane, surrogate pair) | ||
* 0xD7FF, // Last code point in the low BMP range | ||
* 0xE000, // First code point in the high BMP range | ||
* 0x10FFFF, // Maximum valid code point in Unicode | ||
* 0x110000, // Invalid code point (outside Unicode range) | ||
* ] | ||
* exampleCodePoints.forEach((codePoint) => { | ||
* const utf16Result = codePointToUtf16(codePoint) | ||
* console.log(`Code Point: U+${codePoint.toString(16).toUpperCase()}`) | ||
* console.log(`UTF-16: ${utf16Result.map(u16 => u16.toString(16).toUpperCase()).join(' ')}`) | ||
* }) | ||
* ``` | ||
*/ | ||
const codePointToUtf16 = (codePoint) => { | ||
@@ -25,4 +79,88 @@ if (isBmpCodePoint(codePoint)) { | ||
}; | ||
/** | ||
* Converts a UTF-16 sequence to its corresponding Unicode code points. | ||
* | ||
* This function handles: | ||
* 1. Single U16 values in the Basic Multilingual Plane (BMP) [0x0000β0xFFFF]. | ||
* 2. Surrogate pairs representing code points in the Supplementary Plane [0x10000β0x10FFFF]. | ||
* 3. Invalid input sequences by applying an error mask to the resulting code point. | ||
* | ||
* @param utf16 - A list of UTF-16 code units (U16) to convert. | ||
* @returns A list of Unicode code points. Each code point corresponds to one or more U16 | ||
* values in the input. Invalid sequences are marked with the `errorMask`. | ||
* @example | ||
* | ||
* ```ts | ||
* const exampleUtf16: List<U16> = [ | ||
* 0x0041, // 'A' (BMP, single U16) | ||
* 0xD83D, 0xDE00, // π (Emoji, surrogate pair) | ||
* 0xD800, // Unpaired high surrogate | ||
* 0xDC00, // Unpaired low surrogate | ||
* ] | ||
* | ||
* const codePoints = toCodePointList(exampleUtf16) | ||
* codePoints.forEach((codePoint) => { | ||
* if (codePoint & errorMask) { | ||
* console.log(`Invalid sequence detected: ${codePoint.toString(16).toUpperCase()}`) | ||
* } else { | ||
* console.log(`Code Point: U+${codePoint.toString(16).toUpperCase()}`) | ||
* } | ||
* }) | ||
* ``` | ||
*/ | ||
export const fromCodePointList = flatMap(codePointToUtf16); | ||
/** | ||
* Validates whether a given 16-bit unsigned integer (U16) falls within the valid range for UTF-16 code units. | ||
* | ||
* UTF-16 uses 16-bit code units to encode characters. The valid range for these code units is [0x0000, 0xFFFF]. | ||
* This function is used to verify that a number is within this range. | ||
* | ||
* @param i - A 16-bit unsigned integer (U16) to validate. | ||
* @returns A boolean value indicating whether the input is a valid UTF-16 code unit. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const validU16 = u16(0x0041) // true: U+0041 ('A') | ||
* const invalidU16 = u16(0x110000) // false: Value is outside the valid range | ||
* const edgeCaseLow = u16(0x0000) // true: Minimum valid value for UTF-16 | ||
* const edgeCaseHigh = u16(0xFFFF) // true: Maximum valid value for UTF-16 | ||
* ``` | ||
*/ | ||
const u16 = contains([0x0000, 0xFFFF]); | ||
/** | ||
* A stateful operation that converts a UTF-16 word (U16) to a list of Unicode code points (CodePoint), | ||
* while maintaining the state of surrogate pair decoding. | ||
* | ||
* This operation processes UTF-16 code units and decodes them into Unicode code points. It handles: | ||
* 1. BMP code points (single U16). | ||
* 2. Surrogate pairs (two U16s representing a single code point in the supplementary planes). | ||
* 3. Invalid or malformed code units. | ||
* | ||
* It also manages the internal state, which is necessary to handle surrogate pairs. If the state is null, | ||
* it expects a valid BMP code point or a high surrogate. If the state is not null, it processes a low surrogate | ||
* and combines the pair into a single supplementary code point. | ||
* | ||
* @param state - The current state of the UTF-16 decoding operation. | ||
* This can be either `null` (no state) or the previous high surrogate value. | ||
* @param word - The current UTF-16 word (U16) to process. | ||
* @returns A tuple where the first element is a list of decoded Unicode code points (`CodePoint`), and | ||
* the second element is the updated state. If the word is invalid, an error code `0xffffffff` is returned. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const state: Utf16State = null; | ||
* const word: U16 = 0xD83D; // High surrogate for π emoji | ||
* const [decodedCodePoints, newState] = utf16ByteToCodePointOp(state)(word); | ||
* ``` | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const state: Utf16State = 0xD83D; // High surrogate already stored | ||
* const word: U16 = 0xDC00; // Low surrogate for π emoji | ||
* const [decodedCodePoints, newState] = utf16ByteToCodePointOp(state)(word); | ||
* ``` | ||
*/ | ||
const utf16ByteToCodePointOp = state => word => { | ||
@@ -54,6 +192,106 @@ if (!u16(word)) { | ||
}; | ||
/** | ||
* Handles the EOF (end-of-file) condition during UTF-16 decoding. | ||
* | ||
* If there is no pending state (`state === null`), it simply returns an empty list | ||
* of code points, indicating no further input to process. If there is a pending state, | ||
* it is treated as an unpaired surrogate, and the `errorMask` is applied to flag | ||
* the invalid sequence. | ||
* | ||
* @param state - The current UTF-16 decoding state. This can be: | ||
* - `null`: No pending surrogate to process. | ||
* - A high surrogate (0xD800β0xDBFF) left from an earlier input, waiting for a low surrogate. | ||
* @returns A tuple: | ||
* - The first element is a list of code points. If thereβs a pending state, it is returned | ||
* with the `errorMask` applied. | ||
* - The second element is the next state, which will always be `null` because EOF means no | ||
* further processing. | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const eofState = utf16EofToCodePointOp(0xD800) // Unpaired high surrogate | ||
* const validState = utf16EofToCodePointOp(null) // No pending state | ||
* ``` | ||
*/ | ||
const utf16EofToCodePointOp = (state) => [state === null ? empty : [state | errorMask], null]; | ||
/** | ||
* A stateful scan operation that processes UTF-16 input (word or EOF). | ||
* This function determines whether to handle a UTF-16 word or an end-of-file (EOF) | ||
* signal during decoding: | ||
* 1. If the input is `null` (EOF), it calls `utf16EofToCodePointOp` to process | ||
* any remaining state. | ||
* 2. If the input is a valid UTF-16 word, it calls `utf16ByteToCodePointOp` to | ||
* process the word and update the state accordingly. | ||
* @param state - The current state in the UTF-16 decoding process: | ||
* - `null`: No pending surrogate. | ||
* - A high surrogate waiting for a low surrogate. | ||
* @param input - The current UTF-16 word to process, or `null` to signal EOF. | ||
* @returns A tuple: | ||
* - A list of decoded code points (if any). | ||
* - The updated decoding state. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* // Example 1: Process a valid UTF-16 word | ||
* const input1 = 0x0041 // 'A' (BMP code point) | ||
* const result1 = utf16ByteOrEofToCodePointOp(null)(input1) | ||
* console.log(result1) // [[0x0041], null] | ||
* // Example 2: Process a high surrogate, followed by EOF | ||
* const input2 = 0xD83D // High surrogate | ||
* const result2 = utf16ByteOrEofToCodePointOp(null)(input2) | ||
* console.log(result2) // [[], 0xD83D] (waiting for a low surrogate) | ||
* const eofResult = utf16ByteOrEofToCodePointOp(0xD83D)(null) | ||
* console.log(eofResult) // [[0xD83D | errorMask], null] (unpaired high surrogate) | ||
* // Example 3: Handle EOF with no pending state | ||
* const eofResult2 = utf16ByteOrEofToCodePointOp(null)(null) | ||
* ``` | ||
*/ | ||
const utf16ByteOrEofToCodePointOp = state => input => input === null ? utf16EofToCodePointOp(state) : utf16ByteToCodePointOp(state)(input); | ||
/** | ||
* Represents an end-of-file (EOF) indicator in a list of UTF-16 code units. | ||
* | ||
* This list contains a single element, `null`, which is used to signal the end | ||
* of input during UTF-16 decoding operations. | ||
* @example | ||
* | ||
* ```ts | ||
* const input = [...utf16Data, ...eofList] | ||
* // Ensures the EOF is handled during processing. | ||
* ``` | ||
*/ | ||
const eofList = [null]; | ||
/** | ||
* Converts a list of UTF-16 code units to a list of Unicode code points (CodePoint). | ||
* This function processes each UTF-16 code unit, decoding them into their corresponding Unicode code points. | ||
* The input list of `U16` values may represent characters in the Basic Multilingual Plane (BMP) or supplementary planes, | ||
* with surrogate pairs handled correctly. The function also handles EOF (`null`). | ||
* @param input - A list of UTF-16 code units (`U16`), possibly containing surrogate pairs. | ||
* @returns A list of Unicode code points (`CodePoint`), one for each valid code unit or surrogate pair. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const utf16List: List<U16> = [0x0041, 0xD83D, 0xDE00] // 'A' and π (surrogate pair) | ||
* const codePoints = toCodePointList(utf16List) | ||
* ``` | ||
*/ | ||
export const toCodePointList = (input) => flat(stateScan(utf16ByteOrEofToCodePointOp)(null)(flat([input, eofList]))); | ||
/** | ||
* Converts a string to a list of UTF-16 code units (U16). | ||
* | ||
* This function processes each character in the input string and converts it to its corresponding UTF-16 code unit(s). | ||
* Characters in the Basic Multilingual Plane (BMP) will produce a single `U16`, while supplementary plane characters | ||
* (those requiring surrogate pairs) will produce two `U16` values. | ||
* @param s - The input string to convert to UTF-16 code units. | ||
* @returns A list of UTF-16 code units (`U16`) representing the string. | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const inputString = "Hello, π" | ||
* const utf16List = stringToList(inputString) | ||
* ``` | ||
*/ | ||
export const stringToList = (s) => { | ||
@@ -66,6 +304,53 @@ const at = (i) => { | ||
}; | ||
/** | ||
* Converts a string to a list of Unicode code points (CodePoint). | ||
* This function first converts the string to a list of UTF-16 code units (U16) using `stringToList`, | ||
* then it converts the UTF-16 code units to Unicode code points using `toCodePointList`. This is useful for handling | ||
* Unicode characters, including supplementary characters represented by surrogate pairs in UTF-16. | ||
* | ||
* @param input - The input string to convert. | ||
* @returns A list of Unicode code points (`CodePoint`) corresponding to the characters in the string. | ||
* | ||
* @example | ||
* | ||
* ```js | ||
* const inputString = "Hello, π" | ||
* const codePoints = stringToCodePointList(inputString) | ||
* ``` | ||
*/ | ||
export const stringToCodePointList = (input) => toCodePointList(stringToList(input)); | ||
/** | ||
* Converts a list of UTF-16 code units (U16) to a string. | ||
* This function takes a list of `U16` values (UTF-16 code units) and reconstructs the original string by mapping | ||
* each code unit back to its character using `String.fromCharCode`. The resulting characters are concatenated | ||
* to form the final string. | ||
* | ||
* @param input - A list of UTF-16 code units (`U16`). | ||
* @returns A string representing the characters encoded by the input UTF-16 code units. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const utf16List: List<U16> = [0x0041, 0x0042, 0x0043] // 'ABC' | ||
* const outputString = listToString(utf16List) | ||
* ``` | ||
*/ | ||
export const listToString = fn(map(String.fromCharCode)) | ||
.then(reduce(concat)('')) | ||
.result; | ||
/** | ||
* Converts a list of Unicode code points (CodePoint) to a string. | ||
* This function first converts the list of Unicode code points to a list of UTF-16 code units using `fromCodePointList`, | ||
* then it uses `listToString` to reconstruct the string from the UTF-16 code units. | ||
* | ||
* @param input - A list of Unicode code points (`CodePoint`). | ||
* @returns A string representing the characters encoded by the input code points. | ||
* | ||
* @example | ||
* | ||
* ```ts | ||
* const codePoints: List<CodePoint> = [0x48, 0x65, 0x6C, 0x6C, 0x6F] | ||
* const outputString = codePointListToString(codePoints) | ||
* ``` | ||
*/ | ||
export const codePointListToString = (input) => listToString(fromCodePointList(input)); |
@@ -5,3 +5,7 @@ declare const _default: { | ||
string: (() => void)[]; | ||
stringToList: (() => void)[]; | ||
listToString: (() => void)[]; | ||
stringToCodePointList: (() => void)[]; | ||
codePointListToString: (() => void)[]; | ||
}; | ||
export default _default; |
@@ -149,3 +149,31 @@ import { toCodePointList, fromCodePointList, stringToList, listToString, stringToCodePointList, codePointListToString } from "./module.f.js"; | ||
} | ||
], | ||
stringToList: [ | ||
() => { | ||
const inputString = "Hello, i like js"; | ||
const utf16List = stringToList(inputString); | ||
}, | ||
() => { | ||
const inputString = "ππ€¬π«₯ππ« "; | ||
const utf16List = stringToList(inputString); | ||
} | ||
], | ||
listToString: [ | ||
() => { | ||
const utf16List = [0x0041, 0x0042, 0x0043]; | ||
const outputString = listToString(utf16List); | ||
} | ||
], | ||
stringToCodePointList: [ | ||
() => { | ||
const inputString = "Hello, π"; | ||
const codePoints = stringToCodePointList(inputString); | ||
} | ||
], | ||
codePointListToString: [ | ||
() => { | ||
const codePoints = [0x48, 0x65, 0x6C, 0x6C, 0x6F]; | ||
const outputString = codePointListToString(codePoints); | ||
} | ||
] | ||
}; |
@@ -1,2 +0,2 @@ | ||
import type { Reduce } from "../function/operator/module.f.ts"; | ||
import type { Reduce } from '../function/operator/module.f.ts'; | ||
/** | ||
@@ -55,2 +55,4 @@ * Represents a monoid, an algebraic structure with a binary operation | ||
* | ||
* See also {@link https://en.wikipedia.org/wiki/Exponentiation_by_squaring}. | ||
* | ||
* @example | ||
@@ -57,0 +59,0 @@ * |
@@ -10,2 +10,4 @@ /** | ||
* | ||
* See also {@link https://en.wikipedia.org/wiki/Exponentiation_by_squaring}. | ||
* | ||
* @example | ||
@@ -12,0 +14,0 @@ * |
@@ -11,1 +11,19 @@ import { type List } from '../list/module.f.ts'; | ||
export declare const fromMap: <T>(m: BtMap<T>) => Map<T>; | ||
/** | ||
* A set of objects with a single key. | ||
* | ||
* See also | ||
* https://stackoverflow.com/questions/57571664/typescript-type-for-an-object-with-only-one-key-no-union-type-allowed-as-a-key | ||
*/ | ||
export type OneKey<K extends string, V> = { | ||
[P in K]: (Record<P, V> & Partial<Record<Exclude<K, P>, never>>) extends infer O ? { | ||
[Q in keyof O]: O[Q]; | ||
} : never; | ||
}[K]; | ||
/** | ||
* https://stackoverflow.com/questions/61112584/typing-a-single-record-entry | ||
*/ | ||
export type NotUnion<T, U = T> = T extends unknown ? [ | ||
U | ||
] extends [T] ? T : never : never; | ||
export type SingleProperty<T extends Record<string, never>> = keyof T extends NotUnion<keyof T> ? T : never; |
@@ -6,3 +6,3 @@ import { iterable } from "../list/module.f.js"; | ||
const r = getOwnPropertyDescriptor(object, name); | ||
return r === void 0 ? null : r.value; | ||
return r === undefined ? null : r.value; | ||
}; | ||
@@ -9,0 +9,0 @@ export const sort = e => mapEntries(mapFromEntries(e)); |
607434
7.28%249
10.67%17328
6.9%