Explorar el Código

Adding an optimization flag that removes checks to try and grind some extra speed for the usecase where ink is a sanitized bytecode

main
Ludovic 'Archivist' Lagouardette hace 1 semana
padre
commit
0c9891f750
Se han modificado 2 ficheros con 208 adiciones y 34 borrados
  1. +3
    -0
      CMakeLists.txt
  2. +205
    -34
      lib.c

+ 3
- 0
CMakeLists.txt Ver fichero

@ -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)

+ 205
- 34
lib.c Ver fichero

@ -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;
}
}

Cargando…
Cancelar
Guardar