merge yield return values

lib
Avril 3 years ago
commit beb4c6bb27
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -34,6 +34,8 @@ struct _sm_user_page {
struct _sm_frame {
uint64_t pc;
_sm_user* rval; // Pointer to the return value of this function
_sm_user_page user;
_sm_frame* prev;

@ -4,6 +4,34 @@
typedef sm_yield (*sm_gen_fun)(sm_state* state); //NOTE: Same as sm_yield
typedef _sm_user sm_output;
void sm_free_output(sm_output* data);
template<typename T>
inline const T* sm_output_ptr(const sm_output& data)
{
if(data.set)
return _sm_get<T>(const_cast<_sm_user*>(&data));
else return nullptr;
}
template<typename T>
inline bool sm_output_value(const sm_output& data, T* output)
{
auto ptr = sm_output_ptr<T>(data);
if(ptr) {
*output = *ptr;
return true;
} else return false;
}
template<typename T>
inline T sm_output_assume_value(const sm_output& data)
{
return *sm_output_ptr<T>(data);
}
// A generator method
struct sm_generator;
@ -13,4 +41,5 @@ sm_generator* sm_generate(sm_gen_fun function);
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);
/// Any output value yielded from the generator is returned in the output pointer, unless the pointer is NULL, in which case the output is discarded.
bool sm_next(sm_generator** gen, sm_state* state, sm_output* output);

@ -15,6 +15,29 @@ inline uint64_t _sm_compute_key(uint64_t name)
return _sm_confine_key(name);
}
template<typename T>
inline T* _sm_replace(_sm_user* frame, T value)
{
if(frame->set) _sm_free(frame);
frame->set = true;
frame->free = false;
// Key is left the same
return _sm_init(frame, value);
}
template<typename T>
inline T* _sm_replace_ip(_sm_user** frame, T value)
{
if(! (*frame)) {
*frame = box<_sm_user, true>();
}
return _sm_replace(*frame, value);
}
template<typename T, typename U>
inline T* _sm_var(_sm_user_page* user, U name, T init)
{
@ -76,6 +99,11 @@ inline sm_yield sm_continue() { return (sm_yield)_sm_noop; }
#define SM_END } return sm_end()
#define SM_YIELD(v) do { state->current->pc = __LINE__; return (sm_yield)(v); case __LINE__:; } while(0)
#define SM_YIELD_VALUE(v) do { _sm_replace_ip(&state->current->rval, (v)); SM_YIELD(sm_continue()); } while(0)
#define SM_GENERATOR(name) sm_yield name(sm_state* state)
// ---
#define SM_GENERATOR(name) sm_yield name(sm_state* state)

@ -22,11 +22,16 @@ void sm_free_generator(sm_generator* gen)
}
// Returns false if the generator ends.
bool sm_next(sm_generator** gen, sm_state* state)
bool sm_next(sm_generator** gen, sm_state* state, _sm_user* output)
{
if( !(*gen)->current) return false;
sm_yield next = (*gen)->current(state);
// 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:

@ -23,6 +23,16 @@ inline static void sm_free_user(_sm_user* data)
}
}
void sm_free_output(_sm_user* data)
{
if(!data) return;
if(data->set)
sm_free_user(data);
data->set = data->free = false;
}
inline static void _sm_free_page(_sm_user_page* page)
{
for (int i=0;i<_SM_STACK_SIZE;i++) sm_free_user(&page->data[i]);
@ -45,6 +55,11 @@ void sm_free_state(sm_state* state)
while(frame)
{
if(frame->rval) {
sm_free_user(frame->rval);
unbox(frame->rval);
}
_sm_free_all_pages(frame->user.next);
_sm_free_page(&frame->user);
@ -59,6 +74,11 @@ void _sm_pop_stack(sm_state* state)
auto last = unbox(state->current);
state->current = last.prev;
if(last.rval)
{
sm_free_user(last.rval);
unbox(last.rval);
}
_sm_free_all_pages(last.user.next);
_sm_free_page(&last.user);
}

@ -0,0 +1,73 @@
#include <state.h>
#include <gen.h>
#include <cstdio>
struct _test {
int a, b;
};
SM_GENERATOR(sm_test_2)
{
int* a = SM_VAR(-10);
SM_BEGIN;
while( (*a) < 0 ) {
printf("(2) a = %d\n", *a);
SM_YIELD_VALUE(*a);
(*a)+=1;
}
printf("Done!\n");
SM_END;
}
SM_GENERATOR(sm_test)
{
int* a = SM_VAR(10);
auto c = SM_SLOT(_test);
float* d = SM_SLOT(float);
*c = { 200, 300 };
*d = 10.f;
SM_BEGIN;
*a = 5;
SM_YIELD_VALUE(*a);
printf("IN a = %d\n", *a);
*a = 1;
SM_YIELD_VALUE(*a);
printf("IN a = %d\n", *a);
//printf("Starting function 2\n");
SM_YIELD(sm_test_2);
//printf("2 done\n");
SM_END;
}
int main()
{
auto state = sm_new_state();
auto gen = sm_generate(&sm_test);
sm_output output;
while(sm_next(&gen, state, &output)) {
int out_int;
if(!sm_output_value(output, &out_int))
continue;
printf("OUT \t\ta = %d\n", out_int);
}
sm_free_output(&output);
sm_free_generator(gen);
sm_free_state(state);
/*
//TODO: `sm_state` creation/initialisation & freeing functions
//TODO: Test `sm_test`
_test hi = { 0, 0 };
auto _a = _sm_init(nullptr, hi);
*/
return 0;
}
Loading…
Cancel
Save