refactor calltree WIP

This commit is contained in:
Dmitry Vasilev
2022-11-15 16:58:15 +08:00
parent 97e952f2d3
commit a81dbe74a2
4 changed files with 37 additions and 51 deletions

View File

@@ -176,8 +176,7 @@ const do_external_imports_loaded = (
node.type == 'do' /* toplevel AST node */ node.type == 'do' /* toplevel AST node */
) { ) {
const result = eval_modules( const result = eval_modules(
state.parse_result.modules, state.parse_result,
state.parse_result.sorted,
external_imports, external_imports,
state.on_async_call, state.on_async_call,
) )
@@ -199,8 +198,7 @@ const do_external_imports_loaded = (
} }
const result = eval_modules( const result = eval_modules(
state.parse_result.modules, state.parse_result,
state.parse_result.sorted,
external_imports, external_imports,
state.on_async_call, state.on_async_call,
{index: node.index, module: state.current_module}, {index: node.index, module: state.current_module},
@@ -680,7 +678,7 @@ const get_value_explorer = (state, index) => {
result = { result = {
ok: true, ok: true,
value: pick_keys( value: pick_keys(
state.calltree[stmt.full_import_path].exports, state.modules[stmt.full_import_path],
stmt.imports.map(i => i.value) stmt.imports.map(i => i.value)
), ),
} }

View File

@@ -240,7 +240,7 @@ const codegen = (node, cxt, parent) => {
return do_codegen(node.key) + ' : ' + do_codegen(node.value); return do_codegen(node.key) + ' : ' + do_codegen(node.value);
} else if(node.type == 'import') { } else if(node.type == 'import') {
const names = node.imports.map(n => n.value) const names = node.imports.map(n => n.value)
return `const {${names.join(',')}} = __modules['${node.full_import_path}'].exports;`; return `const {${names.join(',')}} = __modules['${node.full_import_path}'];`;
} else if(node.type == 'export') { } else if(node.type == 'export') {
const identifiers = collect_destructuring_identifiers(node.binding.name_node) const identifiers = collect_destructuring_identifiers(node.binding.name_node)
.map(i => i.value) .map(i => i.value)
@@ -254,8 +254,7 @@ const codegen = (node, cxt, parent) => {
} }
export const eval_modules = ( export const eval_modules = (
modules, parse_result,
sorted,
external_imports, external_imports,
on_async_call, on_async_call,
location location
@@ -311,11 +310,11 @@ export const eval_modules = (
const find_call = (location) => { const find_call = (location) => {
searched_location = location searched_location = location
const calltree = run() const {modules, calltree} = run()
searched_location = null searched_location = null
const call = found_call const call = found_call
found_call = null found_call = null
return {calltree, call} return {modules, calltree, call}
} }
const trace = (fn, name, argscount, __location, get_closure) => { const trace = (fn, name, argscount, __location, get_closure) => {
@@ -488,23 +487,22 @@ export const eval_modules = (
` `
+ +
sorted parse_result.sorted
.map((m, i) => .map((m, i) =>
` `
__modules['${m}'] = {} const current_module = '${m}'
found_call = null found_call = null
children = null children = null
current_call = { current_call = {
toplevel: true, toplevel: true,
module: '${m}', module: current_module,
id: call_counter++ id: call_counter++
} }
__modules['${m}'].calls = current_call __modules[current_module] =
__modules['${m}'].exports =
(() => { (() => {
try { try {
const __exports = {}; const __exports = {};
${codegen(modules[m], {module: m})}; ${codegen(parse_result.modules[m], {module: m})};
current_call.ok = true current_call.ok = true
return __exports return __exports
} catch(error) { } catch(error) {
@@ -513,10 +511,10 @@ export const eval_modules = (
} }
})() })()
current_call.children = children current_call.children = children
if(!__modules['${m}'].calls.ok) { if(!current_call.ok) {
is_recording_async_calls = true is_recording_async_calls = true
children = null children = null
return __modules return { modules: __modules, calltree: current_call }
} }
` `
) )
@@ -525,7 +523,7 @@ export const eval_modules = (
` `
is_recording_async_calls = true is_recording_async_calls = true
children = null children = null
return __modules return { modules: __modules, call: calltree: current_call }
} }
return { return {
@@ -549,18 +547,18 @@ export const eval_modules = (
, ,
/* on_async_call */ /* on_async_call */
call => on_async_call(assign_code(modules, call)) call => on_async_call(assign_code(parse_result.modules, call))
) )
const calltree_actions = { const calltree_actions = {
expand_calltree_node: (node) => { expand_calltree_node: (node) => {
const expanded = actions.expand_calltree_node(node) const expanded = actions.expand_calltree_node(node)
return assign_code(modules, expanded) return assign_code(parse_result.modules, expanded)
}, },
find_call: (loc) => { find_call: (loc) => {
const {calltree, call} = actions.find_call(loc) const {modules, calltree, call} = actions.find_call(loc)
return { return {
calltree: assign_code_calltree(modules, calltree), calltree: assign_code(parse_result.modules, calltree),
// TODO: `call` does not have `code` property here. Currently it is // TODO: `call` does not have `code` property here. Currently it is
// worked around by callers. Refactor // worked around by callers. Refactor
call, call,
@@ -568,38 +566,23 @@ export const eval_modules = (
} }
} }
let calltree, call const result = location == null
? actions.run()
if(location == null) { : calltree_actions.find_call(location)
calltree = actions.run()
} else {
const result = calltree_actions.find_call(location)
calltree = result.calltree
call = result.call
}
return { return {
calltree: assign_code_calltree(modules, calltree), modules: result.modules,
call, calltree: assign_code(parse_result.modules, result.calltree),
call: result.call,
calltree_actions, calltree_actions,
} }
} }
// TODO: assign_code: benchmark and use imperative version for perf? // TODO: assign_code: benchmark and use imperative version for perf?
const assign_code_calltree = (modules, calltree) => const assign_code = (modules, call) => {
map_object(
calltree,
(module, {calls, exports, is_external}) => {
return is_external
? {is_external, exports}
: {exports, calls: assign_code(modules, calls, modules[module])}
}
)
const assign_code = (modules, call, module) => {
if(call.toplevel) { if(call.toplevel) {
return {...call, return {...call,
code: module, code: modules[call.module],
children: call.children && call.children.map(call => assign_code(modules, call)), children: call.children && call.children.map(call => assign_code(modules, call)),
} }
} else { } else {
@@ -614,7 +597,12 @@ const assign_code = (modules, call, module) => {
} }
export const eval_tree = node => { export const eval_tree = node => {
return eval_modules({'': node}, ['']).calltree[''].calls return eval_modules(
{
modules: {'': node}},
sorted: ['']
}
).calltree[''].calls
} }

View File

@@ -54,7 +54,7 @@ run([
} else { } else {
assert_equal(parsed.ok, true) assert_equal(parsed.ok, true)
console.time('eval') console.time('eval')
const result = eval_modules(parsed.modules, parsed.sorted).calltree const result = eval_modules(parsed).calltree
console.timeEnd('eval') console.timeEnd('eval')
/* TODO remove /* TODO remove

View File

@@ -633,7 +633,7 @@ export const tests = [
'b' : 'import {a} from "a"; export const b = a*2;', 'b' : 'import {a} from "a"; export const b = a*2;',
} }
) )
const calltree = eval_modules(parsed.modules, parsed.sorted).calltree; const calltree = eval_modules(parsed).calltree;
const frame = eval_frame(calltree.b.calls, calltree) const frame = eval_frame(calltree.b.calls, calltree)
assert_equal(frame.children[1].result, {ok: true}) assert_equal(frame.children[1].result, {ok: true})
assert_equal(frame.children[1].children[0].children[1].result, {ok: true, value: 2}) assert_equal(frame.children[1].children[0].children[1].result, {ok: true, value: 2})
@@ -757,7 +757,7 @@ export const tests = [
} }
) )
assert_equal(parsed.sorted, ['a', 'b', 'c1', 'c2', 'd']) assert_equal(parsed.sorted, ['a', 'b', 'c1', 'c2', 'd'])
const result = eval_modules(parsed.modules, parsed.sorted).calltree; const result = eval_modules(parsed).calltree;
assert_equal(result.d.exports.d, 8) assert_equal(result.d.exports.d, 8)
}), }),
@@ -779,7 +779,7 @@ export const tests = [
'leaf' : 'export const leaf = {}', 'leaf' : 'export const leaf = {}',
} }
) )
const mods = eval_modules(parsed.modules, parsed.sorted).calltree const mods = eval_modules(parsed).calltree
// Check that the same symbol improted through different paths gives the // Check that the same symbol improted through different paths gives the
// same result // same result
assert_equal(mods.root.exports.is_eq, true) assert_equal(mods.root.exports.is_eq, true)