123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- %
- % CATCH-THROW.RED - Common Lisp dynamic non-local exits
- %
- % Author: Eric Benson
- % Symbolic Computation Group
- % Computer Science Dept.
- % University of Utah
- % Date: 12 October 1982
- % Copyright (c) 1982 University of Utah
- %
- % Edit by Cris Perdue, 23 Feb 1983 1624-PST
- % Modified the stack overflow warning message
- % Edit by Cris Perdue, 16 Feb 1983 1032-PST
- % Changed catch stack overflow checking to give a continuable error
- % when stack gets low, Reset when all out.
- % Edit by Cris Perdue, 4 Feb 1983 1209-PST
- % Moved ERRSET to ERROR-ERRORSET from here.
- % Edit by Cris Perdue, 3 Feb 1983 1520-PST
- % Changed catch stack overflow to talk about the CATCH stack. (!)
- % Deleted definition of "errset".
- % <PSL.KERNEL>CATCH-THROW.RED.13, 21-Dec-82 15:55:26, Edit by BENSON
- % Added %clear-catch-stack
- % <PSL.KERNEL>CATCH-THROW.RED.13, 16-Dec-82 09:58:59, Edit by BENSON
- % Error not within ErrorSet now causes fatal error, not infinite loop
- fluid '(ThrowSignal!*
- EMSG!*
- ThrowTag!*);
- macro procedure catch!-all u;
- (lambda(fn, forms);
- list(list('lambda, '(!&!&Value!&!&),
- list('cond, list('ThrowSignal!*,
- list('Apply,
- fn,
- '(list ThrowTag!* !&!&Value!&!&))),
- '(t !&!&Value!&!&))),
- 'catch . nil . forms))(cadr U, cddr U);
- macro procedure unwind!-all u;
- (lambda(fn, forms);
- list(list('lambda, '(!&!&Value!&!&),
- list('Apply,
- fn,
- '(list (and ThrowSignal!* ThrowTag!*)
- !&!&Value!&!&))),
- 'catch . nil . forms))(cadr U, cddr U);
- macro procedure unwind!-protect u;
- (lambda(protected_form, cleanup_forms);
- list(list('lambda, '(!&!&Value!&!&),
- list('lambda, '(!&!&Thrown!&!& !&!&Tag!&!&),
- 'progn . cleanup_forms,
- '(cond (!&!&Thrown!&!&
- (!%Throw !&!&Tag!&!& !&!&Value!&!&))
- (t !&!&Value!&!&)))
- . '(ThrowSignal!* ThrowTag!*)),
- list('catch, ''!$unwind!-protect!$, protected_form)))(cadr U,cddr U);
- off R2I;
- % This funny definition is due to a PA1FN for CATCH
- fexpr procedure Catch U;
- (lambda(Tag, Forms);
- Catch(Eval Tag, EvProgN Forms))(car U, cdr U);
- on R2I;
- % Temporary compatibility package.
- macro procedure !*Catch U;
- 'Catch . cdr U;
- expr procedure !*Throw(x,y);
- throw(x,y);
- on Syslisp;
- % Size is in terms of number of frames
- internal WConst CatchStackSize = 400;
- internal WArray CatchStack[CatchStackSize*4];
- internal WVar CatchStackPtr = &CatchStack[0];
- CompileTime <<
- smacro procedure CatchPop();
- CatchStackPtr := &CatchStackPtr[-4];
- smacro procedure CatchStackDecrement X;
- &X[-4];
- % Rather large for a smacro, used only from CatchSetupAux /csp
- % Tests structured for fast usual execution /csp
- % Random constant 5 for "reserve" catch stack frames /csp
- smacro procedure CatchPush(Tag, PC, SP, Env);
- << CatchStackPtr := &CatchStackPtr[4];
- if CatchStackPtr >= &CatchStack[(CatchStackSize-5)*4] then
- << if CatchStackPtr = &CatchStack[(CatchStackSize-5)*4] then
- ContinuableError(99,"Catch-throw stack overflow (warning)", NIL);
- if CatchStackPtr >= &CatchStack[CatchStackSize*4] then
- << (LispVar EMSG!*) := "Catch stack overflow";
- reset() >> >>;
- CatchStackPtr[0] := Tag;
- CatchStackPtr[1] := PC;
- CatchStackPtr[2] := SP;
- CatchStackPtr[3] := Env >>;
- smacro procedure CatchTopTag();
- CatchStackPtr[0];
- smacro procedure CatchTagAt X;
- X[0];
- smacro procedure CatchTopPC();
- CatchStackPtr[1];
- smacro procedure CatchTopSP();
- CatchStackPtr[2];
- smacro procedure CatchTopEnv();
- CatchStackPtr[3];
- flag('(CatchSetupAux ThrowAux FindCatchMarkAndThrow), 'InternalFunction);
- >>;
- % CatchSetup puts the return address in reg 2, the stack pointer in reg 3
- % and calls CatchSetupAux
- lap '((!*entry CatchSetup expr 1) %. CatchSetup(Tag)
- (!*MOVE (MEMORY (reg st) (WConst 0)) (reg 2))
- (!*MOVE (reg st) (reg 3))
- (!*JCALL CatchSetupAux)
- );
- syslsp procedure CatchSetupAux(Tag, PC, SP);
- begin scalar Previous;
- Previous := CatchStackPtr;
- CatchPush(Tag, PC, SP, CaptureEnvironment());
- LispVar ThrowSignal!* := NIL;
- return Previous;
- end;
- syslsp procedure !%UnCatch Previous;
- << CatchStackPtr := Previous;
- LispVar ThrowSignal!* := NIL >>;
- syslsp procedure !%clear!-catch!-stack();
- CatchStackPtr := &CatchStack[0];
- syslsp procedure !%Throw(Tag, Value);
- begin scalar TopTag;
- TopTag := CatchTopTag();
- return if not (null TopTag
- or TopTag eq '!$unwind!-protect!$
- or Tag eq TopTag) then
- << CatchPop();
- !%Throw(Tag, Value) >>
- else begin scalar PC, SP;
- PC := CatchTopPC();
- SP := CatchTopSP();
- RestoreEnvironment CatchTopEnv();
- CatchPop();
- LispVar ThrowSignal!* := T;
- LispVar ThrowTag!* := Tag;
- return ThrowAux(Value, PC, SP);
- end;
- end;
- lap '((!*entry ThrowAux expr 3)
- (!*MOVE (reg 3) (reg st))
- (!*MOVE (reg 2) (MEMORY (reg st) (WConst 0)))
- (!*EXIT 0)
- );
- syslsp procedure Throw(Tag, Value);
- FindCatchMarkAndThrow(Tag, Value, CatchStackPtr);
- % Throw to $Error$ that doesn't have a catch can't cause a normal error
- % else an infinite loop will result. Changed to use FatalError instead.
- syslsp procedure FindCatchMarkAndThrow(Tag, Value, P);
- if P = &CatchStack[0] then
- if not (Tag eq '!$Error!$) then
- ContError(99,
- "Catch tag %r not found in Throw",
- Tag,
- Throw(Tag, Value))
- else FatalError "Error not within ErrorSet"
- else if null CatchTagAt P or Tag eq CatchTagAt P then
- !%Throw(Tag, Value)
- else FindCatchMarkAndThrow(Tag, Value, CatchStackDecrement P);
- off Syslisp;
- END;
|