summaryrefslogtreecommitdiff
path: root/src/interpreter/builtins.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpreter/builtins.ts')
-rw-r--r--src/interpreter/builtins.ts106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/interpreter/builtins.ts b/src/interpreter/builtins.ts
new file mode 100644
index 0000000..200131f
--- /dev/null
+++ b/src/interpreter/builtins.ts
@@ -0,0 +1,106 @@
+import {
+ type DenotableFunctionSignature,
+ Environment,
+ type Denotable,
+} from '.';
+
+const addUnaryIntegerOperationsTo = (env: Environment) => {
+ const unaryIntegerOperationSignatures: DenotableFunctionSignature[] = [
+ {
+ arguments: ['int'],
+ return: 'int',
+ },
+ ];
+
+ for (const { name, fn } of [
+ { name: '~', fn: (a: number) => ~a },
+ { name: '!', fn: (a: number) => (!a ? 1 : 0) },
+ ]) {
+ env.set(name, {
+ type: 'function',
+ value: {
+ signatures: unaryIntegerOperationSignatures,
+ body: ({ value }: Denotable) => fn(value as number),
+ },
+ });
+ }
+
+ return env;
+};
+
+const addBinaryIntegerOperationsTo = (env: Environment) => {
+ const binaryIntegerOperationSignatures: DenotableFunctionSignature[] = [
+ {
+ arguments: ['int', 'int'],
+ return: 'int',
+ },
+ ];
+
+ for (const { name, fn } of [
+ { name: '%', fn: (a: number, b: number) => a % b },
+ { name: '>>', fn: (a: number, b: number) => a >> b },
+ { name: '<<', fn: (a: number, b: number) => a << b },
+ { name: '|', fn: (a: number, b: number) => a | b },
+ { name: '^', fn: (a: number, b: number) => a ^ b },
+ { name: '&&', fn: (a: number, b: number) => (a && b ? 1 : 0) },
+ { name: '<=', fn: (a: number, b: number) => (a <= b ? 1 : 0) },
+ { name: '<', fn: (a: number, b: number) => (a < b ? 1 : 0) },
+ { name: '>', fn: (a: number, b: number) => (a > b ? 1 : 0) },
+ { name: '>=', fn: (a: number, b: number) => (a >= b ? 1 : 0) },
+ { name: '||', fn: (a: number, b: number) => (a || b ? 1 : 0) },
+ ]) {
+ env.set(name, {
+ type: 'function',
+ value: {
+ signatures: binaryIntegerOperationSignatures,
+ body: ({ value: a }: Denotable, { value: b }: Denotable) =>
+ fn(a as number, b as number),
+ },
+ });
+ }
+
+ return env;
+};
+
+const addBinaryArithmeticOperationsTo = (env: Environment) => {
+ const binaryArithmeticSignatures: DenotableFunctionSignature[] = [
+ {
+ arguments: ['int', 'int'],
+ return: 'int',
+ },
+ {
+ arguments: [
+ ['int', 'real'],
+ ['int', 'real'],
+ ],
+ return: 'real',
+ },
+ ];
+
+ for (const { name, fn } of [
+ { name: '+', fn: (a: number, b: number) => a + b },
+ { name: '-', fn: (a: number, b: number) => a - b },
+ { name: '*', fn: (a: number, b: number) => a * b },
+ { name: '/', fn: (a: number, b: number) => a / b },
+ { name: '**', fn: (a: number, b: number) => a ** b },
+ ]) {
+ env.set(name, {
+ type: 'function',
+ value: {
+ signatures: binaryArithmeticSignatures,
+ body: ({ value: a }: Denotable, { value: b }: Denotable) =>
+ fn(a as number, b as number),
+ },
+ });
+ }
+
+ return env;
+};
+
+export const putBuiltinsOnEnvironemtn = (env: Environment) => {
+ return [
+ addBinaryArithmeticOperationsTo,
+ addBinaryIntegerOperationsTo,
+ addUnaryIntegerOperationsTo,
+ ].reduce((acc, builtinsAdder) => builtinsAdder(acc), env);
+};