You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
1.3 KiB
68 lines
1.3 KiB
#include <gen.h>
|
|
#include "dev.h"
|
|
|
|
#include <cstdio>
|
|
|
|
struct sm_generator
|
|
{
|
|
sm_generator* prev;
|
|
sm_gen_fun current;
|
|
};
|
|
|
|
EX_C sm_generator* sm_generate(sm_gen_fun function)
|
|
{
|
|
auto gen = box<sm_generator>();
|
|
gen->prev = nullptr;
|
|
gen->current = function;
|
|
return gen;
|
|
}
|
|
|
|
EX_C 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.
|
|
EX_C bool sm_next(sm_generator** gen, sm_state* state, _sm_user* output)
|
|
{
|
|
if( !(*gen)->current) return false;
|
|
|
|
sm_yield next = (*gen)->current(state);
|
|
|
|
if(sm_state_getopt(state, INTERMEDIATE_RETURNS) || next == nullptr) {
|
|
// Set the return value to `output`.
|
|
if(output && state->current->rval) *output = *state->current->rval;
|
|
else if(output) output->set = false;
|
|
}
|
|
|
|
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;
|
|
}
|