diff options
author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2024-02-28 14:59:28 -0500 |
---|---|---|
committer | simponic <elizabeth.hunt@simponic.xyz> | 2024-02-28 14:59:28 -0500 |
commit | 7cc3ef5fa1feec8087618c899441a11052f84c48 (patch) | |
tree | 6d65d585fcf61e9cee7193dfb2af4d719074f732 /src/interpreter/interpreter.ts | |
parent | c8336ee48791f00378a35e463e2962f4c856beb2 (diff) | |
download | cps-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.ts | 124 |
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); +}; |