Support continue/break in constant functions

Add support for `continue` and `break` in constant functions. This is done
in a similar way to how `disable` is implemented for constant functions.

Two new global flags are introduced `loop_break` and `loop_continue` that
get set when evaluating the corresponding statement. If either of these
flags are set all other statements are ignored until the end of a loop is
reached. At the end of the loop both `loop_break` and `loop_continue` get
cleared. If `loop_break` was set before clearing it the loop is exited.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2021-12-12 11:40:05 +01:00
parent edaa6e6c76
commit ea3884fa1e
2 changed files with 66 additions and 1 deletions

View File

@ -32,6 +32,8 @@ using namespace std;
* to the target block.
*/
static const NetScope*disable = 0;
static bool loop_break;
static bool loop_continue;
static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs)
{
@ -534,7 +536,7 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
bool cur_flag = cur->evaluate_function(loc, use_context_map);
flag = flag && cur_flag;
} while (cur != last_ && !disable);
} while (cur != last_ && !disable && !loop_break && !loop_continue);
if (debug_eval_tree) {
cerr << get_fileline() << ": NetBlock::evaluate_function: "
@ -710,6 +712,30 @@ bool NetDisable::evaluate_function(const LineInfo&,
return true;
}
bool NetBreak::evaluate_function(const LineInfo&,
map<perm_string, LocalVar>&) const
{
loop_break = true;
if (debug_eval_tree) {
cerr << get_fileline() << ": NetBreak::evaluate_function" << endl;
}
return true;
}
bool NetContinue::evaluate_function(const LineInfo&,
map<perm_string, LocalVar>&) const
{
loop_continue = true;
if (debug_eval_tree) {
cerr << get_fileline() << ": NetContinue::evaluate_function" << endl;
}
return true;
}
bool NetDoWhile::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
@ -726,6 +752,13 @@ bool NetDoWhile::evaluate_function(const LineInfo&loc,
if (! flag)
break;
if (loop_break) {
loop_break = false;
break;
}
loop_continue = false;
// Evaluate the condition expression to try and get the
// condition for the loop.
NetExpr*cond = cond_->evaluate_function(loc, context_map);
@ -765,6 +798,13 @@ bool NetForever::evaluate_function(const LineInfo&loc,
while (flag && !disable) {
flag = flag && statement_->evaluate_function(loc, context_map);
if (loop_break) {
loop_break = false;
break;
}
loop_continue = false;
}
if (debug_eval_tree) {
@ -818,6 +858,13 @@ bool NetForLoop::evaluate_function(const LineInfo&loc,
if (disable)
break;
if (loop_break) {
loop_break = false;
break;
}
loop_continue = false;
tmp_flag = step_statement_->evaluate_function(loc, context_map);
flag &= tmp_flag;
}
@ -854,6 +901,13 @@ bool NetRepeat::evaluate_function(const LineInfo&loc,
while ((count > 0) && flag && !disable) {
flag = flag && statement_->evaluate_function(loc, context_map);
count -= 1;
if (loop_break) {
loop_break = false;
break;
}
loop_continue = false;
}
if (debug_eval_tree) {
@ -905,6 +959,13 @@ bool NetWhile::evaluate_function(const LineInfo&loc,
bool tmp_flag = proc_->evaluate_function(loc, context_map);
if (! tmp_flag)
flag = false;
if (loop_break) {
loop_break = false;
break;
}
loop_continue = false;
}
if (debug_eval_tree) {

View File

@ -3068,6 +3068,8 @@ class NetBreak : public NetProc {
public:
virtual void dump(std::ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
bool evaluate_function(const LineInfo &loc,
std::map<perm_string,LocalVar> &ctx) const final;
};
/*
@ -3222,6 +3224,8 @@ class NetContinue : public NetProc {
public:
virtual void dump(std::ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
bool evaluate_function(const LineInfo &loc,
std::map<perm_string,LocalVar> &ctx) const final;
};
/*