source: doc/working/exception/translate.c @ 7ab24fef

Last change on this file since 7ab24fef was f1a10a7, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Updated translate.c, new translation reduces the chance of name mixup.

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