Finish implementing lambda application
This commit is contained in:
@@ -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()
|
||||
})
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user