|
@ -241,54 +241,89 @@ int ink_add_native(struct context* ctx, const char* name, void(*value)(struct co |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int ink_add_indigenous(struct context* ctx, char* name, struct elem* m, size_t count) { |
|
|
static int ink_add_indigenous(struct context* ctx, char* name, struct elem* m, size_t count) { |
|
|
int tid; |
|
|
|
|
|
struct elem e; |
|
|
|
|
|
int i; |
|
|
|
|
|
struct ink_array ary; |
|
|
|
|
|
const char* name_it; |
|
|
|
|
|
struct elem character; |
|
|
|
|
|
tid = get_type_by_name(ctx, "array"); |
|
|
|
|
|
ary.elements = NULL; |
|
|
|
|
|
ary.top = 0; |
|
|
|
|
|
ary.capacity = 0; |
|
|
|
|
|
ary.flags = 0; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
name_it = name; |
|
|
|
|
|
while (utf8_consume(&name_it, &character)) { |
|
|
|
|
|
array_push_s(ctx, &ary, character); |
|
|
|
|
|
} |
|
|
|
|
|
e = ink_make_native(ctx, tid, &ary); |
|
|
|
|
|
for(i = 0; i < ctx->words_top; ++i) { |
|
|
|
|
|
struct ink_array* inner_name = ink_get_value(ctx, ctx->words[i].name); |
|
|
|
|
|
if(ary.top == inner_name->top && memcmp(ary.elements, inner_name->elements, sizeof(struct elem)*ary.top) == 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; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
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 = e; |
|
|
|
|
|
return ctx->words_top++; |
|
|
|
|
|
|
|
|
int tid; |
|
|
|
|
|
struct elem e; |
|
|
|
|
|
int i; |
|
|
|
|
|
struct ink_array ary; |
|
|
|
|
|
const char* name_it; |
|
|
|
|
|
struct elem character; |
|
|
|
|
|
tid = get_type_by_name(ctx, "array"); |
|
|
|
|
|
ary.elements = NULL; |
|
|
|
|
|
ary.top = 0; |
|
|
|
|
|
ary.capacity = 0; |
|
|
|
|
|
ary.flags = 0; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
name_it = name; |
|
|
|
|
|
while (utf8_consume(&name_it, &character)) { |
|
|
|
|
|
array_push_s(ctx, &ary, character); |
|
|
|
|
|
} |
|
|
|
|
|
e = ink_make_native(ctx, tid, &ary); |
|
|
|
|
|
for(i = 0; i < ctx->words_top; ++i) { |
|
|
|
|
|
struct ink_array* inner_name = ink_get_value(ctx, ctx->words[i].name); |
|
|
|
|
|
if(ary.top == inner_name->top && memcmp(ary.elements, inner_name->elements, sizeof(struct elem)*ary.top) == 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; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
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 = e; |
|
|
|
|
|
return ctx->words_top++; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int ink_add_indigenous_already_array(struct context* ctx, struct elem e, struct elem* m, size_t count) { |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
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(e.value == ctx->words[i].name.value) { |
|
|
|
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
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 = e; |
|
|
|
|
|
return ctx->words_top++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -578,11 +613,13 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
for(;it != *end;++it) { |
|
|
for(;it != *end;++it) { |
|
|
struct elem character; |
|
|
|
|
|
|
|
|
const char* iterator; |
|
|
character.type = INK_INTEGER; |
|
|
character.type = INK_INTEGER; |
|
|
/* TODO: codepoint conversion and coalescence is required here */ |
|
|
/* TODO: codepoint conversion and coalescence is required here */ |
|
|
character.value = r[it]; |
|
|
|
|
|
|
|
|
iterator = r + it; |
|
|
|
|
|
utf8_consume(&iterator, &character); |
|
|
array_push(pContext, routine, ary, character); |
|
|
array_push(pContext, routine, ary, character); |
|
|
|
|
|
it += (iterator - (r + it)) - 1; |
|
|
} |
|
|
} |
|
|
*end = 0; |
|
|
*end = 0; |
|
|
return 0; |
|
|
return 0; |
|
@ -888,7 +925,8 @@ int ink_kill_routine(struct context* ctx, int routine){ |
|
|
*/ |
|
|
*/ |
|
|
static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) { |
|
|
static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) { |
|
|
struct ink_routine* currentRoutine; |
|
|
struct ink_routine* currentRoutine; |
|
|
int i, function_buffer_top, function_name, mode; |
|
|
|
|
|
|
|
|
int i, function_buffer_top, mode; |
|
|
|
|
|
struct elem function_name; |
|
|
int func_is_macro = 0; |
|
|
int func_is_macro = 0; |
|
|
#pragma GCC diagnostic push |
|
|
#pragma GCC diagnostic push |
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter" |
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter" |
|
@ -902,7 +940,8 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
/* TODO: add checks for overflows in these arrays */ |
|
|
/* TODO: add checks for overflows in these arrays */ |
|
|
currentRoutine = pContext->routines + pContext->routine_current; |
|
|
currentRoutine = pContext->routines + pContext->routine_current; |
|
|
function_buffer_top = 0; |
|
|
function_buffer_top = 0; |
|
|
function_name = -1; |
|
|
|
|
|
|
|
|
function_name.type = INK_RESERVED; |
|
|
|
|
|
function_name.value = -1; |
|
|
#define MODE_EXECUTABLE 0 |
|
|
#define MODE_EXECUTABLE 0 |
|
|
#define MODE_FUNCTION 1 |
|
|
#define MODE_FUNCTION 1 |
|
|
#define MODE_DO 2 |
|
|
#define MODE_DO 2 |
|
@ -918,13 +957,13 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
switch(current.type) { |
|
|
switch(current.type) { |
|
|
case INK_FUNCTION_KW: |
|
|
case INK_FUNCTION_KW: |
|
|
mode = MODE_FUNCTION; |
|
|
mode = MODE_FUNCTION; |
|
|
function_name = -1; |
|
|
|
|
|
|
|
|
function_name.value = -1; |
|
|
func_is_macro = 0; |
|
|
func_is_macro = 0; |
|
|
goto next_token; |
|
|
goto next_token; |
|
|
case INK_MACRO_KW: |
|
|
case INK_MACRO_KW: |
|
|
mode = MODE_FUNCTION; |
|
|
mode = MODE_FUNCTION; |
|
|
func_is_macro = 1; |
|
|
func_is_macro = 1; |
|
|
function_name = -1; |
|
|
|
|
|
|
|
|
function_name.value = -1; |
|
|
goto next_token; |
|
|
goto next_token; |
|
|
#ifndef NOEXTRACHECKS |
|
|
#ifndef NOEXTRACHECKS |
|
|
case INK_DO_KW: |
|
|
case INK_DO_KW: |
|
@ -946,7 +985,7 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
case MODE_FUNCTION: |
|
|
case MODE_FUNCTION: |
|
|
if(current.type == INK_DO_KW) { |
|
|
if(current.type == INK_DO_KW) { |
|
|
#ifndef NOEXTRACHECKS |
|
|
#ifndef NOEXTRACHECKS |
|
|
if(function_name == -1) { |
|
|
|
|
|
|
|
|
if(function_name.value == -1) { |
|
|
currentRoutine->parse_error.is_set = 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.error_message = "Found start of function body before the name of the function was provided"; |
|
|
currentRoutine->parse_error.offset= i; |
|
|
currentRoutine->parse_error.offset= i; |
|
@ -958,20 +997,20 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
goto next_token; |
|
|
goto next_token; |
|
|
} |
|
|
} |
|
|
#ifndef NOEXTRACHECKS |
|
|
#ifndef NOEXTRACHECKS |
|
|
if(function_name != -1) { |
|
|
|
|
|
|
|
|
if(function_name.value != -1) { |
|
|
currentRoutine->parse_error.is_set = 1; |
|
|
currentRoutine->parse_error.is_set = 1; |
|
|
currentRoutine->parse_error.error_message = "Function name was not found"; |
|
|
currentRoutine->parse_error.error_message = "Function name was not found"; |
|
|
currentRoutine->parse_error.offset= i; |
|
|
currentRoutine->parse_error.offset= i; |
|
|
return -28; |
|
|
return -28; |
|
|
} |
|
|
} |
|
|
if(current.type != INK_RESERVED) { |
|
|
|
|
|
|
|
|
if(current.type != INK_RESERVED && current.type != INK_FUNCTION && current.type != INK_NATIVE_FUNCTION) { |
|
|
currentRoutine->parse_error.is_set = 1; |
|
|
currentRoutine->parse_error.is_set = 1; |
|
|
currentRoutine->parse_error.error_message = "Expected special token"; |
|
|
currentRoutine->parse_error.error_message = "Expected special token"; |
|
|
currentRoutine->parse_error.offset= i; |
|
|
currentRoutine->parse_error.offset= i; |
|
|
return -29; |
|
|
return -29; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
function_name = current.value; |
|
|
|
|
|
|
|
|
function_name = current; |
|
|
break; |
|
|
break; |
|
|
case MODE_DO: |
|
|
case MODE_DO: |
|
|
if(current.type == INK_END_KW) { |
|
|
if(current.type == INK_END_KW) { |
|
@ -1025,7 +1064,15 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top); |
|
|
|
|
|
|
|
|
if(function_name.type == INK_RESERVED) { |
|
|
|
|
|
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name.value], function_buffer, function_buffer_top); |
|
|
|
|
|
} else { |
|
|
|
|
|
if(function_name.type == INK_NATIVE_FUNCTION) { |
|
|
|
|
|
err = ink_add_indigenous_already_array(pContext, pContext->native_words[function_name.value].name,function_buffer, function_buffer_top); |
|
|
|
|
|
} else if(function_name.type == INK_FUNCTION) { |
|
|
|
|
|
err = ink_add_indigenous_already_array(pContext, pContext->words[function_name.value].name,function_buffer, function_buffer_top); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
#ifndef NOEXTRACHECKS |
|
|
#ifndef NOEXTRACHECKS |
|
|
if(err < 0) { |
|
|
if(err < 0) { |
|
|
pContext->panic = 1; |
|
|
pContext->panic = 1; |
|
@ -1064,7 +1111,17 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
pContext->routine_current = parser_routine_index; |
|
|
pContext->routine_current = parser_routine_index; |
|
|
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], macro_cooking_routine->stack, macro_cooking_routine->top); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(function_name.type == INK_RESERVED) { |
|
|
|
|
|
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name.value], function_buffer, function_buffer_top); |
|
|
|
|
|
} else { |
|
|
|
|
|
if(function_name.type == INK_NATIVE_FUNCTION) { |
|
|
|
|
|
err = ink_add_indigenous_already_array(pContext, pContext->native_words[function_name.value].name,function_buffer, function_buffer_top); |
|
|
|
|
|
} else if(function_name.type == INK_FUNCTION) { |
|
|
|
|
|
err = ink_add_indigenous_already_array(pContext, pContext->words[function_name.value].name,function_buffer, function_buffer_top); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
macro_cooking_routine->panic = INK_ROUTINE_SUCCESS; |
|
|
macro_cooking_routine->panic = INK_ROUTINE_SUCCESS; |
|
|
#ifndef NOEXTRACHECKS |
|
|
#ifndef NOEXTRACHECKS |
|
|
if(err < 0) { |
|
|
if(err < 0) { |
|
|