summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-02-28 14:59:28 -0500
committersimponic <elizabeth.hunt@simponic.xyz>2024-02-28 14:59:28 -0500
commit7cc3ef5fa1feec8087618c899441a11052f84c48 (patch)
tree6d65d585fcf61e9cee7193dfb2af4d719074f732 /test
parentc8336ee48791f00378a35e463e2962f4c856beb2 (diff)
downloadcps-interpreter-7cc3ef5fa1feec8087618c899441a11052f84c48.tar.gz
cps-interpreter-7cc3ef5fa1feec8087618c899441a11052f84c48.zip
builtin_match_signatures (#1)
Co-authored-by: Lizzy Hunt <lizzy.hunt@usu.edu> Reviewed-on: https://git.simponic.xyz/simponic/cps-interpreter/pulls/1 Co-authored-by: Elizabeth Hunt <elizabeth.hunt@simponic.xyz> Co-committed-by: Elizabeth Hunt <elizabeth.hunt@simponic.xyz>
Diffstat (limited to 'test')
-rw-r--r--test/interpreter.spec.ts35
-rw-r--r--test/parser.spec.ts42
-rw-r--r--test/programs/add-1-3.cps3
-rw-r--r--test/programs/index.ts9
-rw-r--r--test/programs/primop-scope.cps5
-rw-r--r--test/programs/string-equal.cps1
-rw-r--r--test/programs/string-unequal.cps1
-rw-r--r--test/signature_match.spec.ts160
8 files changed, 252 insertions, 4 deletions
diff --git a/test/interpreter.spec.ts b/test/interpreter.spec.ts
new file mode 100644
index 0000000..fa74ef0
--- /dev/null
+++ b/test/interpreter.spec.ts
@@ -0,0 +1,35 @@
+import { expect, test } from 'bun:test';
+import { TestPrograms } from './programs';
+import { peggyParse } from '@/parser';
+import { evaluate } from '@/interpreter';
+import { testingLogger } from './logger';
+
+test('Add (1 real) and (3 int) => (4 real)', async () => {
+ const ast = peggyParse(await TestPrograms.AddOneThree);
+
+ const result = await evaluate(ast, testingLogger);
+ expect(result).toEqual({ type: 'real', value: 4 });
+});
+
+test('Add (1 real) and (3 int) -> result => (real 1 - result) = -3 done with correct lexical scope', async () => {
+ const ast = peggyParse(await TestPrograms.PrimopScope);
+
+ const result = await evaluate(ast, testingLogger);
+ expect(result).toEqual({ type: 'real', value: -3 });
+});
+
+/*
+test('String equality', async () => {
+ const ast = peggyParse(await TestPrograms.StringEquality);
+
+ const result = await evaluate(ast, testingLogger);
+ expect(result).toEqual({ type: 'int', value: 1 });
+});
+
+test('String inequality', async () => {
+ const ast = peggyParse(await TestPrograms.StringInEquality);
+
+ const result = await evaluate(ast, testingLogger);
+ expect(result).toEqual({ type: 'int', value: 0 });
+});
+*/
diff --git a/test/parser.spec.ts b/test/parser.spec.ts
index e174383..07353b8 100644
--- a/test/parser.spec.ts
+++ b/test/parser.spec.ts
@@ -2,6 +2,44 @@ import { expect, test } from 'bun:test';
import { TestPrograms } from './programs';
import { peggyParse } from '@/parser';
-test('Primitive Operations', async () => {
- const ast = peggyParse(await TestPrograms.AddOneThree);
+test('primitive operation', async () => {
+ const [operation] = peggyParse(await TestPrograms.AddOneThree);
+ const { primitiveOperation } = operation;
+
+ expect(primitiveOperation).toEqual({
+ opr: '+',
+ operands: [{ real: 1 }, { int: 3 }],
+ resultBindings: [{ name: 'result' }],
+ continuations: [],
+ });
+});
+
+test('primitive operation with continuation', async () => {
+ const [operation] = peggyParse(await TestPrograms.PrimopScope);
+ const { primitiveOperation } = operation;
+
+ const continuation = {
+ primitiveOperation: {
+ opr: '-',
+ operands: [{ real: 1 }, { name: 'result' }],
+ resultBindings: [{ name: 'result' }],
+ continuations: [
+ {
+ primitiveOperation: {
+ opr: '+',
+ operands: [{ name: 'result' }, { real: 0 }],
+ resultBindings: [],
+ continuations: [],
+ },
+ },
+ ],
+ },
+ };
+
+ expect(primitiveOperation).toEqual({
+ opr: '+',
+ operands: [{ real: 1 }, { int: 3 }],
+ resultBindings: [{ name: 'result' }],
+ continuations: [continuation],
+ });
});
diff --git a/test/programs/add-1-3.cps b/test/programs/add-1-3.cps
index 95b9939..66759f7 100644
--- a/test/programs/add-1-3.cps
+++ b/test/programs/add-1-3.cps
@@ -1,2 +1 @@
-PRIMOP(+, [INT 1, INT 2], [u],
- [APP(LABEL identity, [VAR u])]) \ No newline at end of file
+PRIMOP(+, [REAL 1.0, INT 3], [result], []) \ No newline at end of file
diff --git a/test/programs/index.ts b/test/programs/index.ts
index e0403fd..c8f3c85 100644
--- a/test/programs/index.ts
+++ b/test/programs/index.ts
@@ -4,4 +4,13 @@ export namespace TestPrograms {
export const AddOneThree = Bun.file(
join(import.meta.dir + '/add-1-3.cps'),
).text();
+ export const PrimopScope = Bun.file(
+ join(import.meta.dir + '/primop-scope.cps'),
+ ).text();
+ export const StringEquality = Bun.file(
+ join(import.meta.dir + '/string-equal.cps'),
+ ).text();
+ export const StringInEquality = Bun.file(
+ join(import.meta.dir + '/string-unequal.cps'),
+ ).text();
}
diff --git a/test/programs/primop-scope.cps b/test/programs/primop-scope.cps
new file mode 100644
index 0000000..eb834fd
--- /dev/null
+++ b/test/programs/primop-scope.cps
@@ -0,0 +1,5 @@
+PRIMOP(+, [REAL 1.0, INT 3], [result], [
+ PRIMOP(-, [REAL 1.0, VAR result], [result], [
+ PRIMOP(+, [VAR result, REAL 0], [], [])
+ ])
+]) \ No newline at end of file
diff --git a/test/programs/string-equal.cps b/test/programs/string-equal.cps
new file mode 100644
index 0000000..ea49b22
--- /dev/null
+++ b/test/programs/string-equal.cps
@@ -0,0 +1 @@
+PRIMOP(==, ["asdf", "asdf"], [result], []) \ No newline at end of file
diff --git a/test/programs/string-unequal.cps b/test/programs/string-unequal.cps
new file mode 100644
index 0000000..ccd278e
--- /dev/null
+++ b/test/programs/string-unequal.cps
@@ -0,0 +1 @@
+PRIMOP(==, ["asdfasdf", "asdf"], [result], [])
diff --git a/test/signature_match.spec.ts b/test/signature_match.spec.ts
new file mode 100644
index 0000000..10be880
--- /dev/null
+++ b/test/signature_match.spec.ts
@@ -0,0 +1,160 @@
+import { expect, test } from 'bun:test';
+import { TestPrograms } from './programs';
+import { peggyParse } from '@/parser';
+import {
+ evaluate,
+ type DenotableFunctionSignature,
+ denotableTypesEquivalent,
+ matchSignature,
+} from '@/interpreter';
+import { testingLogger } from './logger';
+
+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();
+});