Allow parse_execution_context to take ownership of a parse tree

Introduces a new template moved_ref which is like an rvalue reference.
This allows passing around objects while being explicit that the
receiver may acquire ownership. This will help reduce some allocations.
This commit is contained in:
ridiculousfish
2016-02-28 00:33:11 -08:00
parent 077757a30b
commit e3970f9cbb
7 changed files with 45 additions and 35 deletions

View File

@@ -813,18 +813,8 @@ profile_item_t *parser_t::create_profile_item()
return result;
}
int parser_t::eval(const wcstring &cmd, const io_chain_t &io, enum block_type_t block_type)
{
CHECK_BLOCK(1);
if (block_type != TOP && block_type != SUBST)
{
debug(1, INVALID_SCOPE_ERR_MSG, parser_t::get_block_desc(block_type));
bugreport();
return 1;
}
/* Parse the source into a tree, if we can */
parse_node_tree_t tree;
parse_error_list_t error_list;
@@ -833,34 +823,42 @@ int parser_t::eval(const wcstring &cmd, const io_chain_t &io, enum block_type_t
/* Get a backtrace. This includes the message. */
wcstring backtrace_and_desc;
this->get_backtrace(cmd, error_list, &backtrace_and_desc);
/* Print it */
fprintf(stderr, "%ls", backtrace_and_desc.c_str());
return 1;
}
return this->eval_acquiring_tree(cmd, io, block_type, moved_ref<parse_node_tree_t>(tree));
}
int parser_t::eval_acquiring_tree(const wcstring &cmd, const io_chain_t &io, enum block_type_t block_type, moved_ref<parse_node_tree_t> tree)
{
CHECK_BLOCK(1);
assert(block_type == TOP || block_type == SUBST);
if (tree.val.empty())
{
return 0;
}
//print_stderr(block_stack_description());
/* Determine the initial eval level. If this is the first context, it's -1; otherwise it's the eval level of the top context. This is sort of wonky because we're stitching together a global notion of eval level from these separate objects. A better approach would be some profile object that all contexts share, and that tracks the eval levels on its own. */
int exec_eval_level = (execution_contexts.empty() ? -1 : execution_contexts.back()->current_eval_level());
/* Append to the execution context stack */
parse_execution_context_t *ctx = new parse_execution_context_t(tree, cmd, this, exec_eval_level);
execution_contexts.push_back(ctx);
/* Execute the first node */
if (! tree.empty())
{
this->eval_block_node(0, io, block_type);
}
this->eval_block_node(0, io, block_type);
/* Clean up the execution context stack */
assert(! execution_contexts.empty() && execution_contexts.back() == ctx);
execution_contexts.pop_back();
delete ctx;
return 0;
}