diff options
author | Peter Mikkelsen <peter@pmikkelsen.com> | 2022-02-22 20:41:56 +0000 |
---|---|---|
committer | Peter Mikkelsen <peter@pmikkelsen.com> | 2022-02-22 20:41:56 +0000 |
commit | ae6471f1c94f51df540d95edc09c7749002f44e8 (patch) | |
tree | d810e349ef9926b256d73b0af5b2497a0d355555 /error.c | |
parent | e8e6feeb95cdc3b81a2c17b5a342a3d0b170ccb4 (diff) |
Implement some form of error guards. It may not be perfect yet
Diffstat (limited to 'error.c')
-rw-r--r-- | error.c | 49 |
1 files changed, 45 insertions, 4 deletions
@@ -5,7 +5,7 @@ #include "apl9.h" -ErrorHandler globalerror; +ErrorGuard *globalerrorguard; Rune *errorstrs[] = { [ESyntax] = L"SYNTAX ERROR", @@ -20,11 +20,52 @@ Rune *errorstrs[] = { [ENotImplemented] = L"NOT IMPLEMENTED", }; +ErrorGuard * +newerrorguard(Array *codes, Statement *guard) +{ + DfnFrame *fr = getcurrentdfn(); + ErrorGuard *eg = emallocz(sizeof(ErrorGuard), 1); + eg->active = 1; + eg->guard = guard; + + if(fr == nil) + globalerrorguard = eg; + else{ + eg->next = fr->errorguards; + fr->errorguards = eg; + eg->frame = dupdfnframe(fr); + } + + for(int i = 0; i < GetSize(codes); i++) + eg->code |= (1<<codes->intdata[i]); + + return eg; +} + void throwerror(Rune *msg, int err) { - free(globalerror.msg); - globalerror.msg = msg ? runestrdup(msg) : nil; - longjmp(globalerror.jmp, err); + ErrorGuard *matching = globalerrorguard; + DfnFrame *frame = getcurrentdfn(); + ThreadData *td = getthreaddata(); + td->lasterror = err; + if(td->lasterrormsg) + free(td->lasterrormsg); + td->lasterrormsg = msg; + + while(frame != nil){ + for(ErrorGuard *eg = frame->errorguards; eg != nil; eg = eg->next){ + if(!eg->active) + continue; + if(((1<<err) & eg->code) || (eg->code == 1)){ + matching = eg; + goto match; + } + } + frame = frame->prev; + popdfnframe(); + } +match: + longjmp(matching->jmp, 1); } |