Path: news.daimi.aau.dk!news.uni-c.dk!sunic!sunic.sunet.se!seunet!news2.swip.net!plug.news.pipex.net!pipex!tank.news.pipex.net!pipex!news.mathworks.com!fu-berlin.de!marie.physik.tu-berlin.DE!wpp From: wpp@marie.physik.tu-berlin.de (Kai Petzke) Newsgroups: comp.lang.beta Subject: nested patterns and leave/restart Date: 12 Aug 95 16:34:27 GMT Lines: 69 Message-ID: NNTP-Posting-Host: marie.physik.tu-berlin.de (130.149.40.96) NNTP-Posting-User: wpp X-Access: 16 915 Summary: How to handle cases, where a leave/restart is executed out of place? Keywords: bug, leave, restart, pattern, nesting BETA implements the LEAVE and RESTART imperatives, which leave a block respective restart a block. It is possible, to use LEAVE and RESTART from blocks, that are nested within the block to leave respective restart. This yields an interesting problem, though, which is best demonstrated with a code example: ORIGIN '~beta/basiclib/v1.4/betaenv' ---program: Descriptor--- (# m: (# i: @integer enter i do 'p'->put; i->putint; newline #); f1: (# o: ^Object do l1: &(# do 1->m; leave l1; 2->m #)[]->o[] exit o[] #); f2: (# todo: ^Object enter todo[] do todo #); do f1->f2; 3->m #) This code compiles correctly with the Mjolner BETA system, but when run on linux, it just prints "p1", then crashes with a bus error. The problem is, that the object descriptor following the l1 label is not executed in place. Rather, an object is dynamically generated from that object descriptor, and executed later in a different environment. When the "leave l1" imperative is reached there, it is quite understandable, that this causes confusion to the run-time system. My question is to how expand the BETA language defintion to handle this particular case. I can right now think of the following two possibilities: 1) Forbid LEAVE and/or RESTART of enclosing blocks inside of patterns, that are not inserted items. 2) Allow LEAVE and/or RESTART also in non-safe places, like dynamically generated items or general attributes. When such an unsafe LEAVE/RESTART is encountered at run-time, the call stack is traversed to check, if an apopriate label can be found. If that is not the case, a runtime error occurs. Note, that concept 1) is a restriction of the current semantics, while concept 2) is a generalisation, a bit similiar to the throw/try/catch mechanism of C++ or the setjmp()/longjmp() of C. It would allow the following usage, which has been illegal so far: patt: (# part1: (# do (if (* some error condition *) then leave patt if) #); part2: (# ... #); do part1; part2 #) This example requests, that part1 is called directly or indirectly from the do-part of patt. In many cases, this is exactly, what you want: abort a set of routines, if some error or event occurs. Kai -- Kai Petzke | How fast can computers get? Technical University of Berlin | Berlin, Germany | Warp 9, of course, on Star Trek. wpp@marie.physik.tu-berlin.de |