import { todo } from "./util.ts"; // export type File = IdBase & { readonly _: unique symbol }; export type IdentId = IdBase & { readonly _: unique symbol }; export type AstId = IdBase & { readonly _: unique symbol }; export type DefId = IdBase & { readonly _: unique symbol }; // export type IdBase = { rawId: number }; export type IdRaw<IdType extends IdBase> = IdType["rawId"]; export const idRaw = <IdType extends IdBase>(id: IdType): IdRaw<IdType> => id.rawId; export const idFromRaw = <IdType extends IdBase>( rawId: IdRaw<IdType>, ): IdType => ({ rawId } as IdType); export class Ids<IdType extends IdBase> { private next = 0; public nextThenStep(): IdType { const rawId = this.next; this.next += 1; return idFromRaw(rawId); } } export class IdSet<Id extends IdBase> implements Set<Id> { private set = new Set<IdRaw<Id>>(); add(value: Id): this { this.set.add(idRaw(value)); return this; } clear(): void { this.set.clear(); } delete(value: Id): boolean { return this.set.delete(idRaw(value)); } forEach( callbackfn: (value: Id, value2: Id, set: Set<Id>) => void, thisArg?: unknown, ): void { this.set.forEach( (v1, v2) => callbackfn(idFromRaw(v1), idFromRaw(v2), this), thisArg, ); } has(value: Id): boolean { return this.set.has(idRaw(value)); } get size(): number { return this.set.size; } entries(): SetIterator<[Id, Id]> { return this.set.entries() .map(([v1, v2]) => [idFromRaw(v1), idFromRaw(v2)]); } keys(): SetIterator<Id> { return this.set.keys() .map((v) => idFromRaw(v)); } values(): SetIterator<Id> { return this.set.values() .map((v) => idFromRaw(v)); } union<U>(_other: ReadonlySetLike<U>): Set<Id | U> { return todo(); } intersection<U>(_other: ReadonlySetLike<U>): Set<Id & U> { return todo(); } difference<U>(_other: ReadonlySetLike<U>): Set<Id> { return todo(); } symmetricDifference<U>(_other: ReadonlySetLike<U>): Set<Id | U> { return todo(); } isSubsetOf(_other: ReadonlySetLike<unknown>): boolean { return todo(); } isSupersetOf(_other: ReadonlySetLike<unknown>): boolean { return todo(); } isDisjointFrom(_other: ReadonlySetLike<unknown>): boolean { return todo(); } [Symbol.iterator](): SetIterator<Id> { return this.set[Symbol.iterator]().map((v) => idFromRaw(v)); } get [Symbol.toStringTag](): string { return this.set[Symbol.toStringTag]; } } export class IdMap<Id extends IdBase, V> implements Map<Id, V> { private map = new Map<IdRaw<Id>, V>(); set(id: Id, val: V): this { this.map.set(idRaw(id), val); return this; } get(id: Id): V | undefined { return this.map.get(idRaw(id)); } has(id: Id): boolean { return this.map.has(idRaw(id)); } keys(): MapIterator<Id> { return this.map.keys() .map((rawId) => idFromRaw(rawId)); } clear(): void { this.map.clear(); } delete(id: Id): boolean { return this.map.delete(idRaw(id)); } forEach( callbackfn: (value: V, key: Id, map: Map<Id, V>) => void, thisArg?: unknown, ): void { this.map.forEach( (value, key, _map) => callbackfn(value, idFromRaw(key), this), thisArg, ); } get size(): number { return this.map.size; } entries(): MapIterator<[Id, V]> { return this.map.entries() .map(([rawId, v]) => [idFromRaw(rawId), v]); } values(): MapIterator<V> { return this.map.values(); } [Symbol.iterator](): MapIterator<[Id, V]> { return this.map[Symbol.iterator]() .map(([rawId, v]) => [idFromRaw(rawId), v]); } get [Symbol.toStringTag](): string { return this.map[Symbol.toStringTag]; } }