summaryrefslogtreecommitdiff
path: root/error.c
blob: a0e2a1bdcd38c1a79870501ba96d1b833523f9a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <thread.h>

#include "apl9.h"

ErrorGuard *
newerrorguard(Array *codes, Statement *guard)
{
	ThreadData *td = getthreaddata();
	DfnFrame *fr = getcurrentdfn();
	ErrorGuard *eg = emallocz(sizeof(ErrorGuard), 1);
	eg->active = 1;
	eg->guard = guard;

	if(fr == nil)
		td->globalerrorguard = eg;
	else{
		eg->next = fr->errorguards;
		fr->errorguards = eg;
		eg->frame = dupdfnframe(fr);
	}

	for(int i = 0; i < codes->size; i++)
		eg->code |= (1<<codes->intdata[i]);

	return eg;
}

void
throwerror(Rune *msg, int err)
{
	ThreadData *td = getthreaddata();
	ErrorGuard *matching = td->globalerrorguard;
	DfnFrame *frame = getcurrentdfn();
	td->lasterror = err;
	if(td->lasterrormsg)
		free(td->lasterrormsg);
	td->lasterrormsg = msg ? runestrdup(msg) : nil;

	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);
}

Rune *
errorstr(int code)
{
	Rune *err;
	switch(code){
	case ESyntax: err = L"SYNTAX ERROR"; break;
	case EIndex: err = L"INDEX ERROR"; break;
	case ERank: err = L"RANK ERROR"; break;
	case ELength: err = L"LENGTH ERROR"; break;
	case EValue: err = L"VALUE ERROR"; break;
	case EDomain: err = L"DOMAIN ERROR"; break;
	case ETimeout: err = L"TIMEOUT ERROR"; break;
	case EStack: err = L"STACK OVERFLOW"; break;
	case ENotImplemented: err = L"NOT IMPLEMENTED"; break;
	default: err = L""; break;
	}
	return err;
}

void
displayerror(void)
{
	ThreadData *td = getthreaddata();
	Array *error = allocarray(AtypeArray, 1, 3);
	error->shape[0] = 3;
	error->arraydata[0] = mkrunearray(errorstr(td->lasterror));
	error->arraydata[1] = mkrunearray(td->lasterrormsg ? td->lasterrormsg : L"");
	error->arraydata[2] = fnSame(td->name);
	rundfn(L"0::⎕RAWIO←⍵ ⋄ ('!' ⍵) ⍈ ⎕SESSION", nil, nil, nil, error);
	freearray(error);
}