Finish implementing lambda application
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import {Command, ParseContext, StrTerm} from "./command.js";
|
import {Command, ParseContext, StrTerm} from "./command.js";
|
||||||
import {LexInput} from "../lexer.js";
|
import {LexInput} from "../lexer.js";
|
||||||
import {StrVM} from "../vm.js";
|
import {ExecutionError, StrVM} from "../vm.js";
|
||||||
|
|
||||||
type CallData = {
|
type CallData = {
|
||||||
callable: StrTerm,
|
callable: StrTerm,
|
||||||
@@ -32,7 +32,7 @@ export class Call extends Command<CallData> {
|
|||||||
|
|
||||||
async execute(vm: StrVM, data: CallData): Promise<StrVM> {
|
async execute(vm: StrVM, data: CallData): Promise<StrVM> {
|
||||||
return vm.replaceContextMatchingTerm(ctx => ({
|
return vm.replaceContextMatchingTerm(ctx => ({
|
||||||
override: (s) => {
|
override: async () => {
|
||||||
// Resolve the callable and params
|
// Resolve the callable and params
|
||||||
const callable = ctx.resolveLambda(data.callable)
|
const callable = ctx.resolveLambda(data.callable)
|
||||||
const params = data.params.map(p => ctx.resolveRequired(p))
|
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