2024-02-28 15:29:52 -07:00

258 lines
6.0 KiB
TypeScript

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 }]) {
env.set(name, {
type: 'function',
value: {
signatures: unaryIntegerOperationSignatures,
body: ({ value }: Denotable) => fn(value as number),
},
});
}
return env;
};
const addNumberComparisonOperationsTo = (env: Environment) => {
const comparisonOperationsSignatures: DenotableFunctionSignature[] = [
{
arguments: [
['real', 'int'],
['real', 'int'],
],
return: 'bool',
},
];
for (const { name, fn } of [
{ 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: comparisonOperationsSignatures,
body: ({ value: a }: Denotable, { value: b }: Denotable) =>
fn(a as number, b as number),
},
});
}
return env;
};
const addEqualityOperationsTo = (env: Environment) => {
const equalityOperationSignatures: DenotableFunctionSignature[] = [
{
arguments: ['int', 'int'],
return: 'bool',
},
{
arguments: ['real', 'real'],
return: 'bool',
},
{
arguments: ['bool', 'bool'],
return: 'bool',
},
{
arguments: ['string', 'string'],
return: 'bool',
},
];
for (const { name, fn } of [
{
name: '==',
fn: (a: number | string, b: number | string) => (a === b ? 1 : 0),
},
{
name: '!=',
fn: (a: number | string, b: number | string) => (a !== b ? 1 : 0),
},
]) {
env.set(name, {
type: 'function',
value: {
signatures: equalityOperationSignatures,
body: ({ value: a }: Denotable, { value: b }: Denotable) =>
fn(a as number | string, b as number | string),
},
});
}
return env;
};
const addBooleanAlgebraOperationsTo = (env: Environment) => {
const binaryBooleanOps: DenotableFunctionSignature[] = [
{
arguments: ['bool', 'bool'],
return: 'bool',
},
];
for (const { name, fn } of [
{ name: '||', fn: (a: number, b: number) => (a === 1 || b === 1 ? 1 : 0) },
{ name: '&&', fn: (a: number, b: number) => (a === 1 && b === 1 ? 1 : 0) },
]) {
env.set(name, {
type: 'function',
value: {
signatures: binaryBooleanOps,
body: ({ value: a }: Denotable, { value: b }: Denotable) =>
fn(a as number, b as number),
},
});
}
env.set('!', {
type: 'function',
value: {
signatures: [
{
arguments: ['bool'],
return: 'bool',
},
],
body: ({ value }: Denotable) => (value === 1 ? 0 : 1),
},
});
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 },
]) {
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;
};
const addIdentityFunctionTo = (env: Environment) => {
env.set('id', {
type: 'function',
value: {
signatures: [
{
arguments: ['null'],
return: 'null',
},
{
arguments: ['int'],
return: 'int',
},
{
arguments: ['real'],
return: 'real',
},
{
arguments: ['bool'],
return: 'bool',
},
{
arguments: ['string'],
return: 'string',
},
{
arguments: ['bytearray'],
return: 'bytearray',
},
{
arguments: ['function'],
return: 'function',
},
{
arguments: ['reference'],
return: 'reference',
},
],
body: ({ value }: Denotable) => value,
},
});
return env;
};
export const putBuiltinsOnEnvironemtn = (env: Environment) => {
return [
addBinaryArithmeticOperationsTo,
addBinaryIntegerOperationsTo,
addUnaryIntegerOperationsTo,
addNumberComparisonOperationsTo,
addBooleanAlgebraOperationsTo,
addEqualityOperationsTo,
addIdentityFunctionTo,
].reduce((acc, builtinsAdder) => builtinsAdder(acc), env);
};