import {Command, CommandData, ParseContext, StrLVal} from "./command.js"; import {Executable} from "../parse.js"; import {LexInput} from "../lexer.js"; import {StrVM} from "../vm.js"; export type OverData = { subject: StrLVal, exec: Executable, } export class Over extends Command { async attemptParse(context: ParseContext): Promise { return { subject: context.popLVal(), exec: await context.popExecutable(), } } getDisplayName(): string { return 'over' } isParseCandidate(token: LexInput): boolean { return this.isKeyword(token, 'over') } async execute(vm: StrVM, data: OverData): Promise { return vm.tapInPlace(async parentCtx => { const oldValue = parentCtx.resolveRequired(data.subject) const newValue = await vm.runInChild(async (child, childCtx) => { await childCtx.replaceSubject(() => oldValue) await data.exec.command.execute(child, data.exec.data) return childCtx.getSubject() }) parentCtx.inScope(scope => scope.setOrShadowValue(data.subject, newValue)) }) } }