Make block_type_t an enum class

This commit is contained in:
ridiculousfish 2019-12-22 15:37:14 -08:00
parent 4529e7d183
commit a59f35a378
13 changed files with 129 additions and 124 deletions

View file

@ -165,7 +165,7 @@ void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *
// If it's an error, redirect the output of __fish_print_help to stderr
ios.push_back(std::make_shared<io_fd_t>(STDOUT_FILENO, STDERR_FILENO));
}
parser.eval(cmd, ios, TOP);
parser.eval(cmd, ios, block_type_t::top);
// ignore the exit status of __fish_print_help
}
@ -265,11 +265,11 @@ static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar
// Paranoia: ensure we have a real loop.
bool has_loop = false;
for (const auto &b : parser.blocks()) {
if (b.type() == WHILE || b.type() == FOR) {
if (b.type() == block_type_t::while_block || b.type() == block_type_t::for_block) {
has_loop = true;
break;
}
if (b.is_function()) break;
if (b.is_function_call()) break;
}
if (!has_loop) {
wcstring error_message = format_string(_(L"%ls: Not inside of loop\n"), argv[0]);
@ -298,7 +298,7 @@ static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t *
// Ensure we don't allow creating a breakpoint at an interactive prompt. There may be a simpler
// or clearer way to do this but this works.
const block_t *block1 = parser.block_at_index(1);
if (!block1 || block1->type() == BREAKPOINT) {
if (!block1 || block1->type() == block_type_t::breakpoint) {
streams.err.append_format(_(L"%ls: Command not valid at an interactive prompt\n"), cmd);
return STATUS_ILLEGAL_CMD;
}

View file

@ -117,8 +117,7 @@ int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
break;
}
case UNSET: {
while (block != nullptr && block->type() != FUNCTION_CALL &&
block->type() != FUNCTION_CALL_NO_SHADOW) {
while (block && !block->is_function_call()) {
// Set it in function scope
block = parser.block_at_index(++block_idx);
}

View file

@ -27,7 +27,7 @@ int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
const auto cached_exec_count = parser.libdata().exec_count;
int status = STATUS_CMD_OK;
if (argc > 1) {
if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::TOP) !=
if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::top) !=
eval_result_t::ok) {
status = STATUS_CMD_ERROR;
} else if (cached_exec_count == parser.libdata().exec_count) {

View file

@ -93,7 +93,7 @@ int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
// Find the function block.
bool has_function_block = false;
for (const auto &b : parser.blocks()) {
if (b.is_function()) {
if (b.is_function_call()) {
has_function_block = true;
break;
}

View file

@ -286,7 +286,7 @@ static void event_fire_internal(parser_t &parser, const event_t &event) {
auto prev_statuses = parser.get_last_statuses();
block_t *b = parser.push_block(block_t::event_block(event));
parser.eval(buffer, io_chain_t(), TOP);
parser.eval(buffer, io_chain_t(), block_type_t::top);
parser.pop_block(b);
parser.set_last_statuses(std::move(prev_statuses));
}

View file

@ -733,7 +733,7 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job
tnode_t<grammar::statement> node = p->internal_block_node;
assert(source && node && "Process is missing node info");
return [=](parser_t &parser) {
eval_result_t res = parser.eval_node(source, node, TOP, lineage);
eval_result_t res = parser.eval_node(source, node, block_type_t::top, lineage);
switch (res) {
case eval_result_t::ok:
case eval_result_t::error:
@ -758,7 +758,8 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job
const auto &ld = parser.libdata();
auto saved_exec_count = ld.exec_count;
const block_t *fb = function_prepare_environment(parser, *argv, *props);
auto res = parser.eval_node(props->parsed_source, props->body_node, TOP, lineage);
auto res = parser.eval_node(props->parsed_source, props->body_node, block_type_t::top,
lineage);
function_restore_environment(parser, fb);
switch (res) {
@ -1175,7 +1176,7 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstrin
// be null.
std::shared_ptr<io_buffer_t> buffer;
if (auto bufferfill = io_bufferfill_t::create(fd_set_t{}, ld.read_limit)) {
if (parser.eval(cmd, io_chain_t{bufferfill}, SUBST) == eval_result_t::ok) {
if (parser.eval(cmd, io_chain_t{bufferfill}, block_type_t::subst) == eval_result_t::ok) {
subcommand_statuses = parser.get_last_statuses();
}
buffer = io_bufferfill_t::finish(std::move(bufferfill));

View file

@ -228,7 +228,7 @@ static void source_config_in_directory(const wcstring &dir) {
const wcstring cmd = L"builtin source " + escaped_pathname;
parser_t &parser = parser_t::principal_parser();
set_is_within_fish_initialization(true);
parser.eval(cmd, io_chain_t(), TOP);
parser.eval(cmd, io_chain_t(), block_type_t::top);
set_is_within_fish_initialization(false);
}
@ -254,7 +254,7 @@ int run_command_list(std::vector<std::string> *cmds, const io_chain_t &io) {
for (const auto &cmd : *cmds) {
const wcstring cmd_wcs = str2wcstring(cmd);
eval_result_t eval_res = parser.eval(cmd_wcs, io, TOP);
eval_result_t eval_res = parser.eval(cmd_wcs, io, block_type_t::top);
res = (eval_res == eval_result_t::ok ? 0 : 1);
}

View file

@ -1003,16 +1003,17 @@ static void test_parser() {
// Ensure that we don't crash on infinite self recursion and mutual recursion. These must use
// the principal parser because we cannot yet execute jobs on other parsers.
say(L"Testing recursion detection");
parser->eval(L"function recursive ; recursive ; end ; recursive; ", io_chain_t(), TOP);
parser->eval(L"function recursive ; recursive ; end ; recursive; ", io_chain_t(),
block_type_t::top);
#if 0
// This is disabled since it produces a long backtrace. We should find a way to either visually
// compress the backtrace, or disable error spewing.
parser->.eval(L"function recursive1 ; recursive2 ; end ; "
L"function recursive2 ; recursive1 ; end ; recursive1; ", io_chain_t(), TOP);
L"function recursive2 ; recursive1 ; end ; recursive1; ", io_chain_t(), block_type_t::top);
#endif
say(L"Testing empty function name");
parser->eval(L"function '' ; echo fail; exit 42 ; end ; ''", io_chain_t(), TOP);
parser->eval(L"function '' ; echo fail; exit 42 ; end ; ''", io_chain_t(), block_type_t::top);
say(L"Testing eval_args");
completion_list_t comps = parser_t::expand_argument_list(
@ -1032,7 +1033,8 @@ static void test_1_cancellation(const wchar_t *src) {
usleep(delay * 1E6);
pthread_kill(thread, SIGINT);
});
eval_result_t ret = parser_t::principal_parser().eval(src, io_chain_t{filler}, TOP);
eval_result_t ret =
parser_t::principal_parser().eval(src, io_chain_t{filler}, block_type_t::top);
auto buffer = io_bufferfill_t::finish(std::move(filler));
if (buffer->buffer().size() != 0) {
err(L"Expected 0 bytes in out_buff, but instead found %lu bytes, for command %ls\n",
@ -1074,7 +1076,7 @@ static void test_cancellation() {
bool iis = is_interactive_session();
set_interactive_session(true);
const wchar_t *child_self_destructor = L"while true ; sh -c 'sleep .25; kill -s INT $$' ; end";
parser_t::principal_parser().eval(child_self_destructor, io_chain_t(), TOP);
parser_t::principal_parser().eval(child_self_destructor, io_chain_t(), block_type_t::top);
set_interactive_session(iis);
// Restore signal handling.
@ -5198,7 +5200,7 @@ static void test_illegal_command_exit_code() {
parser_t &parser = parser_t::principal_parser();
for (const auto &test : tests) {
parser.eval(test.txt, empty_ios, TOP);
parser.eval(test.txt, empty_ios, block_type_t::top);
int exit_status = parser.get_last_status();
if (exit_status != test.result) {

View file

@ -389,7 +389,7 @@ void inputter_t::mapping_execute(const input_mapping_t &m, bool allow_commands)
// see that until all other commands have also been run.
auto last_statuses = parser_->get_last_statuses();
for (const wcstring &cmd : m.commands) {
parser_->eval(cmd, io_chain_t(), TOP);
parser_->eval(cmd, io_chain_t(), block_type_t::top);
}
parser_->set_last_statuses(std::move(last_statuses));
event_queue_.push_front(char_event_type_t::check_exit);

View file

@ -105,7 +105,7 @@ tnode_t<g::plain_statement> parse_execution_context_t::infinite_recursive_statem
// on function invocation changes, then this check will break.
const block_t *current = parser->block_at_index(0), *parent = parser->block_at_index(1);
bool is_within_function_call =
(current && parent && current->type() == TOP && parent->type() == FUNCTION_CALL);
(current && parent && current->type() == block_type_t::top && parent->is_function_call());
if (!is_within_function_call) {
return {};
}
@ -322,7 +322,7 @@ eval_result_t parse_execution_context_t::run_if_statement(tnode_t<g::if_statemen
eval_result_t parse_execution_context_t::run_begin_statement(tnode_t<g::job_list> contents) {
// Basic begin/end block. Push a scope block, run jobs, pop it
trace_if_enabled(*parser, L"begin");
block_t *sb = parser->push_block(block_t::scope_block(BEGIN));
block_t *sb = parser->push_block(block_t::scope_block(block_type_t::begin));
eval_result_t ret = run_job_list(contents, sb);
parser->pop_block(sb);
trace_if_enabled(*parser, L"end begin");
@ -380,7 +380,7 @@ bool parse_execution_context_t::is_function_context() const {
const block_t *current = parser->block_at_index(0);
const block_t *parent = parser->block_at_index(1);
bool is_within_function_call =
(current && parent && current->type() == TOP && parent->type() == FUNCTION_CALL);
(current && parent && current->type() == block_type_t::top && parent->is_function_call());
return is_within_function_call;
}
@ -1461,7 +1461,7 @@ eval_result_t parse_execution_context_t::eval_node(tnode_t<g::job_list> job_list
}
// Check for stack overflow. The TOP check ensures we only do this for function calls.
if (associated_block->type() == TOP && parser->function_stack_is_overflowing()) {
if (associated_block->type() == block_type_t::top && parser->function_stack_is_overflowing()) {
return this->report_error(job_list, CALL_STACK_LIMIT_EXCEEDED_ERR_MSG);
}
return this->run_job_list(job_list, associated_block);

View file

@ -75,33 +75,6 @@ class io_chain_t;
/// Unknown block description.
#define UNKNOWN_BLOCK N_(L"unknown/invalid block")
/// Data structure to describe a block type, like while blocks, command substitution blocks, etc.
struct block_lookup_entry {
// The block type id. The legal values are defined in parser.h.
block_type_t type;
// The name of the builtin that creates this type of block, if any.
const wchar_t *name;
// A description of this block type.
const wchar_t *desc;
};
/// List of all legal block types.
static const struct block_lookup_entry block_lookup[] = {
{WHILE, L"while", WHILE_BLOCK},
{FOR, L"for", FOR_BLOCK},
{IF, L"if", IF_BLOCK},
{FUNCTION_CALL, nullptr, FUNCTION_CALL_BLOCK},
{FUNCTION_CALL_NO_SHADOW, nullptr, FUNCTION_CALL_NO_SHADOW_BLOCK},
{SWITCH, L"switch", SWITCH_BLOCK},
{TOP, nullptr, TOP_BLOCK},
{SUBST, nullptr, SUBST_BLOCK},
{BEGIN, L"begin", BEGIN_BLOCK},
{SOURCE, L"source", SOURCE_BLOCK},
{EVENT, nullptr, EVENT_BLOCK},
{BREAKPOINT, L"breakpoint", BREAKPOINT_BLOCK},
{VARIABLE_ASSIGNMENT, L"variable assignment", VARIABLE_ASSIGNMENT_BLOCK},
{static_cast<block_type_t>(0), nullptr, nullptr}};
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
wcstring parser_t::user_presentable_path(const wcstring &path) const {
return replace_home_directory_with_tilde(path, vars());
@ -148,17 +121,18 @@ block_t *parser_t::push_block(block_t &&block) {
new_current.src_filename = intern(filename);
}
// Types TOP and SUBST are not considered blocks for the purposes of `status is-block`.
if (type != TOP && type != SUBST) {
// Types top and subst are not considered blocks for the purposes of `status is-block`.
if (type != block_type_t::top && type != block_type_t::subst) {
libdata().is_block = true;
}
if (type == BREAKPOINT) {
if (type == block_type_t::breakpoint) {
libdata().is_breakpoint = true;
}
if (new_current.type() != TOP) {
vars().push(type == FUNCTION_CALL);
if (new_current.type() != block_type_t::top) {
bool shadow = (type == block_type_t::function_call);
vars().push(shadow);
new_current.wants_pop_env = true;
}
@ -181,7 +155,7 @@ void parser_t::pop_block(const block_t *expected) {
// Figure out if `status is-block` should consider us to be in a block now.
bool new_is_block = false;
for (const auto &b : block_list) {
if (b.type() != TOP && b.type() != SUBST) {
if (b.type() != block_type_t::top && b.type() != block_type_t::subst) {
new_is_block = true;
break;
}
@ -191,7 +165,7 @@ void parser_t::pop_block(const block_t *expected) {
// Are we still in a breakpoint?
bool new_is_breakpoint = false;
for (const auto &b : block_list) {
if (b.type() == BREAKPOINT) {
if (b.type() == block_type_t::breakpoint) {
new_is_breakpoint = true;
break;
}
@ -199,11 +173,35 @@ void parser_t::pop_block(const block_t *expected) {
libdata().is_breakpoint = new_is_breakpoint;
}
const wchar_t *parser_t::get_block_desc(int block) const {
for (size_t i = 0; block_lookup[i].desc; i++) {
if (block_lookup[i].type == block) {
return _(block_lookup[i].desc);
}
const wchar_t *parser_t::get_block_desc(block_type_t block) {
switch (block) {
case block_type_t::while_block:
return WHILE_BLOCK;
case block_type_t::for_block:
return FOR_BLOCK;
case block_type_t::if_block:
return IF_BLOCK;
case block_type_t::function_call:
return FUNCTION_CALL_BLOCK;
case block_type_t::function_call_no_shadow:
return FUNCTION_CALL_NO_SHADOW_BLOCK;
case block_type_t::switch_block:
return SWITCH_BLOCK;
case block_type_t::subst:
return SUBST_BLOCK;
case block_type_t::top:
return TOP_BLOCK;
case block_type_t::begin:
return BEGIN_BLOCK;
case block_type_t::source:
return SOURCE_BLOCK;
case block_type_t::event:
return EVENT_BLOCK;
case block_type_t::breakpoint:
return BREAKPOINT_BLOCK;
case block_type_t::variable_assignment:
return VARIABLE_ASSIGNMENT_BLOCK;
}
return _(UNKNOWN_BLOCK);
}
@ -339,7 +337,7 @@ std::shared_ptr<parser_t> parser_t::shared() { return shared_from_this(); }
wcstring parser_t::stack_trace() const {
wcstring trace;
for (const auto &b : blocks()) {
if (b.type() == EVENT) {
if (b.type() == block_type_t::event) {
// This is an event handler.
assert(b.event && "Should have an event");
wcstring description = event_get_desc(*b.event);
@ -353,18 +351,19 @@ wcstring parser_t::stack_trace() const {
break;
}
if (b.type() == FUNCTION_CALL || b.type() == FUNCTION_CALL_NO_SHADOW ||
b.type() == SOURCE || b.type() == SUBST) {
if (b.type() == block_type_t::function_call ||
b.type() == block_type_t::function_call_no_shadow || b.type() == block_type_t::source ||
b.type() == block_type_t::subst) {
// These types of blocks should be printed.
switch (b.type()) {
case SOURCE: {
case block_type_t::source: {
const wchar_t *source_dest = b.sourced_file;
append_format(trace, _(L"from sourcing file %ls\n"),
user_presentable_path(source_dest).c_str());
break;
}
case FUNCTION_CALL:
case FUNCTION_CALL_NO_SHADOW: {
case block_type_t::function_call:
case block_type_t::function_call_no_shadow: {
append_format(trace, _(L"in function '%ls'"), b.function_name.c_str());
// Print arguments on the same line.
wcstring args_str;
@ -385,7 +384,7 @@ wcstring parser_t::stack_trace() const {
trace.push_back('\n');
break;
}
case SUBST: {
case block_type_t::subst: {
append_format(trace, _(L"in command substitution\n"));
break;
}
@ -422,9 +421,9 @@ const wchar_t *parser_t::is_function(size_t idx) const {
for (size_t block_idx = idx; block_idx < block_list.size(); block_idx++) {
const block_t &b = block_list[block_idx];
if (b.is_function()) {
if (b.is_function_call()) {
return b.function_name.c_str();
} else if (b.type() == SOURCE) {
} else if (b.type() == block_type_t::source) {
// If a function sources a file, obviously that function's offset doesn't
// contribute.
break;
@ -442,9 +441,9 @@ const wchar_t *parser_t::get_function_name(int level) {
// Walk until we find a breakpoint, then take the next function.
bool found_breakpoint = false;
for (const auto &b : block_list) {
if (b.type() == BREAKPOINT) {
if (b.type() == block_type_t::breakpoint) {
found_breakpoint = true;
} else if (found_breakpoint && b.is_function()) {
} else if (found_breakpoint && b.is_function_call()) {
return b.function_name.c_str();
}
}
@ -457,7 +456,7 @@ const wchar_t *parser_t::get_function_name(int level) {
// Level 1 is the topmost function call. Level 2 is its caller. Etc.
int funcs_seen = 0;
for (const auto &b : block_list) {
if (b.is_function()) {
if (b.is_function_call()) {
funcs_seen++;
if (funcs_seen == level) {
return b.function_name.c_str();
@ -479,9 +478,9 @@ const wchar_t *parser_t::current_filename() const {
ASSERT_IS_MAIN_THREAD();
for (const auto &b : block_list) {
if (b.is_function()) {
if (b.is_function_call()) {
return function_get_definition_file(b.function_name);
} else if (b.type() == SOURCE) {
} else if (b.type() == block_type_t::source) {
return b.sourced_file;
}
}
@ -499,7 +498,7 @@ bool parser_t::function_stack_is_overflowing() const {
// Count the functions.
int depth = 0;
for (const auto &b : block_list) {
depth += b.is_function();
depth += b.is_function_call();
}
return depth > FISH_MAX_STACK_DEPTH;
}
@ -620,7 +619,7 @@ eval_result_t parser_t::eval(const wcstring &cmd, const io_chain_t &io,
eval_result_t parser_t::eval(parsed_source_ref_t ps, const io_chain_t &io,
enum block_type_t block_type) {
assert(block_type == TOP || block_type == SUBST);
assert(block_type == block_type_t::top || block_type == block_type_t::subst);
if (!ps->tree.empty()) {
job_lineage_t lineage;
lineage.block_io = io;
@ -648,7 +647,8 @@ eval_result_t parser_t::eval_node(parsed_source_ref_t ps, tnode_t<T> node, block
}
// Only certain blocks are allowed.
assert((block_type == TOP || block_type == SUBST) && "Invalid block type");
assert((block_type == block_type_t::top || block_type == block_type_t::subst) &&
"Invalid block type");
job_reap(*this, false); // not sure why we reap jobs here
@ -728,55 +728,55 @@ block_t::~block_t() = default;
wcstring block_t::description() const {
wcstring result;
switch (this->type()) {
case WHILE: {
case block_type_t::while_block: {
result.append(L"while");
break;
}
case FOR: {
case block_type_t::for_block: {
result.append(L"for");
break;
}
case IF: {
case block_type_t::if_block: {
result.append(L"if");
break;
}
case FUNCTION_CALL: {
case block_type_t::function_call: {
result.append(L"function_call");
break;
}
case FUNCTION_CALL_NO_SHADOW: {
case block_type_t::function_call_no_shadow: {
result.append(L"function_call_no_shadow");
break;
}
case SWITCH: {
case block_type_t::switch_block: {
result.append(L"switch");
break;
}
case SUBST: {
case block_type_t::subst: {
result.append(L"substitution");
break;
}
case TOP: {
case block_type_t::top: {
result.append(L"top");
break;
}
case BEGIN: {
case block_type_t::begin: {
result.append(L"begin");
break;
}
case SOURCE: {
case block_type_t::source: {
result.append(L"source");
break;
}
case EVENT: {
case block_type_t::event: {
result.append(L"event");
break;
}
case BREAKPOINT: {
case block_type_t::breakpoint: {
result.append(L"breakpoint");
break;
}
case VARIABLE_ASSIGNMENT: {
case block_type_t::variable_assignment: {
result.append(L"variable_assignment");
break;
}
@ -793,33 +793,35 @@ wcstring block_t::description() const {
// Various block constructors.
block_t block_t::if_block() { return block_t(IF); }
block_t block_t::if_block() { return block_t(block_type_t::if_block); }
block_t block_t::event_block(event_t evt) {
block_t b{EVENT};
block_t b{block_type_t::event};
b.event = std::move(evt);
return b;
}
block_t block_t::function_block(wcstring name, wcstring_list_t args, bool shadows) {
block_t b{shadows ? FUNCTION_CALL : FUNCTION_CALL_NO_SHADOW};
block_t b{shadows ? block_type_t::function_call : block_type_t::function_call_no_shadow};
b.function_name = std::move(name);
b.function_args = std::move(args);
return b;
}
block_t block_t::source_block(const wchar_t *src) {
block_t b{SOURCE};
block_t b{block_type_t::source};
b.sourced_file = src;
return b;
}
block_t block_t::for_block() { return block_t{FOR}; }
block_t block_t::while_block() { return block_t{WHILE}; }
block_t block_t::switch_block() { return block_t{SWITCH}; }
block_t block_t::for_block() { return block_t{block_type_t::for_block}; }
block_t block_t::while_block() { return block_t{block_type_t::while_block}; }
block_t block_t::switch_block() { return block_t{block_type_t::switch_block}; }
block_t block_t::scope_block(block_type_t type) {
assert((type == BEGIN || type == TOP || type == SUBST) && "Invalid scope type");
assert(
(type == block_type_t::begin || type == block_type_t::top || type == block_type_t::subst) &&
"Invalid scope type");
return block_t(type);
}
block_t block_t::breakpoint_block() { return block_t(BREAKPOINT); }
block_t block_t::variable_assignment_block() { return block_t(VARIABLE_ASSIGNMENT); }
block_t block_t::breakpoint_block() { return block_t(block_type_t::breakpoint); }
block_t block_t::variable_assignment_block() { return block_t(block_type_t::variable_assignment); }

View file

@ -31,20 +31,20 @@ inline bool event_block_list_blocks_type(const event_blockage_list_t &ebls) {
}
/// Types of blocks.
enum block_type_t {
WHILE, /// While loop block
FOR, /// For loop block
IF, /// If block
FUNCTION_CALL, /// Function invocation block
FUNCTION_CALL_NO_SHADOW, /// Function invocation block with no variable shadowing
SWITCH, /// Switch block
SUBST, /// Command substitution scope
TOP, /// Outermost block
BEGIN, /// Unconditional block
SOURCE, /// Block created by the . (source) builtin
EVENT, /// Block created on event notifier invocation
BREAKPOINT, /// Breakpoint block
VARIABLE_ASSIGNMENT, /// Variable assignment before a command
enum class block_type_t {
while_block, /// While loop block
for_block, /// For loop block
if_block, /// If block
function_call, /// Function invocation block
function_call_no_shadow, /// Function invocation block with no variable shadowing
switch_block, /// Switch block
subst, /// Command substitution scope
top, /// Outermost block
begin, /// Unconditional block
source, /// Block created by the . (source) builtin
event, /// Block created on event notifier invocation
breakpoint, /// Breakpoint block
variable_assignment, /// Variable assignment before a command
};
/// Possible states for a loop.
@ -91,8 +91,9 @@ class block_t {
wcstring description() const;
/// \return if we are a function call (with or without shadowing).
bool is_function() const {
return type() == FUNCTION_CALL || type() == FUNCTION_CALL_NO_SHADOW;
bool is_function_call() const {
return type() == block_type_t::function_call ||
type() == block_type_t::function_call_no_shadow;
}
/// Entry points for creating blocks.
@ -329,7 +330,7 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
void pop_block(const block_t *expected);
/// Return a description of the given blocktype.
const wchar_t *get_block_desc(int block) const;
static const wchar_t *get_block_desc(block_type_t block);
/// Return the function name for the specified stack frame. Default is one (current frame).
const wchar_t *get_function_name(int level = 1);

View file

@ -1952,7 +1952,7 @@ void reader_run_command(parser_t &parser, const wcstring &cmd) {
gettimeofday(&time_before, nullptr);
parser.eval(cmd, io_chain_t(), TOP);
parser.eval(cmd, io_chain_t(), block_type_t::top);
job_reap(parser, true);
gettimeofday(&time_after, nullptr);
@ -2205,7 +2205,7 @@ void reader_bg_job_warning(const parser_t &parser) {
static void handle_end_loop(const parser_t &parser) {
if (!reader_exit_forced()) {
for (const auto &b : parser.blocks()) {
if (b.type() == BREAKPOINT) {
if (b.type() == block_type_t::breakpoint) {
// We're executing within a breakpoint so we do not want to terminate the shell and
// kill background jobs.
return;
@ -3551,7 +3551,7 @@ static int read_ni(parser_t &parser, int fd, const io_chain_t &io) {
parsed_source_ref_t pstree;
if (!parse_util_detect_errors(str, &errors, false /* do not accept incomplete */,
&pstree)) {
parser.eval(pstree, io, TOP);
parser.eval(pstree, io, block_type_t::top);
} else {
wcstring sb;
parser.get_backtrace(str, errors, sb);