-
Notifications
You must be signed in to change notification settings - Fork 2
/
error.c
126 lines (103 loc) · 2.46 KB
/
error.c
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <assert.h>
#include <stdlib.h>
#include "agent.h"
#include "error.h"
#include "eval.h"
#include "module.h"
#include "value.h"
struct cb_error {
struct cb_value value;
struct cb_traceback *tb;
};
int cb_error_p(void)
{
return cb_vm_state.error != NULL;
}
struct cb_value *cb_error_value(void)
{
assert(cb_error_p());
return &cb_vm_state.error->value;
}
void cb_error_set(struct cb_value value)
{
struct cb_error *err;
err = malloc(sizeof(struct cb_error));
err->tb = NULL;
err->value = value;
/* FIXME: handle errors raised while handling errors */
if (cb_vm_state.error)
free(cb_vm_state.error);
cb_vm_state.error = err;
}
void cb_error_recover(void)
{
struct cb_traceback *tb, *tmp;
if (!cb_vm_state.error)
return;
tb = cb_vm_state.error->tb;
while (tb) {
tmp = tb->next;
free(tb);
tb = tmp;
}
free(cb_vm_state.error);
cb_vm_state.error = NULL;
}
/* NOTE: frame is copied, ownership is not take by this function */
void cb_traceback_add_frame(struct cb_frame *frame)
{
struct cb_traceback *tb;
assert(cb_vm_state.error);
tb = malloc(sizeof(struct cb_traceback));
tb->frame = *frame;
if (CB_VALUE_IS_USER_FN(&frame->func))
tb->func = cb_vm_state.stack[frame->bp];
tb->next = cb_vm_state.error->tb;
cb_vm_state.error->tb = tb;
}
void cb_traceback_print(FILE *f, struct cb_traceback *tb)
{
struct cb_function *func;
struct cb_user_function *ufunc;
const cb_modspec *spec;
if (CB_VALUE_IS_USER_FN(&tb->frame.func)) {
cb_str buf;
func = tb->func.val.as_function;
fputs("\tin ", f);
/* FIXME: add module information to native functions */
if (func->type == CB_FUNCTION_USER) {
ufunc = &func->value.as_user;
spec = cb_agent_get_modspec(ufunc->module_id);
cb_str modname = cb_agent_get_string(
cb_modspec_name(spec));
fprintf(f, "%s.", cb_strptr(&modname));
}
buf = cb_value_to_string(&tb->func);
fprintf(f, "%s\n", cb_strptr(&buf));
cb_str_free(buf);
} else {
const char *buf;
spec = tb->frame.module->spec;
cb_str modname = cb_agent_get_string(cb_modspec_name(spec));
buf = cb_strptr(&modname);
fprintf(f, "\tin module %s\n", buf);
}
}
struct cb_traceback *cb_error_tb(void)
{
assert(cb_vm_state.error);
return cb_vm_state.error->tb;
}
void cb_error_mark(void)
{
struct cb_error *e;
struct cb_traceback *tb;
e = cb_vm_state.error;
if (!e)
return;
cb_value_mark(&e->value);
for (tb = e->tb; tb; tb = tb->next) {
if (CB_VALUE_IS_USER_FN(&tb->frame.func))
cb_value_mark(&tb->func);
}
}