2606 - handle cycles inside stash
The idea is that to-text-line should truncate blindly past some threshold, even if to-text isn't smart enough to avoid infinite loops. Maybe I should define a 'truncating buffer' which stops once it fills up. That would be an easy way to eliminate all infinite loops in to-text-line.
This commit is contained in:
parent
c9b98c21ff
commit
afb467ea02
|
@ -438,25 +438,22 @@ case TRACE_SHOULD_CONTAIN: {
|
|||
:(code)
|
||||
// simplified version of check_trace_contents() that emits errors rather
|
||||
// than just printing to stderr
|
||||
bool check_trace(const string& expected) {
|
||||
void check_trace(const string& expected) {
|
||||
Trace_stream->newline();
|
||||
vector<trace_line> expected_lines = parse_trace(expected);
|
||||
if (expected_lines.empty()) return true;
|
||||
if (expected_lines.empty()) return;
|
||||
long long int curr_expected_line = 0;
|
||||
for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
|
||||
if (expected_lines.at(curr_expected_line).label != p->label) continue;
|
||||
if (expected_lines.at(curr_expected_line).contents != trim(p->contents)) continue;
|
||||
// match
|
||||
++curr_expected_line;
|
||||
if (curr_expected_line == SIZE(expected_lines)) {
|
||||
return true;
|
||||
}
|
||||
if (curr_expected_line == SIZE(expected_lines)) return;
|
||||
}
|
||||
|
||||
raise_error << "missing [" << expected_lines.at(curr_expected_line).contents << "] "
|
||||
<< "in trace with label " << expected_lines.at(curr_expected_line).label << '\n' << end();
|
||||
Passed = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<trace_line> parse_trace(const string& expected) {
|
||||
|
|
|
@ -35,7 +35,7 @@ void rewrite_stashes_to_text_named(recipe& caller) {
|
|||
if (is_literal(inst.ingredients.at(j))) continue;
|
||||
if (is_mu_string(inst.ingredients.at(j))) continue;
|
||||
instruction def;
|
||||
def.name = "to-text";
|
||||
def.name = "to-text-line";
|
||||
def.ingredients.push_back(inst.ingredients.at(j));
|
||||
ostringstream ingredient_name;
|
||||
ingredient_name << "stash_" << stash_instruction_idx << '_' << j << ":address:array:character";
|
||||
|
|
10
070text.mu
10
070text.mu
|
@ -1,6 +1,14 @@
|
|||
# Some useful helpers for dealing with text (arrays of characters)
|
||||
|
||||
# to-text gets called implicitly in various places
|
||||
# to-text-line gets called implicitly in various places
|
||||
# define it to be identical to 'to-text' by default
|
||||
recipe to-text-line x:_elem -> y:address:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- to-text x
|
||||
]
|
||||
|
||||
# to-text on text is just the identity function
|
||||
recipe to-text x:address:array:character -> y:address:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
|
40
073list.mu
40
073list.mu
|
@ -61,6 +61,16 @@ recipe to-text in:address:list:_elem -> result:address:array:character [
|
|||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
# variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)
|
||||
recipe to-text-line in:address:list:_elem -> result:address:array:character [
|
||||
local-scope
|
||||
#? $print [to text line: list], 10/newline
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
buf <- to-buffer in, buf, 6 # max elements to display
|
||||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
|
||||
local-scope
|
||||
#? $print [to buffer: list], 10/newline
|
||||
|
@ -85,7 +95,23 @@ recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer
|
|||
n:number <- length *s
|
||||
buf <- append buf, s
|
||||
# and recurse
|
||||
buf <- to-buffer next, buf
|
||||
remaining:number, optional-ingredient-found?:boolean <- next-ingredient
|
||||
{
|
||||
break-if optional-ingredient-found?
|
||||
# unlimited recursion
|
||||
buf <- to-buffer next, buf
|
||||
reply
|
||||
}
|
||||
{
|
||||
break-unless remaining
|
||||
# limited recursion
|
||||
remaining <- subtract remaining, 1
|
||||
buf <- to-buffer next, buf, remaining
|
||||
reply
|
||||
}
|
||||
# past recursion depth; insert ellipses and stop
|
||||
s:address:array:character <- new [...]
|
||||
append buf, s
|
||||
]
|
||||
|
||||
scenario stash-on-list-converts-to-text [
|
||||
|
@ -99,3 +125,15 @@ scenario stash-on-list-converts-to-text [
|
|||
app: foo foo 6 -> 5 -> 4
|
||||
]
|
||||
]
|
||||
|
||||
scenario stash-handles-list-with-cycle [
|
||||
run [
|
||||
x:address:list:number <- push 4, 0
|
||||
y:address:address:list:number <- get-address *x, next:offset
|
||||
*y <- copy x
|
||||
stash [foo foo], x
|
||||
]
|
||||
trace-should-contain [
|
||||
app: foo foo 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> ...
|
||||
]
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user