From 0c9891f75051c1d8435c52cd254fb8dc8e9724c0 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Mon, 11 Nov 2024 09:16:48 +0100 Subject: [PATCH] Adding an optimization flag that removes checks to try and grind some extra speed for the usecase where ink is a sanitized bytecode --- CMakeLists.txt | 3 + lib.c | 239 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 208 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c92f0e4..5856821 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ add_library(ink lib.c include/ink.h) # Ensures the interpreter doesn't use the standard C library functions # add_definitions(-DNOSTDLIB) +# Removes several checks to improve performance in cases where ink is used as a bytecode +# add_definitions(-DNOEXTRACHECKS) + add_executable(ink_exe main.c) target_link_libraries(ink_exe PUBLIC ink) target_include_directories(ink PUBLIC include) diff --git a/lib.c b/lib.c index b7cb538..c09c546 100644 --- a/lib.c +++ b/lib.c @@ -240,12 +240,14 @@ int ink_push(struct context* ctx, struct elem value) { void* renewed; new_count = (current->capacity + current->capacity/2); renewed = ctx->realloc(ctx, current->stack, sizeof(struct elem) * new_count); +#ifndef NOEXTRACHECKS if(renewed == NULL) { return -18; - } else { - current->stack = renewed; - current->capacity = new_count; } +#endif + current->stack = renewed; + current->capacity = new_count; + } current->stack[current->top] = value; current->top++; @@ -424,10 +426,12 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s } value = routine->stack[routine->top - 1]; ary = ink_get_value(pContext, value); +#ifndef NOEXTRACHECKS if(ary == NULL) { pContext->panic = -1; return -8747; } +#endif for(;it != *end;++it) { struct elem character; character.type = INK_INTEGER; @@ -527,9 +531,11 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s value.type = INK_RESERVED; } err = ink_push(pContext, value); +#ifndef NOEXTRACHECKS if(err < 0) { return -23; } +#endif } *end = 0; return 0; @@ -578,7 +584,7 @@ static int ink_lex(struct context *pContext, const char* buffer) { r[end] = *buffer; ++end; } - } else /* ... */ + } else /* go on parsing something else if it is not a string, like this to be able to disable strings */ #endif if(isspace(*buffer)) { if(end == 1 && r[0] == '#') { @@ -589,10 +595,12 @@ static int ink_lex(struct context *pContext, const char* buffer) { goto restart_after_comment; } err = ink_consume_one(&end, pContext, r, 0); +#ifndef NOEXTRACHECKS if(err < 0) { pContext->panic = 1; return -8; } +#endif } else /* ... */ #ifndef NOSTRINGLITERALS if(end == 0 && *buffer == '"' && !parses_string) { @@ -606,10 +614,12 @@ static int ink_lex(struct context *pContext, const char* buffer) { ++buffer; } err = ink_consume_one(&end, pContext, r, 0); +#ifndef NOEXTRACHECKS if(err < 0) { pContext->panic = 1; return -9; } +#endif return 0; } @@ -647,22 +657,23 @@ int ink_make_routine(struct context* ctx) { void* renewed; new_count = (ctx->routines_capacity + ctx->routines_capacity/2); renewed = ctx->inner_realloc(ctx, ctx->routines, sizeof(struct ink_routine) * new_count); +#ifndef NOEXTRACHECKS if(renewed == NULL) { return -99; - } else { - ctx->routines = renewed; - it = ctx->routines + ctx->routines_capacity; - end = ctx->routines + new_count; - for(;it != end;++it) { - it->stack = NULL; - it->function_stack = NULL; - it->panic = INK_ROUTINE_CAN_REUSE; - it->parse_error.is_set = 0; - it->runtime_error.is_set = 0; - } - ctx->routines_capacity = new_count; } - } +#endif + ctx->routines = renewed; + it = ctx->routines + ctx->routines_capacity; + end = ctx->routines + new_count; + for(;it != end;++it) { + it->stack = NULL; + it->function_stack = NULL; + it->panic = INK_ROUTINE_CAN_REUSE; + it->parse_error.is_set = 0; + it->runtime_error.is_set = 0; + } + ctx->routines_capacity = new_count; + } it = ctx->routines; end = ctx->routines + ctx->routines_capacity; @@ -716,7 +727,11 @@ 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; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" int err; +#pragma GCC diagnostic pop #define LABEL_BUFFER 128 #define FUNCTION_BUFFER 256 struct label labels[LABEL_BUFFER]; @@ -742,6 +757,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i mode = MODE_FUNCTION; function_name = -1; goto next_token; +#ifndef NOEXTRACHECKS case INK_DO_KW: currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Found start of function body unexpectedly"; @@ -752,6 +768,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i currentRoutine->parse_error.error_message = "Found end of function unexpectedly"; currentRoutine->parse_error.offset= i; return -26; +#endif default: executable_buffer[*executable_buffer_top] = current; *executable_buffer_top += 1; @@ -759,17 +776,19 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i break; case MODE_FUNCTION: if(current.type == INK_DO_KW) { +#ifndef NOEXTRACHECKS if(function_name == -1) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Found start of function body before the name of the function was provided"; currentRoutine->parse_error.offset= i; return -27; - } else { - mode = MODE_DO; - memset(labels, 0, sizeof(struct label)*128); - goto next_token; } +#endif + mode = MODE_DO; + memset(labels, 0, sizeof(struct label)*128); + goto next_token; } +#ifndef NOEXTRACHECKS if(function_name != -1) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Function name was not found"; @@ -782,6 +801,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i currentRoutine->parse_error.offset= i; return -29; } +#endif function_name = current.value; break; case MODE_DO: @@ -794,6 +814,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i int k; for(k = 0; k < LABEL_BUFFER; k++) { if(labels[k].active) { +#ifndef NOEXTRACHECKS if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) { labels[k].dest = j; currentRoutine->parse_error.is_set = 1; @@ -802,6 +823,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i return -30; break; } +#endif } else { labels[k].active = 1; labels[k].name = pContext->lex_reserved_words[pt.value]; @@ -835,10 +857,12 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i } } err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top); +#ifndef NOEXTRACHECKS if(err < 0) { pContext->panic = 1; return -33; } +#endif function_buffer_top = 0; mode = MODE_EXECUTABLE; goto next_token; @@ -849,12 +873,14 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i } next_token: i=i; } +#ifndef NOEXTRACHECKS if(mode == MODE_FUNCTION || mode == MODE_DO) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Expected a function to be complete"; currentRoutine->parse_error.offset= i; return -32; } +#endif return 0; #undef MODE_EXECUTABLE #undef MODE_FUNCTION @@ -885,22 +911,26 @@ int ink_step(struct context *pContext) { ink_pop_fn(pContext); } else { top->index++; +#ifndef NOEXTRACHECKS if(pContext->native_words_top <= top->executing.value) { currentRoutine->runtime_error.is_set = 1; currentRoutine->runtime_error.error_message = "Bytecode contained out of bound executable word"; pContext->panic = 1; return -1; } +#endif pContext->native_words[top->executing.value].value(pContext); } break; case INK_FUNCTION: +#ifndef NOEXTRACHECKS if(pContext->words_top <= top->executing.value) { currentRoutine->runtime_error.is_set = 1; currentRoutine->runtime_error.error_message = "Bytecode contained out of bound artificial word"; pContext->panic = 1; return -1; } +#endif if(top->index >= pContext->words[top->executing.value].size) { ink_pop_fn(pContext); } else { @@ -912,23 +942,27 @@ int ink_step(struct context *pContext) { frame.executing = next; frame.index = 0; t = ink_push_fn(pContext, frame); +#ifndef NOEXTRACHECKS if(t < 0) { pContext->panic = 1; currentRoutine->runtime_error.is_set = 1; currentRoutine->runtime_error.error_message = "Instruction pointer underflow"; return -11; } +#endif top->index++; } break; default: t = ink_push(pContext, top->executing); +#ifndef NOEXTRACHECKS if(t < 0) { currentRoutine->runtime_error.is_set = 1; currentRoutine->runtime_error.error_message = "Literal token could not be pushed"; pContext->panic = 1; return -25; } +#endif ink_pop_fn(pContext); break; } @@ -955,22 +989,26 @@ int ink_compile(struct context *pContext, const char* buffer) { currentRoutine->capacity = 0; err = ink_lex(pContext, buffer); if(err < 0) { +#ifndef NOEXTRACHECKS if(!currentRoutine->parse_error.is_set) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Unknown lexer error"; currentRoutine->parse_error.offset = -1; } +#endif pContext->panic = 1; return -1; } executable_buffer_top = 0; err = ink_parse(pContext, executable_buffer, &executable_buffer_top); if(err < 0) { +#ifndef NOEXTRACHECKS if(!currentRoutine->parse_error.is_set) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Unknown parser error"; currentRoutine->parse_error.offset = -1; } +#endif pContext->panic = 1; return -1; } @@ -983,11 +1021,13 @@ int ink_compile(struct context *pContext, const char* buffer) { main_fn[10 + integer_size] = 0; frame.executing.value = ink_add_indigenous(pContext, main_fn, executable_buffer, executable_buffer_top); if (frame.executing.value < 0) { +#ifndef NOEXTRACHECKS if(!currentRoutine->parse_error.is_set) { currentRoutine->parse_error.is_set = 1; currentRoutine->parse_error.error_message = "Could not start execution: no valid way to create a frame"; currentRoutine->parse_error.offset = -1; } +#endif pContext->panic = 1; return -1; } @@ -995,6 +1035,7 @@ int ink_compile(struct context *pContext, const char* buffer) { frame.index = 0; err = ink_push_fn(pContext, frame); pContext->routines[pContext->routine_current].top = 0; +#ifndef NOEXTRACHECKS if (err < 0) { if(!currentRoutine->parse_error.is_set) { currentRoutine->parse_error.is_set = 1; @@ -1004,6 +1045,7 @@ int ink_compile(struct context *pContext, const char* buffer) { pContext->panic = 1; return -1; } +#endif } else { pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS; } @@ -1102,13 +1144,17 @@ int ink_new_type( static struct element_slab* ink_get_value_link(struct context* ctx, struct elem ref) { int type_id; +#ifndef NOEXTRACHECKS if(ref.type < 16) return NULL; +#endif type_id = ref.type - 16; +#ifndef NOEXTRACHECKS if(type_id >= ctx->types_top) return NULL; if(ctx->types[type_id].element_size == 0) return NULL; if(ref.value < 0) return NULL; if(ref.value >= ctx->types[type_id].elements_top) return NULL; if(! ctx->types[type_id].elements[ref.value].in_use) return NULL; +#endif return ctx->types[type_id].elements + ref.value; } @@ -1350,16 +1396,20 @@ static void add_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { ctx->panic = 1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value; } @@ -1369,16 +1419,20 @@ static void sub_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value; } @@ -1388,16 +1442,20 @@ static void mult_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value; } @@ -1407,16 +1465,20 @@ static void div_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value; } @@ -1427,10 +1489,12 @@ static void is_equal(struct context* ctx) { struct elem b; struct elem ret; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; ink_pop(ctx); @@ -1446,10 +1510,12 @@ static void is_different(struct context* ctx) { struct elem b; struct elem ret; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; ink_pop(ctx); @@ -1466,16 +1532,20 @@ static void rem_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value; } @@ -1485,16 +1555,20 @@ static void xor_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value ^ a.value; } @@ -1504,16 +1578,20 @@ static void gt_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value > a.value; } @@ -1523,16 +1601,20 @@ static void gte_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value >= a.value; } @@ -1542,16 +1624,20 @@ static void lte_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value <= a.value; } @@ -1563,16 +1649,20 @@ static void lt_int(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value; } @@ -1580,49 +1670,72 @@ static void lt_int(struct context* ctx) { static void dupe_elem(struct context* ctx) { struct ink_routine* currentRoutine; struct elem a; - int err; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + int err; +#pragma GCC diagnostic pop currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1) { ctx->panic = 1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; err = ink_push(ctx, a); +#ifndef NOEXTRACHECKS if(err < 0) ctx->panic = 1; +#endif } static void drop_elem(struct context* ctx) { +#ifndef NOEXTRACHECKS struct ink_routine* currentRoutine; currentRoutine = ctx->routines + ctx->routine_current; if(currentRoutine->top < 1) { ctx->panic = 1; return; } +#endif ink_pop(ctx); } static void pluck_elem(struct context* ctx) { struct ink_routine* currentRoutine; struct elem a; - int position, err; + int position; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + int err; +#pragma GCC diagnostic pop currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; +#ifndef NOEXTRACHECKS if(a.type != INK_INTEGER) { ctx->panic = 1; return; } +#endif position = currentRoutine->top - (a.value + 1); +#ifndef NOEXTRACHECKS if(position >= currentRoutine->top || position < 0) { ctx->panic = 1; return; } +#endif ink_pop(ctx); err = ink_push(ctx, currentRoutine->stack[position]); +#ifndef NOEXTRACHECKS if(err < 0) ctx->panic = 1; +#endif } static void swap_elem(struct context* ctx) { @@ -1630,10 +1743,12 @@ static void swap_elem(struct context* ctx) { struct elem a; struct elem b; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; b = currentRoutine->stack[currentRoutine->top-2]; currentRoutine->stack[currentRoutine->top-2] = a; @@ -1644,15 +1759,19 @@ static void return_if(struct context* ctx) { struct ink_routine* currentRoutine; struct elem a; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1) { ctx->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; +#ifndef NOEXTRACHECKS if(a.type != INK_INTEGER) { ctx->panic = 1; return; } +#endif if(a.value) { ink_pop_fn(ctx); ink_pop_fn(ctx); @@ -1666,16 +1785,20 @@ static void jump_if(struct context* ctx) { struct elem label; struct elem condition; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2) { ctx->panic = -1; return; } +#endif label = currentRoutine->stack[currentRoutine->top-1]; condition = currentRoutine->stack[currentRoutine->top-2]; +#ifndef NOEXTRACHECKS if(label.type != INK_INTEGER || condition.type != INK_INTEGER) { ctx->panic = -1; return; } +#endif ink_pop(ctx); ink_pop(ctx); ink_pop_fn(ctx); @@ -1692,10 +1815,12 @@ static void print_int(struct context* ctx) { char* n; char* str; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; ink_pop(ctx); n = ink_itoa(ctx, a.value); @@ -1712,10 +1837,12 @@ static void print_as_utf8(struct context* ctx) { struct ink_routine* currentRoutine; struct elem a; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) { ctx->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; if(a.value <= 0x7F) { ctx->putchar(ctx, a.value); @@ -1884,22 +2011,28 @@ void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct } static void push_array(struct context* ctx) { - int tid; struct elem a; struct ink_routine* currentRoutine; struct ink_array* ary; +#ifndef NOEXTRACHECKS + int tid; tid = get_type_by_name(ctx, "array"); +#endif currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top-1]; ary= ink_get_value(ctx, a); +#ifndef NOEXTRACHECKS if(ary == NULL) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); array_push(ctx, currentRoutine, ary, currentRoutine->stack[currentRoutine->top-1]); ink_pop(ctx); @@ -1912,10 +2045,12 @@ static void push_delimited_array(struct context* ctx) { struct ink_array* ary; tid = get_type_by_name(ctx, "array_marker"); currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if(currentRoutine->top < 1) { currentRoutine->panic = -1; return; } +#endif new_array(ctx); a = currentRoutine->stack[currentRoutine->top-1]; ink_pop(ctx); @@ -1933,10 +2068,12 @@ static void push_delimited_array(struct context* ctx) { idx -= 1; ary->elements = malloc(sizeof(struct elem) * idx); +#ifndef NOEXTRACHECKS if(ary->elements == NULL) { currentRoutine->panic = -541; return; } +#endif ary->capacity = idx; ary->top = 0; @@ -1956,65 +2093,80 @@ static void push_delimited_array(struct context* ctx) { } static void index_array(struct context* ctx) { - int tid; struct ink_routine *currentRoutine; struct elem a; struct ink_array *ary; struct elem idx; - - tid = get_type_by_name(ctx, "array"); +#ifndef NOEXTRACHECKS + int tid; + tid = get_type_by_name(ctx, "array"); +#endif currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top - 1]; ary = ink_get_value(ctx, a); +#ifndef NOEXTRACHECKS if (ary == NULL) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); idx = currentRoutine->stack[currentRoutine->top - 1]; ink_pop(ctx); +#ifndef NOEXTRACHECKS if(ary->top <= idx.value) { currentRoutine->panic = -1; return; } +#endif ink_push(ctx, ary->elements[idx.value]); } static void set_array(struct context* ctx) { - int tid; struct ink_routine *currentRoutine; struct elem a; struct ink_array *ary; struct elem idx; struct elem value; +#ifndef NOEXTRACHECKS + int tid; + tid = get_type_by_name(ctx, "array"); +#endif - tid = get_type_by_name(ctx, "array"); currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 3 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top - 1]; ary = ink_get_value(ctx, a); +#ifndef NOEXTRACHECKS if (ary == NULL) { currentRoutine->panic = -1; return; } +#endif idx = currentRoutine->stack[currentRoutine->top - 2]; value = currentRoutine->stack[currentRoutine->top - 3]; +#ifndef NOEXTRACHECKS if(ary->top <= idx.value) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); ink_pop(ctx); ink_pop(ctx); @@ -2024,24 +2176,30 @@ static void set_array(struct context* ctx) { } static void get_size_array(struct context* ctx) { - int tid; struct ink_routine *currentRoutine; struct elem a; struct ink_array *ary; struct elem sz; - tid = get_type_by_name(ctx, "array"); +#ifndef NOEXTRACHECKS + int tid; + tid = get_type_by_name(ctx, "array"); +#endif currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top - 1]; ary = ink_get_value(ctx, a); +#ifndef NOEXTRACHECKS if (ary == NULL) { currentRoutine->panic = -1; return; } +#endif ink_pop(ctx); sz.type = INK_INTEGER; @@ -2057,10 +2215,12 @@ static void is_array(struct context* ctx) { tid = get_type_by_name(ctx, "array"); currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 1) { currentRoutine->panic = -1; return; } +#endif a.type = INK_INTEGER; a.value = currentRoutine->stack[currentRoutine->top - 1].type == tid; ink_pop(ctx); @@ -2073,10 +2233,12 @@ static void is_int(struct context* ctx) { struct elem a; currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 1) { currentRoutine->panic = -1; return; } +#endif a.type = INK_INTEGER; a.value = currentRoutine->stack[currentRoutine->top - 1].type == INK_INTEGER; ink_pop(ctx); @@ -2085,26 +2247,33 @@ static void is_int(struct context* ctx) { } static void print_array_of_codepoints(struct context* ctx) { - int tid, i; + int i; struct ink_routine *currentRoutine; struct elem a; struct ink_array *ary; - tid = get_type_by_name(ctx, "array"); +#ifndef NOEXTRACHECKS + int tid; + tid = get_type_by_name(ctx, "array"); +#endif currentRoutine = ctx->routines + ctx->routine_current; +#ifndef NOEXTRACHECKS if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) { currentRoutine->panic = -1; return; } +#endif a = currentRoutine->stack[currentRoutine->top - 1]; ary = ink_get_value(ctx, a); +#ifndef NOEXTRACHECKS for(i = 0; i < ary->top; ++i) { if(ary->elements[i].type != INK_INTEGER) { currentRoutine->panic = -1; return; } } +#endif ink_pop(ctx); for(i = 0; i < ary->top; ++i) { ink_push(ctx, ary->elements[i]); @@ -2122,10 +2291,12 @@ static void arrayify_stack(struct context* ctx) { if(currentRoutine->panic < 0) return; array_ref = currentRoutine->stack[currentRoutine->top - 1]; ary = ink_get_value(ctx, array_ref); +#ifndef NOEXTRACHECKS if(ary == NULL) { currentRoutine->panic = -717; return; } +#endif ink_pop(ctx); for(idx = 0; idx < currentRoutine->top; ++idx) { array_push(ctx, currentRoutine, ary, currentRoutine->stack[idx]); @@ -2185,4 +2356,4 @@ int ink_std_library(struct context* ctx) { #endif /* NOARRAYLIB */ return v; -} \ No newline at end of file +}