summaryrefslogtreecommitdiff
path: root/src/interpreter/interpreter.ts
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 /src/interpreter/interpreter.ts
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 'src/interpreter/interpreter.ts')
-rw-r--r--src/interpreter/interpreter.ts124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/interpreter/interpreter.ts b/src/interpreter/interpreter.ts
new file mode 100644
index 0000000..ebd605c
--- /dev/null
+++ b/src/interpreter/interpreter.ts
@@ -0,0 +1,124 @@
+import {
+ type ContinuationExpression,
+ type PrimitiveOperationExpression,
+ type Program,
+ type Value,
+} from '@/parser';
+import { Environment, type Denotable } from '.';
+import {
+ BadArgumentError,
+ InvalidStateError,
+ NotImplementedError,
+ type TracingLogger,
+} from '@/utils';
+import { putBuiltinsOnEnvironemtn } from './builtins';
+
+const evaluateValue = (
+ value: Value,
+ env: Environment,
+ logger: TracingLogger,
+): Denotable => {
+ if (typeof value === 'string') {
+ return { type: 'string', value };
+ }
+
+ if ('real' in value) {
+ return { type: 'real', value: value.real };
+ }
+ if ('int' in value) {
+ return { type: 'int', value: value.int };
+ }
+ if ('name' in value) {
+ logger.debug(`Evaluating variable: ${value.name}`);
+ return env.get(value.name);
+ }
+
+ throw new InvalidStateError(`Invalid value: ${value}`);
+};
+
+const evaluatePrimitiveOperation = (
+ { primitiveOperation }: PrimitiveOperationExpression,
+ env: Environment,
+ logger: TracingLogger,
+) => {
+ const { opr, operands, resultBindings, continuations } = primitiveOperation;
+ if (operands.length !== 2) {
+ throw new BadArgumentError('Primitive operations must have 2 operands');
+ }
+
+ const operandValues = operands.map(operand =>
+ evaluateValue(operand, env, logger.createChild('evaluteValue')),
+ );
+
+ const result = env.apply(opr, operandValues);
+ const continuationEnvironment = env.createChild();
+ for (const { name } of resultBindings) {
+ continuationEnvironment.set(name, result);
+ }
+
+ // return the result of the last continuation
+ return continuations.reduce((_, continuation, i) => {
+ const childLogger = logger.createChild(`continuation[${i}]`);
+ return evaluteContinuationExpression(
+ continuation,
+ continuationEnvironment,
+ childLogger,
+ );
+ }, result);
+};
+
+const evaluteContinuationExpression = (
+ expr: ContinuationExpression,
+ env: Environment,
+ logger: TracingLogger,
+): Denotable => {
+ if ('primitiveOperation' in expr) {
+ logger.debug('Evaluating primitive operation');
+ return evaluatePrimitiveOperation(
+ expr,
+ env,
+ logger.createChild('evaluatePrimitiveOperation'),
+ );
+ }
+
+ if ('record' in expr) {
+ throw new NotImplementedError('Continuation records are not supported yet');
+ }
+ if ('select' in expr) {
+ throw new NotImplementedError('Continuation select is not supported yet');
+ }
+ if ('offset' in expr) {
+ throw new NotImplementedError('Continuation offset is not supported yet');
+ }
+ if ('application' in expr) {
+ throw new NotImplementedError(
+ 'Continuation application is not supported yet',
+ );
+ }
+ if ('switch' in expr) {
+ throw new NotImplementedError('Continuation switch is not supported yet');
+ }
+ if ('fix' in expr) {
+ throw new NotImplementedError('Continuation fix is not supported yet');
+ }
+
+ throw new InvalidStateError(`Invalid continuation expression: ${expr}`);
+};
+
+export const evaluate = async (
+ ast: Program,
+ logger: TracingLogger,
+): Promise<Denotable> => {
+ const globalEnvironment = putBuiltinsOnEnvironemtn(
+ new Environment(logger.createChild('RootEnv')),
+ );
+
+ return ast.reduce((_, continuation, i) => {
+ const exprLogger = logger.createChild(`statement[${i}]`);
+ return evaluteContinuationExpression(
+ continuation as ContinuationExpression,
+ globalEnvironment,
+ exprLogger,
+ );
+ }, null);
+};