diff options
Diffstat (limited to 'src/interpreter')
-rw-r--r-- | src/interpreter/denotable.ts | 10 | ||||
-rw-r--r-- | src/interpreter/interpreter.ts | 103 |
2 files changed, 108 insertions, 5 deletions
diff --git a/src/interpreter/denotable.ts b/src/interpreter/denotable.ts index 119cccf..ea1ddfb 100644 --- a/src/interpreter/denotable.ts +++ b/src/interpreter/denotable.ts @@ -22,9 +22,14 @@ export type DenotableType = | 'real' | 'bool' | 'string' + | 'record' | 'bytearray' - | 'function' - | 'reference'; + | 'function'; + +export type DenotableRecord = { + length: number; + record: Array<Denotable>; +}; export type DenotableValue = | null @@ -32,6 +37,7 @@ export type DenotableValue = | string | Uint8Array | DenotableFunction + | DenotableRecord | Identifier; export type Denotable = { 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'); |