mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-14 17:07:44 +00:00
Continued adoption of tnode_t in parse_execution
Migrate boolean statements
This commit is contained in:
parent
7a3d5ddeae
commit
8a14a4a5ff
5 changed files with 25 additions and 30 deletions
|
@ -1002,11 +1002,10 @@ bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement
|
|||
}
|
||||
|
||||
parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
||||
job_t *job, process_t *proc, const parse_node_t &bool_statement) {
|
||||
job_t *job, process_t *proc, tnode_t<g::boolean_statement> bool_statement) {
|
||||
// Handle a boolean statement.
|
||||
bool skip_job = false;
|
||||
assert(bool_statement.type == symbol_boolean_statement);
|
||||
switch (parse_node_tree_t::statement_boolean_type(bool_statement)) {
|
||||
switch (bool_statement_type(bool_statement)) {
|
||||
case parse_bool_and: {
|
||||
// AND. Skip if the last job failed.
|
||||
skip_job = (proc_get_last_status() != 0);
|
||||
|
@ -1027,8 +1026,8 @@ parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
|||
if (skip_job) {
|
||||
return parse_execution_skipped;
|
||||
}
|
||||
const parse_node_t &subject = *tree().get_child(bool_statement, 1, symbol_statement);
|
||||
return this->populate_job_process(job, proc, subject);
|
||||
return this->populate_job_process(job, proc,
|
||||
bool_statement.require_get_child<g::statement, 1>());
|
||||
}
|
||||
|
||||
parse_execution_result_t parse_execution_context_t::populate_block_process(
|
||||
|
@ -1051,20 +1050,16 @@ parse_execution_result_t parse_execution_context_t::populate_block_process(
|
|||
return parse_execution_success;
|
||||
}
|
||||
|
||||
// Returns a process_t allocated with new. It's the caller's responsibility to delete it (!).
|
||||
parse_execution_result_t parse_execution_context_t::populate_job_process(
|
||||
job_t *job, process_t *proc, const parse_node_t &statement_node) {
|
||||
assert(statement_node.type == symbol_statement);
|
||||
assert(statement_node.child_count == 1);
|
||||
|
||||
job_t *job, process_t *proc, tnode_t<grammar::statement> statement) {
|
||||
// Get the "specific statement" which is boolean / block / if / switch / decorated.
|
||||
const parse_node_t &specific_statement = *get_child(statement_node, 0);
|
||||
const parse_node_t &specific_statement = *get_child(statement, 0);
|
||||
|
||||
parse_execution_result_t result = parse_execution_success;
|
||||
|
||||
switch (specific_statement.type) {
|
||||
case symbol_boolean_statement: {
|
||||
result = this->populate_boolean_process(job, proc, specific_statement);
|
||||
result = this->populate_boolean_process(job, proc, {&tree(), &specific_statement});
|
||||
break;
|
||||
}
|
||||
case symbol_block_statement:
|
||||
|
@ -1100,15 +1095,15 @@ parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(
|
|||
|
||||
// We are going to construct process_t structures for every statement in the job. Get the first
|
||||
// statement.
|
||||
tnode_t<g::statement> statement_node = job_node.child<0>();
|
||||
assert(statement_node);
|
||||
tnode_t<g::statement> statement = job_node.child<0>();
|
||||
assert(statement);
|
||||
|
||||
parse_execution_result_t result = parse_execution_success;
|
||||
|
||||
// Create processes. Each one may fail.
|
||||
process_list_t processes;
|
||||
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);
|
||||
|
||||
// Construct process_ts for job continuations (pipelines), by walking the list until we hit the
|
||||
// terminal (empty) job continuation.
|
||||
|
|
|
@ -85,9 +85,9 @@ class parse_execution_context_t {
|
|||
|
||||
// These create process_t structures from statements.
|
||||
parse_execution_result_t populate_job_process(job_t *job, process_t *proc,
|
||||
const parse_node_t &statement_node);
|
||||
parse_execution_result_t populate_boolean_process(job_t *job, process_t *proc,
|
||||
const parse_node_t &bool_statement);
|
||||
tnode_t<grammar::statement> statement);
|
||||
parse_execution_result_t populate_boolean_process(
|
||||
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,
|
||||
const parse_node_t &statement);
|
||||
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
||||
|
|
|
@ -1327,6 +1327,10 @@ enum parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statemen
|
|||
return decoration;
|
||||
}
|
||||
|
||||
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt) {
|
||||
return static_cast<parse_bool_statement_type_t>(stmt.tag());
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -1429,12 +1433,6 @@ parse_node_tree_t::parse_node_list_t parse_node_tree_t::comment_nodes_for_node(
|
|||
return result;
|
||||
}
|
||||
|
||||
enum parse_bool_statement_type_t parse_node_tree_t::statement_boolean_type(
|
||||
const parse_node_t &node) {
|
||||
assert(node.type == symbol_boolean_statement);
|
||||
return static_cast<parse_bool_statement_type_t>(node.tag);
|
||||
}
|
||||
|
||||
bool parse_node_tree_t::job_should_be_backgrounded(const parse_node_t &job) const {
|
||||
assert(job.type == symbol_job);
|
||||
const parse_node_t *opt_background = get_child(job, 2, symbol_optional_background);
|
||||
|
|
|
@ -222,9 +222,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
|
|||
/// Given a node, return all of its comment nodes.
|
||||
parse_node_list_t comment_nodes_for_node(const parse_node_t &node) const;
|
||||
|
||||
/// Returns the boolean type for a boolean node.
|
||||
static enum parse_bool_statement_type_t statement_boolean_type(const parse_node_t &node);
|
||||
|
||||
/// Given a job, return whether it should be backgrounded, because it has a & specifier.
|
||||
bool job_should_be_backgrounded(const parse_node_t &job) const;
|
||||
|
||||
|
@ -303,6 +300,9 @@ class tnode_t {
|
|||
// return the tag, or 0 if missing.
|
||||
parse_node_tag_t tag() const { return nodeptr ? nodeptr->tag : 0; }
|
||||
|
||||
// return the number of children, or 0 if missing.
|
||||
uint8_t child_count() const { return nodeptr ? nodeptr->child_count : 0; }
|
||||
|
||||
maybe_t<source_range_t> source_range() const {
|
||||
if (!has_source()) return none();
|
||||
return source_range_t{nodeptr->source_start, nodeptr->source_length};
|
||||
|
@ -416,6 +416,9 @@ maybe_t<wcstring> command_for_plain_statement(tnode_t<grammar::plain_statement>
|
|||
/// Return the decoration for a plain statement.
|
||||
parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> stmt);
|
||||
|
||||
/// Return the type for a boolean statement.
|
||||
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt);
|
||||
|
||||
/// The big entry point. Parse a string, attempting to produce a tree for the given goal type.
|
||||
bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags,
|
||||
parse_node_tree_t *output, parse_error_list_t *errors,
|
||||
|
|
|
@ -1068,8 +1068,7 @@ static bool detect_errors_in_backgrounded_job(const parse_node_tree_t &node_tree
|
|||
tnode_t<grammar::statement> next_stmt = next_job.child<0>();
|
||||
if (auto bool_stmt = next_stmt.try_get_child<grammar::boolean_statement, 0>()) {
|
||||
// The next job is indeed a boolean statement.
|
||||
parse_bool_statement_type_t bool_type =
|
||||
parse_node_tree_t::statement_boolean_type(*bool_stmt.node());
|
||||
parse_bool_statement_type_t bool_type = bool_statement_type(bool_stmt);
|
||||
if (bool_type == parse_bool_and) { // this is not allowed
|
||||
errored = append_syntax_error(parse_errors, bool_stmt.source_range()->start,
|
||||
BOOL_AFTER_BACKGROUND_ERROR_MSG, L"and");
|
||||
|
@ -1145,7 +1144,7 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
|
|||
has_unclosed_block = true;
|
||||
} else if (node.type == symbol_boolean_statement) {
|
||||
// 'or' and 'and' can be in a pipeline, as long as they're first.
|
||||
parse_bool_statement_type_t type = parse_node_tree_t::statement_boolean_type(node);
|
||||
parse_bool_statement_type_t type = bool_statement_type({&node_tree, &node});
|
||||
if ((type == parse_bool_and || type == parse_bool_or) &&
|
||||
node_tree.statement_is_in_pipeline(node, false /* don't count first */)) {
|
||||
errored = append_syntax_error(&parse_errors, node.source_start, EXEC_ERR_MSG,
|
||||
|
|
Loading…
Reference in a new issue