From 62b32be4940c7fc529e032178fe112df62e18d62 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Thu, 14 Nov 2024 13:19:33 +0100 Subject: [PATCH] Added the macro keyword and feature: allows to process a function at compile time and reuse the results instead of calculating it every time #1 --- include/ink.h | 2 +- lib.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- main.c | 22 ------------------- test/test04.nk | 6 +++++- test/test07.nk | 21 ++++++++++++++++++ 5 files changed, 84 insertions(+), 25 deletions(-) create mode 100644 test/test07.nk diff --git a/include/ink.h b/include/ink.h index 2a17929..430e0f3 100644 --- a/include/ink.h +++ b/include/ink.h @@ -45,7 +45,7 @@ struct elem { */ struct stack_frame { struct elem executing; - int index; + int index; /*< Indicates the next instruction to execute (should start at 0) */ }; /** diff --git a/lib.c b/lib.c index 27b1302..10fbd48 100644 --- a/lib.c +++ b/lib.c @@ -15,8 +15,10 @@ #define INK_END_KW (-4) #define INK_LABEL (-5) #define INK_RETURN (-6) +#define INK_MACRO_KW (-7) #define _KEYWORD_INK_FUNCTION "fn" +#define _KEYWORD_INK_MACRO "macro" #define _KEYWORD_INK_DO "do" #define _KEYWORD_INK_END "end" #define _KEYWORD_INK_RETURN "return" @@ -462,6 +464,11 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s value.type = INK_FUNCTION_KW; done = 1; } + if (strcmp(r, _KEYWORD_INK_MACRO) == 0) { + value.value = 0; + value.type = INK_MACRO_KW; + done = 1; + } if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) { value.value = 0; value.type = INK_DO_KW; @@ -603,6 +610,7 @@ static int ink_lex(struct context *pContext, const char* buffer) { goto restart_after_comment; } err = ink_consume_one(&end, pContext, r, 0); + /* Send the token off to the wizard (ink_parse) */ #ifndef NOEXTRACHECKS if(err < 0) { pContext->panic = 1; @@ -741,6 +749,7 @@ int ink_kill_routine(struct context* ctx, int routine){ static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) { struct ink_routine* currentRoutine; int i, function_buffer_top, function_name, mode; + int func_is_macro = 0; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-but-set-variable" @@ -770,6 +779,12 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i case INK_FUNCTION_KW: mode = MODE_FUNCTION; function_name = -1; + func_is_macro = 0; + goto next_token; + case INK_MACRO_KW: + mode = MODE_FUNCTION; + func_is_macro = 1; + function_name = -1; goto next_token; #ifndef NOEXTRACHECKS case INK_DO_KW: @@ -877,6 +892,47 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i return -33; } #endif + /* Handle the case where what we just pushed should be transformed into a macro instead */ + if(func_is_macro) { + struct stack_frame macro_frame; + struct elem macro_id; + struct ink_routine* macro_cooking_routine; + int step_value; + int parser_routine_index = pContext->routine_current; + int macro_cooking_routine_ref = ink_make_routine(pContext); +#ifndef NOEXTRACHECKS + if(macro_cooking_routine_ref < 0) { + pContext->panic = 1; + return macro_cooking_routine_ref; + } +#endif + pContext->routine_current = macro_cooking_routine_ref; + macro_cooking_routine = pContext->routines + macro_cooking_routine_ref; + macro_id.type = INK_FUNCTION; + macro_id.value = err; + macro_frame.executing = macro_id; + macro_frame.index = 0; + ink_push_fn(pContext, macro_frame); + step_value = 1; + while(step_value > 0 && macro_cooking_routine->panic == 0 && pContext->panic == 0) { + step_value = ink_step(pContext); + } +#ifndef NOEXTRACHECKS + if(macro_cooking_routine->panic != 0 || pContext->panic != 0 || step_value < 0) { + pContext->panic = 1; + return -138445; + } +#endif + pContext->routine_current = parser_routine_index; + err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], macro_cooking_routine->stack, macro_cooking_routine->top); + macro_cooking_routine->panic = INK_ROUTINE_SUCCESS; +#ifndef NOEXTRACHECKS + if(err < 0) { + pContext->panic = 1; + return -542151; + } +#endif + } function_buffer_top = 0; mode = MODE_EXECUTABLE; goto next_token; @@ -1334,7 +1390,7 @@ void ink_gc(struct context* ctx) { } } - for(i = 0; i < ctx->native_words_top; ++i) { + for(i = 0; i < ctx->words_top; ++i) { struct fn* function = ctx->words + i; for(j = 0; j < function->size; ++j) { thing = function->things + j; diff --git a/main.c b/main.c index a11d14f..c2a8b5d 100644 --- a/main.c +++ b/main.c @@ -29,28 +29,6 @@ int main(int argc, char** argv) { fclose(file); } - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); - ink_compile(ctx, read_buffer); int increment = 1 << 16; int counter = increment; diff --git a/test/test04.nk b/test/test04.nk index 6937c9a..ce8c3b8 100644 --- a/test/test04.nk +++ b/test/test04.nk @@ -1 +1,5 @@ -"""Hello world"""/"" array.print_utf8 \ No newline at end of file + +macro my-macro do + 10 10 + 10 10 + + 10 10 + 10 10 + + + +end + diff --git a/test/test07.nk b/test/test07.nk new file mode 100644 index 0000000..bcd20c8 --- /dev/null +++ b/test/test07.nk @@ -0,0 +1,21 @@ + +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop +my-macro drop