summaryrefslogtreecommitdiff
path: root/src/interpreter/interpreter.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpreter/interpreter.ts')
-rw-r--r--src/interpreter/interpreter.ts103
1 files changed, 100 insertions, 3 deletions
diff --git a/src/interpreter/interpreter.ts b/src/interpreter/interpreter.ts
index 7a49f7d..cfbb042 100644
--- a/src/interpreter/interpreter.ts
+++ b/src/interpreter/interpreter.ts
@@ -2,13 +2,17 @@ import {
type ContinuationExpression,
type PrimitiveOperationExpression,
type ApplicationExpression,
+ type RecordExpression,
type Program,
type Value,
+ type RecordExpressionTuple,
+ type SelectExpression,
} from '@/parser';
-import { Environment, type Denotable } from '.';
+import { Environment, type Denotable, type DenotableRecord } from '.';
import {
BadArgumentError,
InvalidStateError,
+ InvalidType,
NotImplementedError,
type TracingLogger,
} from '@/utils';
@@ -112,6 +116,89 @@ const evaluatePrimitiveOperation = (
);
};
+export const evaluateRecordTuple = (
+ tuple: RecordExpressionTuple,
+ env: Environment,
+ logger: TracingLogger,
+): Denotable => {
+ const { value, accessPath } = tuple;
+ const record = evaluateValue(value, env, logger.createChild('evaluateValue'));
+ if (record.type === 'record') {
+ // TODO: Implement nested records at accessPath
+ logger.debug(JSON.stringify(accessPath, null, 2));
+ throw new NotImplementedError('Nested records are not yet supported');
+ }
+
+ return record;
+};
+
+export const evaluateRecordExpression = (
+ { record }: RecordExpression,
+ env: Environment,
+ logger: TracingLogger,
+): Denotable => {
+ const {
+ records,
+ address: { name: address },
+ body,
+ } = record;
+
+ const childEnv = env.createChild();
+ const recordTuple = records.map(record =>
+ evaluateRecordTuple(
+ record,
+ childEnv,
+ logger.createChild('evaluateRecordTuple'),
+ ),
+ );
+ const length = recordTuple.length;
+
+ childEnv.set(address, {
+ type: 'record',
+ value: { length, record: recordTuple },
+ });
+
+ return evaluteContinuationExpression(
+ body,
+ childEnv,
+ logger.createChild('evaluteContinuationExpression'),
+ );
+};
+
+export const evaluateSelectExpression = (
+ { select }: SelectExpression,
+ env: Environment,
+ logger: TracingLogger,
+): Denotable => {
+ const {
+ index: { int: index },
+ record,
+ bind,
+ continuation,
+ } = select;
+ const childEnv = env.createChild();
+
+ const recordValue = evaluateValue(
+ record,
+ env,
+ logger.createChild('evaluateValue'),
+ );
+ if (recordValue.type !== 'record') {
+ throw new InvalidType('Expected record type');
+ }
+
+ const { value } = recordValue as { value: DenotableRecord };
+
+ const selected = value.record[index];
+ childEnv.set(bind.name, selected);
+
+ return evaluteContinuationExpression(
+ continuation,
+ childEnv,
+ logger.createChild('evaluteContinuationExpression'),
+ );
+};
+
const evaluteContinuationExpression = (
expr: ContinuationExpression,
env: Environment,
@@ -136,10 +223,20 @@ const evaluteContinuationExpression = (
}
if ('record' in expr) {
- throw new NotImplementedError('Continuation records are not supported yet');
+ logger.debug('Evaluating record');
+ return evaluateRecordExpression(
+ expr,
+ env,
+ logger.createChild('evaluateRecordExpression'),
+ );
}
if ('select' in expr) {
- throw new NotImplementedError('Continuation select is not supported yet');
+ logger.debug('Evaluating select');
+ return evaluateSelectExpression(
+ expr,
+ env,
+ logger.createChild('evaluateSelectExpression'),
+ );
}
if ('offset' in expr) {
throw new NotImplementedError('Continuation offset is not supported yet');