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