done, but I much prefer the loop version to the last version.
Can't you use a macro processor to generate the verbose code? ;-)
Yes, I would use the Pascal Macro Compiler for this chore, but whether I code it by hand or generate using the PMC, my program still would contain the verbose code.
Anyway, I see that this is an example, at least in theory. However, I'd probably do it differently in practice. I think this is more efficient, since you don't need any comparisons, and in particular no extra code in the innermost loop which is the most time-critical. If you need the original start values afterwards, copy the array before the first loop, of course.
for a1 := start[1] to max[1] do begin for a2 := start[2] to max[2] do begin for a3 := start[3] to max[3] do begin ... end; start[3] := 1 end; start[2] := 1 end;
Frank
This is much nicer code than my version. However I would still choose to make the loop control variables a[1], a[2], a[3], etc., so that when I take the checkpoint the checkpointing procedure could use a loop like
for n := 1 to depth do writeln (checkfile, a[n]);
Incidentally, when I do this in practice I do not usually test for interruptions at every level in the nested loops. If the loops are nested 30 levels deep I might test for user interrupts only at levels 5, 10, 15 and 20. However, if the interrupt occurs at, say, level 15, you still need to write all of the control variable values from 1 through 15 to the checkpoint file.
Frank Rubin
Anyway, I see that this is an example, at least in theory. However, I'd probably do it differently in practice. I think this is more efficient, since you don't need any comparisons, and in particular no extra code in the innermost loop which is the most time-critical. If you need the original start values afterwards, copy the array before the first loop, of course.
for a1 := start[1] to max[1] do begin for a2 := start[2] to max[2] do begin
This is much nicer code than my version. However I would still choose to make the loop control variables a[1], a[2], a[3], etc., so that when I take the checkpoint the checkpointing procedure could use a loop like
for n := 1 to depth do writeln (checkfile, a[n]);
But surely regardless of any of this, even if the compiler refuses to allow a[1] (or much worse a[i]) as an index, any for loop can easily be rewritten in to a while loop a1 := start[1]; while a1 < max[1] do begin ... Inc(a1); end;
(possibly adding a temporary for the maximum if appropriate).
Personally, I don't see any particular reason to restrict the compiler to what can be used for an index variable unless there is some good reason for it. If it significantly simplifies the compiler to only allow index variables that are local simple variables, that's fine. But otherwise, why worry about it, as long as the semantics are clearly spelled out and self consistent, then if the user wants to shoot themselves in the foot with weird uses, that's their own fault. I would suggest implementing a for loop as:
for index := lower to upper do begin whatever; end;
exactly equivalent to:
temp_indexptr := @index; temp_indexptr^ := lower; temp_upper := upper while temp_indexptr^ <= temp_upper do begin whatever; Inc(temp_indexptr^); end;
(expanding for the other options of for loops as required).
Then change the documentation from:
Please note: A modification of the index variable may result in unpredictable action.
to
Please note: A modification of the index variable, or any subpart of it, may result in unpredictable action.
or words to that effect.
Enjoy, Peter.
Peter N Lewis wrote:
Anyway, I see that this is an example, at least in theory. However, I'd probably do it differently in practice. I think this is more efficient, since you don't need any comparisons, and in particular no extra code in the innermost loop which is the most time-critical. If you need the original start values afterwards, copy the array before the first loop, of course.
for a1 := start[1] to max[1] do begin for a2 := start[2] to max[2] do begin
This is much nicer code than my version. However I would still choose to make the loop control variables a[1], a[2], a[3], etc., so that when I take the checkpoint the checkpointing procedure could use a loop like
for n := 1 to depth do writeln (checkfile, a[n]);
But surely regardless of any of this, even if the compiler refuses to allow a[1] (or much worse a[i]) as an index, any for loop can easily be rewritten in to a while loop a1 := start[1]; while a1 < max[1] do begin ... Inc(a1); end;
(possibly adding a temporary for the maximum if appropriate).
Please don't strip attributions for quoted material.
You forget that there are, or were, many machines out there with peculiar looping constructs available. A for can usually be mapped into these if certain restrictions are applied. Thus the prohibition against modifying the for variable, which may not exist within the loop. The terminal condition may then have very little obvious connection with the actual code. Using this looping construct may have major efficiency effects.
One such machine is the HP3000. I suspect the various Burroughs are/were similar. It is a long time since I used these, so the details have become hazy.
Peter N Lewis wrote:
Personally, I don't see any particular reason to restrict the compiler to what can be used for an index variable unless there is some good reason for it. If it significantly simplifies the compiler to only allow index variables that are local simple variables, that's fine. But otherwise, why worry about it, as long as the semantics are clearly spelled out and self consistent, then if the user wants to shoot themselves in the foot with weird uses, that's their own fault. I would suggest implementing a for loop as:
for index := lower to upper do begin whatever; end;
exactly equivalent to:
temp_indexptr := @index; temp_indexptr^ := lower; temp_upper := upper while temp_indexptr^ <= temp_upper do begin whatever; Inc(temp_indexptr^); end;
(expanding for the other options of for loops as required).
But Pascal for-loops are more than while loops. They guarantee that the loop will be executed as specified in the for-clause, without side-effects. I don't see any particular reason to abandon these guarantees.
I might allow constant indicies in BP mode if it's not too much work. In this case, I'll probably have to consider threatening the whole array as dangerous, as we don't track threatening of single fields. Anyway, in BP mode this is a warning only ...
(As a side-note, not related to the actual issue here, the above code would be wrong if temp_upper is the maximum value of the control variable. Then it would produce an out-of-range value, and if not checked, possibly a wrap-around, looping forever. Standard for-loops are described in more complex ways to avoid these problems. See the standards, or actually the BP manual as well, which in this regard mostly copied the text from the standards.)
Then change the documentation from:
Please note: A modification of the index variable may result in unpredictable action.
Oops, I hadn't noticed this wrong statement in the documentation. I'm changing it to this:
@strong{Please note:} A modification of the index variable would result in undefined behaviour. Therefore it is forbidden by the standards, and GPC does not allow it. In some modes for compatibility with other dialects that do not enforce this restriction, GPC only gives a warning. Heed the warning, the behaviour is still undefined.
Frank
We had a problem on the mail server. I'm not sure if this mail was sent corrently, so I'm resending it. Sorry if you get it twice. If anyone else sent a mail to the list in the last few hours, please check the archives and resend if it's not there.
Peter N Lewis wrote:
Personally, I don't see any particular reason to restrict the compiler to what can be used for an index variable unless there is some good reason for it. If it significantly simplifies the compiler to only allow index variables that are local simple variables, that's fine. But otherwise, why worry about it, as long as the semantics are clearly spelled out and self consistent, then if the user wants to shoot themselves in the foot with weird uses, that's their own fault. I would suggest implementing a for loop as:
for index := lower to upper do begin whatever; end;
exactly equivalent to:
temp_indexptr := @index; temp_indexptr^ := lower; temp_upper := upper while temp_indexptr^ <= temp_upper do begin whatever; Inc(temp_indexptr^); end;
(expanding for the other options of for loops as required).
But Pascal for-loops are more than while loops. They guarantee that the loop will be executed as specified in the for-clause, without side-effects. I don't see any particular reason to abandon these guarantees.
I might allow constant indicies in BP mode if it's not too much work. In this case, I'll probably have to consider threatening the whole array as dangerous, as we don't track threatening of single fields. Anyway, in BP mode this is a warning only ...
(As a side-note, not related to the actual issue here, the above code would be wrong if temp_upper is the maximum value of the control variable. Then it would produce an out-of-range value, and if not checked, possibly a wrap-around, looping forever. Standard for-loops are described in more complex ways to avoid these problems. See the standards, or actually the BP manual as well, which in this regard mostly copied the text from the standards.)
Then change the documentation from:
Please note: A modification of the index variable may result in unpredictable action.
Oops, I hadn't noticed this wrong statement in the documentation. I'm changing it to this:
@strong{Please note:} A modification of the index variable would result in undefined behaviour. Therefore it is forbidden by the standards, and GPC does not allow it. In some modes for compatibility with other dialects that do not enforce this restriction, GPC only gives a warning. Heed the warning, the behaviour is still undefined.
Frank