209 lines
5.2 KiB
C
209 lines
5.2 KiB
C
#ifndef STACK_MACHINE_H
|
|
#define STACK_MACHINE_H
|
|
|
|
////////////////////////////////
|
|
// Little Base Layer
|
|
|
|
#include <stdint.h>
|
|
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
|