Skip to content

Instantly share code, notes, and snippets.

@al6x
Last active December 24, 2024 11:34
Show Gist options
  • Save al6x/8315d1036fe89366303229a630b94d03 to your computer and use it in GitHub Desktop.
Save al6x/8315d1036fe89366303229a630b94d03 to your computer and use it in GitHub Desktop.
import './mfun'
declare global {
function fsize<T>(a: T[]): number
function fempty7<T>(a: T[]): boolean
}
mfun(Array, function fsize<T>(a: T[]): number { return a.length })
mfun(Array, function fempty7<T>(a: T[]): boolean { return a.length == 0 })
import './mfun'
import './object'
import './array'
import './undefined'
console.log(fsize([1, 2, 3]))
console.log(fsize({ a: 1 }))
console.log(fempty7([1, 2, 3]))
console.log(fempty7({ a: 1 }))
console.log(fempty7(undefined))
declare global {
function mfun<T extends Function>(types: Type | [Type, Type], method: T): T
}
export type Primitive = string | number | boolean | null | undefined
export type Klass = { new(...args: any[]): any }
export type Type = Primitive | Klass
globalThis.mfun = function mfun<T extends Function>(types: Type | [Type, Type], method: T): T {
const [t1, t2] = Array.isArray(types) ? [ftype_id(types[0]), ftype_id(types[0])] : [ftype_id(types), 0]
const fname = method.name
if (!fname) throw new Error('Method must have a name')
;((fns_table[t1] ??= [])[t2] ??= {})[fname] = method
function dispatch(): any {
const mfuns = fns_table[finstance_type_id(arguments[0])]?.[finstance_type_id(arguments[1])]
if (!mfuns) throw new Error(`No methods for [${arguments[0]}, ${arguments[1]}]`)
const method = mfuns[fname]
if (!method) throw new Error(`No method for [${arguments[0]}, ${arguments[1]}] ${fname}`)
return method.apply(null, arguments)
}
fns[fname] = dispatch
return dispatch as any
}
const fns = globalThis as any as Record<string, Function>
const fns_table: Record<string, Function>[][] = []
function finstance_type_id(o: any): number {
if (o === undefined) return 0
if (o === null) return 1
return o.constructor[type_id_property] ??= type_counter++
}
function ftype_id(klass: any): number {
return klass[type_id_property] ??= type_counter++
}
const type_id_property = Symbol('type_id'); let type_counter = 2
;[
Boolean, Number, BigInt, String, Array, RegExp, Function, Date, Error, Map, Set,
Symbol, WeakMap, WeakSet, ArrayBuffer,
Object // Must be last
]
.forEach((klass: any) => klass[type_id_property] = type_counter++)
import './mfun'
declare global {
function fsize(o: Record<string, any>): number
function fempty7(o: Record<string, any>): boolean
}
mfun(Object, function fsize(o: Record<string, any>): number {
let i = 0; for (let _ in o) if (o.hasOwnProperty(_)) i++; return i
})
mfun(Object, function fempty7(o: Record<string, any>): boolean {
for (let _ in o) return false
return true
})
import './mfun'
declare global {
function fempty7(a: undefined): boolean
}
mfun(Array, function fempty7<T>(a: undefined): boolean { return true })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment