#ifndef STACK_MACHINE_H #define STACK_MACHINE_H //////////////////////////////// // Little Base Layer #include typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; typedef struct String8{ U8 *str; U64 size; } String8; #define str8_const(S) {(U8*)(S), (U64)(sizeof(S) - 1)} typedef struct Arena{ void *memory; U64 pos; U64 cap; } Arena; static Arena arena_alloc(U64 cap); static void* arena_push(Arena *arena, U64 size); static void arena_pop_to(Arena *arena, U64 pos); static U64 arena_pos(Arena *arena); #define push_array(a,T,c) (T*)arena_push((a), sizeof(T)*(c)) //////////////////////////////// // Macros: Linked Lists #define DLLPushBack_NPZ(f,l,n,next,prev,nil)\ (((f) == (nil))?\ ((f)=(l)=(n),(n)->next=(n)->prev=(nil)):\ ((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=(nil))) #define DLLPushBack(f,l,n) DLLPushBack_NPZ(f,l,n,next,prev,0) #define DLLPushFront(f,l,n) DLLPushBack_NPZ(l,f,n,prev,next,0) #define DLLInsert_NPZ(f,l,p,n,next,prev,nil) \ (((p) != (l))?\ ((n)->next = (p)->next,\ (n)->prev = (p),\ (p)->next->prev = (n),\ (p)->next = (n))\ :((n)->next = (nil),\ (n)->prev = (l),\ (l)->next = (n),\ (l) = (n))) #define DLLInsert(f,l,p,n) DLLInsert_NPZ(f,l,p,n,next,prev,0) #define DLLRemove_NPZ(f,l,n,next,prev,nil)\ ((f)==(n)?\ ((f)==(l)?\ ((f)=(l)=(nil)):\ ((f)=(f)->next,(f)->prev=(nil))):\ (l)==(n)?\ ((l)=(l)->prev,(l)->next=(nil)):\ ((n)->next->prev=(n)->prev,\ (n)->prev->next=(n)->next)) #define DLLRemove(f,l,n) DLLRemove_NPZ(f,l,n,next,prev,0) #define SLLQueuePush_NZ(f,l,n,next,nil) (((f)==(nil)?\ (f)=(l)=(n):\ ((l)->next=(n),(l)=(n))),\ (n)->next=(nil)) #define SLLQueuePush(f,l,n) SLLQueuePush_NZ(f,l,n,next,0) #define SLLQueuePushFront_NZ(f,l,n,next,nil) ((f)==(nil)?\ ((f)=(l)=(n),(n)->next=(nil)):\ ((n)->next=(f),(f)=(n))) #define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(f,l,n,next,0) #define SLLQueuePop_NZ(f,l,next,nil) ((f)==(l)?\ (f)=(l)=(nil):\ ((f)=(f)->next)) #define SLLQueuePop(f,l) SLLQueuePop_NZ(f,l,next,0) #define SLLStackPush_N(f,n,next) ((n)->next=(f),(f)=(n)) #define SLLStackPush(f,n) SLLStackPush_N(f,n,next) #define SLLStackPop_NZ(f,next,nil) ((f)==(nil)?(nil):\ ((f)=(f)->next)) #define SLLStackPop(f) SLLStackPop_NZ(f,next,0) //////////////////////////////// // Stack Machine typedef struct SM_Ctx SM_Ctx; //// SM_FRAME //// typedef struct SM_Frame{ String8 name; U64 size; U64 return_size; } SM_Frame; #define SYMBOL_SET_DEFINE SM_FRAME #define SM_FRAME_Type SM_Frame #define SM_FRAME_elf_section ".sy.frame" #define SM_FRAME_coff_a_section ".sy$frame_a" #define SM_FRAME_coff_m_section ".sy$frame_m" #define SM_FRAME_coff_z_section ".sy$frame_z" #define SM_FRAME_marker frame #include "symbol_set.define.h" #define SM_FRAME_STRUCT(F) typedef struct SM_Frame_##F SM_Frame_##F; \ struct SM_Frame_##F #define SM_FRAME_TYPE_DEF(F,T) typedef T SM_Frame_##F #define SM_FRAME_RETURN_STRUCT(F) typedef struct SM_FrameReturn_##F SM_FrameReturn_##F; \ struct SM_FrameReturn_##F #define SM_FRAME_RETURN_TYPE_DEF(F,T) typedef T SM_FrameReturn_##F #define SM_FRAME(F) \ SyDefine(SM_FRAME, F) = { str8_const(#F), sizeof(SM_Frame_##F), sizeof(SM_FrameReturn_##F) } //// SM_STATE //// typedef void SM_StateFunc(SM_Ctx *ctx, void *frame); typedef struct SM_State{ String8 name; SM_StateFunc *func; SY__UAddr frame_id; } SM_State; #define SYMBOL_SET_DEFINE SM_STATE #define SM_STATE_Type SM_State #define SM_STATE_elf_section ".sy.state" #define SM_STATE_coff_a_section ".sy$state_a" #define SM_STATE_coff_m_section ".sy$state_m" #define SM_STATE_coff_z_section ".sy$state_z" #define SM_STATE_marker state #include "symbol_set.define.h" #define SM_STATE_DECL(F,N) SyDeclare(SM_STATE, F##_##N) #define SM_STATE(F,N) \ static void sm_statefunc__##F##_##N(SM_Ctx *ctx, SM_Frame_##F *frame); \ SyDefine(SM_STATE, F##_##N) = { \ .name = str8_const(#F "." #N), \ .func = (SM_StateFunc*)sm_statefunc__##F##_##N, \ .frame_id = SyRaw(SM_FRAME, F) }; \ static void sm_statefunc__##F##_##N(SM_Ctx *ctx, SM_Frame_##F *frame) #if SY__MAIN SY_INIT(SM_STATE){ for (SyEach(SM_STATE, state)){ state->frame_id = SyIDFromRaw(SM_FRAME, state->frame_id); } } #endif //// Context //// typedef struct SM_StackNode{ struct SM_StackNode *next; U64 pop_pos; void *frame; U32 state_id; } SM_StackNode; struct SM_Ctx{ Arena *run_arena; Arena stack_arena; SM_StackNode *stack; void *prev_return; void *new_return; B32 diagnostics; }; static SM_Ctx sm_ctx_new(U32 initial_state_id); static U32 sm_ctx_get_top_state(SM_Ctx *ctx); static void* sm_ctx_get_top_frame(SM_Ctx *ctx); static B32 sm_ctx_stack_empty(SM_Ctx *ctx); static void* sm_ctx_get_prev_return(SM_Ctx *ctx); static void sm_state_stationary(SM_Ctx *ctx); static void sm_state_next(SM_Ctx *ctx, U32 state_id); static void sm_state_stationary_push(SM_Ctx *ctx, U32 push_state_id); static void sm_state_next_push(SM_Ctx *ctx, U32 next_state_id, U32 push_state_id); static void sm_state_pop(SM_Ctx *ctx, void *return_data); static void sm__stack_push(SM_Ctx *ctx, U32 state_id); #endif //STACK_MACHINE_H