From 4768c42f5dcc00ecdbe79f62506bbaf6d7b6faca Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 14 Jan 2018 01:17:57 -0800 Subject: [PATCH] Early adoption of tnode_t in parse_execution.cpp --- src/parse_execution.cpp | 37 ++++++++++++++++++------------------- src/parse_execution.h | 2 +- src/parse_tree.h | 10 ++++++++++ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index 407269a4d..53ffab53d 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -47,6 +47,8 @@ #include "wildcard.h" #include "wutil.h" +namespace g = grammar; + /// These are the specific statement types that support redirections. static bool specific_statement_type_is_redirectable_block(const parse_node_t &node) { return node.type == symbol_block_statement || node.type == symbol_if_statement || @@ -1136,17 +1138,16 @@ parse_execution_result_t parse_execution_context_t::populate_job_process( } parse_execution_result_t parse_execution_context_t::populate_job_from_job_node( - job_t *j, const parse_node_t &job_node, const block_t *associated_block) { + job_t *j, tnode_t job_node, const block_t *associated_block) { UNUSED(associated_block); - assert(job_node.type == symbol_job); // Tell the job what its command is. j->set_command(get_source(job_node)); // We are going to construct process_t structures for every statement in the job. Get the first // statement. - const parse_node_t *statement_node = get_child(job_node, 0, symbol_statement); - assert(statement_node != NULL); + tnode_t statement_node = job_node.child<0>(); + assert(statement_node); parse_execution_result_t result = parse_execution_success; @@ -1157,31 +1158,29 @@ parse_execution_result_t parse_execution_context_t::populate_job_from_job_node( // Construct process_ts for job continuations (pipelines), by walking the list until we hit the // terminal (empty) job continuation. - const parse_node_t *job_cont = get_child(job_node, 1, symbol_job_continuation); - assert(job_cont != NULL); - while (result == parse_execution_success && job_cont->child_count > 0) { - assert(job_cont->type == symbol_job_continuation); + tnode_t job_cont = job_node.child<1>(); + assert(job_cont); + while (auto pipe = job_cont.try_get_child()) { + if (result != parse_execution_success) { + break; + } + tnode_t statement = job_cont.require_get_child(); // Handle the pipe, whose fd may not be the obvious stdout. - const parse_node_t &pipe_node = *get_child(*job_cont, 0, parse_token_type_pipe); - int pipe_write_fd = fd_redirected_by_pipe(get_source(pipe_node)); + int pipe_write_fd = fd_redirected_by_pipe(get_source(pipe)); if (pipe_write_fd == -1) { - result = report_error(pipe_node, ILLEGAL_FD_ERR_MSG, get_source(pipe_node).c_str()); + result = report_error(pipe, ILLEGAL_FD_ERR_MSG, get_source(pipe).c_str()); break; } processes.back()->pipe_write_fd = pipe_write_fd; - // Get the statement node and make a process from it. - const parse_node_t *statement_node = get_child(*job_cont, 1, symbol_statement); - assert(statement_node != NULL); - // Store the new process (and maybe with an error). processes.emplace_back(new process_t()); - result = this->populate_job_process(j, processes.back().get(), *statement_node); + result = this->populate_job_process(j, processes.back().get(), statement); // Get the next continuation. - job_cont = get_child(*job_cont, 2, symbol_job_continuation); - assert(job_cont != NULL); + job_cont = job_cont.require_get_child(); + assert(job_cont); } // Inform our processes of who is first and last @@ -1289,7 +1288,7 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t // Populate the job. This may fail for reasons like command_not_found. If this fails, an error // will have been printed. parse_execution_result_t pop_result = - this->populate_job_from_job_node(job.get(), job_node, associated_block); + this->populate_job_from_job_node(job.get(), {&tree(), &job_node}, associated_block); // Clean up the job on failure or cancellation. bool populated_job = (pop_result == parse_execution_success); diff --git a/src/parse_execution.h b/src/parse_execution.h index c07265098..6b785473e 100644 --- a/src/parse_execution.h +++ b/src/parse_execution.h @@ -118,7 +118,7 @@ class parse_execution_context_t { const block_t *associated_block); parse_execution_result_t run_job_list(const parse_node_t &job_list_node, const block_t *associated_block); - parse_execution_result_t populate_job_from_job_node(job_t *j, const parse_node_t &job_node, + parse_execution_result_t populate_job_from_job_node(job_t *j, tnode_t job_node, const block_t *associated_block); // Returns the line number of the node at the given index, indexed from 0. Not const since it diff --git a/src/parse_tree.h b/src/parse_tree.h index 5a16b0e46..1c7ffc130 100644 --- a/src/parse_tree.h +++ b/src/parse_tree.h @@ -347,6 +347,16 @@ class tnode_t { return {}; } + /// assert that this is not empty and that the child at index Index has the given type, then + /// return that child. Note this will refuse to compile if the child type is not possible. + template + tnode_t require_get_child() const { + assert(nodeptr && "receiver is missing in require_get_child()"); + auto result = try_get_child(); + assert(result && "require_get_child(): wrong child type"); + return result; + } + /// Type-safe access to a node's parent. /// If the parent exists and has type ParentType, return it. /// Otherwise return a missing tnode.