source: doc/working/exception/impl/test-main.c @ 1a45263

ADTast-experimental
Last change on this file since 1a45263 was e1055441, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Now tests finally during unwind.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1#include "exception.h"
2
3// Use: gcc -fexceptions -Wall -Werror -g exception.c test-main.c
4
5#include <stdio.h>
6#include <stdbool.h>
7
8// Helps with manual translation. It may or may not get folded into the
9// header, that depends on how it interacts with concurancy.
10void __try_resume_node_new(struct __try_resume_node * node,
11        _Bool (*handler)(exception except)) {
12    node->next = shared_stack.top_resume;
13    shared_stack.top_resume = node;
14    node->try_to_handle = handler;
15}
16
17// Local Print On Exit:
18struct raii_base_type {
19        const char * area;
20};
21
22void raii_dtor(struct raii_base_type * this) {
23        printf("Exiting: %s\n", this->area);
24}
25
26#define raii_t __attribute__((cleanup(raii_dtor))) struct raii_base_type
27
28// ===========================================================================
29// Runtime code (post-translation).
30void terminate(int except_value) {
31        raii_t a = {"terminate function"};
32        __throw_terminate(except_value);
33        printf("terminate returned\n");
34}
35
36void resume(int except_value) {
37        raii_t a = {"resume function"};
38        __throw_resume(except_value);
39        printf("resume returned\n");
40}
41
42// Termination Test: Two handlers: no catch, catch
43void bar() {
44        raii_t a = {"bar function"};
45        {
46                void bar_try1() {
47                        terminate(4);
48                }
49                void bar_catch1(int index, exception except) {
50                        switch(except) {
51                        case 1:
52                                printf("bar caught exception 3.\n");
53                                break;
54                        default:
55                                printf("INVALID INDEX in bar: %d (%d)\n", index, except);
56                        }
57                }
58                int bar_match1(exception except) {
59                        if (3 == except) {
60                                return 1;
61                        } else {
62                                return 0;
63                        }
64                }
65                __try_terminate(bar_try1, bar_catch1, bar_match1);
66        }
67}
68
69void foo() {
70        raii_t a = {"foo function"};
71        {
72                void foo_try1() {
73                        bar();
74                }
75                void foo_catch1(int index, exception except) {
76                        switch(index) {
77                        case 1:
78                                printf("foo caught exception 4.\n");
79                                break;
80                        case 2:
81                                printf("foo caught exception 2.\n");
82                                break;
83                        default:
84                                printf("INVALID INDEX in foo: %d (%d)\n", index, except);
85                        }
86                }
87                int foo_match1(exception except) {
88                        if (4 == except) {
89                                return 1;
90                        } else if (2 == except) {
91                                return 2;
92                        } else {
93                                return 0;
94                        }
95                }
96                __try_terminate(foo_try1, foo_catch1, foo_match1);
97        }
98}
99
100// Resumption Two Handler Test: no catch, catch.
101void beta() {
102        raii_t a = {"beta function"};
103        {
104                bool beta_handle1(exception except) {
105                        if (3 == except) {
106                                printf("beta caught exception 3\n");
107                                return true;
108                        } else {
109                                return false;
110                        }
111                }
112                struct __try_resume_node node
113                        __attribute__((cleanup(__try_resume_cleanup)));
114                __try_resume_node_new(&node, beta_handle1);
115                {
116                        resume(4);
117                }
118        }
119}
120void alpha() {
121        raii_t a = {"alpha function"};
122        {
123                bool alpha_handle1(exception except) {
124                        if (2 == except) {
125                                printf("alpha caught exception 2\n");
126                                return true;
127                        } else if (4 == except) {
128                                printf("alpha caught exception 4\n");
129                                return true;
130                        } else {
131                                return false;
132                        }
133                }
134                struct __try_resume_node node
135                        __attribute__((cleanup(__try_resume_cleanup)));
136                __try_resume_node_new(&node, alpha_handle1);
137                {
138                        beta();
139                }
140        }
141}
142
143// Finally Test:
144void farewell(bool jump) {
145        {
146                void farewell_finally1() {
147                        printf("See you next time\n");
148                }
149                struct __cleanup_hook __hidden_hook
150                        __attribute__((cleanup(farewell_finally1)));
151                {
152                        if (jump) {
153                                printf("jump out of farewell\n");
154                                goto endoffunction;
155                        } else {
156                                printf("walk out of farewell\n");
157                        }
158                }
159        }
160        endoffunction:
161        printf("leaving farewell\n");
162}
163
164// Resume-to-Terminate Test:
165void fallback() {
166        {
167                void fallback_try1() {
168                        resume(1);
169                }
170                void fallback_catch1(int index, exception except) {
171                        switch (index) {
172                        case 1:
173                                printf("fallback caught termination 1\n");
174                                break;
175                        default:
176                                printf("INVALID INDEX in fallback: %d (%d)\n", index, except);
177                        }
178                }
179                int fallback_match1(exception except) {
180                        if (1 == except) {
181                                return 1;
182                        } else {
183                                return 0;
184                        }
185                }
186                __try_terminate(fallback_try1, fallback_catch1, fallback_match1);
187        }
188}
189
190// Terminate Throw New Exception:
191void terminate_swap() {
192        raii_t a = {"terminate_swap"};
193        {
194                void fn_try1() {
195                        terminate(2);
196                }
197                void fn_catch1(int index, exception except) {
198                        switch (index) {
199                        case 1:
200                                terminate(1);
201                                break;
202                        default:
203                                printf("INVALID INDEX in terminate_swap: %d (%d)\n",
204                                        index, except);
205                        }
206                }
207                int fn_match1(exception except) {
208                        if (2 == except) {
209                                return 1;
210                        } else {
211                                return 0;
212                        }
213                }
214                __try_terminate(fn_try1, fn_catch1, fn_match1);
215        }
216}
217
218void terminate_swapped() {
219        raii_t a = {"terminate_swapped"};
220        {
221                void fn_try1() {
222                        terminate_swap();
223                }
224                void fn_catch1(int index, exception except) {
225                        switch (index) {
226                        case 1:
227                                printf("terminate_swapped caught exception 1\n");
228                                break;
229                        default:
230                                printf("INVALID INDEX in terminate_swapped: %d (%d)\n",
231                                        index, except);
232                        }
233                }
234                int fn_match1(exception except) {
235                        if (1 == except) {
236                                return 1;
237                        } else {
238                                return 0;
239                        }
240                }
241                __try_terminate(fn_try1, fn_catch1, fn_match1);
242        }
243}
244
245// Resume Throw New Exception:
246void resume_swap() {
247        raii_t a = {"terminate_swap"};
248        {
249                bool fn_handle1(exception except) {
250                        if (2 == except) {
251                                resume(1);
252                                return true;
253                        } else {
254                                return false;
255                        }
256                }
257                struct __try_resume_node node
258                        __attribute__((cleanup(__try_resume_cleanup)));
259                __try_resume_node_new(&node, fn_handle1);
260                {
261                        resume(2);
262                }
263        }
264}
265
266void resume_swapped() {
267        {
268                bool fn_handle1(exception except) {
269                        if (1 == except) {
270                                printf("resume_swapped caught exception 1\n");
271                                return true;
272                        } else {
273                                return false;
274                        }
275                }
276                struct __try_resume_node node
277                        __attribute__((cleanup(__try_resume_cleanup)));
278                __try_resume_node_new(&node, fn_handle1);
279                {
280                        resume_swap();
281                }
282        }
283}
284
285// Terminate Rethrow:
286// I don't have an implementation for this.
287void reterminate() {
288        {
289                void fn_try1() {
290                        void fn_try2() {
291                                terminate(1);
292                        }
293                        void fn_catch2(int index, exception except) {
294                                switch (index) {
295                                case 1:
296                                        printf("reterminate 2 caught and "
297                                               "will rethrow exception 1\n");
298                                        __rethrow_terminate();
299                                        break;
300                                default:
301                                        printf("INVALID INDEX in reterminate 2: %d (%d)\n",
302                                                index, except);
303                                }
304                        }
305                        int fn_match2(exception except) {
306                                if (1 == except) {
307                                        return 1;
308                                } else {
309                                        return 0;
310                                }
311                        }
312                        __try_terminate(fn_try2, fn_catch2, fn_match2);
313                }
314                void fn_catch1(int index, exception except) {
315                        switch (index) {
316                        case 1:
317                                printf("reterminate 1 caught exception 1\n");
318                                break;
319                        default:
320                                printf("INVALID INDEX in reterminate 1: %d (%d)\n",
321                                        index, except);
322                        }
323                }
324                int fn_match1(exception except) {
325                        if (1 == except) {
326                                return 1;
327                        } else {
328                                return 0;
329                        }
330                }
331                __try_terminate(fn_try1, fn_catch1, fn_match1);
332        }
333}
334
335// Resume Rethrow:
336void reresume() {
337        {
338                bool reresume_handle1(exception except) {
339                        if (1 == except) {
340                                printf("reresume 1 caught exception 1\n");
341                                return true;
342                        } else {
343                                return false;
344                        }
345                }
346                struct __try_resume_node node
347                        __attribute__((cleanup(__try_resume_cleanup)));
348                __try_resume_node_new(&node, reresume_handle1);
349                {
350                        bool reresume_handle2(exception except) {
351                                if (1 == except) {
352                                        printf("reresume 2 caught and rethrows exception 1\n");
353                                        return false;
354                                } else {
355                                        return false;
356                                }
357                        }
358                        struct __try_resume_node node
359                                __attribute__((cleanup(__try_resume_cleanup)));
360                        __try_resume_node_new(&node, reresume_handle2);
361                        {
362                                resume(1);
363                        }
364                }
365        }
366}
367
368// Terminate-Resume interaction:
369void fum() {
370        // terminate block, call resume
371        {
372                void fum_try1() {
373                        resume(3);
374                }
375                void fum_catch1(int index, exception except) {
376                        switch (index) {
377                        case 1:
378                                printf("fum caught exception 3\n");
379                                break;
380                        default:
381                                printf("INVALID INDEX in fum: %d (%d)\n", index, except);
382                        }
383                }
384                int fum_match1(exception except) {
385                        if (3 == except) {
386                                return 1;
387                        } else {
388                                return 0;
389                        }
390                }
391                __try_terminate(fum_try1, fum_catch1, fum_match1);
392        }
393}
394
395void foe() {
396        // resume block, call terminate
397        {
398                bool foe_handle1(exception except) {
399                        if (3 == except) {
400                                printf("foe caught exception 3\n");
401                                return true;
402                        } else {
403                                return false;
404                        }
405                }
406                struct __try_resume_node node
407                        __attribute__((cleanup(__try_resume_cleanup)));
408                __try_resume_node_new(&node, foe_handle1);
409                {
410                        terminate(3);
411                }
412        }
413}
414
415void fy() {
416        // terminate block calls fum, call foe
417        {
418                void fy_try1() {
419                        foe();
420                }
421                void fy_catch1(int index, exception except) {
422                        switch (index) {
423                        case 1:
424                                printf("fy caught exception 3\n");
425                                fum();
426                                break;
427                        default:
428                                printf("INVALID INDEX in fy: %d (%d)\n", index, except);
429                        }
430                }
431                int fy_match1(exception except) {
432                        if (3 == except) {
433                                return 1;
434                        } else {
435                                return 0;
436                        }
437                }
438                __try_terminate(fy_try1, fy_catch1, fy_match1);
439        }
440}
441
442void fee() {
443        // resume block, call fy
444        {
445                bool fee_handle1(exception except) {
446                        if (3 == except) {
447                                printf("fee caught exception 3\n");
448                                return true;
449                        } else {
450                                return false;
451                        }
452                }
453                struct __try_resume_node node
454                        __attribute__((cleanup(__try_resume_cleanup)));
455                __try_resume_node_new(&node, fee_handle1);
456                {
457                        fy();
458                }
459        }
460}
461
462
463// main: choose which tests to run
464int main(int argc, char * argv[]) {
465        raii_t a = {"main function"};
466
467        foo(); printf("\n");
468        alpha(); printf("\n");
469        farewell(false); printf("\n");
470        farewell(true); printf("\n");
471        fallback(); printf("\n");
472        terminate_swapped(); printf("\n");
473        resume_swapped(); printf("\n");
474        reterminate(); printf("\n");
475        reresume(); printf("\n");
476        fee(); printf("\n");
477        // Uncaught termination test.
478        terminate(7);
479}
Note: See TracBrowser for help on using the repository browser.