diff --git a/CMakeLists.txt b/CMakeLists.txt index f766265..c2078f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ add_library(ink lib.c include/ink.h) # Removes several checks to improve performance in cases where ink is used as a bytecode # add_definitions(-DNOEXTRACHECKS) -add_definitions(-DINK_STEP_BATCH_COUNT=5) +add_definitions(-DINK_STEP_BATCH_COUNT=20) add_executable(ink_exe main.c) target_link_libraries(ink_exe PUBLIC ink) diff --git a/lib.c b/lib.c index fb1421f..14e7076 100644 --- a/lib.c +++ b/lib.c @@ -35,9 +35,9 @@ #endif struct label { - int active; - int dest; - char* name; + int active; + int dest; + char* name; }; #ifdef NOSTDLIB @@ -121,78 +121,78 @@ static int atoi(const char* c) { #endif int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) { - int len; - char* copy; - if(ctx->native_words == NULL) { - ctx->native_words = ctx->inner_malloc(ctx, sizeof(struct native_fn) * 8); - ctx->native_words_top = 0; - ctx->native_words_capacity = 8; - } else if(ctx->native_words_top == ctx->native_words_capacity) { - int new_count; - void* renewed; - new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2); - renewed = ctx->inner_realloc(ctx, ctx->native_words, sizeof(struct native_fn) * new_count); - if(renewed == NULL) { - return -3; - } else { - ctx->native_words = renewed; - ctx->native_words_capacity = new_count; - } - } - len = strlen(name); - copy = ctx->inner_malloc(ctx, len+1); - if(copy == NULL) { - return -4; - } - memcpy(copy, name, len); - copy[len] = 0; - ctx->native_words[ctx->native_words_top].value = value; - ctx->native_words[ctx->native_words_top].name = copy; - ctx->native_words_top++; - return 0; + int len; + char* copy; + if(ctx->native_words == NULL) { + ctx->native_words = ctx->inner_malloc(ctx, sizeof(struct native_fn) * 8); + ctx->native_words_top = 0; + ctx->native_words_capacity = 8; + } else if(ctx->native_words_top == ctx->native_words_capacity) { + int new_count; + void* renewed; + new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2); + renewed = ctx->inner_realloc(ctx, ctx->native_words, sizeof(struct native_fn) * new_count); + if(renewed == NULL) { + return -3; + } else { + ctx->native_words = renewed; + ctx->native_words_capacity = new_count; + } + } + len = strlen(name); + copy = ctx->inner_malloc(ctx, len+1); + if(copy == NULL) { + return -4; + } + memcpy(copy, name, len); + copy[len] = 0; + ctx->native_words[ctx->native_words_top].value = value; + ctx->native_words[ctx->native_words_top].name = copy; + ctx->native_words_top++; + return 0; } static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) { - int len, i; - char* copy; - - if(ctx->words == NULL) { - ctx->words = ctx->malloc(ctx, sizeof(struct fn) * 8); - ctx->words_top = 0; - ctx->words_capacity = 8; - } else if(ctx->words_top == ctx->words_capacity) { - int new_count; - void* renewed; - new_count = (ctx->words_capacity + ctx->words_capacity/2); - renewed = ctx->realloc(ctx, ctx->words, sizeof(struct fn) * new_count); - if(renewed == NULL) { - return -1; - } else { - ctx->words = renewed; - ctx->words_capacity = new_count; - } - } - for(i = 0; i < ctx->words_top; ++i) { - if(strcmp(name, ctx->words[i].name) == 0) { - if(ctx->words[i].things != NULL) ctx->free(ctx, ctx->words[i].things); - ctx->words[i].things = ctx->malloc(ctx, sizeof(struct elem) * count); - memcpy(ctx->words[i].things, m, sizeof(struct elem) * count); - ctx->words[i].size = count; - return i; - } - } - len = strlen(name); - copy = ctx->malloc(ctx, len+1); - if(copy == NULL) { - return -2; - } - memcpy(copy, name, len); - copy[len] = 0; - ctx->words[ctx->words_top].things = ctx->malloc(ctx, sizeof(struct elem) * count); - memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count); - ctx->words[ctx->words_top].size = count; - ctx->words[ctx->words_top].name = copy; - return ctx->words_top++; + int len, i; + char* copy; + + if(ctx->words == NULL) { + ctx->words = ctx->malloc(ctx, sizeof(struct fn) * 8); + ctx->words_top = 0; + ctx->words_capacity = 8; + } else if(ctx->words_top == ctx->words_capacity) { + int new_count; + void* renewed; + new_count = (ctx->words_capacity + ctx->words_capacity/2); + renewed = ctx->realloc(ctx, ctx->words, sizeof(struct fn) * new_count); + if(renewed == NULL) { + return -1; + } else { + ctx->words = renewed; + ctx->words_capacity = new_count; + } + } + for(i = 0; i < ctx->words_top; ++i) { + if(strcmp(name, ctx->words[i].name) == 0) { + if(ctx->words[i].things != NULL) ctx->free(ctx, ctx->words[i].things); + ctx->words[i].things = ctx->malloc(ctx, sizeof(struct elem) * count); + memcpy(ctx->words[i].things, m, sizeof(struct elem) * count); + ctx->words[i].size = count; + return i; + } + } + len = strlen(name); + copy = ctx->malloc(ctx, len+1); + if(copy == NULL) { + return -2; + } + memcpy(copy, name, len); + copy[len] = 0; + ctx->words[ctx->words_top].things = ctx->malloc(ctx, sizeof(struct elem) * count); + memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count); + ctx->words[ctx->words_top].size = count; + ctx->words[ctx->words_top].name = copy; + return ctx->words_top++; } /** @@ -203,166 +203,166 @@ static int ink_add_indigenous(struct context* ctx, const char* name, struct elem * @return the id of the string in the list */ static int ink_add_lex_string(struct context* ctx, const char* name) { - int i; - int len; - if(ctx->lex_reserved_words == NULL) { - ctx->lex_reserved_words = ctx->inner_malloc(ctx, sizeof(char*) * 8); - ctx->lex_reserved_words_top = 0; - ctx->lex_reserved_words_capacity = 8; - } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) { - int new_count; - void* renewed; - new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2); - renewed = ctx->inner_realloc(ctx, ctx->lex_reserved_words, sizeof(struct native_fn) * new_count); - if(renewed == NULL) { - return -5; - } else { - ctx->lex_reserved_words = renewed; - ctx->lex_reserved_words_capacity = new_count; - } - } - for(i = 0; i < ctx->lex_reserved_words_top; i++) { - if(strcmp(ctx->lex_reserved_words[i], name) == 0) { - return i; - } - } - len = strlen(name); - i = ctx->lex_reserved_words_top; - ctx->lex_reserved_words[i] = ctx->malloc(ctx, len+1); - memcpy(ctx->lex_reserved_words[i], name, len); - ctx->lex_reserved_words[i][len] = 0; - ctx->lex_reserved_words_top++; - return i; + int i; + int len; + if(ctx->lex_reserved_words == NULL) { + ctx->lex_reserved_words = ctx->inner_malloc(ctx, sizeof(char*) * 8); + ctx->lex_reserved_words_top = 0; + ctx->lex_reserved_words_capacity = 8; + } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) { + int new_count; + void* renewed; + new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2); + renewed = ctx->inner_realloc(ctx, ctx->lex_reserved_words, sizeof(struct native_fn) * new_count); + if(renewed == NULL) { + return -5; + } else { + ctx->lex_reserved_words = renewed; + ctx->lex_reserved_words_capacity = new_count; + } + } + for(i = 0; i < ctx->lex_reserved_words_top; i++) { + if(strcmp(ctx->lex_reserved_words[i], name) == 0) { + return i; + } + } + len = strlen(name); + i = ctx->lex_reserved_words_top; + ctx->lex_reserved_words[i] = ctx->malloc(ctx, len+1); + memcpy(ctx->lex_reserved_words[i], name, len); + ctx->lex_reserved_words[i][len] = 0; + ctx->lex_reserved_words_top++; + return i; } int ink_push(struct context* ctx, struct elem value) { - struct ink_routine* current; - if(ctx->routine_current >= ctx->routines_top) return -65; - current = ctx->routines + ctx->routine_current; - if(current->stack == NULL) { - current->stack = ctx->malloc(ctx, sizeof(struct elem) * 8); - current->top = 0; - current->capacity = 8; - } else if(current->top == current->capacity) { - int new_count; - 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; - } -#endif - current->stack = renewed; - current->capacity = new_count; - - } - current->stack[current->top] = value; - current->top++; - return 0; + struct ink_routine* current; + if(ctx->routine_current >= ctx->routines_top) return -65; + current = ctx->routines + ctx->routine_current; + if(current->stack == NULL) { + current->stack = ctx->malloc(ctx, sizeof(struct elem) * 8); + current->top = 0; + current->capacity = 8; + } else if(current->top == current->capacity) { + int new_count; + 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; + } +#endif + current->stack = renewed; + current->capacity = new_count; + + } + current->stack[current->top] = value; + current->top++; + return 0; } int ink_push_fn(struct context* ctx, struct stack_frame value) { - struct ink_routine* current; - - if(ctx->routine_current >= ctx->routines_top) return -55; - current = ctx->routines + ctx->routine_current; - if(current->panic) return -56; - if(current->function_stack == NULL) { - current->function_stack = ctx->malloc(ctx, sizeof(struct stack_frame) * 8); - current->function_stack_top = 0; - current->function_stack_capacity = 8; - } else if(current->function_stack_top == current->function_stack_capacity) { - int new_count; - void* renewed; - new_count = (current->function_stack_capacity + current->function_stack_capacity/2); - renewed = ctx->realloc(ctx, current->function_stack, sizeof(struct stack_frame) * new_count); - if(renewed == NULL) { - return -9; - } else { - current->function_stack = renewed; - current->function_stack_capacity = new_count; - } - } - current->function_stack[current->function_stack_top] = value; - current->function_stack_top++; - return 0; + struct ink_routine* current; + + if(ctx->routine_current >= ctx->routines_top) return -55; + current = ctx->routines + ctx->routine_current; + if(current->panic) return -56; + if(current->function_stack == NULL) { + current->function_stack = ctx->malloc(ctx, sizeof(struct stack_frame) * 8); + current->function_stack_top = 0; + current->function_stack_capacity = 8; + } else if(current->function_stack_top == current->function_stack_capacity) { + int new_count; + void* renewed; + new_count = (current->function_stack_capacity + current->function_stack_capacity/2); + renewed = ctx->realloc(ctx, current->function_stack, sizeof(struct stack_frame) * new_count); + if(renewed == NULL) { + return -9; + } else { + current->function_stack = renewed; + current->function_stack_capacity = new_count; + } + } + current->function_stack[current->function_stack_top] = value; + current->function_stack_top++; + return 0; } void ink_pop_fn(struct context* ctx) { - if(ctx->routine_current >= ctx->routines_top) return; - if(ctx->routines[ctx->routine_current].panic) return; - if(ctx->routines[ctx->routine_current].function_stack == NULL) return; - if(ctx->routines[ctx->routine_current].function_stack_top == 0) return; - ctx->routines[ctx->routine_current].function_stack_top--; + if(ctx->routine_current >= ctx->routines_top) return; + if(ctx->routines[ctx->routine_current].panic) return; + if(ctx->routines[ctx->routine_current].function_stack == NULL) return; + if(ctx->routines[ctx->routine_current].function_stack_top == 0) return; + ctx->routines[ctx->routine_current].function_stack_top--; } void ink_pop(struct context* ctx) { - if(ctx->routine_current >= ctx->routines_top) return; - if(ctx->routines[ctx->routine_current].panic) return; - if(ctx->routines[ctx->routine_current].stack == NULL) return; - if(ctx->routines[ctx->routine_current].top == 0) return; - ctx->routines[ctx->routine_current].top--; + if(ctx->routine_current >= ctx->routines_top) return; + if(ctx->routines[ctx->routine_current].panic) return; + if(ctx->routines[ctx->routine_current].stack == NULL) return; + if(ctx->routines[ctx->routine_current].top == 0) return; + ctx->routines[ctx->routine_current].top--; } struct context* ink_make_context(void*(*malloc)(struct context*, size_t), void*(*realloc)(struct context*, void*, size_t), void(*free)(struct context*, void*), int(*putchar)(struct context*, int)) { - struct context* ctx; - ctx = (struct context*)malloc(NULL, sizeof(struct context)); - ctx->malloc = malloc; - ctx->realloc = realloc; - ctx->free = free; - ctx->inner_malloc = malloc; - ctx->inner_realloc = realloc; - ctx->inner_free = free; - ctx->putchar = putchar; - ctx->panic = 0; - ctx->routines = NULL; - ctx->routines_capacity = 0; - ctx->routines_top = 0; - ctx->types = NULL; - ctx->types_capacity = 0; - ctx->types_top = 0; - ctx->native_words = NULL; - ctx->native_words_capacity = 0; - ctx->native_words_top = 0; - ctx->words = NULL; - ctx->words_capacity = 0; - ctx->words_top = 0; - ctx->lex_reserved_words = NULL; - ctx->lex_reserved_words_capacity = 0; - ctx->lex_reserved_words_top = 0; - ctx->collections = 0; - ctx->steps = 0; - return ctx; + struct context* ctx; + ctx = (struct context*)malloc(NULL, sizeof(struct context)); + ctx->malloc = malloc; + ctx->realloc = realloc; + ctx->free = free; + ctx->inner_malloc = malloc; + ctx->inner_realloc = realloc; + ctx->inner_free = free; + ctx->putchar = putchar; + ctx->panic = 0; + ctx->routines = NULL; + ctx->routines_capacity = 0; + ctx->routines_top = 0; + ctx->types = NULL; + ctx->types_capacity = 0; + ctx->types_top = 0; + ctx->native_words = NULL; + ctx->native_words_capacity = 0; + ctx->native_words_top = 0; + ctx->words = NULL; + ctx->words_capacity = 0; + ctx->words_top = 0; + ctx->lex_reserved_words = NULL; + ctx->lex_reserved_words_capacity = 0; + ctx->lex_reserved_words_top = 0; + ctx->collections = 0; + ctx->steps = 0; + return ctx; } void ink_make_context_inplace(struct context* location, void*(*malloc)(struct context*, size_t), void*(*realloc)(struct context*, void*, size_t), void(*free)(struct context*, void*), int(*putchar)(struct context*, int)) { - struct context* ctx = location; - ctx->malloc = malloc; - ctx->realloc = realloc; - ctx->free = free; - ctx->inner_malloc = malloc; - ctx->inner_realloc = realloc; - ctx->inner_free = free; - ctx->putchar = putchar; - ctx->panic = 0; - ctx->routines = NULL; - ctx->routines_capacity = 0; - ctx->routines_top = 0; - ctx->types = NULL; - ctx->types_capacity = 0; - ctx->types_top = 0; - ctx->native_words = NULL; - ctx->native_words_capacity = 0; - ctx->native_words_top = 0; - ctx->words = NULL; - ctx->words_capacity = 0; - ctx->words_top = 0; - ctx->lex_reserved_words = NULL; - ctx->lex_reserved_words_capacity = 0; - ctx->lex_reserved_words_top = 0; - ctx->collections = 0; - ctx->steps = 0; + struct context* ctx = location; + ctx->malloc = malloc; + ctx->realloc = realloc; + ctx->free = free; + ctx->inner_malloc = malloc; + ctx->inner_realloc = realloc; + ctx->inner_free = free; + ctx->putchar = putchar; + ctx->panic = 0; + ctx->routines = NULL; + ctx->routines_capacity = 0; + ctx->routines_top = 0; + ctx->types = NULL; + ctx->types_capacity = 0; + ctx->types_top = 0; + ctx->native_words = NULL; + ctx->native_words_capacity = 0; + ctx->native_words_top = 0; + ctx->words = NULL; + ctx->words_capacity = 0; + ctx->words_top = 0; + ctx->lex_reserved_words = NULL; + ctx->lex_reserved_words_capacity = 0; + ctx->lex_reserved_words_top = 0; + ctx->collections = 0; + ctx->steps = 0; } /** @@ -373,43 +373,43 @@ void ink_make_context_inplace(struct context* location, void*(*malloc)(struct co * @internal this function is slightly cursed */ static char* ink_itoa(struct context* _, int cpy) { - char* n; - char* it; - n = _->malloc(_, 16); - n[15] = 0; - it = n+15; - do { - it--; - *it = (cpy % 10) + '0'; - cpy = cpy / 10; - } while(cpy); - memmove(n, it, 16 - (it-n)); - return n; + char* n; + char* it; + n = _->malloc(_, 16); + n[15] = 0; + it = n+15; + do { + it--; + *it = (cpy % 10) + '0'; + cpy = cpy / 10; + } while(cpy); + memmove(n, it, 16 - (it-n)); + return n; } #ifndef NOSTDLIB static void* ink_malloc(struct context* _, size_t sz) { - _=_; - return malloc(sz); + _=_; + return malloc(sz); } static void* ink_realloc(struct context* _, void* ptr, size_t sz) { - _=_; - return realloc(ptr, sz); + _=_; + return realloc(ptr, sz); } static void ink_free(struct context* _, void* ptr) { - _=_; - free(ptr); + _=_; + free(ptr); } static int ink_putchar(struct context* _, int c) { - _=_; - return putchar(c); + _=_; + return putchar(c); } struct context* ink_make_default_context(void) { - struct context* ctx; - ctx = ink_make_context(ink_malloc, ink_realloc, ink_free, ink_putchar); - ink_std_library(ctx); - return ctx; + struct context* ctx; + ctx = ink_make_context(ink_malloc, ink_realloc, ink_free, ink_putchar); + ink_std_library(ctx); + return ctx; } #endif @@ -418,311 +418,317 @@ static void new_protected_array(struct context* ctx); #endif static int ink_consume_one(int* end, struct context* pContext, char* r, int is_str) { - int i; - int done; - struct elem value; - int err; + int i; + int done; + struct elem value; + int err; #ifndef NOSTRINGLITERALS - if(is_str) { - struct ink_routine* routine = pContext->routines + pContext->routine_current; - struct ink_array* ary; - int it = 0; - new_protected_array(pContext); - if(routine->top < 1) { - pContext->panic = -1; - return -8746; - } - 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; - /* TODO: codepoint conversion and coalescence is required here */ - character.value = r[it]; - array_push(pContext, routine, ary, character); - } - *end = 0; - return 0; - } -#endif - is_str = is_str; - if(*end == 0) { - return 0; - } - r[*end] = 0; - done = 0; - if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) { - value.value = 0; - value.type = INK_FUNCTION_KW; - done = 1; - } - if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) { - value.value = 0; - value.type = INK_DO_KW; - done = 1; - } - if (!done && strcmp(r, _KEYWORD_INK_END) == 0) { - value.value = 0; - value.type = INK_END_KW; - done = 1; - } - if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) { - value.value = 0; - value.type = INK_RETURN; - done = 1; - } - if(done) { - err = ink_push(pContext, value); - if(err < 0) { - return -19; - } - } - if (!done) { - for (i = 0; i < pContext->words_top; ++i) { - if (strcmp(r, pContext->words[i].name) == 0) { - value.value = i; - value.type = INK_FUNCTION; - err = ink_push(pContext, value); - if(err < 0) { - return -20; - } - done = 1; - break; - } - } - } - if (!done) { - for (i = 0; i < pContext->native_words_top; ++i) { - if (strcmp(r, pContext->native_words[i].name) == 0) { - value.value = i; - value.type = INK_NATIVE_FUNCTION; - err = ink_push(pContext, value); - if(err < 0) { - return -21; - } - done = 1; - break; - } - } - } - if (!done) { - for(i = (r[0] == '-'); i < *end; i++) { - if(!isdigit(r[i])){ - goto not_an_int; - } - } - value.value = atoi(r); - value.type = INK_INTEGER; - err = ink_push(pContext, value); - if(err < 0) { - return -22; - } - done = 1; - } - not_an_int: - if (!done) { - i = ink_add_lex_string(pContext, r); - if(i < 0) { - pContext->panic = 1; - return -7; - } - value.value = i; - if(r[strlen(r) - 1] == ':') { - value.type = INK_LABEL; - } else { - value.type = INK_RESERVED; - } - err = ink_push(pContext, value); -#ifndef NOEXTRACHECKS - if(err < 0) { - return -23; - } -#endif - } - *end = 0; - return 0; + if(is_str) { + struct ink_routine* routine = pContext->routines + pContext->routine_current; + struct ink_array* ary; + int it = 0; + new_protected_array(pContext); + if(routine->top < 1) { + pContext->panic = -1; + return -8746; + } + 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; + /* TODO: codepoint conversion and coalescence is required here */ + character.value = r[it]; + array_push(pContext, routine, ary, character); + } + *end = 0; + return 0; + } +#endif + is_str = is_str; + if(*end == 0) { + return 0; + } + r[*end] = 0; + done = 0; + if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) { + value.value = 0; + value.type = INK_FUNCTION_KW; + done = 1; + } + if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) { + value.value = 0; + value.type = INK_DO_KW; + done = 1; + } + if (!done && strcmp(r, _KEYWORD_INK_END) == 0) { + value.value = 0; + value.type = INK_END_KW; + done = 1; + } + if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) { + value.value = 0; + value.type = INK_RETURN; + done = 1; + } + if(done) { + err = ink_push(pContext, value); + if(err < 0) { + return -19; + } + } + if (!done) { + for (i = 0; i < pContext->words_top; ++i) { + if (strcmp(r, pContext->words[i].name) == 0) { + value.value = i; + value.type = INK_FUNCTION; + err = ink_push(pContext, value); + if(err < 0) { + return -20; + } + done = 1; + break; + } + } + } + if (!done) { + for (i = 0; i < pContext->native_words_top; ++i) { + if (strcmp(r, pContext->native_words[i].name) == 0) { + value.value = i; + value.type = INK_NATIVE_FUNCTION; + err = ink_push(pContext, value); + if(err < 0) { + return -21; + } + done = 1; + break; + } + } + } + if (!done) { + for(i = (r[0] == '-'); i < *end; i++) { + if(!isdigit(r[i])){ + goto not_an_int; + } + } + value.value = atoi(r); + value.type = INK_INTEGER; + err = ink_push(pContext, value); + if(err < 0) { + return -22; + } + done = 1; + } + not_an_int: + if (!done) { + i = ink_add_lex_string(pContext, r); + if(i < 0) { + pContext->panic = 1; + return -7; + } + value.value = i; + if(r[strlen(r) - 1] == ':') { + value.type = INK_LABEL; + } else { + value.type = INK_RESERVED; + } + err = ink_push(pContext, value); +#ifndef NOEXTRACHECKS + if(err < 0) { + return -23; + } +#endif + } + *end = 0; + return 0; } static int ink_lex(struct context *pContext, const char* buffer) { - /* Limits the token size to 127 chars */ - char r[128]; - int end; - int err; + /* Limits the token size to 127 chars */ + char r[128]; + int end; + int err; #ifndef NOSTRINGLITERALS - int parses_string; + int parses_string; #endif - end = 0; - restart_after_comment: + end = 0; + restart_after_comment: #ifndef NOSTRINGLITERALS - parses_string = 0; + parses_string = 0; #endif - while(*buffer != 0) { + while(*buffer != 0) { #ifndef NOSTRINGLITERALS - if(parses_string) { - switch(*buffer) { - case '"': { - if(*(buffer+1) == 0 || isspace(*(buffer+1))) { - err = ink_consume_one(&end, pContext, r, 1); - if(err < 0) { - pContext->panic = 1; - return -995; - } - parses_string = 0; - } else if(*(buffer+1) == '"') { - r[end] = *buffer; - ++end; - ++buffer; - } else if(*(buffer+1) == '/' && *(buffer+2) == '"') { - r[end] = '\n'; - ++end; - ++buffer; - ++buffer; - } else { - pContext->panic = 1; - return -994; - } - }break; - default: - r[end] = *buffer; - ++end; - } - } 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] == '#') { - while(*buffer != '\n' && *buffer != 0) { - ++buffer; - } - end = 0; - goto restart_after_comment; - } - err = ink_consume_one(&end, pContext, r, 0); -#ifndef NOEXTRACHECKS - if(err < 0) { - pContext->panic = 1; - return -8; - } -#endif - } else /* ... */ + if(parses_string) { + switch(*buffer) { + case '"': { + if(*(buffer+1) == 0 || isspace(*(buffer+1))) { + err = ink_consume_one(&end, pContext, r, 1); + if(err < 0) { + pContext->panic = 1; + return -995; + } + parses_string = 0; + } else if(*(buffer+1) == '"') { + r[end] = *buffer; + ++end; + ++buffer; + } else if(*(buffer+1) == '/' && *(buffer+2) == '"') { + r[end] = '\n'; + ++end; + ++buffer; + ++buffer; + } else { + pContext->panic = 1; + return -994; + } + }break; + default: + r[end] = *buffer; + ++end; + } + } 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] == '#') { + while(*buffer != '\n' && *buffer != 0) { + ++buffer; + } + end = 0; + 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) { - parses_string = 1; - } else /* ... */ + if(end == 0 && *buffer == '"' && !parses_string) { + parses_string = 1; + } else /* ... */ #endif - { - r[end] = *buffer; - ++end; - } - ++buffer; - } - err = ink_consume_one(&end, pContext, r, 0); + { + r[end] = *buffer; + ++end; + } + ++buffer; + } + err = ink_consume_one(&end, pContext, r, 0); #ifndef NOEXTRACHECKS - if(err < 0) { - pContext->panic = 1; - return -9; - } + if(err < 0) { + pContext->panic = 1; + return -9; + } #endif - return 0; + return 0; } static int lblcmp(const char* label, const char* other, size_t label_sz) { - while (label_sz != 1) { - if(*other == 0) return 1; - if(*label != *other) return 1; - ++label; - ++other; - label_sz--; - } - return 0; + while (label_sz != 1) { + if(*other == 0) return 1; + if(*label != *other) return 1; + ++label; + ++other; + label_sz--; + } + return 0; } int ink_make_routine(struct context* ctx) { - struct ink_routine* it; - struct ink_routine* end; - - /* Allocate space if needed */ - if(ctx->routines == NULL) { - ctx->routines = ctx->inner_malloc(ctx, sizeof(struct ink_routine) * 8); - ctx->routines_top = 0; - ctx->routines_capacity = 8; - it = ctx->routines; - end = ctx->routines + 8; - 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; - } - } else if(ctx->routines_top == ctx->routines_capacity) { - int new_count; - 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; - } -#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; - /* Looks for a reusable routine space then uses it */ - for(;it != end;++it) { - if(it->panic == INK_ROUTINE_CAN_REUSE) { - int idx; - it->panic = 0; - it->top = 0; - it->function_stack_top = 0; - - idx = it - ctx->routines; - if(idx >= ctx->routines_top) { - ctx->routines_top = idx + 1; - } - return idx; - } - } - /* FIXME: Maybe we need to abort here, this seems like quite an unsteady state */ - return -758; + struct ink_routine* it; + struct ink_routine* end; + + /* Allocate space if needed */ + if(ctx->routines == NULL) { + ctx->routines = ctx->inner_malloc(ctx, sizeof(struct ink_routine) * 8); + ctx->routines_top = 0; + ctx->routines_capacity = 8; + it = ctx->routines; + end = ctx->routines + 8; + for(;it != end;++it) { + it->stack = NULL; + it->function_stack = NULL; + it->top = it->capacity = 0; + it->function_stack_top = it->function_stack_capacity = 0; + it->panic = INK_ROUTINE_CAN_REUSE; + it->parse_error.is_set = 0; + it->runtime_error.is_set = 0; + } + } else if(ctx->routines_top == ctx->routines_capacity) { + int new_count; + 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; + } +#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->top = it->capacity = 0; + it->function_stack_top = it->function_stack_capacity = 0; + 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; + /* Looks for a reusable routine space then uses it */ + for(;it != end;++it) { + if(it->panic == INK_ROUTINE_CAN_REUSE) { + int idx; + it->panic = 0; + it->top = 0; + it->function_stack_top = 0; + + idx = it - ctx->routines; + if(idx >= ctx->routines_top) { + ctx->routines_top = idx + 1; + } + return idx; + } + } + /* FIXME: Maybe we need to abort here, this seems like quite an unsteady state */ + return -758; } int ink_kill_routine(struct context* ctx, int routine){ - struct ink_routine* curr; - if(routine < 0 || routine >= ctx->routines_top) { - return 0; - } - curr = ctx->routines + routine; - if(curr->panic == INK_ROUTINE_CAN_REUSE) { - return 0; - } - if(curr->stack != NULL) { - ctx->free(ctx, curr->stack); - curr->stack = NULL; - } - if(curr->function_stack != NULL) { - ctx->free(ctx, curr->function_stack); - curr->function_stack = NULL; - } - curr->panic = INK_ROUTINE_CAN_REUSE; - return 1; + struct ink_routine* curr; + if(routine < 0 || routine >= ctx->routines_top) { + return 0; + } + curr = ctx->routines + routine; + if(curr->panic == INK_ROUTINE_CAN_REUSE) { + return 0; + } + if(curr->stack != NULL) { + ctx->free(ctx, curr->stack); + curr->stack = NULL; + curr->top = curr->capacity = 0; + } + if(curr->function_stack != NULL) { + ctx->free(ctx, curr->function_stack); + curr->function_stack = NULL; + curr->function_stack_top = curr->function_stack_capacity = 0; + } + curr->panic = INK_ROUTINE_CAN_REUSE; + return 1; } /** @@ -733,163 +739,163 @@ int ink_kill_routine(struct context* ctx, int routine){ * @internal Loop from hell */ 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; + 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; + int err; #pragma GCC diagnostic pop #define LABEL_BUFFER 128 #define FUNCTION_BUFFER 256 - struct label labels[LABEL_BUFFER]; - struct elem function_buffer[FUNCTION_BUFFER]; - /* TODO: add checks for overflows in these arrays */ - currentRoutine = pContext->routines + pContext->routine_current; - function_buffer_top = 0; - function_name = -1; + struct label labels[LABEL_BUFFER]; + struct elem function_buffer[FUNCTION_BUFFER]; + /* TODO: add checks for overflows in these arrays */ + currentRoutine = pContext->routines + pContext->routine_current; + function_buffer_top = 0; + function_name = -1; #define MODE_EXECUTABLE 0 #define MODE_FUNCTION 1 #define MODE_DO 2 - mode = MODE_EXECUTABLE; - memset(labels, 0, sizeof(struct label)*LABEL_BUFFER); - - /* Loop from hell, good luck, pro-tip: leave the parser alone */ - for(i = 0; i < currentRoutine->top; ++i) { - struct elem current; - current = currentRoutine->stack[i]; - switch (mode) { - case MODE_EXECUTABLE: - switch(current.type) { - case INK_FUNCTION_KW: - 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"; - currentRoutine->parse_error.offset= i; - return -26; - case INK_END_KW: - currentRoutine->parse_error.is_set = 1; - 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; - } - 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; - } -#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"; - currentRoutine->parse_error.offset= i; - return -28; - } - if(current.type != INK_RESERVED) { - currentRoutine->parse_error.is_set = 1; - currentRoutine->parse_error.error_message = "Expected special token"; - currentRoutine->parse_error.offset= i; - return -29; - } -#endif - function_name = current.value; - break; - case MODE_DO: - if(current.type == INK_END_KW) { - int j; - for(j = 0; j < function_buffer_top; j++) { - struct elem pt; - pt = function_buffer[j]; - if(pt.type == INK_LABEL) { - 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; - currentRoutine->parse_error.error_message = "Label duplicate label in function"; - currentRoutine->parse_error.offset= i; - return -30; - break; - } -#endif - } else { - labels[k].active = 1; - labels[k].name = pContext->lex_reserved_words[pt.value]; - labels[k].dest = j; - memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1)); - function_buffer_top--; - j--; - break; - } - } - } - } - for(j = 0; j < function_buffer_top; j++) { - struct elem pt; - pt = function_buffer[j]; - if(pt.type == INK_RESERVED) { - int k; - for(k = 0; k < LABEL_BUFFER; k++) { - if(labels[k].active) { - int label_sz; - const char* lbl; - lbl = labels[k].name; - label_sz = strlen(lbl); - if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) { - function_buffer[j].type = INK_INTEGER; - function_buffer[j].value = labels[k].dest - j; - break; - } - } else break; - } - } - } - 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; - } - function_buffer[function_buffer_top] = current; - function_buffer_top += 1; - break; - } - 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; + mode = MODE_EXECUTABLE; + memset(labels, 0, sizeof(struct label)*LABEL_BUFFER); + + /* Loop from hell, good luck, pro-tip: leave the parser alone */ + for(i = 0; i < currentRoutine->top; ++i) { + struct elem current; + current = currentRoutine->stack[i]; + switch (mode) { + case MODE_EXECUTABLE: + switch(current.type) { + case INK_FUNCTION_KW: + 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"; + currentRoutine->parse_error.offset= i; + return -26; + case INK_END_KW: + currentRoutine->parse_error.is_set = 1; + 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; + } + 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; + } +#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"; + currentRoutine->parse_error.offset= i; + return -28; + } + if(current.type != INK_RESERVED) { + currentRoutine->parse_error.is_set = 1; + currentRoutine->parse_error.error_message = "Expected special token"; + currentRoutine->parse_error.offset= i; + return -29; + } +#endif + function_name = current.value; + break; + case MODE_DO: + if(current.type == INK_END_KW) { + int j; + for(j = 0; j < function_buffer_top; j++) { + struct elem pt; + pt = function_buffer[j]; + if(pt.type == INK_LABEL) { + 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; + currentRoutine->parse_error.error_message = "Label duplicate label in function"; + currentRoutine->parse_error.offset= i; + return -30; + break; + } +#endif + } else { + labels[k].active = 1; + labels[k].name = pContext->lex_reserved_words[pt.value]; + labels[k].dest = j; + memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1)); + function_buffer_top--; + j--; + break; + } + } + } + } + for(j = 0; j < function_buffer_top; j++) { + struct elem pt; + pt = function_buffer[j]; + if(pt.type == INK_RESERVED) { + int k; + for(k = 0; k < LABEL_BUFFER; k++) { + if(labels[k].active) { + int label_sz; + const char* lbl; + lbl = labels[k].name; + label_sz = strlen(lbl); + if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) { + function_buffer[j].type = INK_INTEGER; + function_buffer[j].value = labels[k].dest - j; + break; + } + } else break; + } + } + } + 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; + } + function_buffer[function_buffer_top] = current; + function_buffer_top += 1; + break; + } + 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 #undef MODE_DO @@ -899,183 +905,183 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i } int ink_step(struct context *pContext) { - struct ink_routine* currentRoutine; - struct stack_frame frame; - struct stack_frame* top; - struct elem next; - int t; - - currentRoutine = pContext->routines + pContext->routine_current; - pContext->steps++; - if(currentRoutine->function_stack_top == 0) return 0; - if(pContext->panic) { - return -1; - } - top = ¤tRoutine->function_stack[currentRoutine->function_stack_top-1]; - t = top->executing.type; - switch(t) { - case INK_NATIVE_FUNCTION: - if(top->index != 0) { - 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 { - next = pContext->words[top->executing.value].things[top->index]; - if(next.type == INK_RETURN) { - ink_pop_fn(pContext); - return 1; - } - 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; - } - return 1; + struct ink_routine* currentRoutine; + struct stack_frame frame; + struct stack_frame* top; + struct elem next; + int t; + + currentRoutine = pContext->routines + pContext->routine_current; + pContext->steps++; + if(currentRoutine->function_stack_top == 0) return 0; + if(pContext->panic) { + return -1; + } + top = ¤tRoutine->function_stack[currentRoutine->function_stack_top-1]; + t = top->executing.type; + switch(t) { + case INK_NATIVE_FUNCTION: + if(top->index != 0) { + 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 { + next = pContext->words[top->executing.value].things[top->index]; + if(next.type == INK_RETURN) { + ink_pop_fn(pContext); + return 1; + } + 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; + } + return 1; } int ink_compile(struct context *pContext, const char* buffer) { - int routine, saved, executable_buffer_top; - /* Main function has a size limit of 256 (need to know that for REPL */ - struct elem executable_buffer[256]; - struct ink_routine* currentRoutine; - int err; - struct stack_frame frame; - char* integer; - size_t integer_size; - char main_fn[32] = "__-MAIN-__"; - - routine = ink_make_routine(pContext); - saved = pContext->routine_current; - pContext->routine_current = routine; - currentRoutine = pContext->routines + routine; - currentRoutine->stack = NULL; - currentRoutine->top = 0; - 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; - } - if(executable_buffer_top != 0) { - integer = ink_itoa(pContext, routine); - integer_size = strlen(integer); - memcpy(main_fn + 10, integer, integer_size); - pContext->free(pContext, integer); - integer = NULL; - 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; - } - frame.executing.type = INK_FUNCTION; - 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; - currentRoutine->parse_error.error_message = "Could not push any executable frame: push failed"; - currentRoutine->parse_error.offset = -1; - } - pContext->panic = 1; - return -1; - } -#endif - } else { - pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS; - } - - pContext->routine_current = saved; - return routine; + int routine, saved, executable_buffer_top; + /* Main function has a size limit of 256 (need to know that for REPL */ + struct elem executable_buffer[256]; + struct ink_routine* currentRoutine; + int err; + struct stack_frame frame; + char* integer; + size_t integer_size; + char main_fn[32] = "__-MAIN-__"; + + routine = ink_make_routine(pContext); + saved = pContext->routine_current; + pContext->routine_current = routine; + currentRoutine = pContext->routines + routine; + currentRoutine->stack = NULL; + currentRoutine->top = 0; + 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; + } + if(executable_buffer_top != 0) { + integer = ink_itoa(pContext, routine); + integer_size = strlen(integer); + memcpy(main_fn + 10, integer, integer_size); + pContext->free(pContext, integer); + integer = NULL; + 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; + } + frame.executing.type = INK_FUNCTION; + 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; + currentRoutine->parse_error.error_message = "Could not push any executable frame: push failed"; + currentRoutine->parse_error.offset = -1; + } + pContext->panic = 1; + return -1; + } +#endif + } else { + pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS; + } + + pContext->routine_current = saved; + return routine; } int ink_can_run(struct context* pContext) { - int it; - if(pContext->panic) return 0; - if(pContext->routines_top == 0) return 0; - for(it = 0; it < pContext->routines_top; ++it) { - if( - pContext->routines[it].panic == 0 - && !pContext->routines[it].parse_error.is_set - && !pContext->routines[it].runtime_error.is_set - ) { - return 1; - } - } - return 0; + int it; + if(pContext->panic) return 0; + if(pContext->routines_top == 0) return 0; + for(it = 0; it < pContext->routines_top; ++it) { + if( + pContext->routines[it].panic == 0 + && !pContext->routines[it].parse_error.is_set + && !pContext->routines[it].runtime_error.is_set + ) { + return 1; + } + } + return 0; } int ink_step_everyone(struct context* pContext) { @@ -1098,7 +1104,10 @@ int ink_step_everyone(struct context* pContext) { /* Kill? */ if(pContext->routines[pContext->routine_current].panic == INK_ROUTINE_SUCCESS) { - ink_kill_routine(pContext, pContext->routine_current); + goto top_label; + /* We used to kill the routines here, idk if this cleanup is wise as it may happen in somewhat interstitial + * moments and affect performance + * ink_kill_routine(pContext, pContext->routine_current); */ } /* Step! */ @@ -1117,1257 +1126,1263 @@ int ink_step_everyone(struct context* pContext) { } int ink_new_type( - struct context* ctx, - const char* type_name, - int size, - void (*collect)(struct context*,void*), - struct ink_collection_list (*gc)(struct context*,void*) + struct context* ctx, + const char* type_name, + int size, + void (*collect)(struct context*,void*), + struct ink_collection_list (*gc)(struct context*,void*) ) { - if(ctx->panic) return -128; - /* Resize for push */ - if(ctx->types == NULL) { - ctx->types = ctx->inner_malloc(ctx, sizeof(struct ink_type) * 8); - ctx->types_top = 0; - ctx->types_capacity = 8; - } else if(ctx->types_top == ctx->types_capacity) { - int new_count; - void* renewed; - new_count = (ctx->types_capacity + ctx->types_capacity/2); - renewed = ctx->inner_realloc(ctx, ctx->types, sizeof(struct ink_type) * new_count); - if(renewed == NULL) { - return -129; - } else { - ctx->types = renewed; - ctx->types_capacity = new_count; - } - } - - /* Push */ - ctx->types[ctx->types_top].name = type_name; - ctx->types[ctx->types_top].element_size = size; - ctx->types[ctx->types_top].elements = NULL; - ctx->types[ctx->types_top].elements_top = 0; - ctx->types[ctx->types_top].elements_capacity = 0; - ctx->types[ctx->types_top].collect = collect; - ctx->types[ctx->types_top].gc = gc; - - ctx->types_top++; - /* Satisfying the minimal value requirement */ - return ctx->types_top - 1 + 16; + if(ctx->panic) return -128; + /* Resize for push */ + if(ctx->types == NULL) { + ctx->types = ctx->inner_malloc(ctx, sizeof(struct ink_type) * 8); + ctx->types_top = 0; + ctx->types_capacity = 8; + } else if(ctx->types_top == ctx->types_capacity) { + int new_count; + void* renewed; + new_count = (ctx->types_capacity + ctx->types_capacity/2); + renewed = ctx->inner_realloc(ctx, ctx->types, sizeof(struct ink_type) * new_count); + if(renewed == NULL) { + return -129; + } else { + ctx->types = renewed; + ctx->types_capacity = new_count; + } + } + + /* Push */ + ctx->types[ctx->types_top].name = type_name; + ctx->types[ctx->types_top].element_size = size; + ctx->types[ctx->types_top].elements = NULL; + ctx->types[ctx->types_top].elements_top = 0; + ctx->types[ctx->types_top].elements_capacity = 0; + ctx->types[ctx->types_top].collect = collect; + ctx->types[ctx->types_top].gc = gc; + + ctx->types_top++; + /* Satisfying the minimal value requirement */ + return ctx->types_top - 1 + 16; } 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; + int type_id; + if(ref.type < 16) return NULL; + type_id = ref.type - 16; + 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; + return ctx->types[type_id].elements + ref.value; } void* ink_get_value(struct context* ctx, struct elem ref) { - struct element_slab* s; - s = ink_get_value_link(ctx, ref); - if(s == NULL) return NULL; - return s->data; + struct element_slab* s; + s = ink_get_value_link(ctx, ref); + if(s == NULL) return NULL; + return s->data; } struct elem ink_make_native_unsafe(struct context* ctx, int type, void* ptr, int is_protected) { - int type_id; - struct elem ret; - int g, i; - - if(type < 16) { - ret.type = 0; - ret.value = -130; - return ret; - } - - /* Apply invariant of the user defined types */ - type_id = type - 16; - if(type_id >= ctx->types_top) { - ret.type = 0; - ret.value = -129; - return ret; - } - - if(ctx->panic) { - ret.type = 0; - ret.value = -135; - return ret; - } - - /* Resize for push of value in store */ - if(ctx->types[type_id].elements == NULL) { - ctx->types[type_id].elements = ctx->inner_malloc(ctx, sizeof(struct element_slab) * 8); - ctx->types[type_id].elements_top = 0; - ctx->types[type_id].elements_capacity = 8; - memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); - } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) { - int new_count; - void* renewed; - new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2); - renewed = ctx->inner_realloc(ctx, ctx->types[type_id].elements, sizeof(struct element_slab) * new_count); - if(renewed == NULL) { - ret.type = 0; - ret.value = -129; - return ret; - } else { - ctx->types[type_id].elements = renewed; - ctx->types[type_id].elements_capacity = new_count; - memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); - } - } - - /* Push value in store */ - g = ctx->types[type_id].elements_capacity; - for(i = 0; i < g; ++i) { - if(! ctx->types[type_id].elements[i].in_use) { - ctx->types[type_id].elements[i].in_use = 1; - ctx->types[type_id].elements[i].uses = 1; - ctx->types[type_id].elements[i].is_protected = is_protected; - if(ctx->types[type_id].element_size < 0) { - ctx->types[type_id].elements[i].data = ptr; - } else { - void* new_ptr = ctx->malloc(ctx, ctx->types[type_id].element_size); - if(new_ptr == NULL) { - ret.type = 0; - ret.value = -139; - return ret; - } - memcpy(new_ptr, ptr, ctx->types[type_id].element_size); - ctx->types[type_id].elements[i].data = new_ptr; - } - ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1); - ret.type = type; - ret.value = i; - return ret; - } - } - ret.type = 0; - ret.value = -140; - return ret; + int type_id; + struct elem ret; + int g, i; + + if(type < 16) { + ret.type = 0; + ret.value = -130; + return ret; + } + + /* Apply invariant of the user defined types */ + type_id = type - 16; + if(type_id >= ctx->types_top) { + ret.type = 0; + ret.value = -129; + return ret; + } + + if(ctx->panic) { + ret.type = 0; + ret.value = -135; + return ret; + } + + /* Resize for push of value in store */ + if(ctx->types[type_id].elements == NULL) { + ctx->types[type_id].elements = ctx->inner_malloc(ctx, sizeof(struct element_slab) * 8); + ctx->types[type_id].elements_top = 0; + ctx->types[type_id].elements_capacity = 8; + memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); + } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) { + int new_count; + void* renewed; + new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2); + renewed = ctx->inner_realloc(ctx, ctx->types[type_id].elements, sizeof(struct element_slab) * new_count); + if(renewed == NULL) { + ret.type = 0; + ret.value = -129; + return ret; + } else { + ctx->types[type_id].elements = renewed; + ctx->types[type_id].elements_capacity = new_count; + memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); + } + } + + /* Push value in store */ + g = ctx->types[type_id].elements_capacity; + for(i = 0; i < g; ++i) { + if(! ctx->types[type_id].elements[i].in_use) { + ctx->types[type_id].elements[i].in_use = 1; + ctx->types[type_id].elements[i].uses = 1; + ctx->types[type_id].elements[i].is_protected = is_protected; + if(ctx->types[type_id].element_size < 0) { + ctx->types[type_id].elements[i].data = ptr; + } else { + void* new_ptr = ctx->malloc(ctx, ctx->types[type_id].element_size); + if(new_ptr == NULL) { + ret.type = 0; + ret.value = -139; + return ret; + } + memcpy(new_ptr, ptr, ctx->types[type_id].element_size); + ctx->types[type_id].elements[i].data = new_ptr; + } + ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1); + ret.type = type; + ret.value = i; + return ret; + } + } + ret.type = 0; + ret.value = -140; + return ret; } struct elem ink_make_native(struct context* ctx, int type, void* ptr) { - return ink_make_native_unsafe(ctx, type, ptr, 0); + return ink_make_native_unsafe(ctx, type, ptr, 0); } void ink_clean_routines(struct context* ctx) { - int i, j; - struct elem null; - - null.value = 0; - null.type = INK_INTEGER; - for(i = 0; i < ctx->routines_top; ++i) { - if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE || ctx->routines[i].panic == INK_ROUTINE_SUCCESS) { - if(ctx->routines[i].stack != NULL) { - for (j = 0; j < ctx->routines[i].top; ++j) { - ctx->routines[i].stack[j] = null; - } - } - if(ctx->routines[i].function_stack != NULL) { - for (j = 0; j < ctx->routines[i].function_stack_top; ++j) { - ctx->routines[i].function_stack[j].executing = null; - ctx->routines[i].function_stack[j].index = 0; - } - } - ctx->routines[i].top = 0; - ctx->routines[i].function_stack_top = 0; - } - } + int i; +#ifndef NOEXTRACHECKS + int j; + struct elem null; + + null.value = 0; + null.type = INK_INTEGER; +#endif + for(i = 0; i < ctx->routines_top; ++i) { + if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE || ctx->routines[i].panic == INK_ROUTINE_SUCCESS) { +#ifndef NOEXTRACHECKS + if(ctx->routines[i].stack != NULL) { + for (j = 0; j < ctx->routines[i].top; ++j) { + ctx->routines[i].stack[j] = null; + } + } + if(ctx->routines[i].function_stack != NULL) { + for (j = 0; j < ctx->routines[i].function_stack_top; ++j) { + ctx->routines[i].function_stack[j].executing = null; + ctx->routines[i].function_stack[j].index = 0; + } + } +#endif + ctx->routines[i].top = 0; + ctx->routines[i].function_stack_top = 0; + ctx->routines[i].panic = INK_ROUTINE_CAN_REUSE; + } + } } void ink_gc(struct context* ctx) { - int i, j, k; - int marked; - struct element_slab* v; - - for(i = 0; i < ctx->types_top; ++i) { - for(j = 0; j < ctx->types[i].elements_top; ++j) { - ctx->types[i].elements[j].uses = 0; - } - } - - /* Start by marking the roots of the routines, Clear the routines if possible */ - for(i = 0; i < ctx->routines_top; ++i) { - if(ctx->routines[i].panic == INK_ROUTINE_SUCCESS) { - if(ctx->routines[i].stack != NULL) { - ctx->free(ctx, ctx->routines[i].stack); - ctx->routines[i].stack = NULL; - } - if(ctx->routines[i].function_stack != NULL) { - ctx->free(ctx, ctx->routines[i].function_stack); - ctx->routines[i].function_stack = NULL; - } - ctx->routines[i].panic = INK_ROUTINE_CAN_REUSE; - } - if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE) { - continue; - } - for(j = 0; j < ctx->routines[i].top; ++j) { - v = ink_get_value_link(ctx, ctx->routines[i].stack[j]); - if(v != NULL) ++v->uses; - } - } - - /* TODO: Mark objects contained within function code */ - - /* Mark the rest of the data */ - do { - marked = 0; - for (i = 0; i < ctx->types_top; ++i) { - for (j = 0; j < ctx->types[i].elements_top; ++j) { - /* Only mark from things that are active and detected as in use */ - if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) { - struct ink_collection_list c; - c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); - for (k = 0; k < c.count; ++k) { - v = ink_get_value_link(ctx, c.elements[k]); - /* Never mark twice to avoid infinite loops with e.g. arrays that contain themselves */ - if (v != NULL && !v->uses) { - ++v->uses; - marked = 1; - } - } - if (c.elements != NULL) { - ctx->inner_free(ctx, c.elements); - c.elements = NULL; - } - } - } - } - } while(marked); - - /* Sweep phase: explore any allocated data and sweep the unused away */ - for(i = 0; i < ctx->types_top; ++i) { - for(j = 0; j < ctx->types[i].elements_top; ++j) { - if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected == 0) { - ctx->collections++; - ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); - if(ctx->types[i].element_size > 0 && ctx->types[i].elements[j].data != NULL) { - ctx->free(ctx, ctx->types[i].elements[j].data); - } - ctx->types[i].elements[j].data = NULL; - ctx->types[i].elements[j].uses = 0; - ctx->types[i].elements[j].in_use = 0; - } - } - } + int i, j, k; + int marked; + struct element_slab* v; + + for(i = 0; i < ctx->types_top; ++i) { + for(j = 0; j < ctx->types[i].elements_top; ++j) { + ctx->types[i].elements[j].uses = 0; + } + } + + /* Start by marking the roots of the routines, Clear the routines if possible */ + for(i = 0; i < ctx->routines_top; ++i) { + if(ctx->routines[i].panic == INK_ROUTINE_SUCCESS) { +#ifndef NOEXTRACHECKS + if(ctx->routines[i].stack != NULL) { + ctx->free(ctx, ctx->routines[i].stack); + ctx->routines[i].stack = NULL; + } +#endif + ctx->routines[i].top = 0; +#ifndef NOEXTRACHECKS + if(ctx->routines[i].function_stack != NULL) { + ctx->free(ctx, ctx->routines[i].function_stack); + ctx->routines[i].function_stack = NULL; + } +#endif + ctx->routines[i].function_stack_top = 0; + ctx->routines[i].panic = INK_ROUTINE_CAN_REUSE; + } else if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE) { + continue; + } else for(j = 0; j < ctx->routines[i].top; ++j) { + v = ink_get_value_link(ctx, ctx->routines[i].stack[j]); + if(v != NULL) ++v->uses; + } + } + + /* TODO: Mark objects contained within function code */ + + /* Mark the rest of the data */ + do { + marked = 0; + for (i = 0; i < ctx->types_top; ++i) { + for (j = 0; j < ctx->types[i].elements_top; ++j) { + /* Only mark from things that are active and detected as in use */ + if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) { + struct ink_collection_list c; + c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); + for (k = 0; k < c.count; ++k) { + v = ink_get_value_link(ctx, c.elements[k]); + /* Never mark twice to avoid infinite loops with e.g. arrays that contain themselves */ + if (v != NULL && !v->uses) { + ++v->uses; + marked = 1; + } + } + if (c.elements != NULL) { + ctx->inner_free(ctx, c.elements); + c.elements = NULL; + } + } + } + } + } while(marked); + + /* Sweep phase: explore any allocated data and sweep the unused away */ + for(i = 0; i < ctx->types_top; ++i) { + for(j = 0; j < ctx->types[i].elements_top; ++j) { + if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected == 0) { + ctx->collections++; + ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); + if(ctx->types[i].element_size > 0 && ctx->types[i].elements[j].data != NULL) { + ctx->free(ctx, ctx->types[i].elements[j].data); + } + ctx->types[i].elements[j].data = NULL; + ctx->types[i].elements[j].uses = 0; + ctx->types[i].elements[j].in_use = 0; + } + } + } } /**********************************************************************************************************************/ static void print_stacktrace(struct context* _) { - int i; - struct ink_routine* currentRoutine; - currentRoutine = _->routines + _->routine_current; - - for(i = 0; i < currentRoutine->function_stack_top; ++i) { - struct elem thing; - char *n; - thing = currentRoutine->function_stack[i].executing; - switch(thing.type) { - case INK_NATIVE_FUNCTION: { - n = _->native_words[thing.value].name; - while (*n) { - _->putchar(_, *n); - ++n; - } - _->putchar(_, 10); - break; - } - case INK_FUNCTION:{ - n = _->words[thing.value].name; - while (*n) { - _->putchar(_, *n); - ++n; - } - _->putchar(_, ':'); - n = ink_itoa(_, currentRoutine->function_stack[i].index); - while (*n) { - _->putchar(_, *n); - ++n; - } - _->putchar(_, 10); - break; - } - default: - break; - } - } + int i; + struct ink_routine* currentRoutine; + currentRoutine = _->routines + _->routine_current; + + for(i = 0; i < currentRoutine->function_stack_top; ++i) { + struct elem thing; + char *n; + thing = currentRoutine->function_stack[i].executing; + switch(thing.type) { + case INK_NATIVE_FUNCTION: { + n = _->native_words[thing.value].name; + while (*n) { + _->putchar(_, *n); + ++n; + } + _->putchar(_, 10); + break; + } + case INK_FUNCTION:{ + n = _->words[thing.value].name; + while (*n) { + _->putchar(_, *n); + ++n; + } + _->putchar(_, ':'); + n = ink_itoa(_, currentRoutine->function_stack[i].index); + while (*n) { + _->putchar(_, *n); + ++n; + } + _->putchar(_, 10); + break; + } + default: + break; + } + } } static void add_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value; } static void sub_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value; } static void mult_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value; } static void div_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value; } static void is_equal(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - 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); - ink_pop(ctx); - ret.type = INK_INTEGER; - ret.value = a.value == b.value && a.type == b.type; - ink_push(ctx, ret); + struct ink_routine* currentRoutine; + struct elem a; + 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); + ink_pop(ctx); + ret.type = INK_INTEGER; + ret.value = a.value == b.value && a.type == b.type; + ink_push(ctx, ret); } static void is_different(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - 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); - ink_pop(ctx); - ret.type = INK_INTEGER; - ret.value = !(a.value == b.value && a.type == b.type); - ink_push(ctx, ret); + struct ink_routine* currentRoutine; + struct elem a; + 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); + ink_pop(ctx); + ret.type = INK_INTEGER; + ret.value = !(a.value == b.value && a.type == b.type); + ink_push(ctx, ret); } #ifndef NOEXTRAARITHMETIC static void rem_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value; } static void xor_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value ^ a.value; } static void gt_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value > a.value; } static void gte_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value >= a.value; } static void lte_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value <= a.value; } #endif /* NOEXTRAARITHMETIC */ static void lt_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + 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; + ink_pop(ctx); + currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value; } static void dupe_elem(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; + struct ink_routine* currentRoutine; + struct elem a; #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; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if(currentRoutine->top < 1) { - ctx->panic = 1; - return; - } + if(currentRoutine->top < 1) { + ctx->panic = 1; + return; + } #endif - a = currentRoutine->stack[currentRoutine->top-1]; - err = ink_push(ctx, a); + a = currentRoutine->stack[currentRoutine->top-1]; + err = ink_push(ctx, a); #ifndef NOEXTRACHECKS - if(err < 0) ctx->panic = 1; + 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; - } + struct ink_routine* currentRoutine; + currentRoutine = ctx->routines + ctx->routine_current; + if(currentRoutine->top < 1) { + ctx->panic = 1; + return; + } #endif - ink_pop(ctx); + ink_pop(ctx); } static void pluck_elem(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - int position; + struct ink_routine* currentRoutine; + struct elem a; + 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; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if(currentRoutine->top < 1) { - currentRoutine->panic = -1; - return; - } + if(currentRoutine->top < 1) { + currentRoutine->panic = -1; + return; + } #endif - a = currentRoutine->stack[currentRoutine->top-1]; + a = currentRoutine->stack[currentRoutine->top-1]; #ifndef NOEXTRACHECKS - if(a.type != INK_INTEGER) { - ctx->panic = 1; - return; - } + if(a.type != INK_INTEGER) { + ctx->panic = 1; + return; + } #endif - position = currentRoutine->top - (a.value + 1); + position = currentRoutine->top - (a.value + 1); #ifndef NOEXTRACHECKS - if(position >= currentRoutine->top || position < 0) { - ctx->panic = 1; - return; - } + if(position >= currentRoutine->top || position < 0) { + ctx->panic = 1; + return; + } #endif - ink_pop(ctx); - err = ink_push(ctx, currentRoutine->stack[position]); + ink_pop(ctx); + err = ink_push(ctx, currentRoutine->stack[position]); #ifndef NOEXTRACHECKS - if(err < 0) ctx->panic = 1; + if(err < 0) ctx->panic = 1; #endif } static void swap_elem(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - struct elem b; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - currentRoutine->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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; - currentRoutine->stack[currentRoutine->top-1] = b; + a = currentRoutine->stack[currentRoutine->top-1]; + b = currentRoutine->stack[currentRoutine->top-2]; + currentRoutine->stack[currentRoutine->top-2] = a; + currentRoutine->stack[currentRoutine->top-1] = b; } static void return_if(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - currentRoutine = ctx->routines + ctx->routine_current; + struct ink_routine* currentRoutine; + struct elem a; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if(currentRoutine->top < 1) { - ctx->panic = -1; - return; - } + if(currentRoutine->top < 1) { + ctx->panic = -1; + return; + } #endif - a = currentRoutine->stack[currentRoutine->top-1]; + a = currentRoutine->stack[currentRoutine->top-1]; #ifndef NOEXTRACHECKS - if(a.type != INK_INTEGER) { - ctx->panic = 1; - return; - } + if(a.type != INK_INTEGER) { + ctx->panic = 1; + return; + } #endif - if(a.value) { - ink_pop_fn(ctx); - ink_pop_fn(ctx); - } - ink_pop(ctx); - return; + if(a.value) { + ink_pop_fn(ctx); + ink_pop_fn(ctx); + } + ink_pop(ctx); + return; } static void jump_if(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem label; - struct elem condition; - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if(currentRoutine->top < 2) { - ctx->panic = -1; - return; - } + struct ink_routine* currentRoutine; + 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]; + 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; - } + if(label.type != INK_INTEGER || condition.type != INK_INTEGER) { + ctx->panic = -1; + return; + } #endif - ink_pop(ctx); - ink_pop(ctx); - ink_pop_fn(ctx); - if(condition.value) { - currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += label.value - 2; - } - - return; + ink_pop(ctx); + ink_pop(ctx); + ink_pop_fn(ctx); + if(condition.value) { + currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += label.value - 2; + } + + return; } static void print_int(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem a; - 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); - str = n; - while (*str) { - ctx->putchar(ctx, *str); - ++str; - } - ctx->free(ctx, n); - n = NULL; + struct ink_routine* currentRoutine; + struct elem a; + 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); + str = n; + while (*str) { + ctx->putchar(ctx, *str); + ++str; + } + ctx->free(ctx, n); + n = NULL; } 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); - } else if(a.value <= 0x7FF) { - ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 192); - ctx->putchar(ctx, (a.value & 0x3F) | 128); - } else if(a.value <= 0xFFFF) { - ctx->putchar(ctx, ((a.value & 0x3F000) >> 12) | 224); - ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 128); - ctx->putchar(ctx, (a.value & 0x3F) | 128); - } else if(a.value <= 0x10FFFF) { - ctx->putchar(ctx, ((a.value & 0x3C0000) >> 18) | 240); - ctx->putchar(ctx, ((a.value & 0x3F000) >> 12) | 128); - ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 128); - ctx->putchar(ctx, (a.value & 0x3F) | 128); - } else { - ctx->panic = -1; - return; - } - ink_pop(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); + } else if(a.value <= 0x7FF) { + ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 192); + ctx->putchar(ctx, (a.value & 0x3F) | 128); + } else if(a.value <= 0xFFFF) { + ctx->putchar(ctx, ((a.value & 0x3F000) >> 12) | 224); + ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 128); + ctx->putchar(ctx, (a.value & 0x3F) | 128); + } else if(a.value <= 0x10FFFF) { + ctx->putchar(ctx, ((a.value & 0x3C0000) >> 18) | 240); + ctx->putchar(ctx, ((a.value & 0x3F000) >> 12) | 128); + ctx->putchar(ctx, ((a.value & 0xFC0) >> 6) | 128); + ctx->putchar(ctx, (a.value & 0x3F) | 128); + } else { + ctx->panic = -1; + return; + } + ink_pop(ctx); } int get_type_by_name(struct context* ctx, const char* name) { - int i; - for(i = 0; i < ctx->types_top; ++i) { - if(strcmp(ctx->types[i].name, name) == 0) { - return i + 16; - } - } - return -1; + int i; + for(i = 0; i < ctx->types_top; ++i) { + if(strcmp(ctx->types[i].name, name) == 0) { + return i + 16; + } + } + return -1; } static void run_gc(struct context* ctx) { - ink_gc(ctx); + ink_gc(ctx); } static void clear_stack(struct context* ctx) { - struct ink_routine* currentRoutine; - currentRoutine = ctx->routines + ctx->routine_current; - while (currentRoutine->top >= 1) { - ink_pop(ctx); - } - return; + struct ink_routine* currentRoutine; + currentRoutine = ctx->routines + ctx->routine_current; + while (currentRoutine->top >= 1) { + ink_pop(ctx); + } + return; } static void dump_stack(struct context* ctx) { - struct ink_routine* currentRoutine; - int index; - char* idx; - char* type; - char* value; - char* it; - currentRoutine = ctx->routines + ctx->routine_current; - index = currentRoutine->top; - while (index) { - --index; - idx = ink_itoa(ctx,index); - type = ink_itoa(ctx, currentRoutine->stack[index].type); - value = ink_itoa(ctx,currentRoutine->stack[index].value); - for(it = idx; *it; ++it) ctx->putchar(ctx, *it); - ctx->putchar(ctx, ' ');ctx->putchar(ctx, '|');ctx->putchar(ctx, ' '); - for(it = type; *it; ++it) ctx->putchar(ctx, *it); - ctx->putchar(ctx, ' ');ctx->putchar(ctx, '|');ctx->putchar(ctx, ' '); - for(it = value; *it; ++it) ctx->putchar(ctx, *it); - ctx->putchar(ctx, '\n'); - if(value != NULL) ctx->free(ctx, value); - if(type != NULL) ctx->free(ctx, type); - if(idx != NULL) ctx->free(ctx, idx); - value = type = idx = NULL; - } - return; + struct ink_routine* currentRoutine; + int index; + char* idx; + char* type; + char* value; + char* it; + currentRoutine = ctx->routines + ctx->routine_current; + index = currentRoutine->top; + while (index) { + --index; + idx = ink_itoa(ctx,index); + type = ink_itoa(ctx, currentRoutine->stack[index].type); + value = ink_itoa(ctx,currentRoutine->stack[index].value); + for(it = idx; *it; ++it) ctx->putchar(ctx, *it); + ctx->putchar(ctx, ' ');ctx->putchar(ctx, '|');ctx->putchar(ctx, ' '); + for(it = type; *it; ++it) ctx->putchar(ctx, *it); + ctx->putchar(ctx, ' ');ctx->putchar(ctx, '|');ctx->putchar(ctx, ' '); + for(it = value; *it; ++it) ctx->putchar(ctx, *it); + ctx->putchar(ctx, '\n'); + if(value != NULL) ctx->free(ctx, value); + if(type != NULL) ctx->free(ctx, type); + if(idx != NULL) ctx->free(ctx, idx); + value = type = idx = NULL; + } + return; } static void collect_noop() {} static struct ink_collection_list gc_noop() { - struct ink_collection_list c; - c.elements = NULL; - c.count = 0; - return c; + struct ink_collection_list c; + c.elements = NULL; + c.count = 0; + return c; } #ifndef NOARRAYLIB static void collect_array(struct context* ctx, void* array) { - struct ink_array* ary; - ary = array; - if(ary->elements != NULL) { - ctx->free(ctx, ary->elements); - ary->elements = NULL; - } + struct ink_array* ary; + ary = array; + if(ary->elements != NULL) { + ctx->free(ctx, ary->elements); + ary->elements = NULL; + } } static struct ink_collection_list gc_array(struct context* ctx, void* array) { - struct ink_array* ary; - struct ink_collection_list c; - ary = array; - c.elements = ctx->inner_malloc(ctx, sizeof(struct elem)*ary->top); - c.count = ary->top; - memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top); - return c; + struct ink_array* ary; + struct ink_collection_list c; + ary = array; + c.elements = ctx->inner_malloc(ctx, sizeof(struct elem)*ary->top); + c.count = ary->top; + memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top); + return c; } static void new_array(struct context* ctx) { - int tid; - struct elem e; - struct ink_array ary; - tid = get_type_by_name(ctx, "array"); - ary.elements = NULL; - ary.top = 0; - ary.capacity = 0; - ary.flags = 0; - e = ink_make_native(ctx, tid, &ary); - ink_push(ctx, e); + int tid; + struct elem e; + struct ink_array ary; + tid = get_type_by_name(ctx, "array"); + ary.elements = NULL; + ary.top = 0; + ary.capacity = 0; + ary.flags = 0; + e = ink_make_native(ctx, tid, &ary); + ink_push(ctx, e); } #ifndef NOSTRINGLITERALS static void new_protected_array(struct context* ctx) { - int tid; - struct elem e; - struct ink_array ary; - tid = get_type_by_name(ctx, "array"); - ary.elements = NULL; - ary.top = 0; - ary.capacity = 0; - e = ink_make_native_unsafe(ctx, tid, &ary, 1); - ink_push(ctx, e); + int tid; + struct elem e; + struct ink_array ary; + tid = get_type_by_name(ctx, "array"); + ary.elements = NULL; + ary.top = 0; + ary.capacity = 0; + e = ink_make_native_unsafe(ctx, tid, &ary, 1); + ink_push(ctx, e); } #endif static void push_array_stack_delim(struct context* ctx) { - int tid; - struct elem e; - tid = get_type_by_name(ctx, "array_marker"); - e.type = tid; - e.value = 0; - ink_push(ctx, e); + int tid; + struct elem e; + tid = get_type_by_name(ctx, "array_marker"); + e.type = tid; + e.value = 0; + ink_push(ctx, e); } int array_push_s(struct context* ctx, struct ink_array* ary, struct elem value) { - if(ary->elements == NULL) { - ary->elements = ctx->malloc(ctx, sizeof(struct elem) * 8); - ary->top = 0; - ary->capacity = 8; - } else if(ary->top == ary->capacity) { - int new_count; - void* renewed; - new_count = (ary->capacity + ary->capacity/2); - renewed = ctx->realloc(ctx, ary->elements, sizeof(struct elem) * new_count); - if(renewed == NULL) { - return 1; - } else { - ary->elements = renewed; - ary->capacity = new_count; - } - } - ary->elements[ary->top] = value; - ary->top++; - return 0; + if(ary->elements == NULL) { + ary->elements = ctx->malloc(ctx, sizeof(struct elem) * 8); + ary->top = 0; + ary->capacity = 8; + } else if(ary->top == ary->capacity) { + int new_count; + void* renewed; + new_count = (ary->capacity + ary->capacity/2); + renewed = ctx->realloc(ctx, ary->elements, sizeof(struct elem) * new_count); + if(renewed == NULL) { + return 1; + } else { + ary->elements = renewed; + ary->capacity = new_count; + } + } + ary->elements[ary->top] = value; + ary->top++; + return 0; } void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct ink_array* ary, struct elem value) { - if(array_push_s(ctx, ary, value)) { - currentRoutine->panic = -1; - } + if(array_push_s(ctx, ary, value)) { + currentRoutine->panic = -1; + } } static void push_array(struct context* ctx) { - struct elem a; - struct ink_routine* currentRoutine; - struct ink_array* ary; + struct elem a; + struct ink_routine* currentRoutine; + struct ink_array* ary; #ifndef NOEXTRACHECKS int tid; - tid = get_type_by_name(ctx, "array"); + tid = get_type_by_name(ctx, "array"); #endif - currentRoutine = ctx->routines + ctx->routine_current; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) { - currentRoutine->panic = -1; - return; - } + 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); + a = currentRoutine->stack[currentRoutine->top-1]; + ary= ink_get_value(ctx, a); #ifndef NOEXTRACHECKS - if(ary == NULL) { - currentRoutine->panic = -1; - return; - } + if(ary == NULL) { + currentRoutine->panic = -1; + return; + } #endif - ink_pop(ctx); - array_push(ctx, currentRoutine, ary, currentRoutine->stack[currentRoutine->top-1]); - ink_pop(ctx); + ink_pop(ctx); + array_push(ctx, currentRoutine, ary, currentRoutine->stack[currentRoutine->top-1]); + ink_pop(ctx); } static void push_delimited_array(struct context* ctx) { - int tid, idx, counter, i; - struct elem a; - struct ink_routine* currentRoutine; - 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); - ary= ink_get_value(ctx, a); - - for(idx = 1; idx <= currentRoutine->top; ++idx) { - if(currentRoutine->stack[currentRoutine->top-idx].type == tid) { - break; - } - } - /* Save for cleanup */ - counter = idx; - - /* Don't copy the delimiter */ - 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; - - /* Copy the data */ - for(i = currentRoutine->top - idx; i < currentRoutine->top; ++i) { - ary->elements[ary->top] = currentRoutine->stack[i]; - ++(ary->top); - } - - /* Cleanup */ - while(counter--) { - ink_pop(ctx); - } - - /* Put value in place */ - ink_push(ctx, a); + int tid, idx, counter, i; + struct elem a; + struct ink_routine* currentRoutine; + 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); + ary= ink_get_value(ctx, a); + + for(idx = 1; idx <= currentRoutine->top; ++idx) { + if(currentRoutine->stack[currentRoutine->top-idx].type == tid) { + break; + } + } + /* Save for cleanup */ + counter = idx; + + /* Don't copy the delimiter */ + 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; + + /* Copy the data */ + for(i = currentRoutine->top - idx; i < currentRoutine->top; ++i) { + ary->elements[ary->top] = currentRoutine->stack[i]; + ++(ary->top); + } + + /* Cleanup */ + while(counter--) { + ink_pop(ctx); + } + + /* Put value in place */ + ink_push(ctx, a); } static void index_array(struct context* ctx) { - struct ink_routine *currentRoutine; - struct elem a; - struct ink_array *ary; - struct elem idx; + struct ink_routine *currentRoutine; + struct elem a; + struct ink_array *ary; + struct elem idx; #ifndef NOEXTRACHECKS int tid; - tid = get_type_by_name(ctx, "array"); + tid = get_type_by_name(ctx, "array"); #endif - currentRoutine = ctx->routines + ctx->routine_current; + 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; - } + 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); + a = currentRoutine->stack[currentRoutine->top - 1]; + ary = ink_get_value(ctx, a); #ifndef NOEXTRACHECKS - if (ary == NULL) { - currentRoutine->panic = -1; - return; - } + if (ary == NULL) { + currentRoutine->panic = -1; + return; + } #endif - ink_pop(ctx); - - idx = currentRoutine->stack[currentRoutine->top - 1]; - ink_pop(ctx); + ink_pop(ctx); + + idx = currentRoutine->stack[currentRoutine->top - 1]; + ink_pop(ctx); #ifndef NOEXTRACHECKS - if(ary->top <= idx.value) { - currentRoutine->panic = -1; - return; - } + if(ary->top <= idx.value) { + currentRoutine->panic = -1; + return; + } #endif - - ink_push(ctx, ary->elements[idx.value]); + + ink_push(ctx, ary->elements[idx.value]); } static void set_array(struct context* ctx) { - struct ink_routine *currentRoutine; - struct elem a; - struct ink_array *ary; - struct elem idx; - struct elem value; + 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"); + tid = get_type_by_name(ctx, "array"); #endif - - currentRoutine = ctx->routines + ctx->routine_current; + + 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; - } + 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); + a = currentRoutine->stack[currentRoutine->top - 1]; + ary = ink_get_value(ctx, a); #ifndef NOEXTRACHECKS - if (ary == NULL) { - currentRoutine->panic = -1; - return; - } + if (ary == NULL) { + currentRoutine->panic = -1; + return; + } #endif - - idx = currentRoutine->stack[currentRoutine->top - 2]; - value = currentRoutine->stack[currentRoutine->top - 3]; + + idx = currentRoutine->stack[currentRoutine->top - 2]; + value = currentRoutine->stack[currentRoutine->top - 3]; #ifndef NOEXTRACHECKS - if(ary->top <= idx.value) { - currentRoutine->panic = -1; - return; - } + if(ary->top <= idx.value) { + currentRoutine->panic = -1; + return; + } #endif - ink_pop(ctx); - ink_pop(ctx); - ink_pop(ctx); - - ary->elements[idx.value] = value; - + ink_pop(ctx); + ink_pop(ctx); + ink_pop(ctx); + + ary->elements[idx.value] = value; + } static void get_size_array(struct context* ctx) { - struct ink_routine *currentRoutine; - struct elem a; - struct ink_array *ary; - struct elem sz; + struct ink_routine *currentRoutine; + struct elem a; + struct ink_array *ary; + struct elem sz; #ifndef NOEXTRACHECKS int tid; - tid = get_type_by_name(ctx, "array"); + tid = get_type_by_name(ctx, "array"); #endif - currentRoutine = ctx->routines + ctx->routine_current; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) { - currentRoutine->panic = -1; - return; - } + 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); + a = currentRoutine->stack[currentRoutine->top - 1]; + ary = ink_get_value(ctx, a); #ifndef NOEXTRACHECKS - if (ary == NULL) { - currentRoutine->panic = -1; - return; - } + if (ary == NULL) { + currentRoutine->panic = -1; + return; + } #endif - ink_pop(ctx); - - sz.type = INK_INTEGER; - sz.value = ary->top; - - ink_push(ctx, sz); + ink_pop(ctx); + + sz.type = INK_INTEGER; + sz.value = ary->top; + + ink_push(ctx, sz); } static void is_array(struct context* ctx) { - int tid; - struct ink_routine *currentRoutine; - struct elem a; - - tid = get_type_by_name(ctx, "array"); - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if (currentRoutine->top < 1) { - currentRoutine->panic = -1; - return; - } + int tid; + struct ink_routine *currentRoutine; + struct elem a; + + 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); - - ink_push(ctx, a); + a.type = INK_INTEGER; + a.value = currentRoutine->stack[currentRoutine->top - 1].type == tid; + ink_pop(ctx); + + ink_push(ctx, a); } static void is_int(struct context* ctx) { - struct ink_routine *currentRoutine; - struct elem a; - - currentRoutine = ctx->routines + ctx->routine_current; -#ifndef NOEXTRACHECKS - if (currentRoutine->top < 1) { - currentRoutine->panic = -1; - return; - } + struct ink_routine *currentRoutine; + 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); - - ink_push(ctx, a); + a.type = INK_INTEGER; + a.value = currentRoutine->stack[currentRoutine->top - 1].type == INK_INTEGER; + ink_pop(ctx); + + ink_push(ctx, a); } static void print_array_of_codepoints(struct context* ctx) { - int i; - struct ink_routine *currentRoutine; - struct elem a; - struct ink_array *ary; + int i; + struct ink_routine *currentRoutine; + struct elem a; + struct ink_array *ary; #ifndef NOEXTRACHECKS int tid; - tid = get_type_by_name(ctx, "array"); + tid = get_type_by_name(ctx, "array"); #endif - currentRoutine = ctx->routines + ctx->routine_current; + currentRoutine = ctx->routines + ctx->routine_current; #ifndef NOEXTRACHECKS - if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) { - currentRoutine->panic = -1; - return; - } + 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); + 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; - } - } + 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]); - print_as_utf8(ctx); - } + ink_pop(ctx); + for(i = 0; i < ary->top; ++i) { + ink_push(ctx, ary->elements[i]); + print_as_utf8(ctx); + } } static void arrayify_stack(struct context* ctx) { - struct ink_routine* currentRoutine; - struct elem array_ref; - struct ink_array* ary; - int idx; - currentRoutine = ctx->routines + ctx->routine_current; - new_array(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]); - } - while (currentRoutine->top > 0) { - ink_pop(ctx); - } - ink_push(ctx, array_ref); - return; + struct ink_routine* currentRoutine; + struct elem array_ref; + struct ink_array* ary; + int idx; + currentRoutine = ctx->routines + ctx->routine_current; + new_array(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]); + } + while (currentRoutine->top > 0) { + ink_pop(ctx); + } + ink_push(ctx, array_ref); + return; } #endif /* NOARRAYLIB */ int ink_std_library(struct context* ctx) { - int v; - v = 0; - v += ink_add_native(ctx, "sys.trace", print_stacktrace); - v += ink_add_native(ctx, "sys.gc", run_gc); - v += ink_add_native(ctx, "print_int", print_int); - v += ink_add_native(ctx, "print_utf8", print_as_utf8); - v += ink_add_native(ctx, "+", add_int); - v += ink_add_native(ctx, "-", sub_int); - v += ink_add_native(ctx, "*", mult_int); - v += ink_add_native(ctx, "/", div_int); - v += ink_add_native(ctx, "==", is_equal); - v += ink_add_native(ctx, "!=", is_different); - v += ink_add_native(ctx, "<", lt_int); - v += ink_add_native(ctx, "swap", swap_elem); - v += ink_add_native(ctx, "dup", dupe_elem); - v += ink_add_native(ctx, "drop", drop_elem); - v += ink_add_native(ctx, "stack.clear", clear_stack); - v += ink_add_native(ctx, "stack.dump", dump_stack); - v += ink_add_native(ctx, "pluck", pluck_elem); - v += ink_add_native(ctx, "return_if", return_if); - v += ink_add_native(ctx, "jump_if", jump_if); - v += ink_add_native(ctx, "is.int", is_int); + int v; + v = 0; + v += ink_add_native(ctx, "sys.trace", print_stacktrace); + v += ink_add_native(ctx, "sys.gc", run_gc); + v += ink_add_native(ctx, "print_int", print_int); + v += ink_add_native(ctx, "print_utf8", print_as_utf8); + v += ink_add_native(ctx, "+", add_int); + v += ink_add_native(ctx, "-", sub_int); + v += ink_add_native(ctx, "*", mult_int); + v += ink_add_native(ctx, "/", div_int); + v += ink_add_native(ctx, "==", is_equal); + v += ink_add_native(ctx, "!=", is_different); + v += ink_add_native(ctx, "<", lt_int); + v += ink_add_native(ctx, "swap", swap_elem); + v += ink_add_native(ctx, "dup", dupe_elem); + v += ink_add_native(ctx, "drop", drop_elem); + v += ink_add_native(ctx, "stack.clear", clear_stack); + v += ink_add_native(ctx, "stack.dump", dump_stack); + v += ink_add_native(ctx, "pluck", pluck_elem); + v += ink_add_native(ctx, "return_if", return_if); + v += ink_add_native(ctx, "jump_if", jump_if); + v += ink_add_native(ctx, "is.int", is_int); #ifndef NOEXTRAARITHMETIC - v += ink_add_native(ctx, ">", gt_int); - v += ink_add_native(ctx, ">=", gte_int); - v += ink_add_native(ctx, "=<", lte_int); - v += ink_add_native(ctx, "%", rem_int); - v += ink_add_native(ctx, "int.xor", xor_int); + v += ink_add_native(ctx, ">", gt_int); + v += ink_add_native(ctx, ">=", gte_int); + v += ink_add_native(ctx, "=<", lte_int); + v += ink_add_native(ctx, "%", rem_int); + v += ink_add_native(ctx, "int.xor", xor_int); #endif /* NOEXTRAARITHMETIC */ #ifndef NOARRAYLIB - ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array); - ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop); - v += ink_add_native(ctx, "[", push_array_stack_delim); - v += ink_add_native(ctx, "]", push_delimited_array); - v += ink_add_native(ctx, "array.new", new_array); - v += ink_add_native(ctx, "array.push", push_array); - v += ink_add_native(ctx, "array.index", index_array); - v += ink_add_native(ctx, "array.set", set_array); - v += ink_add_native(ctx, "array.size", get_size_array); - v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints); - v += ink_add_native(ctx, "is.array", is_array); - v += ink_add_native(ctx, "stack.to_array", arrayify_stack); + ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array); + ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop); + v += ink_add_native(ctx, "[", push_array_stack_delim); + v += ink_add_native(ctx, "]", push_delimited_array); + v += ink_add_native(ctx, "array.new", new_array); + v += ink_add_native(ctx, "array.push", push_array); + v += ink_add_native(ctx, "array.index", index_array); + v += ink_add_native(ctx, "array.set", set_array); + v += ink_add_native(ctx, "array.size", get_size_array); + v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints); + v += ink_add_native(ctx, "is.array", is_array); + v += ink_add_native(ctx, "stack.to_array", arrayify_stack); #endif /* NOARRAYLIB */ - - return v; + + return v; } diff --git a/main.c b/main.c index 3bc700d..a11d14f 100644 --- a/main.c +++ b/main.c @@ -29,14 +29,46 @@ 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; + int c; begin = clock(); clock_gettime(CLOCK_MONOTONIC, &start_time); while(ink_can_run(ctx)) { - ink_step_everyone(ctx); + for(c = 0; c < 64; ++c) + ink_step_everyone(ctx); + + + if(ctx->steps < counter) { + ink_gc(ctx); + counter += increment; + } } clock_gettime(CLOCK_MONOTONIC, &end_time); - ink_gc(ctx); end = clock(); time_spent = ctx->steps/(double)((end - begin) / CLOCKS_PER_SEC); s_total += (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) / 1.0e9;