Path: utzoo!attcan!uunet!cs.utexas.edu!rutgers!rochester!pt.cs.cmu.edu!dsl.pitt.edu!pitt!willett!guest From: guest@willett.pgh.pa.us (Guest Account) Newsgroups: comp.lang.forth Subject: Catch/Throw Message-ID: <1736.UUL1.3#5129@willett.pgh.pa.us> Date: 15 Sep 90 00:44:51 GMT Organization: String, Scotch tape, and Paperclips. (in Pgh, PA) Lines: 92 [I am posting this with the author's permission. I will forward any *posted* replies back to the author. -dwp] Message-Id: <4660872@AppleLink.Apple.COM> Subject: FORTH CATCH/THROW To: WILLETT!DWP@goofy.apple.com From: D2044@AppleLink.Apple.COM (Flavors Tech, Doug Currie,PRT) Date: 12 Sep 90 18:31 GMT 12Sep90 Doug Phillips... I saw your note in Best of GENIE, FORTH Dimensions XII#3, re: CATCH/THROW. I had no idea that CATCH/THROW had caught on since I recommended the mechanism to George Shaw last year. Your "for free" analysis of the requirements for CATCH/THROW implementation is not quite complete. There is a middle ground between your two approaches. I have used this technique for years in my FORTH systems, and the mechanism is free if your program doesn't use it, and quite cheap if it does. The idea is to have a pointer to the top most catch frame on the return stack, and links from catch frame to catch frame. So far, this is just like your first choice. Now when CATCH is executed, it builds the catch frame, and _calls_ the remainder of its containing routine (instead of returning). When the containing routine returns to the CATCH via NEXT, CATCH simply removes the catch frame and falls into NEXT, too, returning from the containing routine. NEXT itself is not changed in the least! The return stack can have anything at all on it (in fact I use it for my LOCAL mechanism). Now THROW is implemented as a return from the outermost CATCH (which hasn't returned yet... it called its return point) after restoring the catch frame pointer. I also have a routine called PUNT-CATCH which removes the top most catch frame from the return stack. Reproduced below are the CATCH, THROW, and PUNT-CATCH routines in M68000 assembly code (this is a native code FORTH, i.e., NEXT = RTS). The references to the frame pointer (A2) are for local variables. EXPORT catch catch ; ( - n T or F ) catch MOVE.W #0, -(A4) ; rtn val MOVEA.L (SP), A0 ; rtn addr, leave it for throw MOVE.L A2, -(SP) ; save frame ptr MOVE.L _catches_(A6), -(SP) ; setup catch frame MOVE.L SP, _catches_(A6) ; link it in JSR (A0) ; return first time ; colon word RTS comes here MOVE.L (SP)+, _catches_(A6) ; unlink ADDQ.L #8, SP ; remove catch frame RTS ; return from colon word EXPORT throw throw ; ( n - n T ) throw - doesn't return to caller but to catch MOVE.W #-1, -(A4) ; rtn val T MOVE.L _catches_(A6), SP ; get catch frame MOVE.L (SP)+, _catches_(A6) ; unlink it MOVE.L (SP)+, A2 ; restore frame ptr RTS ; return from catch again EXPORT punt_catch punt_catch ; ( - ) removes catch frame MOVEA.L (SP)+, A0 ; rtn addr ADDQ.L #4, SP ; remove catch's rtn addr MOVE.L (SP)+, _catches_(A6) ; unlink ADDQ.L #8, SP ; remove catch frame JMP (A0) ; return As a further optimization, I have two mechanisms to set up local variables. One allows CATCHes in the routine with locals, the other doen't and is very cheap. The two mechanisms may be mixed in one program. This is just one more way to make CATCH/THROW inexpensive when not used. Regards, e (Doug Currie, Flavors Technology, Inc., 3 Northern Blvd., Amherst NH 03031) cc: FORTH Dimensions FORTH Interest Group 1330 S. Bascom Ave., Suite D San Jose CA 95155 SIGFORTH, ANS FORTH Project c/o George Shaw POBox 3471 Hayward CA 94540-3471 P.S. Have you guys (FORTH Dimensions, SIGFORTH, ANS FORTH Project) got INTERNET addresses? I'm not on GENIE!