mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-24 13:03:13 +08:00
Convert populate_block_process to tnode_t
This commit is contained in:
parent
2bf96493fc
commit
fa0f552fe9
|
@ -839,7 +839,7 @@ void highlighter_t::color_redirection(tnode_t<g::redirection> redirection_node)
|
|||
if (redir_prim) {
|
||||
wcstring target;
|
||||
const enum token_type redirect_type =
|
||||
this->parse_tree.type_for_redirection(redirection_node, this->buff, NULL, &target);
|
||||
redirection_type(redirection_node, this->buff, nullptr, &target);
|
||||
|
||||
// We may get a TOK_NONE redirection type, e.g. if the redirection is invalid.
|
||||
auto hl = redirect_type == TOK_NONE ? highlight_spec_error : highlight_spec_redirection;
|
||||
|
|
|
@ -843,7 +843,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(
|
|||
argument_list.insert(argument_list.begin(), cmd);
|
||||
|
||||
// The set of IO redirections that we construct for the process.
|
||||
if (!this->determine_io_chain(statement, &process_io_chain)) {
|
||||
if (!this->determine_io_chain(statement.child<1>(), &process_io_chain)) {
|
||||
return parse_execution_errored;
|
||||
}
|
||||
|
||||
|
@ -912,26 +912,18 @@ parse_execution_result_t parse_execution_context_t::expand_arguments_from_nodes(
|
|||
return parse_execution_success;
|
||||
}
|
||||
|
||||
bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement_node,
|
||||
bool parse_execution_context_t::determine_io_chain(tnode_t<g::arguments_or_redirections_list> node,
|
||||
io_chain_t *out_chain) {
|
||||
io_chain_t result;
|
||||
bool errored = false;
|
||||
|
||||
// We are called with a statement of varying types. We require that the statement have an
|
||||
// arguments_or_redirections_list child.
|
||||
const parse_node_t &args_and_redirections_list =
|
||||
tree().find_child(statement_node, symbol_arguments_or_redirections_list);
|
||||
|
||||
// Get all redirection nodes underneath the statement.
|
||||
const parse_node_tree_t::parse_node_list_t redirect_nodes =
|
||||
tree().find_nodes(args_and_redirections_list, symbol_redirection);
|
||||
for (size_t i = 0; i < redirect_nodes.size(); i++) {
|
||||
const parse_node_t &redirect_node = *redirect_nodes.at(i);
|
||||
|
||||
auto redirect_nodes = node.descendants<g::redirection>();
|
||||
for (tnode_t<g::redirection> redirect_node : redirect_nodes) {
|
||||
int source_fd = -1; // source fd
|
||||
wcstring target; // file path or target fd
|
||||
enum token_type redirect_type =
|
||||
tree().type_for_redirection(redirect_node, pstree->src, &source_fd, &target);
|
||||
redirection_type(redirect_node, pstree->src, &source_fd, &target);
|
||||
|
||||
// PCA: I can't justify this EXPAND_SKIP_VARIABLES flag. It was like this when I got here.
|
||||
bool target_expanded = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0, NULL);
|
||||
|
@ -1019,22 +1011,26 @@ parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
|||
bool_statement.require_get_child<g::statement, 1>());
|
||||
}
|
||||
|
||||
parse_execution_result_t parse_execution_context_t::populate_block_process(
|
||||
job_t *job, process_t *proc, const parse_node_t &statement_node) {
|
||||
template <typename Type>
|
||||
parse_execution_result_t parse_execution_context_t::populate_block_process(job_t *job,
|
||||
process_t *proc,
|
||||
tnode_t<Type> node) {
|
||||
// We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when
|
||||
// it's time to execute them.
|
||||
UNUSED(job);
|
||||
assert(statement_node.type == symbol_block_statement ||
|
||||
statement_node.type == symbol_if_statement ||
|
||||
statement_node.type == symbol_switch_statement);
|
||||
static_assert(Type::token == symbol_block_statement || Type::token == symbol_if_statement ||
|
||||
Type::token == symbol_switch_statement,
|
||||
"Invalid block process");
|
||||
|
||||
// The set of IO redirections that we construct for the process.
|
||||
// TODO: fix this ugly find_child.
|
||||
auto arguments = node.template find_child<g::arguments_or_redirections_list>();
|
||||
io_chain_t process_io_chain;
|
||||
bool errored = !this->determine_io_chain(statement_node, &process_io_chain);
|
||||
bool errored = !this->determine_io_chain(arguments, &process_io_chain);
|
||||
if (errored) return parse_execution_errored;
|
||||
|
||||
proc->type = INTERNAL_BLOCK_NODE;
|
||||
proc->internal_block_node = this->get_offset(statement_node);
|
||||
proc->internal_block_node = this->get_offset(node);
|
||||
proc->set_io_chain(process_io_chain);
|
||||
return parse_execution_success;
|
||||
}
|
||||
|
@ -1052,11 +1048,17 @@ parse_execution_result_t parse_execution_context_t::populate_job_process(
|
|||
break;
|
||||
}
|
||||
case symbol_block_statement:
|
||||
case symbol_if_statement:
|
||||
case symbol_switch_statement: {
|
||||
result = this->populate_block_process(job, proc, specific_statement);
|
||||
result = this->populate_block_process(
|
||||
job, proc, tnode_t<g::block_statement>(&tree(), &specific_statement));
|
||||
break;
|
||||
case symbol_if_statement:
|
||||
result = this->populate_block_process(
|
||||
job, proc, tnode_t<g::if_statement>(&tree(), &specific_statement));
|
||||
break;
|
||||
case symbol_switch_statement:
|
||||
result = this->populate_block_process(
|
||||
job, proc, tnode_t<g::switch_statement>(&tree(), &specific_statement));
|
||||
break;
|
||||
}
|
||||
case symbol_decorated_statement: {
|
||||
// Get the plain statement. It will pull out the decoration itself.
|
||||
tnode_t<g::decorated_statement> dec_stat{&tree(), &specific_statement};
|
||||
|
|
|
@ -90,8 +90,10 @@ class parse_execution_context_t {
|
|||
job_t *job, process_t *proc, tnode_t<grammar::boolean_statement> bool_statement);
|
||||
parse_execution_result_t populate_plain_process(job_t *job, process_t *proc,
|
||||
tnode_t<grammar::plain_statement> statement);
|
||||
|
||||
template <typename Type>
|
||||
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
||||
const parse_node_t &statement_node);
|
||||
tnode_t<Type> statement_node);
|
||||
|
||||
// These encapsulate the actual logic of various (block) statements.
|
||||
parse_execution_result_t run_block_statement(tnode_t<grammar::block_statement> statement);
|
||||
|
@ -113,7 +115,8 @@ class parse_execution_context_t {
|
|||
globspec_t glob_behavior);
|
||||
|
||||
// Determines the IO chain. Returns true on success, false on error.
|
||||
bool determine_io_chain(const parse_node_t &statement, io_chain_t *out_chain);
|
||||
bool determine_io_chain(tnode_t<grammar::arguments_or_redirections_list> node,
|
||||
io_chain_t *out_chain);
|
||||
|
||||
parse_execution_result_t run_1_job(const parse_node_t &job_node,
|
||||
const block_t *associated_block);
|
||||
|
|
|
@ -1331,6 +1331,23 @@ enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_st
|
|||
return static_cast<parse_bool_statement_type_t>(stmt.tag());
|
||||
}
|
||||
|
||||
enum token_type redirection_type(tnode_t<grammar::redirection> redirection, const wcstring &src,
|
||||
int *out_fd, wcstring *out_target) {
|
||||
assert(redirection && "redirection is missing");
|
||||
enum token_type result = TOK_NONE;
|
||||
tnode_t<grammar::tok_redirection> prim = redirection.child<0>(); // like 2>
|
||||
assert(prim && "expected to have primitive");
|
||||
|
||||
if (prim.has_source()) {
|
||||
result = redirection_type_for_string(prim.get_source(src), out_fd);
|
||||
}
|
||||
if (out_target != NULL) {
|
||||
tnode_t<grammar::tok_string> target = redirection.child<1>(); // like &1 or file path
|
||||
*out_target = target ? target.get_source(src) : wcstring();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
||||
bool include_first) const {
|
||||
// Moderately nasty hack! Walk up our ancestor chain and see if we are in a job_continuation.
|
||||
|
@ -1360,25 +1377,6 @@ bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
|||
return result;
|
||||
}
|
||||
|
||||
enum token_type parse_node_tree_t::type_for_redirection(const parse_node_t &redirection_node,
|
||||
const wcstring &src, int *out_fd,
|
||||
wcstring *out_target) const {
|
||||
assert(redirection_node.type == symbol_redirection);
|
||||
enum token_type result = TOK_NONE;
|
||||
const parse_node_t *redirection_primitive =
|
||||
this->get_child(redirection_node, 0, parse_token_type_redirection); // like 2>
|
||||
const parse_node_t *redirection_target =
|
||||
this->get_child(redirection_node, 1, parse_token_type_string); // like &1 or file path
|
||||
|
||||
if (redirection_primitive != NULL && redirection_primitive->has_source()) {
|
||||
result = redirection_type_for_string(redirection_primitive->get_source(src), out_fd);
|
||||
}
|
||||
if (out_target != NULL) {
|
||||
*out_target = redirection_target ? redirection_target->get_source(src) : L"";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const parse_node_t *parse_node_tree_t::header_node_for_block_statement(
|
||||
const parse_node_t &node) const {
|
||||
const parse_node_t *result = NULL;
|
||||
|
|
|
@ -200,10 +200,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
|
|||
/// only the second or additional commands are.
|
||||
bool statement_is_in_pipeline(const parse_node_t &node, bool include_first) const;
|
||||
|
||||
/// Given a redirection, get the redirection type (or TOK_NONE) and target (file path, or fd).
|
||||
enum token_type type_for_redirection(const parse_node_t &node, const wcstring &src, int *out_fd,
|
||||
wcstring *out_target) const;
|
||||
|
||||
/// If the given node is a block statement, returns the header node (for_header, while_header,
|
||||
/// begin_header, or function_header). Otherwise returns NULL.
|
||||
const parse_node_t *header_node_for_block_statement(const parse_node_t &node) const;
|
||||
|
@ -428,6 +424,10 @@ parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> st
|
|||
/// Return the type for a boolean statement.
|
||||
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt);
|
||||
|
||||
/// Given a redirection, get the redirection type (or TOK_NONE) and target (file path, or fd).
|
||||
enum token_type redirection_type(tnode_t<grammar::redirection> redirection, const wcstring &src,
|
||||
int *out_fd, wcstring *out_target);
|
||||
|
||||
/// Return the arguments under an arguments_list or arguments_or_redirection_list
|
||||
using arguments_node_list_t = std::vector<tnode_t<grammar::argument>>;
|
||||
arguments_node_list_t get_argument_nodes(tnode_t<grammar::argument_list>);
|
||||
|
|
Loading…
Reference in New Issue
Block a user