1 /*
2 $Id: errorobj.c 2616 2021-04-25 11:08:26Z soci $
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 */
19 #include <string.h>
20 #include "errorobj.h"
21 #include "eval.h"
22 #include "values.h"
23 #include "error.h"
24 #include "64tass.h"
25 #include "file.h"
26 #include "macro.h"
27
28 #include "typeobj.h"
29 #include "registerobj.h"
30 #include "namespaceobj.h"
31
32 static Type obj;
33
34 Type *const ERROR_OBJ = &obj;
35
destroy(Obj * o1)36 static FAST_CALL void destroy(Obj *o1) {
37 Error *v1 = Error(o1);
38 if (v1->line != NULL) free((uint8_t *)v1->line);
39 switch (v1->num) {
40 case ERROR__INVALID_OPER:
41 val_destroy(v1->u.invoper.v1);
42 if (v1->u.invoper.v2 != NULL) val_destroy(v1->u.invoper.v2);
43 return;
44 case ERROR___NO_REGISTER:
45 val_destroy(Obj(v1->u.reg.reg));
46 return;
47 case ERROR_____CANT_UVAL:
48 case ERROR_____CANT_IVAL:
49 case ERROR______NOT_UVAL:
50 val_destroy(v1->u.intconv.val);
51 return;
52 case ERROR___NOT_DEFINED:
53 val_destroy(v1->u.notdef.symbol);
54 val_destroy(Obj(v1->u.notdef.names));
55 return;
56 case ERROR__NOT_KEYVALUE:
57 case ERROR__NOT_HASHABLE:
58 case ERROR_____CANT_SIGN:
59 case ERROR______CANT_ABS:
60 case ERROR______CANT_INT:
61 case ERROR______CANT_LEN:
62 case ERROR_____CANT_SIZE:
63 case ERROR_____CANT_BOOL:
64 case ERROR______NOT_ITER:
65 case ERROR___MATH_DOMAIN:
66 case ERROR_LOG_NON_POSIT:
67 case ERROR_SQUARE_ROOT_N:
68 case ERROR___INDEX_RANGE:
69 case ERROR_____KEY_ERROR:
70 case ERROR_DIVISION_BY_Z:
71 case ERROR_ZERO_NEGPOWER:
72 val_destroy(v1->u.obj);
73 return;
74 case ERROR__INVALID_CONV:
75 val_destroy(v1->u.conv.val);
76 return;
77 default: return;
78 }
79 }
80
garbage(Obj * o1,int i)81 static FAST_CALL void garbage(Obj *o1, int i) {
82 Error *v1 = Error(o1);
83 Obj *v;
84 if (i == 0) {
85 if (v1->line != NULL) free((uint8_t *)v1->line);
86 return;
87 }
88 switch (v1->num) {
89 case ERROR__INVALID_OPER:
90 v = v1->u.invoper.v1;
91 if (v1->u.invoper.v2 != NULL) {
92 if (i < 0) v->refcount--;
93 else if ((v->refcount & SIZE_MSB) != 0) {
94 v->refcount -= SIZE_MSB - 1;
95 v->obj->garbage(v, 1);
96 } else v->refcount++;
97 v = v1->u.invoper.v2;
98 }
99 break;
100 case ERROR___NO_REGISTER:
101 v = Obj(v1->u.reg.reg);
102 break;
103 case ERROR_____CANT_UVAL:
104 case ERROR_____CANT_IVAL:
105 case ERROR______NOT_UVAL:
106 v = v1->u.intconv.val;
107 break;
108 case ERROR___NOT_DEFINED:
109 v = v1->u.notdef.symbol;
110 if (i < 0) v->refcount--;
111 else if ((v->refcount & SIZE_MSB) != 0) {
112 v->refcount -= SIZE_MSB - 1;
113 v->obj->garbage(v, 1);
114 } else v->refcount++;
115 v = Obj(v1->u.notdef.names);
116 break;
117 case ERROR__NOT_KEYVALUE:
118 case ERROR__NOT_HASHABLE:
119 case ERROR_____CANT_SIGN:
120 case ERROR______CANT_ABS:
121 case ERROR______CANT_INT:
122 case ERROR______CANT_LEN:
123 case ERROR_____CANT_SIZE:
124 case ERROR_____CANT_BOOL:
125 case ERROR______NOT_ITER:
126 case ERROR___MATH_DOMAIN:
127 case ERROR_LOG_NON_POSIT:
128 case ERROR_SQUARE_ROOT_N:
129 case ERROR___INDEX_RANGE:
130 case ERROR_____KEY_ERROR:
131 case ERROR_DIVISION_BY_Z:
132 case ERROR_ZERO_NEGPOWER:
133 v = v1->u.obj;
134 break;
135 case ERROR__INVALID_CONV:
136 v = v1->u.conv.val;
137 break;
138 default:
139 return;
140 }
141 if (i < 0) v->refcount--;
142 else if ((v->refcount & SIZE_MSB) != 0) {
143 v->refcount -= SIZE_MSB - 1;
144 v->obj->garbage(v, 1);
145 } else v->refcount++;
146 }
147
new_error(Error_types num,linepos_t epoint)148 MALLOC Error *new_error(Error_types num, linepos_t epoint) {
149 Error *v = Error(val_alloc(ERROR_OBJ));
150 v->num = num;
151 v->file_list = current_file_list;
152 v->epoint.line = epoint->line;
153 v->caret = epoint->pos;
154 v->epoint.pos = macro_error_translate2(epoint->pos);
155 if (not_in_file(pline, current_file_list->file)) {
156 size_t ln = strlen((const char *)pline) + 1;
157 uint8_t *l = (uint8_t *)malloc(ln);
158 if (l != NULL) memcpy(l, pline, ln);
159 v->line = l;
160 } else v->line = NULL;
161 return v;
162 }
163
new_error_mem(linepos_t epoint)164 MALLOC Obj *new_error_mem(linepos_t epoint) {
165 return Obj(new_error(ERROR_OUT_OF_MEMORY, epoint));
166 }
167
new_error_obj(Error_types num,Obj * v1,linepos_t epoint)168 MALLOC Obj *new_error_obj(Error_types num, Obj *v1, linepos_t epoint) {
169 Error *v = new_error(num, epoint);
170 v->u.obj = val_reference(v1);
171 return Obj(v);
172 }
173
new_error_conv(Obj * v1,Type * t,linepos_t epoint)174 MALLOC Obj *new_error_conv(Obj *v1, Type *t, linepos_t epoint) {
175 Error *v = new_error(ERROR__INVALID_CONV, epoint);
176 v->u.conv.t = t;
177 v->u.conv.val = val_reference(v1);
178 return Obj(v);
179 }
180
new_error_argnum(argcount_t num,argcount_t min,argcount_t max,linepos_t epoint)181 MALLOC Obj *new_error_argnum(argcount_t num, argcount_t min, argcount_t max, linepos_t epoint) {
182 Error *v = new_error(ERROR__WRONG_ARGNUM, epoint);
183 v->u.argnum.num = num;
184 v->u.argnum.min = min;
185 v->u.argnum.max = max;
186 return Obj(v);
187 }
188
calc1(oper_t op)189 static MUST_CHECK Obj *calc1(oper_t op) {
190 return val_reference(op->v1);
191 }
192
calc2(oper_t op)193 static MUST_CHECK Obj *calc2(oper_t op) {
194 return val_reference(op->v1);
195 }
196
rcalc2(oper_t op)197 static MUST_CHECK Obj *rcalc2(oper_t op) {
198 return val_reference(op->v2);
199 }
200
slice(oper_t op,argcount_t UNUSED (indx))201 static MUST_CHECK Obj *slice(oper_t op, argcount_t UNUSED(indx)) {
202 return val_reference(op->v1);
203 }
204
errorobj_init(void)205 void errorobj_init(void) {
206 new_type(&obj, T_ERROR, "error", sizeof(Error));
207 obj.destroy = destroy;
208 obj.garbage = garbage;
209 obj.calc1 = calc1;
210 obj.calc2 = calc2;
211 obj.rcalc2 = rcalc2;
212 obj.slice = slice;
213 }
214
error_obj_update(Error * err,const Obj * v1,Obj * v2)215 void error_obj_update(Error *err, const Obj *v1, Obj *v2) {
216 switch (err->num) {
217 case ERROR__INVALID_OPER:
218 if (err->u.invoper.v1 == v1) {
219 val_replace(&err->u.invoper.v1, v2);
220 }
221 if (err->u.invoper.v2 == v1) {
222 val_replace(&err->u.invoper.v2, v2);
223 }
224 return;
225 case ERROR_____CANT_UVAL:
226 case ERROR_____CANT_IVAL:
227 case ERROR______NOT_UVAL:
228 if (err->u.intconv.val == v1) {
229 val_replace(&err->u.intconv.val, v2);
230 }
231 return;
232 case ERROR__NOT_KEYVALUE:
233 case ERROR__NOT_HASHABLE:
234 case ERROR_____CANT_SIGN:
235 case ERROR______CANT_ABS:
236 case ERROR______CANT_INT:
237 case ERROR______CANT_LEN:
238 case ERROR_____CANT_SIZE:
239 case ERROR_____CANT_BOOL:
240 case ERROR______NOT_ITER:
241 case ERROR___MATH_DOMAIN:
242 case ERROR_LOG_NON_POSIT:
243 case ERROR_SQUARE_ROOT_N:
244 case ERROR___INDEX_RANGE:
245 case ERROR_____KEY_ERROR:
246 case ERROR_DIVISION_BY_Z:
247 case ERROR_ZERO_NEGPOWER:
248 if (err->u.obj == v1) {
249 val_replace(&err->u.obj, v2);
250 }
251 return;
252 default:
253 return;
254 }
255 }
256