[WIP] Start implementing support for history
This commit is contained in:
parent
06ff1b396f
commit
390a6280c2
35
src/vm/vm.ts
35
src/vm/vm.ts
@ -53,6 +53,12 @@ export class Scope {
|
||||
makeChild(): Scope {
|
||||
return new Scope(this)
|
||||
}
|
||||
|
||||
clone(): Scope {
|
||||
const s = new Scope
|
||||
s.entries = {...this.entries}
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,11 +87,31 @@ export type TermOperator = {
|
||||
}
|
||||
|
||||
export class ExecutionContext {
|
||||
private history: [StrRVal, Scope][] = []
|
||||
|
||||
constructor(
|
||||
private subject: StrRVal,
|
||||
private scope: Scope,
|
||||
) {}
|
||||
|
||||
public pushHistory() {
|
||||
this.history.push([this.subject, this.scope.clone()])
|
||||
}
|
||||
|
||||
public restoreHistory() {
|
||||
const [subject, scope] = this.popHistory()
|
||||
this.subject = subject
|
||||
this.scope = scope
|
||||
}
|
||||
|
||||
public popHistory(): [StrRVal, Scope] {
|
||||
const state = this.history.pop()
|
||||
if ( !state ) {
|
||||
throw new Error('No history to undo')
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
async replaceSubject(operator: (sub: StrRVal) => Awaitable<StrRVal>) {
|
||||
this.subject = await operator(this.subject)
|
||||
}
|
||||
@ -201,7 +227,14 @@ export class StrVM {
|
||||
) {}
|
||||
|
||||
public async runInPlace<TReturn>(operator: (ctx: ExecutionContext) => Awaitable<TReturn>): Promise<TReturn> {
|
||||
return operator(this.context)
|
||||
this.context.pushHistory()
|
||||
try {
|
||||
return await operator(this.context)
|
||||
} catch (e: unknown) {
|
||||
// If we got an error, return to the previous state:
|
||||
this.context.restoreHistory()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public async tapInPlace(operator: (ctx: ExecutionContext) => Awaitable<unknown>): Promise<this> {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user