bernhold@qtp.ufl.edu (David E. Bernholdt) (03/11/89)
I run the following code on my Sun 3/50 with VMS compatible f77: PROGRAM LOOP IGO = 1 DO 501 I = 1, 10 WRITE (6,*) 'OUTER LOOP, I =',I IF (IGO .NE. 0) GOTO 501 DO 501 J = 1, 5 WRITE (6,*) 'INNER LOOP, J=',J 501 CONTINUE STOP END And I get the following output: OUTER LOOP, I = 1 INNER LOOP, J= 1 INNER LOOP, J= 2 INNER LOOP, J= 3 INNER LOOP, J= 4 INNER LOOP, J= 5 OUTER LOOP, I = 2 OUTER LOOP, I = 3 OUTER LOOP, I = 4 OUTER LOOP, I = 5 OUTER LOOP, I = 6 OUTER LOOP, I = 7 OUTER LOOP, I = 8 OUTER LOOP, I = 9 OUTER LOOP, I = 10 Notice that the inner DO loop is executed exactly once. My questions are these: 1) Is the code standard-conforming? I think it is, but perhaps I am mistaken. 2) If the code is standard-conforming, is the execution correct? As far as I can tell, the inner DO should never be activated! Please, no flames about the code itself. I did not write it - I just get to port it. -- David Bernholdt bernhold@qtp.ufl.edu Quantum Theory Project bernhold@ufpine.bitnet University of Florida Gainesville, FL 32611 904/392 6365
charlie@mica.stat.washington.edu (Charlie Geyer) (03/12/89)
In article <458@orange19.qtp.ufl.edu> bernhold@qtp.ufl.edu (David E. Bernholdt) writes: > PROGRAM LOOP > IGO = 1 > DO 501 I = 1, 10 > WRITE (6,*) 'OUTER LOOP, I =',I > IF (IGO .NE. 0) GOTO 501 > DO 501 J = 1, 5 > WRITE (6,*) 'INNER LOOP, J=',J > 501 CONTINUE > STOP > END > > 1) Is the code standard-conforming? I think it is, but perhaps I am > mistaken. No. Statement 501 is in the range of the inner DO loop. So the GOTO branches into the range of an inactive loop. This is not allowed. There was a very long discussion about this about a month ago. Some compilers are friendlier about this than others. Two compilers here execute the code the way you expect. But there is no "correct" way to execute this code.
zdenko@csd4.milw.wisc.edu (Zdenko Tomasic) (03/12/89)
In article <458@orange19.qtp.ufl.edu> bernhold@qtp.ufl.edu (David E. Bernholdt) writes: > >I run the following code on my Sun 3/50 with VMS compatible f77: > > PROGRAM LOOP > IGO = 1 > DO 501 I = 1, 10 > WRITE (6,*) 'OUTER LOOP, I =',I > IF (IGO .NE. 0) GOTO 501 ^^^ This branch is illegal > DO 501 J = 1, 5 > WRITE (6,*) 'INNER LOOP, J=',J > 501 CONTINUE ^^^^ since it jumps into the inner loop from outside > STOP > END > (lines to fool stupid inews, hit n key now) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -- ___________________________________________________________________ Zdenko Tomasic, UWM, Chem. Dept., P.O. Box 413, Milwaukee, WI 53201 UUCP: uwvax!uwmcsd1!uwmcsd4!zdenko ARPA: zdenko@csd4.milw.wisc.edu
calvin@dinkum.SGI.COM (Calvin H. Vu) (03/13/89)
I hope this will not turn out (for you) to be like the case of a boy's returning a book about penguin to the publisher with the explanation : "Sorry but this book tells me more about penguins than I ever wanted to know" :-). However, this issue has been discussed before without arriving at any conclusions so I would like to take this opportunity to chip in my 2c. First, to answer your question: << From bernhold@qtp.ufl.edu Sat Mar 11 07:49:54 1989 << I run the following code on my Sun 3/50 with VMS compatible f77: << << PROGRAM LOOP << IGO = 1 << DO 501 I = 1, 10 << WRITE (6,*) 'OUTER LOOP, I =',I << IF (IGO .NE. 0) GOTO 501 << DO 501 J = 1, 5 << WRITE (6,*) 'INNER LOOP, J=',J << 501 CONTINUE << STOP << END << << And I get the following output: << << OUTER LOOP, I = 1 << INNER LOOP, J= 1 << INNER LOOP, J= 2 << INNER LOOP, J= 3 << INNER LOOP, J= 4 << INNER LOOP, J= 5 << OUTER LOOP, I = 2 << OUTER LOOP, I = 3 << OUTER LOOP, I = 4 << OUTER LOOP, I = 5 << OUTER LOOP, I = 6 << OUTER LOOP, I = 7 << OUTER LOOP, I = 8 << OUTER LOOP, I = 9 << OUTER LOOP, I = 10 << << Notice that the inner DO loop is executed exactly once. << The reason the inner loop is executed only once is that there is no code generated by the compiler to determine the currently-active DO loops. Hence the jump to label 501 will execute the loop condition for the inner loop first. As you may guess, the value of J is undefined since the inner loop has never been activated (which causes the DO variable J to be initialized). The first time this jump is taken, J has the value 0 (as the undefined value on most systems but nobody can guarantee this though) and so the inner loop will get activated as if nothing is wrong (NOTE that if your inner loop were DO J=4,5 instead, you will definitely notice something funny going on since the inner loop will still be executed from 1 to 5). On exitting the loop, J will now have the value 6 and so subsequent jump will not cause the inner loop to be executed. To prove this just add one statement to your program as follows: ................ DO 501 I = 1, 10 WRITE (6,*) 'OUTER LOOP, I =',I C Add the following statement to generate a random value from 0 to 6 C for J before the jump is taken and see how randomly the innerloop C gets executed. Of course, if you want more violent behaviour you C can try any random negative values but don't be surprised if it takes C a few days to executes those random semi-infinite loops. J = IMOD(IRAND(), 6) IF (IGO .NE. 0) GOTO 501 DO 501 J = 1, 5 ........... BTW, do not feel p_ssed off if your compiler gives you complete BS. Eight out of ten compilers behave thataway. << My questions are these: << << 1) Is the code standard-conforming? I think it is, but perhaps I am << mistaken. << << 2) If the code is standard-conforming, is the execution correct? As << far as I can tell, the inner DO should never be activated! 1) It conforms with the standard in my interpretation of it. Several people, however, claim that you cannot jump to the terminal statement if that statement is shared with an inside loop. They use the general definition of the range of DO-loop to claim that since the terminal statement partly belongs to the inner loop it has to belong "exclusively" to the inner loop. Some computer systems also support this for expediency reason (I will go into that later with more data to support my theory). 2) The execution is incorrect. You are right that the inner loop should never gets activated (since it is never active according to ANSI definition of active DO loop) but wait until you see all the flames following this ... :-) << Please, no flames about the code itself. I did not write it - I just << get to port it. To make this bitchy code portable and produce the correct result across most computers that do not declaring this as illegal, just add one statement to your code outside both loops to give J a well-define value: IGO = 1 C Initialize J to the value of the inner loop's terminal value. C This will make it works on most computers that allows this C construction. However, there are a few C @#@#@% compilers (standard UNIX f77, for example) that checks for C J=6 (instead of J>5) as the terminating condition so I can't guarantee C this. J = 5 DO 501 I = 1, 10 WRITE (6,*) 'OUTER LOOP, I =',I IF (IGO .NE. 0) GOTO 501 DO 501 J = 1, 5 And now for some discussion about an old ghost, if you are not interested hit 'n' quick. It is going to be lengthy. Flame me for being long-winded. << Tim Hopkins, { trh@ukc.ac.uk << From: trh@ukc.ac.uk (T.R.Hopkins) << "More than one DO-loop may have the same terminal statement" << << Section 11.10.2 states << A DO-loop is either active or inactive. Initially inactive, a DO-loop << becomes active only when its DO statement is executed. << << Seems to me that when the GOTO is executed the inner loop is inactive. << The effect of the transfer is thus to increment the outer loop counter << (see 11.10.3 and 11.10.4) and restart the outer iteration. Hey, there is one person in the net who thinks the same way as I do. And this is the work of Steven R Weintraub (cs.utexas.edu!oakhill!devsys!steve) in the last discussion. Although he arrived at a different conclusion his posting seemed to confirm my suspicion why so many people screwed up this code construction. << Computer Compiler Result Er Msg Comment << -------------------------------- ---------------- ------ ----- ------- << AT&T 3B1 - UNIX PC Model 7300 SVS FORTRAN Yes 2 << AT&T 3B2/400 - 3B2/3B15 Computer FORTRAN 77 XLA+ 92 * << Apollo DN 3000 Aegis 9.7 65785 * << CRAY COS1.15 ? Yes 1 << Cray CFT Yes 4 << Cray CFT77 Yes 4 << Cyber 205 Vsos 237 Yes 2 << -------------------------------- ---------------- ------ ----- ------- << Cyber 855 Nos 2.5.3 82 * << Eta-10Q R0120N2 Yes 2 << Harris H-800 VOS 7.1 sauf77 82 Yes << Harris HCX-9 HCX/UX (unix) f77 82 No << Harris HCX-9 HCX/UX (unix) hf77 92 No << IBM PC/AT Professional FORTRAN Yes 2,5 << ISTLA - Toolpack Static Analyser, Version 1.2 Yes 3 << -------------------------------- ---------------- ------ ----- ------- << Prime Fortran 66 92 * << Prime Fortran 77 ? * 1 << Pyramid OSX4.0 80 * << Rolm 1666 Remora F77 (b-test) Yes 2 << Rolm 1666 Remora F77 (b-test) 80 Yes 2,6 << SUN OS 4.0 92 * << SUN OS 4.2 rel 3.5 92 * << -------------------------------- ---------------- ------ ----- ------- << VAX/VMS 4.7 92 * << *It should be pointed out that it is probably safe to assume if the result << I recieved did not mention a warning message, the compiler probably did not << generate one. << << Index to comments : << 1 Infinite loop generated << 2 Error reported from compiler - compiler produced no code. << 3 Portability anaylzer, not compiler << 4 Final answer not given in post. << 5 Compiler made by Ryan-McFarland Corporation << 6 Option to enable block jumping turned on. Ansi compatablity warning given. << << Let us look at what the proper responses should be. There are actually << three. The first is that the compiler can error out and produce no code. << Of the compilers that were reported, five did this. One of these had << a compiler option to compile through this, generating the next proper << response, 80. 80 is the result that is generated when the outer do << loop misses the K = K + 1 increment (as if a continue existed at that << line). Only one other compiler generated this result. The other correct << result is 82. This the 80 result plus two increments for K = K + 1 << from the outer loop. Only three compilers got this answer. << << Of the wrong answers recieved, they fell into two catagories : 92 and << infinitely large (or loops). 92 was the most common response to the << code, given by six compilers. This leads me to suspect I fail to see << what the code is to do, but I believe that these compilers do two << increments on the internal loop jump-out. As for the infinite answers << three computers answered this way. I generated this case knowing that << on some compilers (specifically the Apollo), DO loops are generated << technically wrong in order to make them perform extensions. From this results, I can classify them into 3 groups: 1) The Do-it-right: These are the people who do take care of active/inactive loop and produce the correct result of 82. In order to do this they have to pay a price in runtime performance and may lose (in sales) to some stupid compiler in some stupid benchmarks. However, they chose integrity over expediency over this. I would give them three cheers. It's a pity that they are the minority. << Cyber 855 Nos 2.5.3 82 * << Harris H-800 VOS 7.1 sauf77 82 Yes << Harris HCX-9 HCX/UX (unix) f77 82 No 2) The Cop-out: These guys sticks with the benchmark but have the decency not to deliberately generate random results for the same piece of code depending whatever the stack happens to contain. They cop out and give an error message for this usage. Note that ETA/Cyber belongs to both group 1 and 2. If they really think that the usage is illegal why do they allow it on another system of theirs ? I know for sure that implementing the proper solution for this would create a dependency that would severely effect vectorization of the DO loops. Therefore, my guess is that they only generate the correct code for the non-vectorizing computers only (Am I correct that Cyber 855 is not a vectorizing computer ?) and generate errors for the vectorizing computers (Cyber 205 & ETA10) to save the users from killing themselves with random results and to save them from killing themselves in the benchmarks. This approach is acceptable but I wish that the manufacturers could be more honest about it and admit their shortcoming instead of blaming the users for writing illegal code. C'mon, give me a break ! Where does it say in the ANSI standard that a DO loop termination label does not belong to its own DO loop if that label is shared by an inner loop ? 3) The Who-cares--You-asked-for-it: These guys just go merrily along and generate the usual loop control code for the shared DO loops without caring about ANSI definition of an active loop (ANSI 11.10.2: "A DO-loop is either active or inactive. Initially inactive, a DO-loop becomes active only when its DO statement is executed.") This causes the code to generate random results depending what you happened to have on the stack. Some company even goes so far to rationalize their shortcoming as to have this in their documentation: "If two or more nested DO loops share the same terminal statement, you can transfer to that statement only from within the range of the innermost loop. Any other transfer to that statement constitutes a transfer from an outer loop to an inner loop because the shared statement is part of the range of the innermost loop." The lame excuse consist of two statements that contradict one another. And maybe it's perfectly fine with them to give random results in executing exactly the same piece of code that's why they never warn the users about what REALLY HAPPENS when that "constitutes a transfer from an outer loop to an inner loop" occurs. Unfortunately, they are considered the pseudo-standard in forfran compiler so a lot of companies can cop out by simply saying "Hey, that's what the pseudo standard says and we are not doing any worse than them!". It is true that the terminal statement is shared with the inner loop but that does not cause the "constitutes blah blah ..." to happen. The statement is executed since it belongs to the currently active DO loop and the loop control processing should proceed according to ANSI rule (see 11.10.4 for details, I'm too lazy to type not that I want to quote anything out of context) : "However, if some of the DO-loops sharing the terminal statement are active, execution continues with incrementation processing, as described in 11.10.7" And ANSI 11.10.7 on incrementation processing: "(1) The DO-variable, the iteration count, and the incrementation parameter of the active DO-loop whose DO statement was most recently executed, are selected for processing." Note the words "active", and "DO statement was most recently executed". Did the DO statement for the inner loop get executed ? Then why all this constitutes-blah-blah BS ? Sorry for blowing off steam but, IMHO, a compiler, of all programs, has to be correct. It is simply frightening to think that it can deliberately be implemented/documented to bluff the users into believing that its incorrect code is correct without warning about the subsequent random results. Remind me of a bridge in Australia that collapsed while under construction (with a huge cost) due to a programming bug. Can you guess which way our missiles will be flying if some hapless programmers use this kind of construction using this kind of compiler ? BTW, the result 92 produced by many compilers is due to the initial value of 0 for the inner loop variable the first time the jump is taken and the value > terminal value for subsequent jumps. In other words, it is exactly the same thing that happened to bernhold@qtp.ufl.edu. That's all for cataloguing. Now, for my own history of the world: The shared terminal statement belongs to both loops but, in no instances, it belongs to both loops at once. In other words, it can belong to either loop at a time but not both. The rule as to which loop it belongs to is the same as the rule for loop control processing i.e. it should belong to the most current active DO loop. (It is similar to some guys sharing a baseball bat, but only one of them can go to bat at a time). This would explain the example in the ANSI standard (section 11.10.7) and gives the correct result of N=0. N=0 DO 200 I=1,10 J=1 DO 200 K=5,1 L=K 200 N=N+1 201 CONTINUE After the DO statement for the inner loop is executed, the shared terminal statement falls into its range and will not be executed (since the inner loop is K=5,1 and is not executed) even though the outside loop is active and gets executed. Since the terminal statements always belong to the most current active DO-loop any GOTO statement from inside the DO loop to its own DO label is permitted and is perfectly legal. That makes sense, doesn't it ? I would welcome any discussion on this but please remember that we are talking about a special case of DO-loops sharing the same terminal statement so please do not quote the following definition on the range of a DO loop (which I can recite backward BTW :-)) and use it as the rule-of-thumb for everything: 11.10.1 _Range_of_a_DO-Loop_. The _range_of_a_DO-Loop_ consists of all of the executable statements that appear following the DO statement that specifies the DO-Loop, up to and including the terminal statement of the DO-loop. and without quoting the statement following it: "More than one DO-loop may have the same terminal statement" and without explaining what the heck the ANSI rule talks about for loop control processing for DO-loops sharing the same terminal statements and the definition of active/inactive DO loops (the whole purpose of this active/inactive definitions is just to resolve this exact seemingly ambiguity anyway). And please do not tell me that since the two DO-loops have the same terminal statement, the statement belongs to only one of them (unless you can quote ANSI to say that the shared statement belongs exclusively to the inner loop and is not shared with the outer loop). If that's what English is I think I'd better learn Greek :-). It can surely save me a lot of headache. Calvin H. Vu Silicon Graphics Computer Systems calvin@sgi.sgi.com "Since homo sapiens have two arms and two legs by the official rule of thumb, anybody without both arms and both legs is not human". Official Definition of Human Range ------------------------------------------------------------------------- DISCLAIMER: "Nobody, even my mum, wants to have anything to do with my foul language"
calvin@dinkum.SGI.COM (Calvin H. Vu) (03/14/89)
In my last article I posted the test results from steve without posting the test itself so it maight be confusing to the people who did not follow the last discussion. So, here it is: K = 0 DO 10 I = 1,10 IF (I.EQ.1.OR.I.EQ.5) GOTO 10 DO 10 J = 1,10 IF (J.EQ.3) GOTO 10 10 K = K + 1 PRINT *,K END BTW, this was NOT a good test since you have no control over the initial value of J. So the three compilers (Cyber 855, Harris H-800, and Harris f77) might have produced the correct result just because J happenned to have an uninitialized random value >10 when the test was run. Sorry for all the doom-saying, Calvin H. Vu Silicon Graphics Computer Systems,
steve@oakhill.UUCP (steve) (03/15/89)
I hate long articles but since I did alot of thought on this subject earlier I though I'd bore you with the benefit of my cognition. The test case I posted earlier had three acts that combine to cause ambiguity. These are: 1) Do loops ending on the same statement 2) The end statement being executable. 3) A jump in the external Do loop to the terminating statement. All three of these are needed to result in the ambiguity. In the test case posted: > << PROGRAM LOOP > << IGO = 1 > << DO 501 I = 1, 10 > << WRITE (6,*) 'OUTER LOOP, I =',I > << IF (IGO .NE. 0) GOTO 501 > << DO 501 J = 1, 5 > << WRITE (6,*) 'INNER LOOP, J=',J > << 501 CONTINUE > << STOP > << END this is not the cause of the problem. The true cause of the problem is that the compiler was tring to resolve the chance of ambiguity, and generated the bad code. This is the same as the compilers that generated 92 in the test case I posted. Let's look at my test case again. K = 0 DO 10 I = 1,10 IF (I.EQ.1.OR.I.EQ.5) GOTO 10 DO 10 J = 1,10 IF (J.EQ.3) GOTO 10 10 K = K + 1 PRINT *,K END I claim there are three responses. 1) Error out. 2) Execute K = K + 1 as part of the inner loop (Thus the external goto jumps past this statement). (result 80) 3) Execute K = K + 1 as part of both loops. (result 82) The biggest problem is the the interpretation of what this last statement means. The three different interpretation result in the three above results. The hardest one to implement is the third. To see why let's look at the block code generated (For the explaination of the bug that is in the first code and produced 92 in my case, it is at the end) For case 2: k = 0 iter1 = 10 i = 1 LABEL1: jump i == 1 or i == 5 LABEL4 iter2 = 10 j = 1 LABEL2: jump j == 3 LABEL3 LABEL3: k = k + 1 iter2 = iter2 - 1 j = j + 1 jump iter2 > 0 LABEL2 LABEL4: iter1 = iter1 - 1 i = i + 1 jump iter1 > 0 LABEL1 call print(k) end For case 3: k = 0 iter1 = 10 i = 1 LABEL1: jump i == 1 or i == 5 LABEL4 iter2 = 10 j = 1 LABEL2: jump j == 3 LABEL3 LABEL3: k = k + 1 iter2 = iter2 - 1 j = j + 1 jump iter2 > 0 LABEL2 jump LABEL5: LABEL4: k = k + 1 LABEL5: iter1 = iter1 - 1 i = i + 1 jump iter1 > 0 LABEL1 call print(k) end Note the differences between the two. The second case must generate k = k + 1 twice. Also it MUST generate the jump to LABEL5:. It is the failure to generate this jump that cause the error in the code (caused the generation of 92 in my case). The code for the second case is both slower and harder to generate. There is a big temptation to try to tamper with the fragile structure to speed it up that results in the generation error. The inifinite loop errors results from this temptation. If you allow block jumps you must use a iteration variable and guard against the iteration count falling below zero (use <= as opposed ==). The reason is that the loop variable can be used outside it's loop. And if a jump is made into a do loop, the iteration will be decremented again, a less than zero will allow the fall through (you can optimize out the iteration variable only once you determine there is no external jump into the loop). Personally I really don't care which interpretation is chosen. My theory is that once one or the other is accepted, that the compiler writer should try to cover the hardship for the user. The complaints I've heard about FORTRAN that the lexical analyser is to hard to write fall in this catagory. If the user perfers to start his programs in column 7, that's his preference. The compiler writer should do his work without complaining. The problem I see is there is a repeated desire to do this code. Unfortunately the standard refuses to see the upcry, and claims the whole situation is illegal. Compiler writers support this extension (often without warning) to support the market cry, unfortunately the ambiguity and bad generated code is the unhappy result. enough from this mooncalf - Steven ---------------------------------------------------------------------------- To flame someone for bad spelling or grammer is a discouragement to net discussion in a timely fashion. ---------------------------------------------------------------------------- These opinions aren't necessarily Motorola's or Remora's - but I'd like to think we share some common views. ---------------------------------------------------------------------------- Steven R Weintraub cs.utexas.edu!oakhill!devsys!steve Motorola Inc. Austin, Texas (512) 440-3023 (office) (512) 453-6953 (home) ----------------------------------------------------------------------------
maine@pioneer.arc.nasa.gov (Richard Edwin Maine D-OFA) (03/15/89)
Calvin Vu of Silicon Graphics gives a long-winded explanation of why he thinks the following piece of code is legal. << PROGRAM LOOP << IGO = 1 << DO 501 I = 1, 10 << WRITE (6,*) 'OUTER LOOP, I =',I << IF (IGO .NE. 0) GOTO 501 << DO 501 J = 1, 5 << WRITE (6,*) 'INNER LOOP, J=',J << 501 CONTINUE << STOP << END His whole argument is based on the statement that: <The shared terminal statement belongs to both loops, but in no instance it <belongs to both loops at once. In other words, it can belong to either <loop at a time but not both. The rule as to which loop it belongs to <is the same as the rule for loop control processing i.e. it should belong to <the most current active DO loop. There is nothing like this anywhere in the ANSI standard. In fact, the ANSI standard (section 11.10.1) makes it quite clear that indeed the statement DOES belong to the range of both do loops. Nowhere does the standard hint that a statement may not belong to the range of multiple do loops at the same time. Indeed, the concept of time is not mentioned at all in conjunction with the range of a do loop. Time relates to the activation of a do loop, but not to its range. This claim and concept seems to come solely from the mind of Calvin Vu (and admitedly others that seem to agree with him). If you claim support for this position in the standard, please provide section reference. Once this arbitrary rule is dismissed, all is clear. There are no contradictions (at least on this subject) in the standard. The only contradictions are with this rule, which is not in the standard. True the terminal statement is in the range of the outer loop, which is active. However it is ALSO in the range of the inactive inner loop. Therefore branching to it is illegal. Note that nowhere do I use the term "exclusive". It is Calvin that is trying to argue that the statement should belong exclusively to one loop at a time, not I. Calvin says <so please do not quote the following definition on the range of a DO loop <(which I can recite backward BTW :-)) and use it as the rule-of-thumb for <everything: < 11.10.1 _Range_of_a_DO-Loop_. The _range_of_a_DO-Loop_ consists of < all of the executable statements that appear following the DO < statement that specifies the DO-Loop, up to and including the terminal < statement of the DO-loop. < <and without quoting the statement following it: < "More than one DO-loop may have the same terminal statement" < ... and stuff about active/inactive loop definitions. Ok, I'll quote em both. And I'll claim that 11.10.1 IS the rule-of-thumb for everything. It is after all the standard. Calvin's claim that a statement cannot simultaneously be in the range of 2 loops is not in the standard and is flatly contradicted by 11.10.1. The statement that more than one DO-loop may have the same terminal statement makes no contradictions. The business about active and inactive loops does NOT have anything to do with the range of the loops. You are trying to make a connection that isn't there. The range is a static concept that is not a function of time. Calvin further states < to make this bitchy code portable and produce the correct result across < most computers that do not declaring this as illegal, just add one < statement to your code outside both loops to give J a well-define value: < <C Initialize J to the value of the inner loop's terminal value. <C This will make it works on most computers that allows this <C construction. However, there are a few <C @#@#@% compilers (standard UNIX f77, for example) that checks for <C J=6 (instead of J>5) as the terminating condition so I can't guarantee <C this. < J = 5 < DO 501 I = 1, 10 < WRITE (6,*) 'OUTER LOOP, I =',I < IF (IGO .NE. 0) GOTO 501 < DO 501 J = 1, 5 Yukk! In the name of "portability" you try to second guess the inner workings of the compiler? Remind me not to try porting any of your code. To make this code portable, add a continue statement with a separate statement number as the terminator of the outer DO-loop. This is not only portable (really - like it'll run on anything), it is even standard. What an odd coincidence. The only "reasonable" (my term, not ANSI's) thing for a compiler to do with this code is bitch. ANSI doesn't demand it, but I do. (Not that I always get what I demand, but it doesn't stop me). If the compiler wants to invent some extension like Calvin's, I suppose its fine with me, as long as it also warns you that this is non-ANSI. As an aside, has anyone noticed that the draft 8X standard (at least the Jun 87 version that I have) DOES require the compiler to provide diagnostics for code that violates the standard? I've never seen much discussion of this "little" change. I sure like it. I've long taken the position that "reasonable" compilers would do this, but with this clause, I'd be able to make that position quite a bit stronger (and includable in procurement specifications, etc.) This would mean that if a compiler did not bitch about non-ANSI usages (to the extent statically determinable), I could claim the compiler was not in conformance. Richard Maine maine@elxsi.dfrf.nasa.gov (sending this from maine@pioneer.arc.nasa.gov because we don't have posting set up on elxsi).
urjlew@ecsvax.UUCP (Rostyk Lewyckyj) (03/16/89)
Arguing about whether this code conforms to the standard, and/or how it should be interpreted beggs what I think is the real problem and rational solution. The problem is that the standard allows a code construction that easily leads to misuse and stepping over the legal limits. I.e. the standard permits a DO loop to end with non trivial executable statements (eg k=k+1 rather than continue or enddo) and it allows the closure of multiple DO loops on one statement. The defensive/safety minded programmer can easily avoid the problem by liberal use of CONTINUE statements to remove ambiguities. I think that the rational solution is to amend the standard (put it in 8x or 9x if 8x never makes it) to require DO loops to be terminated one at a time with CONTINUE or ENDDO statements. I realize that this will require modifying old source. However since the cases that need modifying can (I think) be caught by the compiler it is not as bad a change as the 0 trip vs 1 trip through the loop change which occured in most 66 to 77 compiler rewrites. I don't think that issuing a warning is enough. PS. I tried the test program on IBM VS FOortran rel v 2.2 and the current compiler on our CONVEX C220. IBM gave two warning messages one for each GOTO 10 and produced differnent values of K depending on the initial value of J. CONVEX gave no warning messages and also produced different values of K. ----------------------------------------------- Reply-To: Rostyslaw Jarema Lewyckyj urjlew@ecsvax.UUCP , urjlew@tucc.bitnet or urjlew@tucc.tucc.edu (ARPA,SURA,NSF etc. internet) tel. (919)-962-9107
calvin@dinkum.SGI.COM (Calvin H. Vu) (03/16/89)
I guess I have been so inculcated with the ideas of block-structured programming where each block has a uniquely-identifiable nested level associated with it so I could not think straight in the way ANSI does in its amorphous definition of DO-loop range. I thought since the terminal statement was shared by the two ranges it must belong to both nested levels as an exception to the general rule! But, alah, there is no such thing as a nested level in ANSI. They just have a dozen different rules concerning cross-range activities & definitions to make sure that they don't mess anything up with their rules. In other words, a range in ANSI standard doesn't mean anything. It is simply a point-A-to-point-B definition and is in no way equivalent to the idea of a block which has an implied nested level associated with it. ANSI has to enforce dozens other rules to simulate the illusion of a block which caught me (and, apparently, some other people) off guard. In short, there is no such thing as a block in ANSI. If you want to make sure whether it is legal to do something according to ANSI standard or not, look it up the their numerous rules. I'm sure it is in there somewhere. BTW, I realized this after I had time to really peruse the ANSI standard and realize the full implication of all their rules after my Sunday posting/dinner. I would say that your argument is pretty good though, although it falls into the ANSI track of cerebration that you have to look up in the book and follows the rules instead of relying on your general concept of programming practice. > < to make this bitchy code portable and produce the correct result across > < most computers that do not declaring this as illegal, just add one > < > <C Initialize J to the value of the inner loop's terminal value. > <C This will make it works on most computers that allows this > <C construction. However, there are a few > <C @#@#@% compilers (standard UNIX f77, for example) that checks for > <C J=6 (instead of J>5) as the terminating condition so I can't guarantee > <C this. > > Yukk! In the name of "portability" you try to second guess the inner workings > of the compiler? Remind me not to try porting any of your code. To make > this code portable, add a continue statement with a separate statement > number as the terminator of the outer DO-loop. This is not only portable > (really - like it'll run on anything), it is even standard. What an odd > coincidence. I was so sure that the original poster knew about your approach that was why he asked not to be flamed for it. And now I got flamed because I wanted to join in the fun and explained the phenomenon he encountered and how to hack his way out of it. I hope you don't think that you are the only person who thought of the idea of using two different labels for the two loops! My approach wouldn't work on vectorizing computer where they use their own compiler-generated variables/registers for the DO-loop variables (usually they also state that changing the DO-loop variable inside the loop will not effect the execution of the loop if that's what they implement). However, I'm sure it will work in the way the original poster expected on his Appolo. (I love gambling so I almost always terminate my sentences with "wanna bet ?" but I guess I'd better refrain from it in this case. Etiquette is a real pain: It spoils all the fun !). I don't write program like like that and neither does the original poster (as was made obvious in his don't-flame-me remark) but why shouldn't we have some fun with it ? As I said, it would work with MOST computers that allow the construction but hey, this is obviously hacking and how can I guarantee a hack ?. Calvin Vu "Hackers have more fun!"
khb@fatcity.Sun.COM (Keith Bierman Sun Tactical Engineering) (03/16/89)
In article <22754@ames.arc.nasa.gov> maine@pioneer.arc.nasa.gov.UUCP (Richard Edwin Maine D-OFA) writes: > > >As an aside, has anyone noticed that the draft 8X standard (at least >the Jun 87 version that I have) DOES require the compiler to provide >diagnostics for code that violates the standard? I've never seen >much discussion of this "little" change. I sure like it. I've >long taken the position that "reasonable" compilers would do this, >but with this clause, I'd be able to make that position quite a >bit stronger (and includable in procurement specifications, etc.) >This would mean that if a compiler did not bitch about non-ANSI >usages (to the extent statically determinable), I could claim >the compiler was not in conformance. I have not yet studied the current draft (to be voted on in May), but the general rule of thumb is as f77... define standard conforming PROGRAMS, not compilers (a standard comforming compiler is that thing which compiles the entire class of standard comforming compilers correctly). This is not an oversight, it is a very well thought out position. Ada (and some other languages) take a very different stand. But in order to allow compiler vendors to extend the language, the committee has stuck with the "traditional" fortran design. So I would not start crafting clauses about diagnostics into your procurement spec's yet. btw: For what it is worth, I am no longer a member of the public. I am now the SunAlternate to x3j3. Cheers all. Keith H. Bierman It's Not My Fault ---- I Voted for Bill & Opus
charlie@mica.stat.washington.edu (Charlie Geyer) (03/16/89)
In article <6667@ecsvax.UUCP> urjlew@ecsvax.UUCP (Rostyk Lewyckyj) writes: > The problem is that the standard allows a code construction that > easily leads to misuse and stepping over the legal limits. I.e. > the standard permits a DO loop to end with non trivial executable > statements (eg k=k+1 rather than continue or enddo) and it allows > the closure of multiple DO loops on one statement. > The defensive/safety minded programmer can easily avoid the problem > by liberal use of CONTINUE statements to remove ambiguities. > I think that the rational solution is to amend the standard (put it > in 8x or 9x if 8x never makes it) to require DO loops to be terminated > one at a time with CONTINUE or ENDDO statements. > I realize that this will require modifying old source. A simpler solution would have compilers do run-time error checking and not jump into inactive loops. The beauty of this solution is that it does not not slow down structured code -- no checking necessary. Unstructured code would take a performance hit. Serves it right :-) It's not failure to end every loop with its own CONTINUE that is the problem. It is (surprise!) GOTO's are harmful.
steve@oakhill.UUCP (steve) (03/16/89)
In article <1317@uw-entropy.ms.washington.edu>, charlie@mica.stat.washington.edu (Charlie Geyer) writes: > > A simpler solution would have compilers do run-time error checking and > not jump into inactive loops. The beauty of this solution is that it > does not not slow down structured code -- no checking necessary. > > Unstructured code would take a performance hit. Serves it right :-) > > It's not failure to end every loop with its own CONTINUE that is the > problem. It is (surprise!) GOTO's are harmful. As I stated in my previous post. There is NO problem with the code as posted. It is not ambiguous. The problem is that the compiler, in order to prevent any posssible ambiguity, generates bad code. The true ambiguity results in the following three elements used together. 1) Two or more do loops ending on the same line. 2) One or more of the external do loops (not the inner most) jumping to the terminating statement. 3) The terminating statement being executable (not a CONTINUE). Admittedly the practice of ending do loops on the same line is not sound programming. But it is historic programming, and is still used today. As for the performance hit you talk about, well that's part of the problem here. If you looked at the pseudocode I posted Tuesday, the proper code for is large and slow. Compiler writers don't like this. It doesn't sell compilers. First you MUST use an iteration count. Code generators don't like to. More code. You can only remove that iteration counter once you are sure there are no jumps into the DO block (an illegal situation often supported). This checking to get things right slows down the compiler. The right code is larger and slower than your competition's (who did things wrong but fast). Also for the same reason you must check less than equal to zero on the iteration count. An operation that is slower on many computers. Also one interpretation requires either generating the terminating line's code twice, or making some mechanism which truely does the checking. Bulky and slow. Won't sell the compiler. In order to speed up the code, the compiler maker took a short cut they properly shouldn't have. The compiler generates faster code on all DO loops, but it gets a few marginal cases wrong. Since the workaround here is obvious and better programming methodology (Put two terminal statements), they'll be glad to tell you the workaround and say they are working on the problem. enough from this mooncalf - Steven ---------------------------------------------------------------------------- To flame someone for bad spelling or grammer is a discouragement to net discussion in a timely fashion. ---------------------------------------------------------------------------- These opinions aren't necessarily Motorola's or Remora's - but I'd like to think we share some common views. ---------------------------------------------------------------------------- Steven R Weintraub cs.utexas.edu!oakhill!devsys!steve Motorola Inc. Austin, Texas (512) 440-3023 (office) (512) 453-6953 (home) ----------------------------------------------------------------------------
charlie@mica.stat.washington.edu (Charlie Geyer) (03/17/89)
In article <1317@uw-entropy.ms.washington.edu>, I wrote: A simpler solution would have compilers do run-time error checking and not jump into inactive loops. The beauty of this solution is that it does not not slow down structured code -- no checking necessary. Unstructured code would take a performance hit. Serves it right :-) It's not failure to end every loop with its own CONTINUE that is the problem. It is (surprise!) GOTO's are harmful. In article <1905@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) replies: > As I stated in my previous post. There is NO problem with the code as > posted. It is not ambiguous. The problem is that the compiler, in > order to prevent any posssible ambiguity, generates bad code. The > true ambiguity results in the following three elements used together. > > 1) Two or more do loops ending on the same line. > 2) One or more of the external do loops (not the inner most) > jumping to the terminating statement. > 3) The terminating statement being executable (not a CONTINUE). The code as posted (we are still talking about the original posting aren't we?) is, as several other people have pointed out, wrong. It DOES have a problem. It jumps into the range of an inactive DO loop. This is forbidden. It is not the job of a compiler to guess what conforming program the programmer thought he was writing. It would be nice for compilers to produce code that catches this error, at least as an option. > Admittedly the practice of ending do loops on the same line is not > sound programming. But it is historic programming, and is still used > today. As for the performance hit you talk about, well that's part of > the problem here. So make it an option that can be turned off. In article <18178@vax5.CIT.CORNELL.EDU> btcx@vax5.cit.cornell.edu (Brian T Carcich) replies: > Well, not quite. > > Now, I'm not a GOTO freak, and I learned to only goto CONTINUE's, but > does anybody realize the origin of the anti-GOTO religion? And how the above > statement is a misrepresentation of that origin? (see BTW below) > > It's not GOTO's that are harmful, but POOR USE OF goto's that's harmful. O. K., but that would have made a much weaker punchline. If you want to be pedantic, unstructured use of GOTO's is harmful, and jumping in and out of DO loops is about as unstructured as you can get. Is that o.k.? > Go back to .c or .pascal or .modula or ... where you belong. > leave us dinosaurs alone! Believe me. I don't write FORTRAN by choice. Lately I've taken to writing some of my FORTRAN in C (thereby incurring who knows what portability problems). But you just can't ever get completely away from FORTRAN. It's everywhere.
urjlew@ecsvax.UUCP (Rostyk Lewyckyj) (03/17/89)
In article <1317@uw-entropy.ms.washington.edu>, charlie@mica.stat.washington.edu (Charlie Geyer) writes: > > In article <6667@ecsvax.UUCP> urjlew@ecsvax.UUCP (Rostyk Lewyckyj) writes: > > > I think that the rational solution is to amend the standard (put it > > in 8x or 9x if 8x never makes it) to require DO loops to be terminated > > one at a time with CONTINUE or ENDDO statements. > > I realize that this will require modifying old source. > > A simpler solution would have compilers do run-time error checking and ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ??? By run time the compiler is long gone 8-). > not jump into inactive loops. The beauty of this solution is that it > does not not slow down structured code -- no checking necessary. > > Unstructured code would take a performance hit. Serves it right :-) > If you are dynamically checking your branches at run time you are using time to do it , i.e. taking a performance hit NO??? > It's not failure to end every loop with its own CONTINUE that is the > problem. It is (surprise!) GOTO's are harmful. Baloney! It isn't goGOTOs that are harmfull, its spagetti code that attempts to bend the legal limits of the rules,and and is convoluted either because the programmer can't do better or is attempting to be clever., that is bharmfull. Let me slightly amend my recommentdations. Pro1 Prohibit gotbranches into the scope of a DO loop, whether to a statement well inside the loop or the terminal statement. CThExcept to the DO state- ment itsleelf from a statement outside the DO. 2 Prohibit the extended range of the DO. i.e. branching out of the DO and then back in. 3 Require a each DO loop to be terminated by its own ENDDO, which can not be the target of a branch. I am suggesting these stricter rules because I realize that my previous suggestions could still get misused by transbranching from outside a loop to the terminal cCONTINUE of any loop. If the standard were amended in this way , then probabbly a great amount of special rules and interpretations could be removed, Thus making the language more robust and simplifying the standard at the same time. Since the adherence to the rules I propose should be checkable at compile time there would be no run time performance penalty. I also think that , bthese changes would permit better program srtructure analaysis by the compiler and the production of more optimized code. The onl y problem I see with my suggestions are the at rule 2 will break too many codes. ----------------------------------------------- Reply-To: Rostyslaw Jarema Lewyckyj urjlew@ecsvax.UUCP , urjlew@tucc.bitnet or urjlew@tucc.tucc.edu (ARPA,SURA,NSF etc. internet) tel. (919)-962-9107
steve@oakhill.UUCP (steve) (03/17/89)
In article <1320@uw-entropy.ms.washington.edu>, charlie@mica.stat.washington.edu (Charlie Geyer) writes: > > In article <1317@uw-entropy.ms.washington.edu>, I wrote: > > A simpler solution would have compilers do run-time error checking and > not jump into inactive loops. The beauty of this solution is that it > does not not slow down structured code -- no checking necessary. > > Unstructured code would take a performance hit. Serves it right :-) > > It's not failure to end every loop with its own CONTINUE that is the > problem. It is (surprise!) GOTO's are harmful. > > In article <1905@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) replies: > > > As I stated in my previous post. There is NO problem with the code as > > posted. It is not ambiguous. The problem is that the compiler, in > > order to prevent any posssible ambiguity, generates bad code. The > > true ambiguity results in the following three elements used together. > > > > 1) Two or more do loops ending on the same line. > > 2) One or more of the external do loops (not the inner most) > > jumping to the terminating statement. > > 3) The terminating statement being executable (not a CONTINUE). > > The code as posted (we are still talking about the original posting aren't > we?) is, as several other people have pointed out, wrong. It DOES have a > problem. It jumps into the range of an inactive DO loop. This is > forbidden. It is not the job of a compiler to guess what conforming > program the programmer thought he was writing. It would be nice for > compilers to produce code that catches this error, at least as an option. > There are two problems in this code. 1) It is illegal 2) People want to do it. The ANSI standard, as much as they and we would perfer otherwise, do not live in the real world. They have ordained this code as illegal. But the real world wants to do this. Thus the compiler writers support this. Unfortunately there are some complicated issues of ambiguity to be resolved. Usually at this point we would ask the committe to resolve it. They say, "we did, it is illegal", and we are back to square one. At this point the compiler writer must decide how to support this extension (which was the point of my post). Thus compiler writers put this feature in, otherwise their compilers sit on the shelf. (Believe me, I wrote this code in a FORTRAN compiler. It would error out on jumping into blocks. The customer response. "Gee, could you put in an option which would allow us to do this". Thus the compiler now has a command line option to allow jumping into blocks. I give you 20-1 the command file they compile with has this option set, and the option to turn off non-ansi code warnings). Having put this feature in, they then want to be competive. They take short cuts. Instead of generating the true code (which has an extra variable and several extra pieces of logic), they generate code that is smaller and faster that will work in 99.5% of the cases. So you see. The problem is that the real world is subverting this problem with a double whammy. First the market wants a feature the standard says is illegal. And in the demand for fast effienct generated code, the market causes the compiler maker to take short cuts he can't without badly increasing the size and slowness of the compiler. > > Admittedly the practice of ending do loops on the same line is not > > sound programming. But it is historic programming, and is still used > > today. As for the performance hit you talk about, well that's part of > > the problem here. > > So make it an option that can be turned off. Read above. But to leave this feature out means you won't be able to sell compilers. > In article <18178@vax5.CIT.CORNELL.EDU> btcx@vax5.cit.cornell.edu > (Brian T > Carcich) replies: > [ real meaning of Dykstra's GOTO declaration deleted ] > > O. K., but that would have made a much weaker punchline. If you want to > be pedantic, unstructured use of GOTO's is harmful, and jumping in and out > of DO loops is about as unstructured as you can get. Is that o.k.? Unfortunately you can't save the unwashed masses from themselves. Not only can you not prevent them from doing this. If you forbid it, they cry and want it. If you want to sell compilers, this is something that must be supported. > Believe me. I don't write FORTRAN by choice. Lately I've taken to > writing some of my FORTRAN in C (thereby incurring who knows what > portability problems). But you just can't ever get completely > away from FORTRAN. It's everywhere. Writing in FORTRAN is nothing to be ashamed of. If you write carefully, you can do just as complex things in FORTRAN portably as you can in any other languge. Admittedly you do have to know how do you do your own recursion and handle you own pointers, but any programmer with his salt should know how to do this in his sleep. I hold a patent in AI. The system I wrote was in FORTRAN (for constraints I won't get into). When presenting a paper on it I would always get the question (from the a**hole that seems to always sit in the forth row) "What language did you use, C or LISP". When I replied FORTRAN, there were scoffs in the audience. I would unabashedly point out that the langauge in no way took away from the concept, and while other people had their AI systems still on the drawing board in LISP or C, mine was completed working and part of a marketed system. enough from this mooncalf - Steven ---------------------------------------------------------------------------- To flame someone for bad spelling or grammer is a discouragement to net discussion in a timely fashion. ---------------------------------------------------------------------------- These opinions aren't necessarily Motorola's or Remora's - but I'd like to think we share some common views. ---------------------------------------------------------------------------- Steven R Weintraub cs.utexas.edu!oakhill!devsys!steve Motorola Inc. Austin, Texas (512) 440-3023 (office) (512) 453-6953 (home) ----------------------------------------------------------------------------
shapiro@rb-dc1.UUCP (Mike Shapiro) (03/18/89)
In article <1320@uw-entropy.ms.washington.edu> charlie@mica.stat.washington.edu (Charlie Geyer) writes: ... much deleted ... >Believe me. I don't write FORTRAN by choice. Lately I've taken to >writing some of my FORTRAN in C (thereby incurring who knows what >portability problems). But you just can't ever get completely >away from FORTRAN. It's everywhere. Have you tried the RATFOR preprocessor? I haven't recently, but a few years ago I developed several FORTRAN packages using it. During the Software Tools User Group heyday, I remember talking with people who were using RATFOR to code software whose required delivery language was FORTRAN -- including such things as word processing and financial modeling. I also built some quick prototypes, including a CP/M graphics and music language for the NCR Decision Mate V personal computer (How many people remember it and the Dom Deluise TV ads?) using RATFOR's C-like macro capability. -- Michael Shapiro, Gould/General Systems Division 15378 Avenue of Science, San Diego, CA 92128 (619)485-0910 UUCP: ...sdcsvax!ncr-sd!rb-dc1!shapiro
jlg@lanl.gov (Jim Giles) (03/18/89)
From article <6676@ecsvax.UUCP>, by urjlew@ecsvax.UUCP (Rostyk Lewyckyj): > [...] > Pro1 Prohibit gotbranches into the scope of a DO loop, whether to a statement > well inside the loop or the terminal statement. CThExcept to the DO state- > ment itsleelf from a statement outside the DO. > 2 Prohibit the extended range of the DO. i.e. branching out of the DO > and then back in. > 3 Require a each DO loop to be terminated by its own ENDDO, which can not > be the target of a branch. Your first and second prohibitions are already in the Fortran 77 standard. ANSI: 11.10.8 Transfer into the Range of a DO-Loop. Transfer of control into the range of a DO-loop from outside the range is not permitted. ANSI: 11.10.1 Range of a DO-Loop. The range of a DO-loop consists of all of the executable statements that appear following the DO statement that specifies the Do-loop, up to and including the terminal statement of the DO-loop. These two rules prohibit 'extended range' as well as branches into the loop - including the terminal statement. J. Giles
khb@fatcity.Sun.COM (fatcity) (03/18/89)
In article <1913@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) writes: >> compilers to produce code that catches this error, at least as an option. >> ..................... > >There are two problems in this code. > > 1) It is illegal > 2) People want to do it. > >The ANSI standard, as much as they and we would perfer otherwise, do not >live in the real world. They have ordained this code as illegal. >But the real world wants to do this. Until 2 years ago (a bit less actually) I was part of the real world. I never had any trouble explaining why I was fixing someones code to remove this (relatively RARE, in well tested codes) problem. The key "problem" was that compiler writers allowed it to work on some machine somewhere. Had compiler writers not made the mistake of ignoring the X3J3 directive, we would not be having this discussion. People want to do it, only because it exists in some programs. The correct thing to do (in the best of all possible worlds) is what Lahey does. Don't allow it. Tell the customer to fix the code. Please DO NOT ALTER COMPILERS to start allowing this. Anyone who sells compilers should STOP ALLOWING it. We can't solve the worlds problems, but this one does have a solution. Keith H. Bierman It's Not My Fault ---- I Voted for Bill & Opus
jlg@lanl.gov (Jim Giles) (03/18/89)
From article <1913@devsys.oakhill.UUCP>, by steve@oakhill.UUCP (steve): > [...] > Unfortunately you can't save the unwashed masses from themselves. > Not only can you not prevent them from doing this. If you forbid > it, they cry and want it. If you want to sell compilers, this is > something that must be supported. do 10 i=1,10 print *,i if (i.gt.5) goto 10 do 10 j=1,5 print *,j 10 continue This program infinite loops on the Cray with CFT 1.14. If this is the behaviour that "must be supported" to sell compilers, I don't want any part of it. I consider this to be an _ERROR_ in the compiler and I'm reporting it to Cray as such. To be fair, the CFT compiler does issue a warning that the branch is illegal. If a compiler wants to allow the above program it should at least compile it to something useful. The only "meaningful" interpretation of the above I can think of is equivalent to the following: do 10a i=1,10 print *,i if (i.gt.5) goto 10a do 10 j=1,5 print *,j 10 continue 10a continue If a compiler doesn't issue a FATAL message, it should give the above interpretation - nothing else is acceptable. (Note, I used '10a' as the label in the above example to make it clear that it is a compiler generated label.)
steve@oakhill.UUCP (steve) (03/19/89)
In article <94640@sun.Eng.Sun.COM>, khb@fatcity.Sun.COM (fatcity) writes: > In article <1913@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) writes: > > >> compilers to produce code that catches this error, at least as an option. > >> ..................... > > > >There are two problems in this code. > > > > 1) It is illegal > > 2) People want to do it. > > > >The ANSI standard, as much as they and we would perfer otherwise, do not > >live in the real world. They have ordained this code as illegal. > >But the real world wants to do this. > > Until 2 years ago (a bit less actually) I was part of the real world. > I never had any trouble explaining why I was fixing someones code to > remove this (relatively RARE, in well tested codes) problem. > > The key "problem" was that compiler writers allowed it to work on some > machine somewhere. Had compiler writers not made the mistake of > ignoring the X3J3 directive, we would not be having this discussion. > > People want to do it, only because it exists in some programs. The > correct thing to do (in the best of all possible worlds) is what Lahey > does. Don't allow it. Tell the customer to fix the code. > > Please DO NOT ALTER COMPILERS to start allowing this. Anyone who sells > compilers should STOP ALLOWING it. > > We can't solve the worlds problems, but this one does have a solution. I wish this was true. On the compiler I wrote we had a complete prohibition of block jumps. Unfortunatly the people we wish to sell it to wanted to block jump. Not just in this case, but into the middle of if-then blocks. We were fighting for a limited area market. Since the competing compiler suppied this ability, it was add the feature or give the competition a step above us. To tell the customer to improve the code might be the ideal thing to do, unfortunately it does not make good business sense to tell the customer he doesn't know how to code. And if you are trying for a sell it might get the door slammed in your face. I am unhappy that I had to sell out to the market on this point, but I'm realistic enough not to become cynical about it. The compiler does at least give a warning that this code is non-ANSI standard and generate a proper do loop. The people who support this feature wrongly in order to speed up their compiler turn my stomach (I guess I'm not realistic enough to accept this). enough from this mooncalf - Steven ---------------------------------------------------------------------------- To flame someone for bad spelling or grammer is a discouragement to net discussion in a timely fashion. ---------------------------------------------------------------------------- These opinions aren't necessarily Motorola's or Remora's - but I'd like to think we share some common views. ---------------------------------------------------------------------------- Steven R Weintraub cs.utexas.edu!oakhill!devsys!steve Motorola Inc. Austin, Texas (512) 440-3023 (office) (512) 453-6953 (home) ----------------------------------------------------------------------------
steve@oakhill.UUCP (steve) (03/19/89)
In article <10623@lanl.gov>, jlg@lanl.gov (Jim Giles) writes: > From article <1913@devsys.oakhill.UUCP>, by steve@oakhill.UUCP (steve): > > [...] > > Unfortunately you can't save the unwashed masses from themselves. > > Not only can you not prevent them from doing this. If you forbid > > it, they cry and want it. If you want to sell compilers, this is > > something that must be supported. > > do 10 i=1,10 > print *,i > if (i.gt.5) goto 10 > do 10 j=1,5 > print *,j > 10 continue > > This program infinite loops on the Cray with CFT 1.14. If this is > the behaviour that "must be supported" to sell compilers, I don't > want any part of it. I consider this to be an _ERROR_ in the > compiler and I'm reporting it to Cray as such. To be fair, the CFT > compiler does issue a warning that the branch is illegal. This is the second whammy I talked about happening. The compiler writer decided that to generate faster code 99% of the time was more important that creating correct code all of the time. I disagree with this decision completely. At least when the compiler generates an infinite loop you know you have a compiler problem. When it generates a bad result, you are in bad shape. If you realize it, than you tear your hair out trying to find your error. There is no justifing creating bad code. Unfortunately many compilers writers forget that to support something extra means supporting something extra correctly. > If a compiler wants to allow the above program it should at least > compile it to something useful. The only "meaningful" interpretation > of the above I can think of is equivalent to the following: > > do 10a i=1,10 > print *,i > if (i.gt.5) goto 10a > do 10 j=1,5 > print *,j > 10 continue > 10a continue > > If a compiler doesn't issue a FATAL message, it should give the above > interpretation - nothing else is acceptable. (Note, I used '10a' as > the label in the above example to make it clear that it is a compiler > generated label.) Going back to my code: k = 0 do 10 i = 1,10 if (i.eq.1.or.i.eq.5) goto 10 do 10 j = 1,10 if (j.eq.3) goto 10 10 k = k + 1 I assume this puts you in the camp that when i = 1 or i = 5 that k is not incremented. There is a large segment of coders that think it should be. This is the big arguement on ambiguity that started this arguement. Personally I'm in your camp. If the compiler supports this feature, it should do it right, put out an warning on non-standard code, and assume the jump in the external DO loop ment to skip this statement (Does the next external iteration). In a perfect world every compiler will comform perfectly to the standard and not take short cuts that leave to badly generated code. But then Elijah probably would be writing the compilers, and we'd all be out of a job :-). enough from this mooncalf - Steven ---------------------------------------------------------------------------- To flame someone for bad spelling or grammer is a discouragement to net discussion in a timely fashion. ---------------------------------------------------------------------------- These opinions aren't necessarily Motorola's or Remora's - but I'd like to think we share some common views. ---------------------------------------------------------------------------- Steven R Weintraub cs.utexas.edu!oakhill!devsys!steve Motorola Inc. Austin, Texas (512) 440-3023 (office) (512) 453-6953 (home) ----------------------------------------------------------------------------
btcx@vax5.CIT.CORNELL.EDU (03/22/89)
In article <1913@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) writes: > >I hold a patent in AI. The system I wrote was in FORTRAN (for constraints >I won't get into). When presenting a paper on it I would always get >the question (from the [person] that seems to always sit in the forth row) >"What language did you use, C or LISP". When I replied FORTRAN, there >were scoffs in the audience. I would unabashedly point out that the >langauge in no way took away from the concept, and while other people >had their AI systems still on the drawing board in LISP or C, mine was >completed working and part of a marketed system. Where do these fourth-row-people come from? Do you suppose it's a secret organization or something? I was at a simulation conference a few years ago, and one of the sessions was on laser disks. Now the paper being presented was about a nice system developed to save various scenarios and put an operator-in-training through his paces without human supervision. It was all there, from different events to automatic review of what the system "felt" the trainee did not understand. Sure enough, someone asked "What language did you write the simulation in?" Immediately my ears pricked up as I sensed I was in the presence of a True Believer In Structured Programming Languages (which is to say, a True Believer in Non-existent Entities). "Fortran", came the unashamed reply. The TBISPL/NE revealed his true colors with his next question: "Why Fortran?" To which I was overjoyed to hear the presenter respond "Because we're engineers." Why am I telling this story for the 100th time? (1) I love it. (I'm an engineer.) (2) It emphasizes Steve's point above (that apparently cannot be over-emphasized) that it is not the tools, but the USE of the tools that should be our focus. The recurring theme in comp.sw-eng is programmer discipline; they're even telling the managers that it's their fault if programmer discipline is not an enforced policy. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= How can you tell when an engineer has been using your terminal? By the White-Out on the screen. (White-Out = Liquid Paper) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I once added "Engineers are great" as a (joke) signature to a posting, and got ripped brilliantly and humourously by someone who had worked with some engineers and found they usually (mistakenly) think themselves to be the best hotshot programmers in town. Mea culpa! But, as in Steve's example above, at least my application is on the street and not the drawing board. (BTW, this is not intended as an excuse for poor programming practices nor as a put down of any language, rather as a response to those who focus on tools instead of techniques.)
jlg@lanl.gov (Jim Giles) (03/24/89)
From article <1917@devsys.oakhill.UUCP>, by steve@oakhill.UUCP (steve): > [...] > Going back to my code: > > k = 0 > do 10 i = 1,10 > if (i.eq.1.or.i.eq.5) goto 10 > do 10 j = 1,10 > if (j.eq.3) goto 10 > 10 k = k + 1 > > I assume this puts you in the camp that when i = 1 or i = 5 that > k is not incremented. There is a large segment of coders that think > it should be. [...] Consider: do 10 i = 1,10 if (i.eq.1.or.i.eq.5) goto 10 do 10 j = 1,10 10 array(j)=array(j)+1 This is the same as your loop except for the final statement (your final IF statement is a no-op and should be eliminated by a smart compiler anyway). Here it is quite clear that the array incrementing should _NOT_ be done as a result of the outer loop GOTO - in the first pass the variable J hasn't even been defined yet! As I pointed out before, either the branch should be illegal or the semantics should be: k = 0 do 10a i = 1,10 if (i.eq.1.or.i.eq.5) goto 10a do 10 j = 1,10 if (j.eq.3) goto 10 10 k = k + 1 10a continue This interpretation is at least consistent and well defined on both examples. J. Giles Los Alamos