-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy patherrors.c
332 lines (310 loc) · 11.1 KB
/
errors.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
* Description: Errors module of the Chaos Programming Language's source
*
* Copyright (c) 2019-2021 Chaos Language Development Authority <[email protected]>
*
* License: GNU General Public License v3.0
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>
*
* Authors: M. Mert Yildiran <[email protected]>
*/
#include "errors.h"
extern i64* ast_stack;
extern i64 ast_stack_p;
extern i64 ast_ref;
extern FILE* tmp_stdin;
void throw_error_var(throw_error_args in) {
unsigned short code = in.code ? in.code : 0;
char *str1 = in.str1 ? in.str1 : "";
char *str2 = in.str2 ? in.str2 : "";
long long lld1 = in.lld1 ? in.lld1 : 0;
unsigned long long llu1 = in.llu1 ? in.llu1 : 0;
_Function* function = in.function ? in.function : NULL;
throw_error_base(code, str1, str2, lld1, llu1, function);
}
void throw_error_base(
unsigned short code,
char *str1, char *str2,
long long lld1,
unsigned long long llu1,
_Function* function
) {
char title_msg[__KAOS_MSG_LINE_LENGTH__];
char error_msg[__KAOS_MSG_LINE_LENGTH__];
char error_msg_out[__KAOS_MSG_LINE_LENGTH__ + 4];
char bg_color[3];
int indent = 2;
sprintf(bg_color, "41");
sprintf(title_msg, "%*c%s Error (most recent call last):", indent, ' ', __KAOS_LANGUAGE_NAME__);
switch (code) {
case E_UNKNOWN_VARIABLE_TYPE:
sprintf(error_msg, "Unknown variable type: %s for variable: %s", str1, str2);
break;
case E_VARIABLE_ALREADY_DEFINED:
sprintf(error_msg, "The variable name '%s' is already defined!", str1);
break;
case E_UNDEFINED_VARIABLE:
sprintf(error_msg, "Undefined variable: %s", str1);
break;
case E_MEMORY_ALLOCATION_FOR_LIST_FAILED:
sprintf(error_msg, "Memory allocation for list '%s' is failed!", str1);
break;
case E_ILLEGAL_ELEMENT_TYPE_FOR_TYPED_LIST:
sprintf(error_msg, "Illegal element type: %s for the typed list: %s", str1, str2);
break;
case E_VARIABLE_IS_NOT_AN_LIST:
sprintf(error_msg, "Variable '%s' is not an list!", str1);
break;
case E_INDEX_OUT_OF_RANGE:
sprintf(error_msg, "Index out of range: %lld for the list!", lld1);
break;
case E_ILLEGAL_VARIABLE_TYPE_FOR_VARIABLE:
sprintf(error_msg, "Illegal variable type: %s, for variable: %s", str1, str2);
break;
case E_VARIABLE_IS_NOT_A_DICTIONARY:
sprintf(error_msg, "Variable '%s' is not a dictionary!", str1);
break;
case E_UNDEFINED_KEY:
sprintf(error_msg, "Undefined key: %s for dictionary: %s", str1, str2);
break;
case E_UNRECOGNIZED_COMPLEX_DATA_TYPE:
sprintf(error_msg, "Unrecognized complex data type: %s for variable: %s", str1, str2);
break;
case E_ILLEGAL_VARIABLE_TYPE_FOR_FUNCTION:
sprintf(error_msg, "Illegal variable type: %s for function: %s", str1, str2);
break;
case E_UNDEFINED_FUNCTION:
sprintf(error_msg, "Undefined function: %s in %s", str1, str2);
break;
case E_MEMORY_ALLOCATION_FOR_FUNCTION_FAILED:
sprintf(error_msg, "Memory allocation for the function is failed!");
break;
case E_UNEXPECTED_VALUE_TYPE:
sprintf(error_msg, "Unexpected value type: %llu for variable: %s", llu1, str1);
break;
case E_FUNCTION_DID_NOT_RETURN_ANYTHING:
sprintf(error_msg, "The function '%s' did not return anything!", str1);
break;
case E_MODULE_IS_EMPTY_OR_NOT_EXISTS_ON_PATH:
sprintf(error_msg, "The module %s is either empty or not exists on the path!", str1);
break;
case E_NO_VARIABLE_WITH_ID:
sprintf(error_msg, "No variable with given id: %llu is found!", llu1);
break;
case E_INDEX_OUT_OF_RANGE_STRING:
sprintf(error_msg, "Index out of range: %lld for the string!", lld1);
break;
case E_ILLEGAL_CHARACTER_ASSIGNMENT_FOR_STRING:
sprintf(error_msg, "Illegal character assignment for string: %s", str1);
break;
case E_NOT_A_CHARACTER:
sprintf(error_msg, "Right hand side of the assignment is not a character for string: %s", str1);
break;
case E_PROGRAM_FILE_DOES_NOT_EXISTS_ON_PATH:
sprintf(error_msg, "Program file does not exists on the given path: %s", str1);
break;
case E_INCORRECT_FUNCTION_ARGUMENT_COUNT:
sprintf(error_msg, "Incorrect argument count for function: %s", str1);
break;
case E_NOT_A_LIST:
sprintf(error_msg, "'%s' is not a list!", str1);
break;
case E_NOT_A_DICT:
sprintf(error_msg, "'%s' is not a dictionary!", str1);
break;
case E_RAISED_FROM_AN_EXTENSION:
sprintf(error_msg, "%s", str1);
break;
case E_ILLEGAL_VARIABLE_TYPE_FOR_FUNCTION_PARAMETER:
sprintf(error_msg, "Illegal variable type for function parameter: %s of function: %s", str1, str2);
break;
case E_UNEXPECTED_ACCESSOR_DATA_TYPE:
sprintf(error_msg, "Unexpected accessor data type: %s for variable: %s", str1, str2);
break;
case E_NEGATIVE_ITERATION_COUNT:
sprintf(error_msg, "Negative iteration count: %lld", lld1);
break;
case E_BREAK_CALL_OUTSIDE_LOOP:
sprintf(error_msg, "Call to a function with `break` from outside a loop: %s", str1);
break;
case E_BREAK_CALL_MULTILINE_LOOP:
sprintf(error_msg, "Call to a function with `break` from a multiline loop: %s", str1);
break;
case E_STACK_OVERFLOW:
sprintf(error_msg, "Stack overflow! Report this error to https://github.com/chaos-lang/chaos/issues");
break;
default:
sprintf(error_msg, "Unkown error.");
break;
}
sprintf(error_msg_out, " %s", error_msg);
char* new_error_msg_out = str_replace(error_msg_out, "\n", "\\n");
unsigned traceback_size = ast_stack_p + 1;
int cols[2 + traceback_size * 2];
char traceback_line_msg[traceback_size][__KAOS_MSG_LINE_LENGTH__];
char traceback_line[traceback_size][__KAOS_MSG_LINE_LENGTH__];
FILE* fp_module = NULL;
AST* current_ast = NULL;
for (unsigned i = 0; i < ast_stack_p; i++) {
// current_ast = i != 0 ? (void *)ast_stack[i - 1] : (void *)ast_stack[i];
current_ast = (void *)ast_stack[i];
sprintf(
traceback_line_msg[i],
"%*cFile: \"%s\", line %d",
indent * 2,
' ',
current_ast->file->module_path,
current_ast->lineno
);
#ifndef CHAOS_COMPILER
if (current_ast->file->is_interactive) {
fseek(tmp_stdin, 0, SEEK_SET);
fp_module = tmp_stdin;
} else {
#endif
fp_module = fopen(current_ast->file->module_path, "r");
#ifndef CHAOS_COMPILER
}
#endif
char *line = NULL;
if (fp_module == NULL) {
line = malloc(4);
strcpy(line, "???");
} else {
line = get_nth_line(fp_module, current_ast->lineno);
#ifndef CHAOS_COMPILER
if (fp_module != tmp_stdin)
#endif
fclose(fp_module);
if (line == NULL) {
line = malloc(4);
strcpy(line, "???");
}
}
sprintf(
traceback_line[i],
"%*c%s",
indent * 3,
' ',
trim(line)
);
free(line);
}
if (code == E_INDEX_OUT_OF_RANGE || code == E_INDEX_OUT_OF_RANGE_STRING)
// Runtime error
current_ast = (void *)ast_stack[ast_stack_p];
else
// Compile-time error
current_ast = (void *)ast_ref;
if (ast_stack != NULL)
ast_stack[0] = 0;
sprintf(
traceback_line_msg[traceback_size - 1],
"%*cFile: \"%s\", line %d",
indent * 2,
' ',
current_ast->file->module_path,
current_ast->lineno
);
#ifndef CHAOS_COMPILER
if (current_ast->file->is_interactive) {
fseek(tmp_stdin, 0, SEEK_SET);
fp_module = tmp_stdin;
} else {
#endif
fp_module = fopen(current_ast->file->module_path, "r");
#ifndef CHAOS_COMPILER
}
#endif
char *line = NULL;
if (fp_module == NULL) {
line = malloc(4);
strcpy(line, "???");
} else {
line = get_nth_line(fp_module, current_ast->lineno);
#ifndef CHAOS_COMPILER
if (fp_module != tmp_stdin)
#endif
fclose(fp_module);
if (line == NULL) {
line = malloc(4);
strcpy(line, "???");
}
}
sprintf(
traceback_line[traceback_size - 1],
"%*c%s",
indent * 3,
' ',
trim(line)
);
free(line);
cols[0] = (int) strlen(title_msg) + 1;
unsigned j = 0;
for (unsigned i = 0; i < traceback_size; i++) {
cols[j + 1] = (int) strlen(traceback_line_msg[i]) + 1;
cols[j + 2] = (int) strlen(traceback_line[i]) + 1;
j++; j++;
}
cols[1 + traceback_size * 2] = (int) strlen(new_error_msg_out) + 1;
int ws_col = largest(cols, (int) (2 + traceback_size * 2)) + 4;
InteractiveShellErrorAbsorber_ws_col = ws_col;
fflush(stdout);
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[1;%sm", bg_color);
#endif
fprintf(stderr, "%-*s", ws_col, title_msg);
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0m");
#endif
fprintf(stderr, "\n");
for (unsigned i = 0; i < traceback_size; i++) {
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0;%sm", bg_color);
#endif
fprintf(stderr, "%-*s", ws_col, traceback_line_msg[i]);
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0m");
#endif
fprintf(stderr, "\n");
# if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0;%sm", bg_color);
# endif
fprintf(stderr, "%-*s", ws_col, traceback_line[i]);
# if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0m");
# endif
fprintf(stderr, "\n");
}
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[1;%sm", bg_color);
#endif
fprintf(stderr, "%-*s", ws_col, new_error_msg_out);
#if defined(__linux__) || defined(__APPLE__) || defined(__MACH__)
fprintf(stderr, "\033[0m");
#endif
fprintf(stderr, "\n");
free(new_error_msg_out);
fflush(stderr);
#ifndef CHAOS_COMPILER
if (!is_interactive) {
#endif
freeEverything();
exit(code);
#ifndef CHAOS_COMPILER
} else {
absorbError();
}
#endif
}