import { expect, test } from 'bun:test'; import { type DenotableFunctionSignature, denotableTypesEquivalent, matchSignature, } from '@/interpreter'; test('simple denotable types are equivalent', () => { expect(denotableTypesEquivalent('int', 'int')).toBe(true); expect(denotableTypesEquivalent('int', 'real')).toBe(false); expect(denotableTypesEquivalent('int', 'null')).toBe(false); expect(denotableTypesEquivalent('null', 'null')).toBe(true); }); test('union data types are equivalent', () => { expect(denotableTypesEquivalent(['int', 'real'], ['int', 'real'])).toBe(true); expect(denotableTypesEquivalent('int', ['int', 'real'])).toBe(false); }); test('function data types are equivalent', () => { expect( denotableTypesEquivalent( [ { arguments: ['int', 'real'], return: 'int', }, ], [ { arguments: ['int', 'real'], return: 'int', }, ], ), ).toBe(true); expect( denotableTypesEquivalent( [ { arguments: ['int', 'real'], return: 'real', }, ], [ { arguments: ['int', 'real'], return: 'int', }, ], ), ).toBe(false); }); test('matches simple signatures', async () => { const simpleSignature: DenotableFunctionSignature[] = [ { arguments: ['int'], return: 'int', }, ]; expect(matchSignature(['int'], simpleSignature)).toEqual(simpleSignature[0]); }); test('finds first match', async () => { const simpleSignature: DenotableFunctionSignature[] = [ { arguments: ['int', 'int'], return: 'int', }, { arguments: [['int', 'real'], 'int'], return: 'real', }, ]; expect(matchSignature(['int', 'int'], simpleSignature)).toEqual( simpleSignature[0], ); expect(matchSignature(['real', 'int'], simpleSignature)).toEqual( simpleSignature[1], ); }); test('finds first match with a function signature', async () => { const testSignature: DenotableFunctionSignature = { arguments: ['int', 'real'], return: 'int', }; const simpleSignature: DenotableFunctionSignature[] = [ { arguments: ['int', 'int'], return: 'int', }, { arguments: [[testSignature, 'real'], 'int'], return: 'function', }, ]; expect(matchSignature(['int', 'int'], simpleSignature)).toEqual( simpleSignature[0], ); expect(matchSignature(['real', 'int'], simpleSignature)).toEqual( simpleSignature[1], ); expect(matchSignature([testSignature, 'int'], simpleSignature)).toEqual( simpleSignature[1], ); }); test('finds first match with a function with many signatures', async () => { const testSignature: DenotableFunctionSignature[] = [ { arguments: ['int', 'real'], return: 'int', }, { arguments: ['int', 'int'], return: 'int', }, ]; const simpleSignature: DenotableFunctionSignature[] = [ { arguments: ['int', 'int'], return: 'int', }, { arguments: [[testSignature, 'real'], 'int'], return: 'function', }, ]; expect(matchSignature(['int', 'int'], simpleSignature)).toEqual( simpleSignature[0], ); expect(matchSignature(['real', 'int'], simpleSignature)).toEqual( simpleSignature[1], ); expect(matchSignature([testSignature, 'int'], simpleSignature)).toEqual( simpleSignature[1], ); expect( matchSignature([[testSignature[0]], 'int'], simpleSignature), ).toBeUndefined(); });