import { debug } from "./debug.js"; import { nat } from "./primitives.js"; import { AssertionFailed } from "./test.js"; export function freeze(x : V) : V { if (typeof x === "function") { Object.freeze(x.prototype); Object.freeze(x); } else { Object.freeze(x); } return x; } freeze(freeze); export function notImplemented() : never { throw new Error("not implemented yet"); } export function privateConstructor(name : string) : never { throw new Error("Private constructor of " + name + " cannot be called directly."); } export function internalError(msg? : string) : never { if (msg) throw new Error("Internal error: " + msg); else throw new Error("Internal error."); } export function force(value : V | undefined | null) : V { if (value === null || value === undefined) { if (value === null) throw new Error("value is null"); else throw new Error("value is undefined"); } return value; } freeze(force); export function isUnicodeLetter(c : string) : boolean { return RegExp(/^\p{L}$/u).test(c); } export function isDigit(c : string) : boolean { return c.length === 1 && c >= "0" && c <= "9"; } export function isUnicodeDigit(c : string) : boolean { return RegExp(/^\p{N}$/u).test(c); } export function isUnicodePunctuation(c : string) : boolean { return RegExp(/^\p{P}$/u).test(c); } export function isUnicodeDelimiterOpen(c : string) : boolean { return RegExp(/^\p{Ps}|\p{Pi}$/u).test(c); } export function isUnicodeDelimiterClose(c : string) : boolean { return RegExp(/^\p{Pe}|\p{Pf}$/u).test(c); } export function isUnicodeMathSymbol(c : string) : boolean { return RegExp(/^\p{Sm}$/u).test(c); } export function isUnicodeSpace(c : string) : boolean { return RegExp(/^\p{Zs}$/u).test(c); } export function groupBy(groupOf : (elem : E) => G, elems : Iterable) : [G, E[]][] { let groups : [G, E[]][] = []; let group : [G, E[]] | undefined = undefined; for (const e of elems) { const g = groupOf(e); if (group === undefined) { group = [g, [e]]; } else { if (group[0] === g) { group[1].push(e); } else { groups.push(group); group = [g, [e]]; } } } if (group !== undefined) groups.push(group); return groups; } export type Printer = (line : string) => void export function timeIt(label : string, op : () => R, print : Printer = debug) : R { const start_time = performance.now(); const result = op(); const end_time = performance.now(); const duration = Math.round((end_time - start_time) * 10000) / 10000; print("Performed '" + label + "' in " + duration + " milliseconds."); return result; } export function assertTrue(condition : boolean, message? : string) : asserts condition is true { if (condition !== true) throw new AssertionFailed(message); } export function assertFalse(condition : boolean, message? : string) : asserts condition is false { if (condition !== false) throw new AssertionFailed(message); } function addMessage(s : string, message? : string) { if (message === undefined) return s; else return s + ", " + message; } export function assertNever(value : never, message? : string) : never { throw new AssertionFailed(addMessage("unexpected value '" + value + "'", message)); } export function assertIsDefined(value : T, message? : string) : asserts value is NonNullable { if (value === undefined || value === null) throw new AssertionFailed(addMessage("undefined value", message)); } export type NotUndefined = T extends undefined ? never : T; export type Defined = Exclude; export function hexString(code : nat, minLength : nat = 0) : string { return code.toString(16).padStart(minLength, '0').toUpperCase(); }