mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
refactor multiversion
This commit is contained in:
@@ -19,25 +19,22 @@ function binarySearch(arr, el, compare_fn) {
|
|||||||
export class Multiversion {
|
export class Multiversion {
|
||||||
constructor(cxt, initial) {
|
constructor(cxt, initial) {
|
||||||
this.cxt = cxt
|
this.cxt = cxt
|
||||||
this.is_expanding_calltree_node = cxt.is_expanding_calltree_node
|
this.expand_calltree_node_number = cxt.expand_calltree_node_number
|
||||||
this.latest = initial
|
this.latest = initial
|
||||||
this.versions = [{version_number: cxt.version_counter, value: initial}]
|
this.versions = [{version_number: cxt.version_counter, value: initial}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_created_during_current_expand() {
|
||||||
|
return this.expand_calltree_node_number == this.cxt.expand_calltree_node_number
|
||||||
|
}
|
||||||
|
|
||||||
get() {
|
get() {
|
||||||
if(!this.cxt.is_expanding_calltree_node) {
|
if(!this.cxt.is_expanding_calltree_node) {
|
||||||
return this.latest
|
return this.latest
|
||||||
} else {
|
} else {
|
||||||
if(this.is_expanding_calltree_node) {
|
if(this.is_created_during_current_expand()) {
|
||||||
// var was created during current expansion, use its latest value
|
|
||||||
return this.latest
|
return this.latest
|
||||||
} else {
|
} else {
|
||||||
if(this.latest_copy != null) {
|
|
||||||
// value was set during expand_calltree_node, use this value
|
|
||||||
return this.latest
|
|
||||||
}
|
|
||||||
// TODO on first read, set latest and latest_copy? Note that it will
|
|
||||||
// interfere with at_moment_in_time
|
|
||||||
const version_number = this.cxt.version_counter
|
const version_number = this.cxt.version_counter
|
||||||
return this.get_version(version_number)
|
return this.get_version(version_number)
|
||||||
}
|
}
|
||||||
@@ -61,16 +58,11 @@ export class Multiversion {
|
|||||||
set(value) {
|
set(value) {
|
||||||
const version_number = ++this.cxt.version_counter
|
const version_number = ++this.cxt.version_counter
|
||||||
if(this.cxt.is_expanding_calltree_node) {
|
if(this.cxt.is_expanding_calltree_node) {
|
||||||
if(this.is_expanding_calltree_node) {
|
if(this.is_created_during_current_expand()) {
|
||||||
this.latest = value
|
this.latest = value
|
||||||
this.set_version(version_number, value)
|
this.set_version(version_number, value)
|
||||||
this.cxt.touched_multiversions.add(this)
|
|
||||||
} else {
|
} else {
|
||||||
if(this.latest_copy == null) {
|
// do nothing
|
||||||
this.latest_copy = {value: this.latest}
|
|
||||||
}
|
|
||||||
this.cxt.touched_multiversions.add(this)
|
|
||||||
this.latest = value
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.latest = value
|
this.latest = value
|
||||||
|
|||||||
@@ -194,7 +194,9 @@ export const set_record_call = cxt => {
|
|||||||
export const do_eval_expand_calltree_node = (cxt, node) => {
|
export const do_eval_expand_calltree_node = (cxt, node) => {
|
||||||
cxt.is_recording_deferred_calls = false
|
cxt.is_recording_deferred_calls = false
|
||||||
cxt.is_expanding_calltree_node = true
|
cxt.is_expanding_calltree_node = true
|
||||||
cxt.touched_multiversions = new Set()
|
cxt.expand_calltree_node_number = cxt.expand_calltree_node_number == null
|
||||||
|
? 0
|
||||||
|
: cxt.expand_calltree_node_number + 1
|
||||||
|
|
||||||
// Save call counter and set it to the value it had when executed 'fn' for
|
// Save call counter and set it to the value it had when executed 'fn' for
|
||||||
// the first time
|
// the first time
|
||||||
@@ -227,16 +229,6 @@ export const do_eval_expand_calltree_node = (cxt, node) => {
|
|||||||
// Restore version_counter
|
// Restore version_counter
|
||||||
cxt.version_counter = version_counter
|
cxt.version_counter = version_counter
|
||||||
|
|
||||||
// Recover multiversions affected by expand_calltree_node
|
|
||||||
for(let m of cxt.touched_multiversions) {
|
|
||||||
if(m.is_expanding_calltree_node) {
|
|
||||||
delete m.is_expanding_calltree_node
|
|
||||||
}
|
|
||||||
if(m.latest_copy != null) {
|
|
||||||
m.latest = m.latest_copy.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete cxt.touched_multiversions
|
|
||||||
|
|
||||||
cxt.is_expanding_calltree_node = false
|
cxt.is_expanding_calltree_node = false
|
||||||
cxt.is_recording_deferred_calls = true
|
cxt.is_recording_deferred_calls = true
|
||||||
|
|||||||
28
test/test.js
28
test/test.js
@@ -4682,4 +4682,32 @@ const y = x()`
|
|||||||
const moved = COMMANDS.move_cursor(expanded, code.indexOf('return x'))
|
const moved = COMMANDS.move_cursor(expanded, code.indexOf('return x'))
|
||||||
assert_equal(moved.value_explorer.result.value, 2)
|
assert_equal(moved.value_explorer.result.value, 2)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
test('let_versions deferred calls get value', () => {
|
||||||
|
const code = `
|
||||||
|
let x = 0
|
||||||
|
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(value) {
|
||||||
|
x = value
|
||||||
|
noop()
|
||||||
|
}
|
||||||
|
|
||||||
|
set(1)
|
||||||
|
set(2)
|
||||||
|
set(3)
|
||||||
|
|
||||||
|
export const get = () => x
|
||||||
|
`
|
||||||
|
|
||||||
|
const {state: i} = test_deferred_calls_state(code)
|
||||||
|
|
||||||
|
const second_set_call = root_calltree_node(i).children[1]
|
||||||
|
assert_equal(second_set_call.has_more_children, true)
|
||||||
|
|
||||||
|
const exp = COMMANDS.calltree.click(i, second_set_call.id)
|
||||||
|
assert_equal(exp.modules[''].get(), 3)
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user