mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -08:00
WIP
This commit is contained in:
@@ -2,7 +2,7 @@ import {map_accum, map_find, map_object, stringify, findLast} from './utils.js'
|
|||||||
import {is_eq, find_error_origin_node} from './ast_utils.js'
|
import {is_eq, find_error_origin_node} from './ast_utils.js'
|
||||||
import {find_node, find_leaf, ancestry_inc} from './ast_utils.js'
|
import {find_node, find_leaf, ancestry_inc} from './ast_utils.js'
|
||||||
import {color} from './color.js'
|
import {color} from './color.js'
|
||||||
import {eval_frame} from './eval.js'
|
import {eval_frame, eval_expand_calltree_node, eval_find_call} from './eval.js'
|
||||||
|
|
||||||
export const pp_calltree = tree => ({
|
export const pp_calltree = tree => ({
|
||||||
id: tree.id,
|
id: tree.id,
|
||||||
@@ -176,7 +176,11 @@ const replace_calltree_node = (root, node, replacement) => {
|
|||||||
|
|
||||||
const expand_calltree_node = (state, node) => {
|
const expand_calltree_node = (state, node) => {
|
||||||
if(node.has_more_children) {
|
if(node.has_more_children) {
|
||||||
const next_node = state.calltree_actions.expand_calltree_node(node)
|
const next_node = eval_expand_calltree_node(
|
||||||
|
state.eval_cxt,
|
||||||
|
state.parse_result,
|
||||||
|
node
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
state: {...state,
|
state: {...state,
|
||||||
calltree: replace_calltree_node(state.calltree, node, next_node)
|
calltree: replace_calltree_node(state.calltree, node, next_node)
|
||||||
@@ -594,7 +598,11 @@ export const find_call = (state, index) => {
|
|||||||
|
|
||||||
if(call != null) {
|
if(call != null) {
|
||||||
if(call.has_more_children) {
|
if(call.has_more_children) {
|
||||||
active_calltree_node = state.calltree_actions.expand_calltree_node(call)
|
active_calltree_node = eval_expand_calltree_node(
|
||||||
|
state.eval_cxt,
|
||||||
|
state.parse_result,
|
||||||
|
call
|
||||||
|
)
|
||||||
next_calltree = replace_calltree_node(
|
next_calltree = replace_calltree_node(
|
||||||
state.calltree,
|
state.calltree,
|
||||||
call,
|
call,
|
||||||
@@ -605,7 +613,12 @@ export const find_call = (state, index) => {
|
|||||||
next_calltree = state.calltree
|
next_calltree = state.calltree
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const find_result = state.calltree_actions.find_call(state.calltree, loc)
|
const find_result = eval_find_call(
|
||||||
|
state.eval_cxt,
|
||||||
|
state.parse_result,
|
||||||
|
state.calltree,
|
||||||
|
loc
|
||||||
|
)
|
||||||
if(find_result == null) {
|
if(find_result == null) {
|
||||||
return add_calltree_node_by_loc(
|
return add_calltree_node_by_loc(
|
||||||
// Remove active_calltree_node
|
// Remove active_calltree_node
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const apply_eval_result = (state, eval_result) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
calltree: make_calltree(eval_result.calltree, null),
|
calltree: make_calltree(eval_result.calltree, null),
|
||||||
calltree_actions: eval_result.calltree_actions,
|
eval_cxt: eval_result.eval_cxt,
|
||||||
logs: {
|
logs: {
|
||||||
logs: collect_logs(eval_result.logs, eval_result.calltree),
|
logs: collect_logs(eval_result.logs, eval_result.calltree),
|
||||||
log_position: null
|
log_position: null
|
||||||
@@ -84,7 +84,7 @@ const run_code = (s, dirty_files) => {
|
|||||||
// Shows that calltree is brand new and requires entire rerender
|
// Shows that calltree is brand new and requires entire rerender
|
||||||
calltree_changed_token: {},
|
calltree_changed_token: {},
|
||||||
|
|
||||||
calltree_actions: null,
|
eval_cxt: null,
|
||||||
logs: null,
|
logs: null,
|
||||||
current_calltree_node: null,
|
current_calltree_node: null,
|
||||||
active_calltree_node: null,
|
active_calltree_node: null,
|
||||||
|
|||||||
311
src/eval.js
311
src/eval.js
@@ -15,6 +15,10 @@ import {
|
|||||||
|
|
||||||
import {has_toplevel_await} from './find_definitions.js'
|
import {has_toplevel_await} from './find_definitions.js'
|
||||||
|
|
||||||
|
// external
|
||||||
|
// TODO
|
||||||
|
// import {} from './runtime.js'
|
||||||
|
|
||||||
// TODO: fix error messages. For example, "__fn is not a function"
|
// TODO: fix error messages. For example, "__fn is not a function"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -89,7 +93,8 @@ const codegen_function_expr = (node, cxt) => {
|
|||||||
// on first call (see `__trace`)
|
// on first call (see `__trace`)
|
||||||
const get_closure = `() => ({${[...node.closed].join(',')}})`
|
const get_closure = `() => ({${[...node.closed].join(',')}})`
|
||||||
|
|
||||||
return `__trace(${call}, "${node.name}", ${argscount}, ${location}, ${get_closure})`
|
return `__trace(__cxt, ${call}, "${node.name}", ${argscount}, ${location}, \
|
||||||
|
${get_closure})`
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -121,15 +126,16 @@ const codegen_function_call = (node, cxt) => {
|
|||||||
return `(
|
return `(
|
||||||
__obj = ${do_codegen(node.fn.object)},
|
__obj = ${do_codegen(node.fn.object)},
|
||||||
__fn = __obj${op}[${do_codegen(node.fn.property)}],
|
__fn = __obj${op}[${do_codegen(node.fn.property)}],
|
||||||
__trace_call(__fn, __obj, ${args}, ${JSON.stringify(errormessage)})
|
__trace_call(__cxt, __fn, __obj, ${args}, ${JSON.stringify(errormessage)})
|
||||||
)`
|
)`
|
||||||
} else {
|
} else {
|
||||||
return `__trace_call(${do_codegen(node.fn)}, null, ${args}, \
|
return `__trace_call(__cxt, ${do_codegen(node.fn)}, null, ${args}, \
|
||||||
${JSON.stringify(errormessage)})`
|
${JSON.stringify(errormessage)})`
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO rename cxt, to not confuse with another cxt
|
||||||
const codegen = (node, cxt, parent) => {
|
const codegen = (node, cxt, parent) => {
|
||||||
|
|
||||||
const do_codegen = (n, parent) => codegen(n, cxt, parent)
|
const do_codegen = (n, parent) => codegen(n, cxt, parent)
|
||||||
@@ -225,7 +231,7 @@ const codegen = (node, cxt, parent) => {
|
|||||||
+ ']'
|
+ ']'
|
||||||
} else if(node.type == 'unary') {
|
} else if(node.type == 'unary') {
|
||||||
if(node.operator == 'await') {
|
if(node.operator == 'await') {
|
||||||
return `(await __do_await(${do_codegen(node.expr)}))`
|
return `(await __do_await(__cxt, ${do_codegen(node.expr)}))`
|
||||||
} else {
|
} else {
|
||||||
return '(' + node.operator + ' ' + do_codegen(node.expr) + ')'
|
return '(' + node.operator + ' ' + do_codegen(node.expr) + ')'
|
||||||
}
|
}
|
||||||
@@ -241,7 +247,7 @@ const codegen = (node, cxt, parent) => {
|
|||||||
} else if(node.type == 'new') {
|
} else if(node.type == 'new') {
|
||||||
const args = `[${node.args.children.map(do_codegen).join(',')}]`
|
const args = `[${node.args.children.map(do_codegen).join(',')}]`
|
||||||
const errormessage = not_a_function_error(node.constructor)
|
const errormessage = not_a_function_error(node.constructor)
|
||||||
return `__trace_call(${do_codegen(node.constructor)}, null, ${args}, \
|
return `__trace_call(__cxt, ${do_codegen(node.constructor)}, null, ${args},\
|
||||||
${JSON.stringify(errormessage)}, true)`
|
${JSON.stringify(errormessage)}, true)`
|
||||||
} else if(node.type == 'grouping'){
|
} else if(node.type == 'grouping'){
|
||||||
return '(' + do_codegen(node.expr) + ')'
|
return '(' + do_codegen(node.expr) + ')'
|
||||||
@@ -260,14 +266,14 @@ ${JSON.stringify(errormessage)}, true)`
|
|||||||
if(names.length == 0) {
|
if(names.length == 0) {
|
||||||
return ''
|
return ''
|
||||||
} else {
|
} else {
|
||||||
return `const {${names.join(',')}} = __modules['${node.full_import_path}'];`;
|
return `const {${names.join(',')}} = __cxt.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)
|
||||||
return do_codegen(node.binding)
|
return do_codegen(node.binding)
|
||||||
+
|
+
|
||||||
`Object.assign(__exports, {${identifiers.join(',')}});`
|
`Object.assign(__cxt.modules[cxt.module], {${identifiers.join(',')}});`
|
||||||
} else if(node.type == 'function_decl') {
|
} else if(node.type == 'function_decl') {
|
||||||
const expr = node.children[0]
|
const expr = node.children[0]
|
||||||
return `const ${expr.name} = ${codegen_function_expr(expr, cxt)};`
|
return `const ${expr.name} = ${codegen_function_expr(expr, cxt)};`
|
||||||
@@ -284,34 +290,118 @@ export const eval_modules = (
|
|||||||
calltree_changed_token,
|
calltree_changed_token,
|
||||||
location
|
location
|
||||||
) => {
|
) => {
|
||||||
// TODO gensym __modules, __exports, __trace, __trace_call
|
// TODO gensym __cxt, __trace, __trace_call
|
||||||
|
|
||||||
// TODO bug if module imported twice, once as external and as regular
|
// TODO bug if module imported twice, once as external and as regular
|
||||||
|
|
||||||
const is_async = has_toplevel_await(parse_result.modules)
|
const is_async = has_toplevel_await(parse_result.modules)
|
||||||
|
|
||||||
const codestring = `
|
/*
|
||||||
|
TODO remove
|
||||||
let children, prev_children
|
cxt vars:
|
||||||
|
- modules
|
||||||
|
- is_recording_deferred_calls
|
||||||
|
- logs
|
||||||
|
- children
|
||||||
|
- prev_children
|
||||||
|
- call_counter
|
||||||
|
- is_toplevel_call
|
||||||
|
- searched_location
|
||||||
|
- found_call
|
||||||
|
- promise_then
|
||||||
|
- stack
|
||||||
|
- on_deferred_call
|
||||||
|
- calltree_changed_token
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO sort
|
||||||
|
const cxt = {
|
||||||
|
is_recording_deferred_calls: false,
|
||||||
|
call_counter: 0,
|
||||||
|
logs: [],
|
||||||
|
is_toplevel_call: true,
|
||||||
// TODO use native array for stack for perf? stack contains booleans
|
// TODO use native array for stack for perf? stack contains booleans
|
||||||
const stack = new Array()
|
stack: new Array(),
|
||||||
|
children: null,
|
||||||
|
prev_children: null,
|
||||||
|
searched_location: location,
|
||||||
|
found_call: null,
|
||||||
|
promise_then: null,
|
||||||
|
|
||||||
let logs = []
|
modules: external_imports == null
|
||||||
|
? null
|
||||||
|
: map_object(external_imports, (name, {module}) => module),
|
||||||
|
|
||||||
let call_counter = 0
|
on_deferred_call: (call, calltree_changed_token, logs) => {
|
||||||
|
return on_deferred_call(
|
||||||
|
assign_code(parse_result.modules, call),
|
||||||
|
calltree_changed_token,
|
||||||
|
logs,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
let current_module
|
calltree_changed_token
|
||||||
|
}
|
||||||
|
|
||||||
let searched_location
|
const Function = is_async
|
||||||
let found_call
|
? globalThis.run_window.eval('(async function(){})').constructor
|
||||||
|
: globalThis.run_window.Function
|
||||||
|
|
||||||
let is_recording_deferred_calls
|
let calltree
|
||||||
let is_toplevel_call = true
|
|
||||||
|
|
||||||
let promise_then
|
apply_promise_patch(cxt)
|
||||||
|
|
||||||
function apply_promise_patch() {
|
for(let current_module of parse_result.sorted) {
|
||||||
|
cxt.found_call = null
|
||||||
|
cxt.children = null
|
||||||
|
calltree = {
|
||||||
|
toplevel: true,
|
||||||
|
module: current_module,
|
||||||
|
id: cxt.call_counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
const module_fn = new Function(
|
||||||
|
'__cxt',
|
||||||
|
codegen(node, {module: module_name})
|
||||||
|
)
|
||||||
|
|
||||||
|
cxt.modules[current_module] =
|
||||||
|
try {
|
||||||
|
// cxt.modules[current_module] = {}
|
||||||
|
// TODO await
|
||||||
|
module_fn(cxt)
|
||||||
|
calltree.ok = true
|
||||||
|
} catch(error) {
|
||||||
|
calltree.ok = false
|
||||||
|
calltree.error = error
|
||||||
|
}
|
||||||
|
calltree.children = cxt.children
|
||||||
|
if(!calltree.ok) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cxt.is_recording_deferred_calls = true
|
||||||
|
const _logs = cxt.logs
|
||||||
|
cxt.logs = []
|
||||||
|
cxt.children = null
|
||||||
|
|
||||||
|
remove_promise_patch(cxt)
|
||||||
|
|
||||||
|
searched_location = null
|
||||||
|
const call = found_call
|
||||||
|
found_call = null
|
||||||
|
|
||||||
|
return {
|
||||||
|
modules: cxt.modules,
|
||||||
|
calltree: assign_code(parse_result.modules, calltree),
|
||||||
|
call,
|
||||||
|
logs: _logs,
|
||||||
|
eval_cxt: cxt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const apply_promise_patch = cxt => {
|
||||||
|
|
||||||
promise_then = Promise.prototype.then
|
promise_then = Promise.prototype.then
|
||||||
|
|
||||||
@@ -345,12 +435,10 @@ export const eval_modules = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove_promise_patch() {
|
const remove_promise_patch = cxt => {
|
||||||
Promise.prototype.then = promise_then
|
Promise.prototype.then = promise_then
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_promise_patch()
|
|
||||||
|
|
||||||
const set_record_call = () => {
|
const set_record_call = () => {
|
||||||
for(let i = 0; i < stack.length; i++) {
|
for(let i = 0; i < stack.length; i++) {
|
||||||
stack[i] = true
|
stack[i] = true
|
||||||
@@ -374,7 +462,7 @@ export const eval_modules = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const expand_calltree_node = (node) => {
|
export const eval_expand_calltree_node = (parse_result, node) => {
|
||||||
is_recording_deferred_calls = false
|
is_recording_deferred_calls = false
|
||||||
children = null
|
children = null
|
||||||
try {
|
try {
|
||||||
@@ -387,34 +475,7 @@ export const eval_modules = (
|
|||||||
// do nothing. Exception was caught and recorded inside '__trace'
|
// do nothing. Exception was caught and recorded inside '__trace'
|
||||||
}
|
}
|
||||||
is_recording_deferred_calls = true
|
is_recording_deferred_calls = true
|
||||||
return do_expand_calltree_node(node)
|
return assign_code(parse_result.modules, do_expand_calltree_node(node))
|
||||||
}
|
|
||||||
|
|
||||||
const run_and_find_call = (location) => {
|
|
||||||
searched_location = location
|
|
||||||
|
|
||||||
const run_result = run()
|
|
||||||
|
|
||||||
const after_run = ({calltree, modules, logs}) => {
|
|
||||||
searched_location = null
|
|
||||||
const call = found_call
|
|
||||||
found_call = null
|
|
||||||
|
|
||||||
return {
|
|
||||||
calltree,
|
|
||||||
modules,
|
|
||||||
logs,
|
|
||||||
call,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support to paths, one for async 'run', and one for sync, to avoid
|
|
||||||
// refactoring code (mostly test code) to always async
|
|
||||||
if(run_result instanceof Promise) {
|
|
||||||
return run_result.then(after_run)
|
|
||||||
} else {
|
|
||||||
return after_run(run_result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -430,7 +491,7 @@ export const eval_modules = (
|
|||||||
We dont rerun entire execution because we want find_call to be
|
We dont rerun entire execution because we want find_call to be
|
||||||
synchronous for simplicity
|
synchronous for simplicity
|
||||||
*/
|
*/
|
||||||
const find_call = (calltree, location) => {
|
export const eval_find_call = (cxt, parse_result, calltree, location) => {
|
||||||
// TODO remove
|
// TODO remove
|
||||||
if(children != null) {
|
if(children != null) {
|
||||||
throw new Error('illegal state')
|
throw new Error('illegal state')
|
||||||
@@ -484,10 +545,19 @@ export const eval_modules = (
|
|||||||
found_call = null
|
found_call = null
|
||||||
is_recording_deferred_calls = true
|
is_recording_deferred_calls = true
|
||||||
|
|
||||||
return result
|
if(result == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const {node, call} = result
|
||||||
|
const node_with_code = assign_code(parse_result.modules, node)
|
||||||
|
const call_with_code = find_node(node_with_code, n => n.id == call.id)
|
||||||
|
return {
|
||||||
|
node: node_with_code,
|
||||||
|
call: call_with_code,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const __do_await = async value => {
|
const __do_await = async (cxt, value) => {
|
||||||
// children is an array of child calls for current function call. But it
|
// children is an array of child calls for current function call. But it
|
||||||
// can be null to save one empty array allocation in case it has no child
|
// can be null to save one empty array allocation in case it has no child
|
||||||
// calls. Allocate array now, so we can have a reference to this array
|
// calls. Allocate array now, so we can have a reference to this array
|
||||||
@@ -513,7 +583,7 @@ export const eval_modules = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const __trace = (fn, name, argscount, __location, get_closure) => {
|
const __trace = (cxt, fn, name, argscount, __location, get_closure) => {
|
||||||
const result = (...args) => {
|
const result = (...args) => {
|
||||||
if(result.__closure == null) {
|
if(result.__closure == null) {
|
||||||
result.__closure = get_closure()
|
result.__closure = get_closure()
|
||||||
@@ -609,7 +679,7 @@ export const eval_modules = (
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
const __trace_call = (fn, context, args, errormessage, is_new = false) => {
|
const __trace_call = (cxt, fn, context, args, errormessage, is_new = false) => {
|
||||||
if(fn != null && fn.__location != null && !is_new) {
|
if(fn != null && fn.__location != null && !is_new) {
|
||||||
// Call will be traced, because tracing code is already embedded inside
|
// Call will be traced, because tracing code is already embedded inside
|
||||||
// fn
|
// fn
|
||||||
@@ -694,131 +764,6 @@ export const eval_modules = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const run = ${is_async ? 'async' : ''} () => {
|
|
||||||
|
|
||||||
is_recording_deferred_calls = false
|
|
||||||
|
|
||||||
const finish = () => {
|
|
||||||
is_recording_deferred_calls = true
|
|
||||||
const _logs = logs
|
|
||||||
logs = []
|
|
||||||
children = null
|
|
||||||
remove_promise_patch()
|
|
||||||
return { modules: __modules, calltree: current_call, logs: _logs }
|
|
||||||
}
|
|
||||||
|
|
||||||
const __modules = {
|
|
||||||
/* external_imports passed as an argument to function generated with
|
|
||||||
* 'new Function' constructor */
|
|
||||||
...external_imports
|
|
||||||
}
|
|
||||||
let current_call
|
|
||||||
|
|
||||||
`
|
|
||||||
+
|
|
||||||
parse_result.sorted
|
|
||||||
.map((m, i) =>
|
|
||||||
`
|
|
||||||
current_module = '${m}'
|
|
||||||
found_call = null
|
|
||||||
children = null
|
|
||||||
current_call = {
|
|
||||||
toplevel: true,
|
|
||||||
module: current_module,
|
|
||||||
id: call_counter++
|
|
||||||
}
|
|
||||||
__modules[current_module] = ${is_async ? 'await (async' : '('} () => {
|
|
||||||
try {
|
|
||||||
const __exports = {};
|
|
||||||
${codegen(parse_result.modules[m], {module: m})};
|
|
||||||
current_call.ok = true
|
|
||||||
return __exports
|
|
||||||
} catch(error) {
|
|
||||||
current_call.ok = false
|
|
||||||
current_call.error = error
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
current_call.children = children
|
|
||||||
if(!current_call.ok) {
|
|
||||||
return finish()
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
.join('')
|
|
||||||
+
|
|
||||||
`
|
|
||||||
return finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
run,
|
|
||||||
run_and_find_call,
|
|
||||||
expand_calltree_node,
|
|
||||||
find_call,
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const actions = new (globalThis.run_window.Function)(
|
|
||||||
'external_imports',
|
|
||||||
'on_deferred_call',
|
|
||||||
'calltree_changed_token',
|
|
||||||
codestring
|
|
||||||
)(
|
|
||||||
/* external_imports */
|
|
||||||
external_imports == null
|
|
||||||
? null
|
|
||||||
: map_object(external_imports, (name, {module}) => module),
|
|
||||||
|
|
||||||
/* on_deferred_call */
|
|
||||||
(call, calltree_changed_token, logs) => {
|
|
||||||
return on_deferred_call(
|
|
||||||
assign_code(parse_result.modules, call),
|
|
||||||
calltree_changed_token,
|
|
||||||
logs,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
/* calltree_changed_token */
|
|
||||||
calltree_changed_token
|
|
||||||
)
|
|
||||||
|
|
||||||
const calltree_actions = {
|
|
||||||
expand_calltree_node: (node) => {
|
|
||||||
const expanded = actions.expand_calltree_node(node)
|
|
||||||
return assign_code(parse_result.modules, expanded)
|
|
||||||
},
|
|
||||||
find_call: (calltree, location) => {
|
|
||||||
const result = actions.find_call(calltree, location)
|
|
||||||
if(result == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const {node, call} = result
|
|
||||||
const node_with_code = assign_code(parse_result.modules, node)
|
|
||||||
const call_with_code = find_node(node_with_code, n => n.id == call.id)
|
|
||||||
return {
|
|
||||||
node: node_with_code,
|
|
||||||
call: call_with_code,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = location == null
|
|
||||||
? actions.run()
|
|
||||||
: actions.run_and_find_call(location)
|
|
||||||
|
|
||||||
const make_result = result => ({
|
|
||||||
modules: result.modules,
|
|
||||||
calltree: assign_code(parse_result.modules, result.calltree),
|
|
||||||
call: result.call,
|
|
||||||
logs: result.logs,
|
|
||||||
calltree_actions,
|
|
||||||
})
|
|
||||||
|
|
||||||
return is_async
|
|
||||||
? result.then(make_result)
|
|
||||||
: make_result(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: assign_code: benchmark and use imperative version for perf?
|
// TODO: assign_code: benchmark and use imperative version for perf?
|
||||||
const assign_code = (modules, call) => {
|
const assign_code = (modules, call) => {
|
||||||
if(call.toplevel) {
|
if(call.toplevel) {
|
||||||
|
|||||||
0
src/runtime.js
Normal file
0
src/runtime.js
Normal file
Reference in New Issue
Block a user