Created
June 18, 2016 16:59
-
-
Save profound7/0408725cc82068a3019ad1a3b7beacf6 to your computer and use it in GitHub Desktop.
Transforming a function into a generator function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// original function | |
function fib():Iterator<Int> { | |
var a = 0; | |
var b = 1; | |
while (true) { | |
@yield a; | |
b = a + b; | |
@yield b; | |
a = a + b; | |
}; | |
} | |
// add label 0 (start state) and label -1 (end state) | |
function fib():Iterator<Int> { | |
@section start; | |
{ | |
var a = 0; | |
var b = 1; | |
while (true) { | |
@yield a; | |
b = a + b; | |
@yield b; | |
a = a + b; | |
}; | |
}; | |
@section end; | |
return; | |
} | |
// transform var statements | |
function fib():Iterator<Int> { | |
@section start; | |
{ | |
{ | |
__var_a_1 = 0; | |
}; | |
{ | |
__var_b_2 = 1; | |
}; | |
while (true) { | |
@yield __var_a_1; | |
__var_b_2 = __var_a_1 + __var_b_2; | |
@yield __var_b_2; | |
__var_a_1 = __var_a_1 + __var_b_2; | |
}; | |
}; | |
@section end; | |
return; | |
} | |
// transforming control structures | |
function fib():Iterator<Int> { | |
@section start; | |
{ | |
{ | |
__var_a_1 = 0; | |
}; | |
{ | |
__var_b_2 = 1; | |
}; | |
{ | |
@label start_loop; | |
@set cond = true; | |
if (!@get cond) @goto end_loop; | |
{ | |
{ | |
__current = __var_a_1; | |
@state next; | |
return; | |
@label next; | |
@void if (false) null; | |
}; | |
__var_b_2 = __var_a_1 + __var_b_2; | |
{ | |
__current = __var_b_2; | |
@state next; | |
return; | |
@label next; | |
@void if (false) null; | |
}; | |
__var_a_1 = __var_a_1 + __var_b_2; | |
}; | |
@goto start_loop; | |
@label end_loop; | |
@void if (false) null; | |
}; | |
}; | |
@section end; | |
{ | |
@state -1; | |
return; | |
}; | |
} | |
// renaming labels and vars | |
function fib():Iterator<Int> { | |
@label start_1; | |
{ | |
{ | |
__var_a_1 = 0; | |
}; | |
{ | |
__var_b_2 = 1; | |
}; | |
{ | |
@label start_loop_3; | |
__cond_3 = true; | |
if (!__cond_3) @goto end_loop_4; | |
{ | |
{ | |
__current = __var_a_1; | |
@state next_5; | |
return; | |
@label next_5; | |
@void if (false) null; | |
}; | |
__var_b_2 = __var_a_1 + __var_b_2; | |
{ | |
__current = __var_b_2; | |
@state next_6; | |
return; | |
@label next_6; | |
@void if (false) null; | |
}; | |
__var_a_1 = __var_a_1 + __var_b_2; | |
}; | |
@goto start_loop_3; | |
@label end_loop_4; | |
@void if (false) null; | |
}; | |
}; | |
@label end_2; | |
{ | |
__state = -1; | |
return; | |
}; | |
} | |
// merging blocks to flatten the code | |
function fib():Iterator<Int> { | |
@label start_1; | |
__var_a_1 = 0; | |
__var_b_2 = 1; | |
@label start_loop_3; | |
__cond_3 = true; | |
if (!__cond_3) @goto end_loop_4; | |
__current = __var_a_1; | |
@state next_5; | |
return; | |
@label next_5; | |
@void if (false) null; | |
__var_b_2 = __var_a_1 + __var_b_2; | |
__current = __var_b_2; | |
@state next_6; | |
return; | |
@label next_6; | |
@void if (false) null; | |
__var_a_1 = __var_a_1 + __var_b_2; | |
@goto start_loop_3; | |
@label end_loop_4; | |
@void if (false) null; | |
@label end_2; | |
__state = -1; | |
return; | |
} | |
// replace label/goto names to integers | |
function fib():Iterator<Int> { | |
@label 0; | |
__var_a_1 = 0; | |
__var_b_2 = 1; | |
@label 1; | |
__cond_3 = true; | |
if (!__cond_3) { | |
__state = 4; | |
continue; | |
}; | |
__current = __var_a_1; | |
__state = 2; | |
return; | |
@label 2; | |
__var_b_2 = __var_a_1 + __var_b_2; | |
__current = __var_b_2; | |
__state = 3; | |
return; | |
@label 3; | |
__var_a_1 = __var_a_1 + __var_b_2; | |
{ | |
__state = 1; | |
continue; | |
}; | |
@label 4; | |
@label 5; | |
__state = -1; | |
return; | |
} | |
// wrapping with a switch | |
function fib():Iterator<Int> while (true) { | |
switch (__state) { | |
case -1:{ | |
throw moon.core.Async.AsyncException.FunctionEnded; | |
}; | |
case 0:{ | |
__var_a_1 = 0; | |
__var_b_2 = 1; | |
}; | |
case 1:{ | |
__cond_3 = true; | |
if (!__cond_3) { | |
__state = 4; | |
continue; | |
}; | |
__current = __var_a_1; | |
__state = 2; | |
return; | |
}; | |
case 2:{ | |
__var_b_2 = __var_a_1 + __var_b_2; | |
__current = __var_b_2; | |
__state = 3; | |
return; | |
}; | |
case 3:{ | |
__var_a_1 = __var_a_1 + __var_b_2; | |
{ | |
__state = 1; | |
continue; | |
}; | |
}; | |
case 4:{ }; | |
case 5:{ | |
__state = -1; | |
return; | |
}; | |
default:{ | |
throw moon.core.Async.AsyncException.InvalidState(__state); | |
}; | |
}; | |
++__state; | |
} | |
// final pass | |
function fib():Iterator<Int> { | |
var __started:Bool = false; | |
var __state:Int = 0; | |
var __current:StdTypes.Int = 0; | |
var __generator:Iterator<StdTypes.Int> = null; | |
var __var_a_1 = null; | |
var __var_b_2 = null; | |
var __cond_3 = null; | |
function __run():Void while (true) { | |
switch (__state) { | |
case -1:{ | |
throw moon.core.Async.AsyncException.FunctionEnded; | |
}; | |
case 0:{ | |
__var_a_1 = 0; | |
__var_b_2 = 1; | |
}; | |
case 1:{ | |
__cond_3 = true; | |
if (!__cond_3) { | |
__state = 4; | |
continue; | |
}; | |
__current = __var_a_1; | |
__state = 2; | |
return; | |
}; | |
case 2:{ | |
__var_b_2 = __var_a_1 + __var_b_2; | |
__current = __var_b_2; | |
__state = 3; | |
return; | |
}; | |
case 3:{ | |
__var_a_1 = __var_a_1 + __var_b_2; | |
{ | |
__state = 1; | |
continue; | |
}; | |
}; | |
case 4:{ }; | |
case 5:{ | |
__state = -1; | |
return; | |
}; | |
default:{ | |
throw moon.core.Async.AsyncException.InvalidState(__state); | |
}; | |
}; | |
++__state; | |
}; | |
function __hasNext() { | |
return __state >= 0; | |
}; | |
function __next() { | |
if (__started) { | |
var tmp = __current; | |
__run(); | |
return tmp; | |
} else { | |
__started = true; | |
__run(); | |
return __next(); | |
}; | |
}; | |
__generator = { hasNext : __hasNext, next : __next }; | |
return __generator; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment