Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!rice!titan.rice.edu!preston From: preston@titan.rice.edu (Preston Briggs) Newsgroups: comp.lang.modula2 Subject: Re: JPI M2 2.00 - PROCEDURE FUNCTIONS & ERROR CHECKING Message-ID: <10218@brazos.Rice.edu> Date: 25 Jul 90 17:29:48 GMT References: <1990Jul24.060519.23417@portia.Stanford.EDU> <10180@brazos.Rice.edu> <90206.084158TRL3@psuvm.psu.edu> Sender: root@rice.edu Organization: Rice University, Houston Lines: 89 In article <90206.084158TRL3@psuvm.psu.edu> TRL3@psuvm.psu.edu (Tim Larson) writes: > you state the "single-entrance, single-exit" >requirement, which Modula-2 neatly destroys with LOOP..END. Is that require- >ment necessary for the algorithm to work? LOOP - END is ok becase all the flow must come out of the END, regardless of how it gets there. My particular idea needs single-entrance, single-exit, though as another poster pointed out, we could could handle all sorts of nasty things during optimization when a complete flow graph is constructed anyway. I'll assume a recursive descent parser. In the routine handling statement-sequences, keep a flag called "unreachable". Initially, it's false. It is set to true if we notice a RETURN, an EXIT, or a call to HALT. At the end of statement-sequence, return the value of unreachable. In a procedure (function) body, when statement-sequence returns, check the unreachable flag. If it's true, then we must have encountered a RETURN or HALT. (EXITs don't count since they should only occur with a LOOP-END and would have already been caught by another mechanism). Note that unreachable only applies to the current statement-sequence. Nested statement-sequences have their own (local) variable. At the beginning of each statement, see if it's unreachable. If so, you might warn the user. If the statement is a RETURN or HALT or EXIT, set the unreachable flag. Also, if it's an EXIT (and the exit was reachable), set a global flag called "exit_reached". This will come up again in the LOOP handling. The other simple statements are uninteresting. Compound statments require more care. A RETURN occuring in a WHILE statement is ignored, since there's always a path around the body of a WHILE. REPEAT-UNTIL and WITH set the unreachable flag if their statement-sequence returns true (indicating that there's a RETURN inside). CASE statements will set unreachable if *all* of their alternatives contain RETURNs. I don't have a standard for M-2, but Oberon specifies that there's no fall through for a CASE. IF-THEN statements will set the unreachable flag if all the alternatives contain a RETURN and there is an ELSE clause. If there's no ELSE, we assume there's a path around the whole statement. LOOPs are a little tricky. We need a global variable called "exit_reached". When we enter a LOOP, we preserve the old exit_reached, a set it to false. Then we call statement_sequence. If any EXIT is reched within the statement sequence (no matter how nested), then exit_reached will be set. At the END, we set unreachable to NOT exit_reached. We also restore exit_reached. That's about it. I implemented it last night in an Oberon parser, and it works ok. There are some interesting effects. You'll get no error in this case BEGIN LOOP END END function; since we'll hang in the loop and therefore never require a return. It would be easy to print a warning in this case too, since we have all the necessary info. I decided not to. Of course, there are easy examples where you'll get a complaint and you *know* that it's unnecessary. BEGIN IF erroneous THEN emit_error_and_halt(1) ELSE RETURN 3 END END function; Here the compiler doesn't know that "emit_error_and_halt" won't be returning and so will complain of missing returns. I guess I'm not too concerned, but others may have opinions. Regarding JPI, if they've added a GOTO (as implied by an earlier posting) then they'd have to be trickier to issue compile-time warnings. Probably why they've gone to a run-time error. -- Preston Briggs looking for the great leap forward preston@titan.rice.edu