summaryrefslogtreecommitdiff
path: root/src/interpreter/denotable.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpreter/denotable.ts')
-rw-r--r--src/interpreter/denotable.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/interpreter/denotable.ts b/src/interpreter/denotable.ts
new file mode 100644
index 0000000..65aee86
--- /dev/null
+++ b/src/interpreter/denotable.ts
@@ -0,0 +1,93 @@
+import type { Identifier } from '@/parser';
+import { testingLogger } from '@t/logger';
+
+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'
+ | '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]);
+ });
+ });
+};