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.

112 lines
1.9 KiB

#pragma once
#include "box.h"
#include <cstdint>
#define _SM_STACK_SIZE 15
#define _SM_KEY_SIZE (UINT64_MAX >> 2)
struct _sm_user {
uint64_t set : 1; // bool
uint64_t free : 1; // bool
uint64_t key : 62; // Use the rest of the 7 byte hole here for the key.
union {
uint8_t _8;
uint16_t _16;
uint32_t _32;
uint64_t _64;
float _f32;
double _f64;
void* _ptr;
};
};
struct _sm_user_page {
_sm_user data[_SM_STACK_SIZE];
_sm_user_page* next;
};
struct _sm_frame {
uint64_t pc;
_sm_user* rval; // Pointer to the return value of this function
_sm_user_page user;
_sm_frame* prev;
};
/// Options for `state`.
struct _sm_state_opt
{
/// Set the return value within a generator at every yield point, instead of just at the end of the function.
/// (default: true)
bool _opt_INTERMEDIATE_RETURNS;
};
extern const _sm_state_opt _sm_state_opt_default;
struct sm_state {
_sm_state_opt opt;
_sm_frame* current;
};
#define sm_state_setopt(state, name, value) ((state)->opt._opt_ ## name = (value))
#define sm_state_getopt(state, name) ((state)->opt._opt_ ## name)
template<typename T>
inline T* _sm_init(_sm_user* frame, T init)
{
frame->free = true;
T* ptr = box<T>();
*ptr = init;
return (T*) (frame->_ptr = (void*)ptr);
}
template<typename T>
inline T** _sm_init(_sm_user* frame, T* init)
{
frame->free = false;
frame->_ptr = (void*)init;
return (T**) &frame->_ptr;
}
template<typename T>
inline T* _sm_get(_sm_user* frame)
{
return (T*) frame->_ptr;
}
inline void _sm_free(_sm_user* frame)
{
if (frame->free)
free(frame->_ptr);
frame->free = frame->set = false;
}
#define _SM_DEF(T) template<> T* _sm_init<T>(_sm_user* frame, T init); \
template<> T* _sm_get<T>(_sm_user* frame)
_SM_DEF(char);
_SM_DEF(unsigned char);
_SM_DEF(short);
_SM_DEF(unsigned short);
_SM_DEF(int);
_SM_DEF(unsigned int);
_SM_DEF(long);
_SM_DEF(unsigned long);
_SM_DEF(float);
_SM_DEF(double);
#undef _SM_DEF