[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 {
|
makeChild(): Scope {
|
||||||
return new Scope(this)
|
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 {
|
export class ExecutionContext {
|
||||||
|
private history: [StrRVal, Scope][] = []
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private subject: StrRVal,
|
private subject: StrRVal,
|
||||||
private scope: Scope,
|
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>) {
|
async replaceSubject(operator: (sub: StrRVal) => Awaitable<StrRVal>) {
|
||||||
this.subject = await operator(this.subject)
|
this.subject = await operator(this.subject)
|
||||||
}
|
}
|
||||||
@ -201,7 +227,14 @@ export class StrVM {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async runInPlace<TReturn>(operator: (ctx: ExecutionContext) => Awaitable<TReturn>): Promise<TReturn> {
|
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> {
|
public async tapInPlace(operator: (ctx: ExecutionContext) => Awaitable<unknown>): Promise<this> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user