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:
parent
edaa6e6c76
commit
ea3884fa1e
|
|
@ -32,6 +32,8 @@ using namespace std;
|
||||||
* to the target block.
|
* to the target block.
|
||||||
*/
|
*/
|
||||||
static const NetScope*disable = 0;
|
static const NetScope*disable = 0;
|
||||||
|
static bool loop_break;
|
||||||
|
static bool loop_continue;
|
||||||
|
|
||||||
static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs)
|
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);
|
bool cur_flag = cur->evaluate_function(loc, use_context_map);
|
||||||
flag = flag && cur_flag;
|
flag = flag && cur_flag;
|
||||||
} while (cur != last_ && !disable);
|
} while (cur != last_ && !disable && !loop_break && !loop_continue);
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
cerr << get_fileline() << ": NetBlock::evaluate_function: "
|
cerr << get_fileline() << ": NetBlock::evaluate_function: "
|
||||||
|
|
@ -710,6 +712,30 @@ bool NetDisable::evaluate_function(const LineInfo&,
|
||||||
return true;
|
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,
|
bool NetDoWhile::evaluate_function(const LineInfo&loc,
|
||||||
map<perm_string,LocalVar>&context_map) const
|
map<perm_string,LocalVar>&context_map) const
|
||||||
{
|
{
|
||||||
|
|
@ -726,6 +752,13 @@ bool NetDoWhile::evaluate_function(const LineInfo&loc,
|
||||||
if (! flag)
|
if (! flag)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (loop_break) {
|
||||||
|
loop_break = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_continue = false;
|
||||||
|
|
||||||
// Evaluate the condition expression to try and get the
|
// Evaluate the condition expression to try and get the
|
||||||
// condition for the loop.
|
// condition for the loop.
|
||||||
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
||||||
|
|
@ -765,6 +798,13 @@ bool NetForever::evaluate_function(const LineInfo&loc,
|
||||||
|
|
||||||
while (flag && !disable) {
|
while (flag && !disable) {
|
||||||
flag = flag && statement_->evaluate_function(loc, context_map);
|
flag = flag && statement_->evaluate_function(loc, context_map);
|
||||||
|
|
||||||
|
if (loop_break) {
|
||||||
|
loop_break = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_continue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
|
|
@ -818,6 +858,13 @@ bool NetForLoop::evaluate_function(const LineInfo&loc,
|
||||||
if (disable)
|
if (disable)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (loop_break) {
|
||||||
|
loop_break = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_continue = false;
|
||||||
|
|
||||||
tmp_flag = step_statement_->evaluate_function(loc, context_map);
|
tmp_flag = step_statement_->evaluate_function(loc, context_map);
|
||||||
flag &= tmp_flag;
|
flag &= tmp_flag;
|
||||||
}
|
}
|
||||||
|
|
@ -854,6 +901,13 @@ bool NetRepeat::evaluate_function(const LineInfo&loc,
|
||||||
while ((count > 0) && flag && !disable) {
|
while ((count > 0) && flag && !disable) {
|
||||||
flag = flag && statement_->evaluate_function(loc, context_map);
|
flag = flag && statement_->evaluate_function(loc, context_map);
|
||||||
count -= 1;
|
count -= 1;
|
||||||
|
|
||||||
|
if (loop_break) {
|
||||||
|
loop_break = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_continue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
|
|
@ -905,6 +959,13 @@ bool NetWhile::evaluate_function(const LineInfo&loc,
|
||||||
bool tmp_flag = proc_->evaluate_function(loc, context_map);
|
bool tmp_flag = proc_->evaluate_function(loc, context_map);
|
||||||
if (! tmp_flag)
|
if (! tmp_flag)
|
||||||
flag = false;
|
flag = false;
|
||||||
|
|
||||||
|
if (loop_break) {
|
||||||
|
loop_break = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_continue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
|
|
|
||||||
|
|
@ -3068,6 +3068,8 @@ class NetBreak : public NetProc {
|
||||||
public:
|
public:
|
||||||
virtual void dump(std::ostream&, unsigned ind) const;
|
virtual void dump(std::ostream&, unsigned ind) const;
|
||||||
virtual bool emit_proc(struct target_t*) 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:
|
public:
|
||||||
virtual void dump(std::ostream&, unsigned ind) const;
|
virtual void dump(std::ostream&, unsigned ind) const;
|
||||||
virtual bool emit_proc(struct target_t*) const;
|
virtual bool emit_proc(struct target_t*) const;
|
||||||
|
bool evaluate_function(const LineInfo &loc,
|
||||||
|
std::map<perm_string,LocalVar> &ctx) const final;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue