Prev: Data Representation in COBOL
Next: xml acucobol
From: Chuck Stevens on 10 Jan 2006 12:16 "Oliver Wong" <owong(a)castortech.com> wrote in message news:mnRwf.73044$OU5.13400(a)clgrps13... > http://www.csis.ul.ie/COBOL/Course/Iteration.htm > <quote> > Although Netexpress does allow recursive Performs, this is a nonstandard > extension. Please do not take advantage of it.. > </quote> > <quote> > Recursion not allowed. > Although Performs can be nested, neither direct nor indirect recursion is > allowed. This means that a paragraph must not contain a PERFORM that > invokes itself or any ancestor paragraph (parent, grandparent etc). > Unfortunately this restriction is not enforced by the compiler but your > program will not work correctly if you use recursive Performs > </quote> OK, I still haven't found anything in ANSI X3.23-1974 or ANSI X3.23-1985 or ISO/IEC 1989:2002 that leads me to believe that this restriction is anything more than a caution against Bad Practice. > http://docs.hp.com/cgi-bin/doc3k/B3150090014.11950/16 > <quote> > Do not write an illegal program, even if it works on the first > machine for which you are writing the program. It may not work > the same way on another machine. (Examples of illegal things that > may work differently on different machines are: branching out of > PERFORM paragraphs, PERFORM statements with common exit points, > and indirectly recursive PERFORM statements.) > </quote> This is a *directly* recursive PERFORM statement; the restriction isn't relevant. I would say indirectly recursive PERFORMs can be *dangerous* (as can branching out of a PERFORM range to a point that causes the PERFORM itself to be re-executed) and should be regarded as "bad practice", but as far as I can tell, they are not, strictly speaking, "illegal". And while PERFORMs with common exit points may be Bad Style, so long as the *execution-time* path leads to the common exit point, who cares? In fact, PERFORM GR8 in the '85 standard makes rather a point of this: what the PERFORM range actually consists of is an *execution-time* determination and thus directly *permits* the practice: "If there are two or more logical paths to the return point, then procedure-name-2 may be the name of a paragraph consisting of the EXIT statement, to which all of these paths must lead." > My understanding of the behaviour of the PERFORM statement, though I > cannot currently find documentation to back this up, is that there is no > "call stack". Rather, each paragraph has a memory slot associated to it in > which it stores the return address, so if a paragraph calls itself > (directly or indirectly), one of the return addresses will get overwritten > and thus lost. That is an implementation detail. Unisys MCP systems use a different approach, different enough, in fact, that the concept of any sort of "memory address" is fairly foreign. *All* data and code addresses are stack-relative, and data and code may disappear from one location and reappear in another location in memory without any knowledge or intervention by the program, and that includes the stack itself. True, there's no separate "call stack"; it's the same stack that's used for evaluation and for data addressing and everything else. The machine's built around it. When a PERFORM is executed, a PCW pointing to the return point is put on the stack, followed by a value identifying the end of the PERFORM range. At each PERFORM range end point, code checks the value on TOS, and if it matches, does a dynamic branch to the code address to which the PCW points, and if it doesn't, preserves the value and the PCW and drops past the label. It's always the most-recently-active PERFORM that gets checked. The limit to which PERFORMs can be nested at execution time is an implementation detail, and in our case the determining factor is "how much space do you want your program's stack to take up at execution time?" Again, I know full well that mucking with control flow during execution of a PERFORM is frowned upon as Bad Practice, but I still haven't seen anything that leads me to believe *any* COBOL standard expressly forbids it. If you *eventually* get to the end of the PERFORM range, it looks to me like how you get there, and what you do in the meantime, is irrelevant. -Chuck Stevens
From: charles hottel on 10 Jan 2006 12:45 "Chuck Stevens" <charles.stevens(a)unisys.com> wrote in message news:dq0k3c$2dsd$1(a)si05.rsvl.unisys.com... > > "charles hottel" <jghottel(a)yahoo.com> wrote in message > news:a9c14$43c31f96$4f9c6e7$32726(a)DIALUPUSA.NET... >> >> "Nicolas Neuss" <firstname.lastname(a)iwr.uni-heidelberg.de> wrote in >> message news:87lkxpgnwc.fsf(a)ortler.iwr.uni-heidelberg.de... >> >> <snip> >> >>> I had found this one already, but had somehow hoped that a nicer version >>> would be possible, e.g. something like in >>> >>> <http://groups.google.com/group/comp.lang.cobol/msg/fae713b0615c1445> >>> >>> Thank you, >>> >>> Nicolas. >> >> I do not think that the program at this link is valid COBOL. A COBOL >> program can be recursive but COBOL paragraphs are not recursive at least >> not in the compilers that I am familiar with. > > Hmmm. I don't have any problem with the following program using either of > the COBOL compilers supported for the Unisys MCP systems ('74 and '85 > standards respectively): > > IDENTIFICATION DIVISION. > ENVIRONMENT DIVISION. > DATA DIVISION. > WORKING-STORAGE SECTION. > 77 FACT-RES PIC 9(8). > 77 ARGUMENT PIC 9(8). > PROCEDURE DIVISION. > MAIN-LINE. > MOVE 1 TO FACT-RES. MOVE 5 TO ARGUMENT. > PERFORM COMPUTE-FACTORIAL. > DISPLAY FACT-RES. > STOP RUN. > COMPUTE-FACTORIAL. > IF ARGUMENT > 1 > COMPUTE FACT-RES = FACT-RES * ARGUMENT > SUBTRACT 1 FROM ARGUMENT > PERFORM COMPUTE-FACTORIAL. > > I've looked at the standards, and don't see anything that says PERFORMing > a paragraph recursively is illegal (though a STACK OVERFLOW fault in a > COBOL program on Unisys MCP systems is virtually diagnostic of > re-executing a PERFORM without ever completing the PERORM range it is in, > so such matters must be handled with care). > > Can you cite some documentation somewhere supporting the assertion that > one can't PERFORM a paragraph from within the paragraph (whether or not > that paragraph is also PERFORMed externally)? > > -Chuck Stevens See www.cs.vu.nl/~nveerman/research/minefield/minefield.pdf Starting on page 5 this is discussed and some summaries from the manuals of different COBOL vendors is given.
From: charles hottel on 10 Jan 2006 12:53 "charles hottel" <jghottel(a)yahoo.com> wrote in message news:b5912$43c3f2d2$4f9c6bb$4276(a)DIALUPUSA.NET... > > "Chuck Stevens" <charles.stevens(a)unisys.com> wrote in message > news:dq0k3c$2dsd$1(a)si05.rsvl.unisys.com... >> >> "charles hottel" <jghottel(a)yahoo.com> wrote in message >> news:a9c14$43c31f96$4f9c6e7$32726(a)DIALUPUSA.NET... >>> >>> "Nicolas Neuss" <firstname.lastname(a)iwr.uni-heidelberg.de> wrote in >>> message news:87lkxpgnwc.fsf(a)ortler.iwr.uni-heidelberg.de... >>> >>> <snip> >>> >>>> I had found this one already, but had somehow hoped that a nicer >>>> version >>>> would be possible, e.g. something like in >>>> >>>> <http://groups.google.com/group/comp.lang.cobol/msg/fae713b0615c1445> >>>> >>>> Thank you, >>>> >>>> Nicolas. >>> >>> I do not think that the program at this link is valid COBOL. A COBOL >>> program can be recursive but COBOL paragraphs are not recursive at least >>> not in the compilers that I am familiar with. >> >> Hmmm. I don't have any problem with the following program using either >> of the COBOL compilers supported for the Unisys MCP systems ('74 and '85 >> standards respectively): >> >> IDENTIFICATION DIVISION. >> ENVIRONMENT DIVISION. >> DATA DIVISION. >> WORKING-STORAGE SECTION. >> 77 FACT-RES PIC 9(8). >> 77 ARGUMENT PIC 9(8). >> PROCEDURE DIVISION. >> MAIN-LINE. >> MOVE 1 TO FACT-RES. MOVE 5 TO ARGUMENT. >> PERFORM COMPUTE-FACTORIAL. >> DISPLAY FACT-RES. >> STOP RUN. >> COMPUTE-FACTORIAL. >> IF ARGUMENT > 1 >> COMPUTE FACT-RES = FACT-RES * ARGUMENT >> SUBTRACT 1 FROM ARGUMENT >> PERFORM COMPUTE-FACTORIAL. >> >> I've looked at the standards, and don't see anything that says PERFORMing >> a paragraph recursively is illegal (though a STACK OVERFLOW fault in a >> COBOL program on Unisys MCP systems is virtually diagnostic of >> re-executing a PERFORM without ever completing the PERORM range it is in, >> so such matters must be handled with care). >> >> Can you cite some documentation somewhere supporting the assertion that >> one can't PERFORM a paragraph from within the paragraph (whether or not >> that paragraph is also PERFORMed externally)? >> >> -Chuck Stevens > > See > www.cs.vu.nl/~nveerman/research/minefield/minefield.pdf > > Starting on page 5 this is discussed and some summaries from the manuals > of different COBOL vendors is given. > > Page 5 also quotes the 2002 standard and says that recursive PERFORM statements are NOT forbidden by the standard.
From: Alain Reymond on 10 Jan 2006 12:58 Peter Lacey a ?crit : > Alain Reymond wrote: > >>Nicolas, >> >>Try to use the recursive posssibilities of modern Cobol. This is good >>for teaching and showing that Cobol is no more an amount of go to's in >>spaghetti code (troll)... >> > > Why teach the more complicated method first? This isn't a case where > using recursion is preferable. Also (troll-reply) an instructor > shouldn't get involved in religious wars unless that happens to be the > course subject. > > PL I should have added a smile! the fact is that factorial is usualy the first approach to recursion when teached to students. As the other solution is quite easy, the aim was to show that an elegant (I hope so!) solution also exists in Cobol using the same concepts as in C or Pascal or java which probably are more teached to students than Cobol. Regards. Alain
From: Chuck Stevens on 10 Jan 2006 13:35
THAT's the sort of thing I was looking for. The standard reference is ISO/IEC 1989:2002 page 494, 14.8.27.3, PERFORM statement, General Rule 11: "The results of executing the following sequence of PERFORM statements are undefined and no exception condition is set to exist when the following sequence is executed: a) a PERFORM statement is executed and has not yet terminated, then b) within the range of that PERFORM statement another PERFORM statement is executed, then c) the execution of the second PERFORM statement passes through the exit of the first PERFORM statement. " I'd contend that "passes through" is not the same thing as "terminates at". I believe the circumstance being described here is that in which the PERFORM terminus of the second is located such that the PERFORM terminus of the first must be *passed through* to get to the remainder of the statements in the second PERFORM range. I'll file an "interpretation request" with J4 on this point, as I believe the "recursive PERFORM" raises different issues from "PERFORMs with overlapping execution ranges". -Chuck Stevens |