Clean up various block types and state as part of new parser

This commit is contained in:
ridiculousfish 2014-03-02 13:46:30 -08:00
parent 6b3a37c597
commit cc12225142
4 changed files with 22 additions and 158 deletions

View File

@ -3309,78 +3309,6 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
} }
/**
Builtin for looping over a list
*/
static int builtin_for(parser_t &parser, wchar_t **argv)
{
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_ERROR;
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_ERROR;
}
if (argc < 3)
{
append_format(stderr_buffer,
BUILTIN_FOR_ERR_COUNT,
argv[0] ,
argc);
builtin_print_help(parser, argv[0], stderr_buffer);
}
else if (wcsvarname(argv[1]))
{
append_format(stderr_buffer,
BUILTIN_FOR_ERR_NAME,
argv[0],
argv[1]);
builtin_print_help(parser, argv[0], stderr_buffer);
}
else if (wcscmp(argv[2], L"in") != 0)
{
append_format(stderr_buffer,
BUILTIN_FOR_ERR_IN,
argv[0]);
builtin_print_help(parser, argv[0], stderr_buffer);
}
else
{
res=0;
}
if (res)
{
parser.push_block(new fake_block_t());
}
else
{
const wchar_t *for_variable = argv[1];
for_block_t *fb = new for_block_t(for_variable);
parser.push_block(fb);
fb->tok_pos = parser.get_pos();
/* Note that we store the sequence of values in opposite order */
wcstring_list_t &for_vars = fb->sequence;
for (int i=argc-1; i>3; i--)
for_vars.push_back(argv[i]);
if (argc > 3)
{
env_set(for_variable, argv[3], ENV_LOCAL);
}
else
{
parser.current_block()->skip=1;
}
}
return res;
}
/** /**
This function handles both the 'continue' and the 'break' builtins This function handles both the 'continue' and the 'break' builtins
that are used for loop control. that are used for loop control.
@ -3509,7 +3437,6 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
for (size_t i=0; i < function_block_idx; i++) for (size_t i=0; i < function_block_idx; i++)
{ {
block_t *b = parser.block_at_index(i); block_t *b = parser.block_at_index(i);
b->mark_as_fake();
b->skip = true; b->skip = true;
} }
parser.block_at_index(function_block_idx)->skip = true; parser.block_at_index(function_block_idx)->skip = true;
@ -3734,7 +3661,7 @@ static const builtin_data_t builtin_datas[]=
{ L"exec", &builtin_generic, N_(L"Run command in current process") }, { L"exec", &builtin_generic, N_(L"Run command in current process") },
{ L"exit", &builtin_exit, N_(L"Exit the shell") }, { L"exit", &builtin_exit, N_(L"Exit the shell") },
{ L"fg", &builtin_fg, N_(L"Send job to foreground") }, { L"fg", &builtin_fg, N_(L"Send job to foreground") },
{ L"for", &builtin_for, N_(L"Perform a set of commands multiple times") }, { L"for", &builtin_generic, N_(L"Perform a set of commands multiple times") },
{ L"function", &builtin_generic, N_(L"Define a new function") }, { L"function", &builtin_generic, N_(L"Define a new function") },
{ L"functions", &builtin_functions, N_(L"List or remove functions") }, { L"functions", &builtin_functions, N_(L"List or remove functions") },
{ L"history", &builtin_history, N_(L"History of commands executed by user") }, { L"history", &builtin_history, N_(L"History of commands executed by user") },

View File

@ -447,7 +447,7 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
/* Get the contents to iterate over. */ /* Get the contents to iterate over. */
const parse_node_t *unmatched_wildcard = NULL; const parse_node_t *unmatched_wildcard = NULL;
wcstring_list_t argument_list = this->determine_arguments(header, &unmatched_wildcard); wcstring_list_t argument_sequence = this->determine_arguments(header, &unmatched_wildcard);
if (unmatched_wildcard != NULL) if (unmatched_wildcard != NULL)
{ {
return report_unmatched_wildcard_error(*unmatched_wildcard); return report_unmatched_wildcard_error(*unmatched_wildcard);
@ -455,15 +455,12 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
parse_execution_result_t ret = parse_execution_success; parse_execution_result_t ret = parse_execution_success;
for_block_t *fb = new for_block_t(for_var_name); for_block_t *fb = new for_block_t();
parser->push_block(fb); parser->push_block(fb);
/* Note that we store the sequence of values in opposite order */
std::reverse(argument_list.begin(), argument_list.end());
fb->sequence = argument_list;
/* Now drive the for loop. */ /* Now drive the for loop. */
while (! fb->sequence.empty()) const size_t arg_count = argument_sequence.size();
for (size_t i=0; i < arg_count; i++)
{ {
if (should_cancel_execution(fb)) if (should_cancel_execution(fb))
{ {
@ -471,10 +468,8 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
break; break;
} }
const wcstring &for_variable = fb->variable; const wcstring &val = argument_sequence.at(i);
const wcstring &val = fb->sequence.back(); env_set(for_var_name, val.c_str(), ENV_LOCAL);
env_set(for_variable, val.c_str(), ENV_LOCAL);
fb->sequence.pop_back();
fb->loop_status = LOOP_NORMAL; fb->loop_status = LOOP_NORMAL;
fb->skip = 0; fb->skip = 0;
@ -551,7 +546,7 @@ parse_execution_result_t parse_execution_context_t::run_switch_statement(const p
} }
const wcstring &switch_value_expanded = switch_values_expanded.at(0).completion; const wcstring &switch_value_expanded = switch_values_expanded.at(0).completion;
switch_block_t *sb = new switch_block_t(switch_value_expanded); switch_block_t *sb = new switch_block_t();
parser->push_block(sb); parser->push_block(sb);
if (result == parse_execution_success) if (result == parse_execution_success)
@ -620,7 +615,6 @@ parse_execution_result_t parse_execution_context_t::run_while_statement(const pa
/* Push a while block */ /* Push a while block */
while_block_t *wb = new while_block_t(); while_block_t *wb = new while_block_t();
wb->status = WHILE_TEST_FIRST;
wb->node_offset = this->get_offset(header); wb->node_offset = this->get_offset(header);
parser->push_block(wb); parser->push_block(wb);

View File

@ -249,7 +249,9 @@ void parser_t::push_block(block_t *new_current)
const block_t *old_current = this->current_block(); const block_t *old_current = this->current_block();
if (old_current && old_current->skip) if (old_current && old_current->skip)
new_current->mark_as_fake(); {
new_current->skip = true;
}
/* /*
New blocks should be skipped if the outer block is skipped, New blocks should be skipped if the outer block is skipped,
@ -1407,7 +1409,6 @@ void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &erro
block_t::block_t(block_type_t t) : block_t::block_t(block_type_t t) :
block_type(t), block_type(t),
made_fake(false),
skip(), skip(),
had_command(), had_command(),
tok_pos(), tok_pos(),
@ -1427,12 +1428,7 @@ block_t::~block_t()
/* Various block constructors */ /* Various block constructors */
if_block_t::if_block_t() : if_block_t::if_block_t() : block_t(IF)
block_t(IF),
if_expr_evaluated(false),
is_elseif_entry(false),
any_branch_taken(false),
else_evaluated(false)
{ {
} }
@ -1455,45 +1451,28 @@ source_block_t::source_block_t(const wchar_t *src) :
{ {
} }
for_block_t::for_block_t(const wcstring &var) : for_block_t::for_block_t() : block_t(FOR)
block_t(FOR),
variable(var),
sequence()
{ {
} }
while_block_t::while_block_t() : while_block_t::while_block_t() : block_t(WHILE)
block_t(WHILE),
status(0)
{ {
} }
switch_block_t::switch_block_t(const wcstring &sv) : switch_block_t::switch_block_t() : block_t(SWITCH)
block_t(SWITCH),
switch_taken(false),
switch_value(sv)
{ {
} }
fake_block_t::fake_block_t() : fake_block_t::fake_block_t() : block_t(FAKE)
block_t(FAKE)
{ {
} }
function_def_block_t::function_def_block_t() : scope_block_t::scope_block_t(block_type_t type) : block_t(type)
block_t(FUNCTION_DEF),
function_data()
{
}
scope_block_t::scope_block_t(block_type_t type) :
block_t(type)
{ {
assert(type == BEGIN || type == TOP || type == SUBST); assert(type == BEGIN || type == TOP || type == SUBST);
} }
breakpoint_block_t::breakpoint_block_t() : breakpoint_block_t::breakpoint_block_t() : block_t(BREAKPOINT)
block_t(BREAKPOINT)
{ {
} }

View File

@ -64,8 +64,7 @@ enum block_type_t
SOURCE, /**< Block created by the . (source) builtin */ SOURCE, /**< Block created by the . (source) builtin */
EVENT, /**< Block created on event notifier invocation */ EVENT, /**< Block created on event notifier invocation */
BREAKPOINT, /**< Breakpoint block */ BREAKPOINT, /**< Breakpoint block */
} };
;
/** /**
block_t represents a block of commands. block_t represents a block of commands.
@ -78,18 +77,11 @@ protected:
private: private:
const block_type_t block_type; /**< Type of block. */ const block_type_t block_type; /**< Type of block. */
bool made_fake;
public: public:
block_type_t type() const block_type_t type() const
{ {
return this->made_fake ? FAKE : this->block_type; return this->block_type;
}
/** Mark a block as fake; this is used by the return statement. */
void mark_as_fake()
{
this->made_fake = true;
} }
bool skip; /**< Whether execution of the commands in this block should be skipped */ bool skip; /**< Whether execution of the commands in this block should be skipped */
@ -122,11 +114,6 @@ public:
struct if_block_t : public block_t struct if_block_t : public block_t
{ {
bool if_expr_evaluated; // whether we've evaluated the if expression
bool is_elseif_entry; // whether we're at the beginning of an ELSEIF branch
bool any_branch_taken; // whether the clause of the if statement or any elseif has been found to be true
bool else_evaluated; // whether we've encountered a terminal else block
if_block_t(); if_block_t();
}; };
@ -151,22 +138,17 @@ struct source_block_t : public block_t
struct for_block_t : public block_t struct for_block_t : public block_t
{ {
wcstring variable; // the variable that will be assigned each value in the sequence for_block_t();
wcstring_list_t sequence; // the sequence of values
for_block_t(const wcstring &var);
}; };
struct while_block_t : public block_t struct while_block_t : public block_t
{ {
int status;
while_block_t(); while_block_t();
}; };
struct switch_block_t : public block_t struct switch_block_t : public block_t
{ {
bool switch_taken; switch_block_t();
const wcstring switch_value;
switch_block_t(const wcstring &sv);
}; };
struct fake_block_t : public block_t struct fake_block_t : public block_t
@ -174,12 +156,6 @@ struct fake_block_t : public block_t
fake_block_t(); fake_block_t();
}; };
struct function_def_block_t : public block_t
{
function_data_t function_data;
function_def_block_t();
};
struct scope_block_t : public block_t struct scope_block_t : public block_t
{ {
scope_block_t(block_type_t type); //must be BEGIN, TOP or SUBST scope_block_t(block_type_t type); //must be BEGIN, TOP or SUBST
@ -201,18 +177,6 @@ enum loop_status
}; };
/**
Possible states for a while block
*/
enum while_status
{
WHILE_TEST_FIRST, /**< This is the first command of the first lap of a while loop */
WHILE_TEST_AGAIN, /**< This is not the first lap of the while loop, but it is the first command of the loop */
WHILE_TESTED, /**< This is not the first command in the loop */
}
;
/** /**
Errors that can be generated by the parser Errors that can be generated by the parser
*/ */