parent
bc2857fc86
commit
2bab6235db
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
|
||||
typedef sm_yield (*sm_gen_fun)(sm_state* state); //NOTE: Same as sm_yield
|
||||
|
||||
// A generator method
|
||||
struct sm_generator;
|
||||
|
||||
/// Create a generator method with this function.
|
||||
sm_generator* sm_generate(sm_gen_fun function);
|
||||
/// Free a generator method
|
||||
void sm_free_generator(sm_generator* generator);
|
||||
/// Run this generator until the next yield.
|
||||
/// Returns false if the generator ends.
|
||||
bool sm_next(sm_generator** gen, sm_state* state);
|
@ -0,0 +1,57 @@
|
||||
#include <gen.h>
|
||||
|
||||
struct sm_generator
|
||||
{
|
||||
sm_generator* prev;
|
||||
sm_gen_fun current;
|
||||
};
|
||||
|
||||
sm_generator* sm_generate(sm_gen_fun function)
|
||||
{
|
||||
auto gen = box<sm_generator>();
|
||||
gen->prev = nullptr;
|
||||
gen->current = function;
|
||||
return gen;
|
||||
}
|
||||
|
||||
void sm_free_generator(sm_generator* gen)
|
||||
{
|
||||
auto g = unbox(gen);
|
||||
if(g.prev)
|
||||
sm_free_generator(g.prev);
|
||||
}
|
||||
|
||||
// Returns false if the generator ends.
|
||||
bool sm_next(sm_generator** gen, sm_state* state)
|
||||
{
|
||||
if( !(*gen)->current) return false;
|
||||
|
||||
sm_yield next = (*gen)->current(state);
|
||||
switch((uintptr_t)next)
|
||||
{
|
||||
case 0:
|
||||
// Pop the current
|
||||
(*gen)->current = nullptr;
|
||||
|
||||
if ((*gen)->prev) {
|
||||
|
||||
// Pop back to previous stack
|
||||
_sm_pop_stack(state);
|
||||
|
||||
*gen = unbox(*gen).prev;
|
||||
return true;
|
||||
} else return false;
|
||||
default:
|
||||
if (next == (sm_yield)_sm_noop) return true;
|
||||
|
||||
auto prev = *gen;
|
||||
*gen = sm_generate((sm_gen_fun) next);
|
||||
(*gen)->prev = prev;
|
||||
|
||||
// Set up new stack frame
|
||||
_sm_push_stack(state);
|
||||
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
Loading…
Reference in new issue