CompuServe Thread

#FOR…BY -1 bug

9 messages in this thread
#8779From: bob hawkinsMay 26, 1989 10:08 PM
Thanks for the reply about .key, but I still don't know why its there. Now I have another, more serious, problem to report, The following program either Gurus (most of the time), or fails to stop when i=0, wrapping around to i=65535 and continuing. In that case, it runs forever. If it runs forever, it does so every time its run: MODULE GuruCall; FROM InOut IMPORT WriteCard, WriteString, WriteLn; VAR i : CARDINAL; BEGIN FOR i := 10 TO 0 BY -1 DO (* This gets the Guru almost every time *) WriteString("Loop index = "); WriteCard (i, 10); WriteLn; DEC(i); END; (* FOR *) END GuruCall. If the FOR-statement is replaced by the equivalent WHILE i>0…DEC(i) construct, it works properly. It's the "BY -1" that seems to do it. "FOR i:=0 TO 10 DO" works fine. "BY 2" seems to work OK. I haven't figured out why it Gurus sometimes and runs forever on some compiles. Linking with RTR or just RT didn't make any difference. I am running Kickstart 1.2 with the appropriate SetPatch, WB 1.3, the ARP 1.3 commands and library but not the ARP shell, on an Amiga 1000 with a Starboard 2 meg on the side and four floppies, morerows, FaccII and vd0:.
#8781From: M2S/Phil CampMay 26, 1989 10:10 PM
Hmm, that's wierd. I'll check it out and let you know what's the deal.
#8783From: M2S/Phil CampMay 26, 1989 10:26 PM
The problem lies with the statement DEC(i) within the FOR loop. This is not allowed in the Modula-2 language. Quoting from "Programming in Modula-2" 3rd edition, page 36: (…) "no components of the expression determining the range must be affected by the repeated statements, and, above all, the control variable itself must not be changed by the repeated statements" So basically, you cannot legally attempt to modify the variable "i" within the scope of the FOR loop. You'll see that by removing the DEC(i) statement, all works fine.
#8812From: bob hawkinsMay 28, 1989 9:26 PM
The language doesn't allow it but the compiler accepts it. OK. How about this one: There is a bug in RealInOut.WriteReal. The following program: MODULE Test; FROM TermInOut IMPORT WriteString, WriteCard, WriteLn; FROM MathLib0 INPORT real; FROM RealInOut IMPORT WriteReal; VAR A : REAL; i : CARDINAL; BEGIN FOR i := 1 TO 100 DO A := real(i); WriteString (" ("); WriteCard (i,5); WriteString (") "); WriteReal (A, 12); WriteLn; END; (* FOR i *) END Test. .. produces the following (partial) output: ( 60) 60.00000 ( 61) 61.00000 ( 62) 62.00000 ( 63) 63.00000 ( 64) 640.00000 ( 65) 650.00000 ( 66) 660.00003 … ( 98) 980.00001 ( 99) 990.00005 ( 100) 100.00000 It also seems to have trouble with numbers less than 1.0.
#8817From: M2S/Phil CampMay 28, 1989 10:02 PM
If you download the file M2Fix.zoo from the M2S DL section, that bug will be fixed. The compiler must allow you to modify loop control variables from within the FOR loop. There is no way for it to ensure that you do not. What if one of the statements in the loop calls a procedure which then modifies the control variable? The compiler couldn't possibly track that. although possible some sort of run-time check might be applied (I'd have to think about that one). Anyway, that one thing you always need to keep in mind because it is one of the few things the compiler or runtime system can't catch (at present) in any case, and I haven't seen an M2 compiler that catches it on any system as well.
#8813From: bob hawkinsMay 28, 1989 9:27 PM
And this: I have been encountering major weirdness in the behavior of your compiler. For example, the following line is from a program that compiles and runs under M2Amiga (all variables are REAL): Sum := Sum + R[i,j]*B[j]; Under M2Sprint 1.0, the program crashes when it reaches this point. The M2Debug that I DL'd from here claims the error occurred in some random line of another procedure that has already executed correctly. The line executes once (with i=3, j=4) and bombs the second time through the loop (with i=2, j=3). If I change the line to: Sum := Sum + B[j]*R[i,j]; the program executes and produces correct numbers. Naturally, this behavior does not show up in a short test program, but only in the real program. This is not by any means the only problem; it's the only one reproducible enough for me to be able to describe it.
#8818From: M2S/Phil CampMay 28, 1989 10:05 PM
I'd like you to send me the smallest possible code fragment that can reproduce the problem. That's odd though, you're the only customer having so many problems with the compiler. The few bugs that have been reported have all been fixed in the very-near-to-be-released 1.1 update if that is any consolation.
#8837From: Art SteinmetzMay 30, 1989 9:03 AM
You've already gotten your answer but I'll throw in a couple comments on the code. Using the FOR construct handles incrementing/decrementing the loop index so even if the DEC(i) statement was allowed you'd be decrementing the index by TWO every time through. If that's what you want BY -2 would legally do the job. Another more philosophical issue. Subtraction is certainly a legitimate operation on type CARDINAL but I am a little leery about using a non-CARDINAL type (-1) as your index BY amount. It smacks of uncontrolled type mixing. If I want to put negative numbers into the FOR BY I would use an INTEGER index variable. This is just a matter of style, though. It is also a case for using range checking. I wonder what FOR i := 10 TO 0 BY -3 would do? — Art
#8839From: M2S/Phil CampMay 30, 1989 11:07 AM
Might I add that I recommend never to use the FOR loop construct. It is always faster and smaller code-wise to use either a REPEAT or a WHILE loop (see the file M2Sprint_Tips in the READ_ME drawer for more info on this). Oberon (the new language from Wirth) actually has removed the FOR loop alltogether.