source: doc/working/exception/translate.c @ cc3e4d0

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since cc3e4d0 was 35ba584c, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Added rethrow to translation.
Implemend and tested termination rethrowing.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/* Translation rules for exception handling code, from Cforall to C.
2 *
3 * Note that these are not final. Names, syntax and the exact translation
4 * will be updated. The first section is the shared definitions, not generated
5 * by the local translations but used by the translated code.
6 *
7 * Most of these exist only after translation (in C code). The first (the
8 * exception type) has to exist in Cforall code so that it can be used
9 * directly in Cforall. The two __throw_* functions might have wrappers in
10 * Cforall, but the underlying functions should probably be C. struct
11 * stack_exception_data has to exist inside of the coroutine data structures
12 * and so should be compiled as they are.
13 */
14
15// Currently it is a typedef for int, but later it will be a new type.
16typedef int exception;
17
18void __throw_terminate(exception except) __attribute__((noreturn));
19void __throw_resume(exception except);
20
21void __try_terminate(void (*try_block)(),
22        void (*catch_block)(int index, exception except),
23        int (*match_block)(exception except));
24
25struct __try_resume_node {
26        struct __try_resume_node * next;
27        bool (*try_to_handle)(exception except);
28};
29
30struct __cleanup_hook {};
31
32// An instance of the following must be paired with every stack.
33struct stack_exception_data {
34        __try_resume_node * top_resume_data;
35        // Other pointers may be required for re-resume.
36
37        exception current_exception;
38        int handler_index;
39};
40
41
42// Translations:
43
44// Throws:
45"Cforall"
46
47throw exception_instance;
48
49resume exception_instance;
50
51"C"
52
53__throw_terminate(exception_instance);
54
55__throw_resume(exception_instance);
56
57
58
59// Rethrows (inside matching handlers):
60"Cforall"
61
62throw;
63
64resume;
65
66"C"
67
68__rethrow_terminate();
69
70return false;
71
72
73// Termination Handlers:
74"Cforall"
75
76void try_terminate() {
77        try {
78                insideTry();
79        }
80        catch (SomeException) {
81                fiddleThing();
82        }
83        catch (OtherException err ; err.priority > 3) {
84                twiddleWidget();
85        }
86}
87
88"C"
89
90void try_terminate() {
91        {
92                void try1() {
93                        insideTry();
94                }
95                // index is not nessasary, but should be much faster than going over
96                // all the checks in if we can find a way to pass it in.
97                void catch1(exception except, int index) {
98                        switch (index) {
99                        case 1:
100                                // if it is referenced in the handler, cast except.
101                                {
102                                        fiddleThing();
103                                }
104                                return;
105                        case 2:
106                                {
107                                        twiddleWidget();
108                                }
109                                return;
110                        default:
111                                // Error, should never be reached.
112                        }
113                }
114                int match1(exception except) {
115                        OtherException inner_except;
116                        if (dynamic_cast__SomeException(except)) {
117                                return 1;
118                        }
119                        else if ( (inner_except = dynamic_cast__OtherException(except)) &&
120                                        inner_except.priority > 3) {
121                                return 2;
122                        }
123                        else return 0;
124                }
125                __try_terminate(try1, catch1, match1);
126        }
127}
128
129
130// Resumption Handlers:
131"Cforall"
132
133void try_resume() {
134        try {
135                insideTry();
136        }
137        catch resume (SomeException) {
138                fiddleThing();
139        }
140        catch resume (OtherException err ; err.priority > 3) {
141                twiddleWidget();
142        }
143}
144
145"C"
146
147void try_resume() {
148        {
149                bool catch1(exception except) {
150                        OtherException inner_except;
151                        if (dynamic_cast__SomeException(except)) {
152                                fiddleThing();
153                                return true;
154                        } else if (dynamic_cast__OtherException(except) &&
155                                        inner_except.priority > 3) {
156                                twiddleWidget();
157                                return true;
158                        } else {
159                                return false;
160                        }
161                }
162                struct __try_resume_node data =
163                        {.next = stack.except.top_resume, .try_to_handle = catch1};
164                stack.except.top_resume = &data;
165
166                struct __cleanup_hook generated_name
167                        __attribute__((cleanup(__try_resume_cleanup)));
168
169                {
170                        insideTry();
171                }
172        }
173}
174
175
176// Finally Clause:
177"Cforall"
178
179void try_finally() {
180        try {
181                insideTry();
182        }
183        finally {
184                twiddleWidget();
185        }
186}
187
188"C"
189
190void try_finally() {
191        {
192                void finally1() {
193                        twiddleWidget();
194                }
195
196                struct __cleanup_hook generated_name
197                        __attribute__((cleanup(finally1)));
198
199                {
200                        insideTry();
201                }
202        }
203}
204
205
206// Combining the Above:
207"Cforall"
208
209void try_all() {
210        try {
211                insideTry();
212        }
213        catch (SomeException) {
214                fiddleThing();
215        }
216        catch resume (OtherException) {
217                twiddleWidget();
218        }
219        finally {
220                twiddleWidget();
221        }
222}
223
224"C"
225
226void try_all() {
227        {
228                void try1 () {
229                        insideTry();
230                }
231                void catch1(exception except, int index) {
232                        switch (index) {
233                        case 1:
234                                fiddleThing();
235                                break;
236                        default:
237                                // Error if reached.
238                        }
239                }
240                int match1(exception except) {
241                        if (dynamic_cast__SomeException(except)) {
242                                return 1;
243                        }
244                        return 0;
245                }
246                bool catch2() {
247                        if (dynamic_cast__OtherException(except)) {
248                                twiddleWidget();
249                                return true;
250                        }
251                        return false;
252                }
253                void finally1() {
254                        // Finally, because of timing, also works for resume.
255                        // However this might not actually be better in any way.
256                        __try_resume_cleanup();
257
258                        twiddleWidget();
259                }
260
261                struct __try_resume_node generated_name =
262                        {.next = stack.except.top_resume, .try_to_handle = catch2};
263                stack.except.top_resume = &data;
264                struct __cleanup_hook generated_name
265                        __attribute__((cleanup(finally1)));
266
267                __try_terminate(try1, catch1, match1);
268        }
269}
Note: See TracBrowser for help on using the repository browser.