// Draft of tests for exception handling. // Outdated: The integer constant exceptions need to be replaced with virtual // exceptions for the new system. // ERROR: exceptions do not interact with ^?{} properly. #include #include #include "except-mac.hfa" TRIVIAL_EXCEPTION(yin) TRIVIAL_EXCEPTION(yang) TRIVIAL_EXCEPTION(zen) // Local type to mark exits from scopes. (see ERROR) struct signal_exit { const char * area; }; void ?{}(signal_exit * this, const char * area) { this->area = area; } void ^?{}(signal_exit * this) { printf("Exiting: %s\n", this->area); // sout | "Exiting:" | this->area; } // Mark throws: make sure to only pass in exception types. forall(dtype T) void terminate(T * except_value) { signal_exit a = {"terminate function"}; THROW(except_value); printf("terminate returned\n"); } forall(dtype T) void resume(T * except_value) { signal_exit a = {"resume function"}; THROW_RESUME(except_value); printf("resume returned\n"); } // Termination Test: Two handlers: no catch, catch void bar() { signal_exit a = {"bar function"}; try { terminate(&(zen){}); } catch (yin * error) { printf("bar caught exception yin.\n"); } } void foo() { signal_exit a = {"foo function"}; try { bar(); } catch (yang * error) { printf("foo caught exception yang.\n"); } catch (zen * error) { printf("foo caught exception zen.\n"); } } // Resumption Two Handler Test: no catch, catch. void beta() { signal_exit a = {"beta function"}; try { zen x; resume(&x); } catchResume (yin * error) { printf("beta caught exception yin\n"); } } void alpha() { signal_exit a = {"alpha function"}; try { beta(); } catchResume (yang * error) { printf("alpha caught exception yang\n"); } catchResume (zen * error) { printf("alpha caught exception zen\n"); } } // Finally Test: void farewell(bool jump) { try { if (jump) { printf("jump out of farewell\n"); goto endoffunction; } else { printf("walk out of farewell\n"); } } finally { printf("See you next time\n"); } endoffunction: printf("leaving farewell\n"); } // Resume-to-Terminate Test: void fallback() { try { zen x; resume(&x); } catch (zen * error) { printf("fallback caught termination zen\n"); } } // Terminate Throw New Exception: void terminate_swap() { signal_exit a = {"terminate_swap"}; try { yin x; terminate(&x); } catch (yin * error) { yang y; terminate(&y); } } void terminate_swapped() { signal_exit a = {"terminate_swapped"}; try { terminate_swap(); } catch (yang * error) { printf("terminate_swapped caught exception yang\n"); } } // Resume Throw New Exception: void resume_swap() { signal_exit a = {"resume_swap"}; try { yin x; resume(&x); } catchResume (yin * error) { yang y; resume(&y); } } void resume_swapped() { try { resume_swap(); } catchResume (yang * error) { printf("resume_swapped caught exception yang\n"); } } // Terminate Rethrow: void reterminate() { try { try { zen x; terminate(&x); } catch (zen * error) { printf("reterminate zen caught and " "will rethrow exception zen\n"); throw; } } catch (zen * error) { printf("reterminate 1 caught exception zen\n"); } } // Resume Rethrow: void reresume() { try { try { zen x; resume(&x); } catchResume (zen * error) { printf("reresume zen caught and rethrows exception zen\n"); throwResume; } } catchResume (zen * error) { printf("reresume 1 caught exception zen\n"); } } // Terminate-Resume interaction: void fum() { // terminate block, call resume try { zen x; resume(&x); } catch (zen * error) { printf("fum caught exception zen\n"); } } void foe() { // resume block, call terminate try { zen y; terminate(&y); } catchResume (zen * error) { printf("foe caught exception zen\n"); } } void fy() { // terminate block calls fum, call foe try { foe(); } catch (zen * error) { printf("fy caught exception zen\n"); fum(); } } void fee() { // resume block, call fy try { fy(); } catchResume (zen * error) { printf("fee caught exception zen\n"); } } // main: choose which tests to run int main(int argc, char * argv[]) { signal_exit a = {"main function"}; foo(); printf("\n"); alpha(); printf("\n"); farewell(false); printf("\n"); farewell(true); printf("\n"); fallback(); printf("\n"); terminate_swapped(); printf("\n"); resume_swapped(); printf("\n"); reterminate(); printf("\n"); reresume(); printf("\n"); fee(); printf("\n"); // Uncaught termination test. printf("Throw uncaught.\n"); yang z; terminate(&z); }