Finish implementing lambda application

This commit is contained in:
2026-04-03 00:03:24 -05:00
parent 98e40183bb
commit 055babc9f3

View File

@@ -1,6 +1,6 @@
import {Command, ParseContext, StrTerm} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
import {ExecutionError, StrVM} from "../vm.js";
type CallData = {
callable: StrTerm,
@@ -32,7 +32,7 @@ export class Call extends Command<CallData> {
async execute(vm: StrVM, data: CallData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
override: (s) => {
override: async () => {
// Resolve the callable and params
const callable = ctx.resolveLambda(data.callable)
const params = data.params.map(p => ctx.resolveRequired(p))
@@ -61,7 +61,27 @@ export class Call extends Command<CallData> {
}
}
return s
if ( params.length > callable.value.params.length ) {
throw new ExecutionError(`Invalid lambda call. Found ${params.length} parameters (expected ${callable.value.params.length})`)
}
// Create a new child VM to execute the lambda in
return vm.runInChild(async (childVM, childCtx) => {
// Shadow the parameters for the lambda in this scope and bind the values
childCtx.inScope(scope => {
for ( let i = 0; i < params.length; i += 1 ) {
const paramLVal = callable.value.params[i]!
const paramRVal = params[i]!
scope.shadowValue(paramLVal, paramRVal)
}
})
for ( const exec of callable.value.body ) {
await exec.command.execute(childVM, exec.data)
}
return childCtx.getSubject()
})
},
}))
}