From fa0f552fe9b36e26115c695e7d851f00275ffc4a Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 15 Jan 2018 15:37:13 -0800 Subject: [PATCH] Convert populate_block_process to tnode_t --- src/highlight.cpp | 2 +- src/parse_execution.cpp | 50 +++++++++++++++++++++-------------------- src/parse_execution.h | 7 ++++-- src/parse_tree.cpp | 36 ++++++++++++++--------------- src/parse_tree.h | 8 +++---- 5 files changed, 53 insertions(+), 50 deletions(-) diff --git a/src/highlight.cpp b/src/highlight.cpp index 7904b5f8f..3d44b1fc1 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -839,7 +839,7 @@ void highlighter_t::color_redirection(tnode_t 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; diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index 56d3dd850..19da7f75b 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -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 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(); + for (tnode_t 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()); } -parse_execution_result_t parse_execution_context_t::populate_block_process( - job_t *job, process_t *proc, const parse_node_t &statement_node) { +template +parse_execution_result_t parse_execution_context_t::populate_block_process(job_t *job, + process_t *proc, + tnode_t 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(); 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(&tree(), &specific_statement)); + break; + case symbol_if_statement: + result = this->populate_block_process( + job, proc, tnode_t(&tree(), &specific_statement)); + break; + case symbol_switch_statement: + result = this->populate_block_process( + job, proc, tnode_t(&tree(), &specific_statement)); break; - } case symbol_decorated_statement: { // Get the plain statement. It will pull out the decoration itself. tnode_t dec_stat{&tree(), &specific_statement}; diff --git a/src/parse_execution.h b/src/parse_execution.h index 52d4f3b30..48d29c7d4 100644 --- a/src/parse_execution.h +++ b/src/parse_execution.h @@ -90,8 +90,10 @@ class parse_execution_context_t { job_t *job, process_t *proc, tnode_t bool_statement); parse_execution_result_t populate_plain_process(job_t *job, process_t *proc, tnode_t statement); + + template parse_execution_result_t populate_block_process(job_t *job, process_t *proc, - const parse_node_t &statement_node); + tnode_t statement_node); // These encapsulate the actual logic of various (block) statements. parse_execution_result_t run_block_statement(tnode_t 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 node, + io_chain_t *out_chain); parse_execution_result_t run_1_job(const parse_node_t &job_node, const block_t *associated_block); diff --git a/src/parse_tree.cpp b/src/parse_tree.cpp index bb01aec7d..56f670864 100644 --- a/src/parse_tree.cpp +++ b/src/parse_tree.cpp @@ -1331,6 +1331,23 @@ enum parse_bool_statement_type_t bool_statement_type(tnode_t(stmt.tag()); } +enum token_type redirection_type(tnode_t redirection, const wcstring &src, + int *out_fd, wcstring *out_target) { + assert(redirection && "redirection is missing"); + enum token_type result = TOK_NONE; + tnode_t 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 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; diff --git a/src/parse_tree.h b/src/parse_tree.h index ab0b3a8ce..6d2a2bea6 100644 --- a/src/parse_tree.h +++ b/src/parse_tree.h @@ -200,10 +200,6 @@ class parse_node_tree_t : public std::vector { /// 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 st /// Return the type for a boolean statement. enum parse_bool_statement_type_t bool_statement_type(tnode_t stmt); +/// Given a redirection, get the redirection type (or TOK_NONE) and target (file path, or fd). +enum token_type redirection_type(tnode_t 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>; arguments_node_list_t get_argument_nodes(tnode_t);