2024-03-05 14:28:28 -07:00

94 lines
2.1 KiB
TypeScript

import type { Identifier } from '@/parser';
export type UnionDenotableType =
| Array<DenotableType | DenotableFunctionSignature>
| DenotableType
| DenotableFunctionSignature
| Array<UnionDenotableType>;
export type DenotableFunctionSignature = {
arguments: Array<UnionDenotableType>;
return: DenotableType;
};
export type DenotableFunction = {
signatures: Array<DenotableFunctionSignature>;
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<UnionDenotableType>,
signatures: Array<DenotableFunctionSignature>,
): 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]);
});
});
};