import assign from "lodash/assign"; import { Type } from "../core/compilation/types"; import { encode } from "he"; export type Mutable = { -readonly [P in keyof T]: T[P] }; export function asMutable(obj: T) : Mutable { return >obj; } // https://github.com/microsoft/TypeScript/issues/5101 export function isInstance(ctor: new(...args: any[]) => T): (x: any) => x is T { return <(x: any) => x is T>(x => x instanceof ctor); } export function assert(condition: any, message: string = "") : asserts condition { if (!condition) { throw Error("Assert failed: " + message); } }; export function assertFalse(message: string = "") : never { throw Error("Assert failed: " + message); }; // https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking export function assertNever(x: never): never { throw new Error("Unexpected object: " + x); } export function createMethodMixin(mix: TargetType[MethodName]) { return (targetProto: TargetType, name: MethodName) => { targetProto[name] = mix; } } export type Constructor = new (...args: any[]) => T; export type Overwrite = Pick> & T2; // https://stackoverflow.com/questions/50125893/typescript-derive-map-from-discriminated-union export type DiscriminateUnion = T extends Record ? T : never; export type MapDiscriminatedUnion, K extends keyof T> = { [V in T[K]]: DiscriminateUnion }; export function htmlDecoratedOperator(operator: string, cssClass: string) { return "" + encode(operator) + ""; }; export function htmlDecoratedKeyword(keyword: string){ return '' + encode(keyword) + ''; }; export function htmlDecoratedType(type: string) { return '' + encode(type) + ''; }; export function htmlDecoratedName(name: string, type?: Type) { if (type) { return '' + encode(type.englishString(false)) + '' + name + ''; } else { return '' + encode(name) + ''; } }; export function htmlDecoratedValue(value: string){ return '' + encode(value) + ''; }; export function htmlDecoratedObject(value: string){ return '' + encode(value) + ''; }; var escapes = ["\\\"", "\\'", "\\?", "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v", "\\0"]; var escaped = ["\"", "\'", "", "\\", "", "\b", "\f", "\n", "\r", "\t", "\v", "\0"]; export function escapeString(text: string) { for (var i = 0; i < escapes.length; ++i) { // text = text.replace(escapes[i], escaped[i]); //! requires ES 2021 // text = text.replaceAll(escapes[i], escaped[i]); while (text.includes(escapes[i])) { text = text.replace(escapes[i], escaped[i]); } } return text; } export function unescapeString(text: string){ var newStr = ""; for(var i = 0; i < text.length; ++i){ var c = text[i]; for(var j = 0; j < escaped.length; ++j){ if (c === escaped[j]){ c = escapes[j]; break; } } newStr += c; } return newStr; }; export class CPPRandom { private seed: number; public constructor(seed: number = 0) { this.seed = seed; } public setRandomSeed(newSeed: number) { this.seed = newSeed; } public random(min: number = 0, max: number = 1) { this.seed = (this.seed * 9301 + 49297) % 233280; return this.seededRandom(this.seed, min, max); } public randomInteger(min: number, max: number) { return Math.floor(this.random(min, max)); } public seededRandom(seed: number, min: number = 0, max: number = 1) { var rnd = seed % 233280 / 233280; rnd = min + rnd * (max - min); rnd = Math.max(min, Math.min(max, rnd)); return rnd; } }