Well, do/while stretched my brain, but eventually:
Code:
> list
10 a = 0
30 do
35 b = 0
40 do
50 print a * 10 + b;
60 b = b + 1
70 while b < 10
75 print
80 a = a + 1
90 while a < 10
100 print "done"
> run
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
done
>
It was tricky: the 'do' sits there looking all innocent, but it has to remember where _it_ is, where the start of the loop is, and where the first instruction after the 'while' is. 'While' returns either a null if the expression is true, or the address of the next line if it's time to escape.
This code still has a load of debugging comments, and needs some clearing up of no-longer required branches, but...
Code:
char * do_do (char * where)
{
/* Execute the 'do' clause by calling it recursively; it continues
* until the matching 'while' statement. That statement returns NULL
* if its comparison clause is true, indicating that the loop should
* continue, or the address of the line following 'while'
*/
char * loop_address; // first line in the do loop
char * cont_address; // first line after the while
char * while_address; // the while line number
where -= 4;
//printf ("do at line %d\n", get_line(where));
where = find_next_line (where);
loop_address = where;
while_address = find_pair (where, DO);
cont_address = find_next_line (while_address); // first line after while
//printf ("cont = %d, loop = %d\n",
// get_line(cont_address), get_line(loop_address));
do
{
where = loop_address;
do
{
// when we execute the while, we are returned a NULL if the
// condition is true
//printf("do: executing line %d\n", get_line(where));
where = execute(where);
if (NULL != where)
{
//printf("in do: next line %d\n", get_line(where));
if (get_line(where) == get_line(cont_address))
{
//printf ("break\n");
break;
}
}
else
{
//printf ("inner done, pointing to %d\n", get_line(where));
}
}
while (NULL != where);
}
while (NULL == where);
//while (get_line(where) < get_line(while_address));
return where;
}
uint8_t * do_while (uint8_t * where)
{
/* test a condition; if true, return the value zero
* otherwise, return the address of the next line
*/
if (compare())
{
//printf ("while is true\n");
return NULL;
}
else
{
//printf ("while is false\n");
return find_next_line (where - 4);
}
return where;
}
Like the other loop constructs, it can call itself recursively to allow nesting.
Neil (that took far too long!)