94 lines
2.1 KiB
TypeScript
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]);
|
|
});
|
|
});
|
|
};
|