haxe-coroutines icon indicating copy to clipboard operation
haxe-coroutines copied to clipboard

Transformation: `try...catch`

Open RealyUniqueName opened this issue 6 years ago • 2 comments

Source

try {
	doSomething();
} catch(e:String) {
	catchString();
} catch(e:Int) {
	catchInt();
} catch(e:Dynamic) {
	catchDynamic();
}

Short legend for next snippet:

  • __ctx__ is a context of state machine (holds current variable values and other data)
  • ${id} is a unique id for current transformation

Preprocessed into:

//This line indicates that next state should be executed inside of a `try...catch` to handle exceptions; 
//and `@state @catchBegin ${id}` is a state which should be executed on exception
__ctx__.enterTry(@state @catchBegin ${id});
//this line finishes current state and advances state machine to specified state
@goto @tryBegin ${id};
//this line indicates that a new state starts here. In the end it will be replaced with `case ${id}:`
@label @tryBegin ${id}
//actual code of `try` block
doSomething();
//this line indicates that exception handling should be turned off now.
__ctx__.leaveTry();
//if we reached this line, it means there were no exceptions, and we should skip `catch` and go to the line after last `catch` block.
@goto @tryCatchEnd ${id}
//this line indicates a start of a state with `catch` blocks
@label @catchBegin ${id}
//each catch is transformed to a type checking of caught exception
//transforming `if`s is a topic for another transformation.
if(Std.is(__ctx__.exception, String)) {
	catchString();
} else if(Std.is(__ctx__.exception, Int)) {
	catchInt();
} else {
	catchDynamic();
	//if no `catch(e:Dynamic)` is defined in user code, then this block is replaced with
	//__ctx__.notCaught()
	//which rethrows exception if current context is not awaited or propagates exception to a caller context otherwise
}
//indicates a start of next state
@label @tryCatchEnd ${id}
//some cleanup if needed
__ctx__.leaveTryCatch();

RealyUniqueName avatar Sep 18 '17 20:09 RealyUniqueName

It would be nice to look at what this generates in the end. For example, I think current Kotlin implementation would generate something like this:

// state-machine context
var __state = 0;
var __exceptionState = 2;
var __exception = null;

do {
	try {
		switch (__state) {
			case 0:
				__exceptionState = 1;
				doSomething();
				return;
			case 1:
				__exceptionState = 2;
				var e = __exception;
				if ((e is String)) {
					catchString();
				} else if ((e is Int)) {
					catchInt();
				} else {
					catchDynamic();
				}
				return;
			case 2: // default one: rethrow
				throw __exception;
		}
	} catch (e:Dynamic) {
		if (__exceptionState == 2)
			throw e; // rethrow
		__state = __exceptionState;
		__exception = e;
	}
} while (true);

nadako avatar Sep 18 '17 20:09 nadako

It's pretty much the same as your snippet, except try..catch is not getenerated, but state machine is executed inside of a try...catch instead when entering corresponding state.

RealyUniqueName avatar Sep 19 '17 11:09 RealyUniqueName