import type { Identifier } from '@/parser'; export type UnionDenotableType = | Array | DenotableType | DenotableFunctionSignature | Array; export type DenotableFunctionSignature = { arguments: Array; return: DenotableType; }; export type DenotableFunction = { signatures: Array; body: Function; }; export type DenotableType = | 'null' | 'int' | 'real' | 'bool' | 'string' | 'bytearray' | 'function' | 'reference'; export type DenotableValue = | null | number | string | Uint8Array | DenotableFunction | Identifier; export type Denotable = { type: DenotableType; value: DenotableValue; }; export const denotableTypesEquivalent = ( a: UnionDenotableType, b: UnionDenotableType, ): boolean => { if (typeof a !== typeof b) return false; if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (!denotableTypesEquivalent(a[i], b[i])) return false; } return true; } if ( typeof a === 'object' && typeof b === 'object' && 'arguments' in a && 'arguments' in b ) { if (a.arguments.length !== b.arguments.length) return false; if (!denotableTypesEquivalent(a.return, b.return)) return false; for (let i = 0; i < a.arguments.length; i++) { if (!denotableTypesEquivalent(a.arguments[i], b.arguments[i])) { return false; } } return true; } if (a === b) return true; return false; }; export const matchSignature = ( args: Array, signatures: Array, ): DenotableFunctionSignature | undefined => { return signatures.find(signature => { if (args.length !== signature.arguments.length) return false; return args.every((arg, i) => { const argSignature = signature.arguments[i]; if (Array.isArray(argSignature)) { return argSignature.some(a => denotableTypesEquivalent(a, arg)); } return denotableTypesEquivalent(arg, signature.arguments[i]); }); }); };