diff options
Diffstat (limited to 'src/interpreter/denotable.ts')
-rw-r--r-- | src/interpreter/denotable.ts | 93 |
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]); + }); + }); +}; |