From 25be3d41bc363671283ab503c9aa8b4190d76b85 Mon Sep 17 00:00:00 2001 From: mr4th Date: Sat, 4 Jul 2026 12:17:28 -0700 Subject: [PATCH] new example 'stack machine' with typed frames --- build.sh | 12 - build_with_cl.bat | 9 +- build_with_clang.bat | 13 +- build_with_clang.sh | 18 ++ examples/example1.h | 5 +- examples/stack_machine.c | 525 +++++++++++++++++++++++++++++++++++ examples/stack_machine.h | 208 ++++++++++++++ project.4coder | 9 +- symbol_set/symbol_set.init.h | 15 +- 9 files changed, 789 insertions(+), 25 deletions(-) delete mode 100755 build.sh create mode 100755 build_with_clang.sh create mode 100644 examples/stack_machine.c create mode 100644 examples/stack_machine.h diff --git a/build.sh b/build.sh deleted file mode 100755 index 6b67cd2..0000000 --- a/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -code=$PWD -opts=-g -inc="-I$code/symbol_set" - -mkdir -p build -cd build - -clang -c $code/examples/example1.c $opts $inc -./symbol_set.ld_meta example1.o -clang -o example1 $code/examples/example1.c $opts $inc -T sy.ld diff --git a/build_with_cl.bat b/build_with_cl.bat index 102cb31..e025003 100644 --- a/build_with_cl.bat +++ b/build_with_cl.bat @@ -2,8 +2,15 @@ set code=%cd% set opts=-FC -GR- -EHa- -nologo -Zi -std:c11 -wd5105 +set linkopts=-link -INCREMENTAL:NO set inc=-I%code%\symbol_set + if not exist "build" ( mkdir build ) pushd build -cl -Feexample1 %code%\examples\example1.c %opts% %inc% -link -INCREMENTAL:NO +if "%1" == "" ( + cl -Feexample1 %code%\examples\example1.c %opts% %inc% %linkopts% +) +if "%1" == "stack_machine" ( + cl -Festack_machine %code%\examples\stack_machine.c %opts% %inc% %linkopts% +) popd diff --git a/build_with_clang.bat b/build_with_clang.bat index a841fea..9e9a531 100644 --- a/build_with_clang.bat +++ b/build_with_clang.bat @@ -2,7 +2,18 @@ set code=%cd% set opts=-g +set linkopts=-Xlinkker -INCREMENTAL:NO set inc=-I%code%\symbol_set + +if not exist "build" ( mkdir build ) pushd build -clang -o example1 %code%\examples\example1.c %opts% %inc% -Xlinker -INCREMENTAL:NO + +if "%1" == "" ( + clang -o example1 %code%\examples\example1.c %opts% %inc% %linkopts% +) +if "%1" == "stack_machine" ( + clang -o stack_machine %code%\examples\stack_machine.c %opts% %inc% %linkopts% +) + popd + diff --git a/build_with_clang.sh b/build_with_clang.sh new file mode 100755 index 0000000..77537e6 --- /dev/null +++ b/build_with_clang.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +code=$PWD +opts=-g +inc="-I$code/symbol_set" + +mkdir -p build +cd build + +if [[ "$1" == "" ]]; then + clang -c $code/examples/example1.c $opts $inc + ./symbol_set.ld_meta example1.o + clang -o example1 $code/examples/example1.c $opts $inc -T sy.ld +elif [[ "$1" == "stack_machine" ]]; then + clang -c $code/examples/stack_machine.c $opts $inc + ./symbol_set.ld_meta stack_machine.o + clang -o stack_machine $code/examples/stack_machine.c $opts $inc -T sy.ld +fi diff --git a/examples/example1.h b/examples/example1.h index 7ef9957..34af4fb 100644 --- a/examples/example1.h +++ b/examples/example1.h @@ -2,7 +2,7 @@ #define EXAMPLE1_H //////////////////////////////// -// Example 1 Header +// Little Base Layer #include typedef int8_t S8; @@ -25,6 +25,9 @@ typedef struct String8{ U64 size; } String8; +//////////////////////////////// +// Example Specifics + typedef struct EX1_Ctx{ S64 foo; } EX1_Ctx; diff --git a/examples/stack_machine.c b/examples/stack_machine.c new file mode 100644 index 0000000..eadadfb --- /dev/null +++ b/examples/stack_machine.c @@ -0,0 +1,525 @@ +/* +** C Scripting - Stack Machine +*/ + +#define SY__MAIN 1 +#include "symbol_set.h" +#include "symbol_set.init.h" + +#include "stack_machine.h" +#include +#include +#include + +//////////////////////////////// +// Little Base Layer + +static Arena +arena_alloc(U64 cap){ + Arena arena = {0}; + arena.memory = malloc(cap); + arena.cap = cap; + return(arena); +} + +static void* +arena_push(Arena *arena, U64 size){ + void *result = 0; + if (arena->pos + size <= arena->cap){ + result = (U8*)arena->memory + arena->pos; + arena->pos += size; + arena->pos = (arena->pos + 7)&~7; // "round up to multiple of 8" + memset(result, 0, size); + } + return(result); +} + +static void +arena_pop_to(Arena *arena, U64 pos){ + if (pos < arena->pos){ + arena->pos = (pos + 7)&~7; // "round up to multiple of 8" + } +} + +static U64 +arena_pos(Arena *arena){ + return(arena->pos); +} + +//////////////////////////////// +// Stack Machine + +//// TICTACTOE Data //// + +struct TICTACTOE_Line{ U32 idx[3]; }; +static struct TICTACTOE_Line tictactoe_lines[8] = { + {.idx = { 0, 1, 2 }}, + {.idx = { 3, 4, 5 }}, + {.idx = { 6, 7, 8 }}, + {.idx = { 0, 3, 6 }}, + {.idx = { 1, 4, 7 }}, + {.idx = { 2, 5, 8 }}, + {.idx = { 0, 4, 8 }}, + {.idx = { 2, 4, 6 }}, +}; + +//// Symbol Definitions //// + +SM_FRAME_STRUCT(TicTacToe){ + B8 turn; + U8 board[9]; +}; + +SM_FRAME_RETURN_TYPE_DEF(TicTacToe, B32); + +SM_FRAME(TicTacToe); + +SM_STATE_DECL(TicTacToe, P1Turn); +SM_STATE_DECL(TicTacToe, P2Turn); +SM_STATE_DECL(TicTacToe, BoardCheck); + +SM_STATE(TicTacToe, Init){ + memset(frame->board, ' ', 9); + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_P1Turn)); +} + +SM_STATE(TicTacToe, P1Turn){ + printf("BOARD:\n"); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[0], frame->board[1], frame->board[2]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[3], frame->board[4], frame->board[5]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[6], frame->board[7], frame->board[8]); + printf("+-+-+-+\n"); + + printf("YOUR MOVE: "); + U32 x = 0; + U32 y = 0; + scanf("%u %u", &x, &y); + + frame->board[y*3 + x] = 'X'; + + frame->turn = 1; + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_BoardCheck)); +} + +SM_STATE(TicTacToe, P2Turn){ + U32 x = 0; + U32 y = 0; + + struct TICTACTOE_Line *lines = tictactoe_lines; + + // if you can win, then win + for (U32 i = 0; i < 8; i += 1){ + U32 count_mine = 0; + U32 blank_spot = ~0; + for (U32 j = 0; j < 3; j += 1){ + U32 idx = lines[i].idx[j]; + U8 c = frame->board[idx]; + if (c == 'O'){ + count_mine += 1; + } + else if (c == ' '){ + blank_spot = idx; + } + } + if (blank_spot != ~0 && count_mine == 2){ + x = blank_spot%3; + y = blank_spot/3; + goto play; + } + } + + // if you need to block, then block + for (U32 i = 0; i < 8; i += 1){ + U32 count_other = 0; + U32 blank_spot = ~0; + for (U32 j = 0; j < 3; j += 1){ + U32 idx = lines[i].idx[j]; + U8 c = frame->board[idx]; + if (c == 'X'){ + count_other += 1; + } + else if (c == ' '){ + blank_spot = idx; + } + } + if (blank_spot != ~0 && count_other == 2){ + x = blank_spot%3; + y = blank_spot/3; + goto play; + } + } + + // otherwise just random + { + U32 potentials[9]; + U32 count = 0; + for (U32 i = 0; i < 9; i += 1){ + if (frame->board[i] == ' '){ + potentials[count] = i; + count += 1; + } + } + + if (count > 0){ + U32 idx = rand()%count; + x = potentials[idx]%3; + y = potentials[idx]/3; + goto play; + } + } + + play: + printf("OPPONENT PLAYED AT: %u %u\n", x, y); + frame->board[y*3 + x] = 'O'; + + frame->turn = 0; + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_BoardCheck)); +} + +SM_STATE(TicTacToe, P1Win){ + printf("You won!\n"); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[0], frame->board[1], frame->board[2]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[3], frame->board[4], frame->board[5]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[6], frame->board[7], frame->board[8]); + printf("+-+-+-+\n"); + + sm_state_pop(ctx, &(B32){1}); +} + +SM_STATE(TicTacToe, P1Lose){ + printf("You lost!\n"); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[0], frame->board[1], frame->board[2]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[3], frame->board[4], frame->board[5]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[6], frame->board[7], frame->board[8]); + printf("+-+-+-+\n"); + + sm_state_pop(ctx, &(B32){0}); +} + +SM_STATE(TicTacToe, Tie){ + printf("You tied!\n"); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[0], frame->board[1], frame->board[2]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[3], frame->board[4], frame->board[5]); + printf("+-+-+-+\n"); + printf("|%c|%c|%c|\n", frame->board[6], frame->board[7], frame->board[8]); + printf("+-+-+-+\n"); + + sm_state_pop(ctx, &(B32){0}); +} + +SM_STATE(TicTacToe, BoardCheck){ + U32 winner = 0; + for (U32 i = 0; i < 8; i += 1){ + U32 count[2] = {0}; + for (U32 j = 0; j < 3; j += 1){ + U32 idx = tictactoe_lines[i].idx[j]; + U8 c = frame->board[idx]; + if (c == 'X'){ + count[0] += 1; + } + else if (c == 'O'){ + count[1] += 1; + } + } + for (U32 k = 0; k < 2; k += 1){ + if (count[k] == 3){ + winner = k + 1; + } + } + } + + B32 tie = 0; + if (winner == 0){ + tie = 1; + for (U32 i = 0; i < 9; i += 1){ + if (frame->board[i] == ' '){ + tie = 0; + break; + } + } + } + + // end states + if (tie){ + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_Tie)); + } + else if (winner == 1){ + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_P1Win)); + } + else if (winner == 2){ + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_P1Lose)); + } + // next turn + else{ + if (frame->turn == 0){ + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_P1Turn)); + } + else{ + sm_state_next(ctx, SyID(SM_STATE, TicTacToe_P2Turn)); + } + } +} + +SM_FRAME_STRUCT(RockPaperScissors){ + S32 score; +}; + +SM_FRAME_RETURN_TYPE_DEF(RockPaperScissors, B32); + +SM_FRAME(RockPaperScissors); + +SM_STATE(RockPaperScissors, Play){ + printf("YOUR SCORE: %d\n", frame->score); + printf("[1] ROCK [2] PAPER [3] SCISSORS SHOOT: "); + U32 m = 0; + scanf("%u", &m); + m = m%3; + + U32 o = rand()%3; + switch (o){ + case 1: printf("YOUR OPPONENT THROWS ROCK.\n"); break; + case 2: printf("YOUR OPPONENT THROWS PAPER.\n"); break; + case 0: printf("YOUR OPPONENT THROWS SCISSORS.\n"); break; + } + + // p1 wins + if ((m + 2)%3 == o){ + frame->score += 1; + if (frame->score < 3){ + printf("YOU WON THIS ROUND!\n"); + sm_state_stationary(ctx); + } + else{ + printf("YOU WIN!\n"); + sm_state_pop(ctx, &(B32){1}); + } + } + + // p2 wins + else if ((o + 2)%3 == m){ + frame->score -= 1; + if (frame->score > -3){ + printf("YOU LOST THIS ROUND!\n"); + sm_state_stationary(ctx); + } + else{ + printf("YOU LOST!\n"); + sm_state_pop(ctx, &(B32){0}); + } + } + + // no winner + else{ + sm_state_stationary(ctx); + } +} + +SM_FRAME_STRUCT(Menu){ + U32 wins[2]; + U32 last_played_game; +}; +SM_FRAME_RETURN_TYPE_DEF(Menu, void); + +SM_FRAME(Menu); + +SM_STATE_DECL(Menu, RecordWin); + +SM_STATE(Menu, Play){ + B32 has_win = 0; + for (U32 i = 0; i < sizeof(frame->wins)/sizeof(*frame->wins); i += 1){ + if (frame->wins[i]){ + has_win = 1; + break; + } + } + if (has_win){ + printf("Your wins:\n"); + printf("Tic-Tac-Toe %u\n", frame->wins[0]); + printf("Rock-Paper-Scissors %u\n", frame->wins[1]); + } + + printf("Choose a game:\n"); + printf("[1] Tic-Tac-Toe\n"); + printf("[2] Rock-Paper-Scissors\n"); + printf("[3] Quit\n"); + + U32 x = 0; + scanf("%u", &x); + switch (x){ + case 1: { + frame->last_played_game = 1; + sm_state_next_push(ctx, SyID(SM_STATE, Menu_RecordWin), + SyID(SM_STATE, TicTacToe_Init)); + }break; + + case 2: { + frame->last_played_game = 2; + sm_state_next_push(ctx, SyID(SM_STATE, Menu_RecordWin), + SyID(SM_STATE, RockPaperScissors_Play)); + }break; + + case 3: sm_state_pop(ctx, 0); break; + default: sm_state_stationary(ctx); break; + } +} + +SM_STATE(Menu, RecordWin){ + B32 *win = sm_ctx_get_prev_return(ctx); + if (win != 0 && *win && + 1 <= frame->last_played_game && + frame->last_played_game <= sizeof(frame->wins)/sizeof(*frame->wins)){ + frame->wins[frame->last_played_game - 1] += 1; + } + sm_state_next(ctx, SyID(SM_STATE, Menu_Play)); +} + +//// Function Definitions //// + +static SM_Ctx +sm_ctx_new(U32 initial_state_id){ + SM_Ctx ctx = {0}; + ctx.stack_arena = arena_alloc((10 << 20)); + sm__stack_push(&ctx, initial_state_id); + return(ctx); +} + +static U32 +sm_ctx_get_top_state(SM_Ctx *ctx){ + U32 result = 0; + if (ctx->stack != 0){ + result = ctx->stack->state_id; + } + return(result); +} + +static void* +sm_ctx_get_top_frame(SM_Ctx *ctx){ + void *result = 0; + if (ctx->stack != 0){ + result = ctx->stack->frame; + } + return(result); +} + +static B32 +sm_ctx_stack_empty(SM_Ctx *ctx){ + B32 result = (ctx->stack == 0); + return(result); +} + +static void* +sm_ctx_get_prev_return(SM_Ctx *ctx){ + void *prev_return = ctx->prev_return; + return(prev_return); +} + +static void +sm_state_stationary(SM_Ctx *ctx){ + // nothing to do +} + +static void +sm_state_next(SM_Ctx *ctx, U32 state_id){ + if (ctx->stack != 0){ + ctx->stack->state_id = state_id; + } +} + +static void +sm_state_stationary_push(SM_Ctx *ctx, U32 push_state_id){ + if (ctx->stack != 0){ + // push + sm__stack_push(ctx, push_state_id); + } +} + +static void +sm_state_next_push(SM_Ctx *ctx, U32 next_state_id, U32 push_state_id){ + if (ctx->stack != 0){ + // next + ctx->stack->state_id = next_state_id; + // push + sm__stack_push(ctx, push_state_id); + } +} + +static void +sm_state_pop(SM_Ctx *ctx, void *return_data){ + if (ctx->stack != 0){ + // save return + if (return_data != 0){ + SM_State *state = SyAddressFromID(SM_STATE, ctx->stack->state_id); + SM_Frame *frame = SyAddressFromID(SM_FRAME, state->frame_id); + ctx->new_return = push_array(ctx->run_arena, U8, frame->return_size); + memcpy(ctx->new_return, return_data, frame->return_size); + } + + // stack pops + U64 pos = ctx->stack->pop_pos; + SLLStackPop(ctx->stack); + arena_pop_to(&ctx->stack_arena, pos); + } +} + +static void +sm__stack_push(SM_Ctx *ctx, U32 state_id){ + SM_State *state = SyAddressFromID(SM_STATE, state_id); + SM_Frame *frame = SyAddressFromID(SM_FRAME, state->frame_id); + + U64 pos = arena_pos(&ctx->stack_arena); + SM_StackNode *new_node = push_array(&ctx->stack_arena, SM_StackNode, 1); + new_node->pop_pos = pos; + new_node->frame = push_array(&ctx->stack_arena, U8, frame->size); + new_node->state_id = state_id; + SLLStackPush(ctx->stack, new_node); +} + +//// Entry Point //// + +int main(void){ + sy__run_init(); + + Arena run_arenas[2] = {0}; + for (U32 i = 0; i < 2; i += 1){ + run_arenas[i] = arena_alloc((1 << 20)); + } + + U32 counter = 0; + + SM_Ctx ctx = sm_ctx_new(SyID(SM_STATE, Menu_Play)); + ctx.diagnostics = 1; + for (;!sm_ctx_stack_empty(&ctx); counter += 1){ + ctx.run_arena = &run_arenas[counter&1]; + arena_pop_to(ctx.run_arena, 0); + ctx.new_return = 0; + + U32 state_id = sm_ctx_get_top_state(&ctx); + SM_State *state = SyAddressFromID(SM_STATE, state_id); + if (state == 0){ + printf("ERROR\n"); + break; + } + if (ctx.diagnostics){ + String8 name = state->name; + printf("DIAGNOSTICS: STATE %.*s\n", (int)name.size, name.str); + } + + void *frame = sm_ctx_get_top_frame(&ctx); + state->func(&ctx, frame); + + ctx.prev_return = ctx.new_return; + } + + return(0); +} diff --git a/examples/stack_machine.h b/examples/stack_machine.h new file mode 100644 index 0000000..f9403c0 --- /dev/null +++ b/examples/stack_machine.h @@ -0,0 +1,208 @@ +#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 diff --git a/project.4coder b/project.4coder index d35c584..d248705 100644 --- a/project.4coder +++ b/project.4coder @@ -12,7 +12,8 @@ load_paths = { commands = { .build_with_clang = { .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, - .win = "build_with_clang.bat", .linux = "./build.sh", .mac = "./build.sh" + .win = "build_with_clang.bat", .linux = "./build_with_clang.sh stack_machine", + .mac = "./build_with_clang.sh" }, .build_with_cl = { .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, @@ -22,12 +23,12 @@ commands = { .footer_panel = true, .save_dirty_files = true, .linux = "./build_ld_meta.sh", .mac = "./build_ld_meta.sh" }, - .run = { .out = "*run*", .footer_panel = false, .save_dirty_files = false, + .run_example1 = { .out = "*run*", .footer_panel = false, .save_dirty_files = false, .win = "build\\example1", .linux = "build/example1", .mac = "build/example1" }, }; fkey_command = { - .F1 = "build_with_cl", - .F2 = "run", + .F1 = "build_with_clang", + .F2 = "run_example1", }; diff --git a/symbol_set/symbol_set.init.h b/symbol_set/symbol_set.init.h index 0126a7a..8cffcfc 100644 --- a/symbol_set/symbol_set.init.h +++ b/symbol_set/symbol_set.init.h @@ -4,21 +4,24 @@ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~ SY Init Definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -typedef void SY_InitFunc(void*); +typedef void SY_InitFunc(void); typedef struct SY_InitRecord{ SY_InitFunc *func; } SY_InitRecord; #define SYMBOL_SET_DEFINE SY_INIT #define SY_INIT_Type SY_InitRecord -#define SY_INIT_section ".sy.init" +#define SY_INIT_elf_section ".sy.init" +#define SY_INIT_coff_a_section ".sy$init_a" +#define SY_INIT_coff_m_section ".sy$init_m" +#define SY_INIT_coff_z_section ".sy$init_z" #define SY_INIT_marker init -#include "mr4th_symbol_set.define.h" +#include "symbol_set.define.h" -#define SY_INIT_DEF(N,T) \ -static void syinit__##N(T*); \ +#define SY_INIT(N) \ +static void syinit__##N(void); \ SyDefine(SY_INIT, N) = { syinit__##N }; \ -static void syinit__##N(T*ptr) +static void syinit__##N(void) void sy__run_init(void);