|
@ -1,11 +1,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include "ink.h" |
|
|
#ifndef NOSTDLIB |
|
|
#ifndef NOSTDLIB |
|
|
#include <stdio.h> |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <string.h> |
|
|
#include <ctype.h> |
|
|
#include <ctype.h> |
|
|
#endif |
|
|
#endif |
|
|
#include "ink.h" |
|
|
|
|
|
|
|
|
|
|
|
#define INK_RESERVED (-1) |
|
|
#define INK_RESERVED (-1) |
|
|
#define INK_FUNCTION_KW (-2) |
|
|
#define INK_FUNCTION_KW (-2) |
|
@ -98,7 +97,7 @@ static int atoi(const char* c) { |
|
|
|
|
|
|
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
void ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) { |
|
|
|
|
|
|
|
|
int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) { |
|
|
if(ctx->native_words == NULL) { |
|
|
if(ctx->native_words == NULL) { |
|
|
ctx->native_words = ctx->malloc(sizeof(struct native_fn) * 8); |
|
|
ctx->native_words = ctx->malloc(sizeof(struct native_fn) * 8); |
|
|
ctx->native_words_top = 0; |
|
|
ctx->native_words_top = 0; |
|
@ -107,7 +106,7 @@ void ink_add_native(struct context* ctx, const char* name, void(*value)(struct c |
|
|
int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2); |
|
|
int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2); |
|
|
void* renewed = ctx->realloc(ctx->native_words, sizeof(struct native_fn) * new_count); |
|
|
void* renewed = ctx->realloc(ctx->native_words, sizeof(struct native_fn) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -3; |
|
|
} else { |
|
|
} else { |
|
|
ctx->native_words = renewed; |
|
|
ctx->native_words = renewed; |
|
|
ctx->native_words_capacity = new_count; |
|
|
ctx->native_words_capacity = new_count; |
|
@ -116,13 +115,14 @@ void ink_add_native(struct context* ctx, const char* name, void(*value)(struct c |
|
|
int len = strlen(name); |
|
|
int len = strlen(name); |
|
|
char* copy = ctx->malloc(len+1); |
|
|
char* copy = ctx->malloc(len+1); |
|
|
if(copy == NULL) { |
|
|
if(copy == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -4; |
|
|
} |
|
|
} |
|
|
memcpy(copy, name, len); |
|
|
memcpy(copy, name, len); |
|
|
copy[len] = 0; |
|
|
copy[len] = 0; |
|
|
ctx->native_words[ctx->native_words_top].value = value; |
|
|
ctx->native_words[ctx->native_words_top].value = value; |
|
|
ctx->native_words[ctx->native_words_top].name = copy; |
|
|
ctx->native_words[ctx->native_words_top].name = copy; |
|
|
ctx->native_words_top++; |
|
|
ctx->native_words_top++; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) { |
|
|
static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) { |
|
@ -134,7 +134,7 @@ static int ink_add_indigenous(struct context* ctx, const char* name, struct elem |
|
|
int new_count = (ctx->words_capacity + ctx->words_capacity/2); |
|
|
int new_count = (ctx->words_capacity + ctx->words_capacity/2); |
|
|
void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count); |
|
|
void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -1; |
|
|
} else { |
|
|
} else { |
|
|
ctx->words = renewed; |
|
|
ctx->words = renewed; |
|
|
ctx->words_capacity = new_count; |
|
|
ctx->words_capacity = new_count; |
|
@ -153,7 +153,7 @@ static int ink_add_indigenous(struct context* ctx, const char* name, struct elem |
|
|
int len = strlen(name); |
|
|
int len = strlen(name); |
|
|
char* copy = ctx->malloc(len+1); |
|
|
char* copy = ctx->malloc(len+1); |
|
|
if(copy == NULL) { |
|
|
if(copy == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -2; |
|
|
} |
|
|
} |
|
|
memcpy(copy, name, len); |
|
|
memcpy(copy, name, len); |
|
|
copy[len] = 0; |
|
|
copy[len] = 0; |
|
@ -174,7 +174,7 @@ static int ink_add_lex_string(struct context* ctx, const char* name) { |
|
|
int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2); |
|
|
int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2); |
|
|
void* renewed = ctx->realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count); |
|
|
void* renewed = ctx->realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -5; |
|
|
} else { |
|
|
} else { |
|
|
ctx->lex_reserved_words = renewed; |
|
|
ctx->lex_reserved_words = renewed; |
|
|
ctx->lex_reserved_words_capacity = new_count; |
|
|
ctx->lex_reserved_words_capacity = new_count; |
|
@ -194,7 +194,7 @@ static int ink_add_lex_string(struct context* ctx, const char* name) { |
|
|
return i; |
|
|
return i; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ink_push(struct context* ctx, struct elem value) { |
|
|
|
|
|
|
|
|
int ink_push(struct context* ctx, struct elem value) { |
|
|
if(ctx->stack == NULL) { |
|
|
if(ctx->stack == NULL) { |
|
|
ctx->stack = ctx->malloc(sizeof(struct elem) * 8); |
|
|
ctx->stack = ctx->malloc(sizeof(struct elem) * 8); |
|
|
ctx->top = 0; |
|
|
ctx->top = 0; |
|
@ -203,7 +203,7 @@ void ink_push(struct context* ctx, struct elem value) { |
|
|
int new_count = (ctx->capacity + ctx->capacity/2); |
|
|
int new_count = (ctx->capacity + ctx->capacity/2); |
|
|
void* renewed = ctx->realloc(ctx->stack, sizeof(struct elem) * new_count); |
|
|
void* renewed = ctx->realloc(ctx->stack, sizeof(struct elem) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -18; |
|
|
} else { |
|
|
} else { |
|
|
ctx->stack = renewed; |
|
|
ctx->stack = renewed; |
|
|
ctx->capacity = new_count; |
|
|
ctx->capacity = new_count; |
|
@ -211,9 +211,10 @@ void ink_push(struct context* ctx, struct elem value) { |
|
|
} |
|
|
} |
|
|
ctx->stack[ctx->top] = value; |
|
|
ctx->stack[ctx->top] = value; |
|
|
ctx->top++; |
|
|
ctx->top++; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ink_push_fn(struct context* ctx, struct stack_frame value) { |
|
|
|
|
|
|
|
|
int ink_push_fn(struct context* ctx, struct stack_frame value) { |
|
|
if(ctx->function_stack == NULL) { |
|
|
if(ctx->function_stack == NULL) { |
|
|
ctx->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8); |
|
|
ctx->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8); |
|
|
ctx->function_stack_top = 0; |
|
|
ctx->function_stack_top = 0; |
|
@ -222,7 +223,7 @@ void ink_push_fn(struct context* ctx, struct stack_frame value) { |
|
|
int new_count = (ctx->function_stack_capacity + ctx->function_stack_capacity/2); |
|
|
int new_count = (ctx->function_stack_capacity + ctx->function_stack_capacity/2); |
|
|
void* renewed = ctx->realloc(ctx->function_stack, sizeof(struct stack_frame) * new_count); |
|
|
void* renewed = ctx->realloc(ctx->function_stack, sizeof(struct stack_frame) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -9; |
|
|
} else { |
|
|
} else { |
|
|
ctx->function_stack = renewed; |
|
|
ctx->function_stack = renewed; |
|
|
ctx->function_stack_capacity = new_count; |
|
|
ctx->function_stack_capacity = new_count; |
|
@ -230,6 +231,7 @@ void ink_push_fn(struct context* ctx, struct stack_frame value) { |
|
|
} |
|
|
} |
|
|
ctx->function_stack[ctx->function_stack_top] = value; |
|
|
ctx->function_stack[ctx->function_stack_top] = value; |
|
|
ctx->function_stack_top++; |
|
|
ctx->function_stack_top++; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void ink_pop_fn(struct context* ctx) { |
|
|
static void ink_pop_fn(struct context* ctx) { |
|
@ -296,48 +298,51 @@ struct context* ink_make_default_context() { |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
static void ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) { |
|
|
|
|
|
|
|
|
static int ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) { |
|
|
int i; |
|
|
int i; |
|
|
if(*end == 0) { |
|
|
if(*end == 0) { |
|
|
return; |
|
|
|
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
r[*end] = 0; |
|
|
r[*end] = 0; |
|
|
int done = 0; |
|
|
int done = 0; |
|
|
|
|
|
struct elem value; |
|
|
if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) { |
|
|
if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = 0; |
|
|
value.value = 0; |
|
|
value.type = INK_FUNCTION_KW; |
|
|
value.type = INK_FUNCTION_KW; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
done = 1; |
|
|
done = 1; |
|
|
} |
|
|
} |
|
|
if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) { |
|
|
if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = 0; |
|
|
value.value = 0; |
|
|
value.type = INK_DO_KW; |
|
|
value.type = INK_DO_KW; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
done = 1; |
|
|
done = 1; |
|
|
} |
|
|
} |
|
|
if (!done && strcmp(r, _KEYWORD_INK_END) == 0) { |
|
|
if (!done && strcmp(r, _KEYWORD_INK_END) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = 0; |
|
|
value.value = 0; |
|
|
value.type = INK_END_KW; |
|
|
value.type = INK_END_KW; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
done = 1; |
|
|
done = 1; |
|
|
} |
|
|
} |
|
|
if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) { |
|
|
if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = 0; |
|
|
value.value = 0; |
|
|
value.type = INK_RETURN; |
|
|
value.type = INK_RETURN; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
done = 1; |
|
|
done = 1; |
|
|
} |
|
|
} |
|
|
|
|
|
if(done) { |
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(pContext, value); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
return -19; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
if (!done) { |
|
|
if (!done) { |
|
|
for (i = 0; i < pContext->words_top; ++i) { |
|
|
for (i = 0; i < pContext->words_top; ++i) { |
|
|
if (strcmp(r, pContext->words[i].name) == 0) { |
|
|
if (strcmp(r, pContext->words[i].name) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = i; |
|
|
value.value = i; |
|
|
value.type = INK_FUNCTION; |
|
|
value.type = INK_FUNCTION; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(pContext, value); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
return -20; |
|
|
|
|
|
} |
|
|
done = 1; |
|
|
done = 1; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -346,10 +351,13 @@ static void ink_consume_one(int* end, struct context* pContext, char** buffer, c |
|
|
if (!done) { |
|
|
if (!done) { |
|
|
for (i = 0; i < pContext->native_words_top; ++i) { |
|
|
for (i = 0; i < pContext->native_words_top; ++i) { |
|
|
if (strcmp(r, pContext->native_words[i].name) == 0) { |
|
|
if (strcmp(r, pContext->native_words[i].name) == 0) { |
|
|
struct elem value; |
|
|
|
|
|
value.value = i; |
|
|
value.value = i; |
|
|
value.type = INK_NATIVE_FUNCTION; |
|
|
value.type = INK_NATIVE_FUNCTION; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(pContext, value); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
return -21; |
|
|
|
|
|
} |
|
|
done = 1; |
|
|
done = 1; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -361,41 +369,63 @@ static void ink_consume_one(int* end, struct context* pContext, char** buffer, c |
|
|
goto not_an_int; |
|
|
goto not_an_int; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
struct elem value; |
|
|
|
|
|
value.value = atoi(r); |
|
|
value.value = atoi(r); |
|
|
value.type = INK_INTEGER; |
|
|
value.type = INK_INTEGER; |
|
|
ink_push(pContext, value); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(pContext, value); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
return -22; |
|
|
|
|
|
} |
|
|
done = 1; |
|
|
done = 1; |
|
|
} |
|
|
} |
|
|
not_an_int: if (!done) { |
|
|
|
|
|
|
|
|
not_an_int: |
|
|
|
|
|
if (!done) { |
|
|
i = ink_add_lex_string(pContext, r); |
|
|
i = ink_add_lex_string(pContext, r); |
|
|
struct elem value; |
|
|
|
|
|
|
|
|
if(i < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -7; |
|
|
|
|
|
} |
|
|
value.value = i; |
|
|
value.value = i; |
|
|
if(r[strlen(r) - 1] == ':') { |
|
|
if(r[strlen(r) - 1] == ':') { |
|
|
value.type = INK_LABEL; |
|
|
value.type = INK_LABEL; |
|
|
} else { |
|
|
} else { |
|
|
value.type = INK_RESERVED; |
|
|
value.type = INK_RESERVED; |
|
|
} |
|
|
} |
|
|
ink_push(pContext, value); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(pContext, value); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
return -23; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
*end = 0; |
|
|
*end = 0; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void ink_lex(struct context *pContext, char* buffer) { |
|
|
|
|
|
|
|
|
static int ink_lex(struct context *pContext, char* buffer) { |
|
|
int i; |
|
|
int i; |
|
|
char r[128]; |
|
|
char r[128]; |
|
|
int end = 0; |
|
|
int end = 0; |
|
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
while(*buffer != 0) { |
|
|
while(*buffer != 0) { |
|
|
if(isspace(*buffer)) { |
|
|
if(isspace(*buffer)) { |
|
|
ink_consume_one(&end, pContext, &buffer, r); |
|
|
|
|
|
|
|
|
err = ink_consume_one(&end, pContext, &buffer, r); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -8; |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
r[end] = *buffer; |
|
|
r[end] = *buffer; |
|
|
++end; |
|
|
++end; |
|
|
} |
|
|
} |
|
|
++buffer; |
|
|
++buffer; |
|
|
} |
|
|
} |
|
|
ink_consume_one(&end, pContext, &buffer, r); |
|
|
|
|
|
|
|
|
err = ink_consume_one(&end, pContext, &buffer, r); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -9; |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int lblcmp(const char* label, const char* other, size_t label_sz) { |
|
|
static int lblcmp(const char* label, const char* other, size_t label_sz) { |
|
@ -416,7 +446,7 @@ static int lblcmp(const char* label, const char* other, size_t label_sz) { |
|
|
* @param executable_buffer_top |
|
|
* @param executable_buffer_top |
|
|
* @internal Loop from hell |
|
|
* @internal Loop from hell |
|
|
*/ |
|
|
*/ |
|
|
static void 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) { |
|
|
int i; |
|
|
int i; |
|
|
#define LABEL_BUFFER 128 |
|
|
#define LABEL_BUFFER 128 |
|
|
#define FUNCTION_BUFFER 256 |
|
|
#define FUNCTION_BUFFER 256 |
|
@ -430,16 +460,18 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
int mode = 0; |
|
|
int mode = 0; |
|
|
memset(labels, 0, sizeof(struct label)*LABEL_BUFFER); |
|
|
memset(labels, 0, sizeof(struct label)*LABEL_BUFFER); |
|
|
for(i = 0; i < pContext->top; ++i) { |
|
|
for(i = 0; i < pContext->top; ++i) { |
|
|
struct elem current = pContext->stack[i]; |
|
|
|
|
|
|
|
|
struct elem current; |
|
|
|
|
|
current = pContext->stack[i]; |
|
|
switch (mode) { |
|
|
switch (mode) { |
|
|
case MODE_EXECUTABLE: |
|
|
case MODE_EXECUTABLE: |
|
|
switch(current.type) { |
|
|
switch(current.type) { |
|
|
case INK_FUNCTION_KW: |
|
|
case INK_FUNCTION_KW: |
|
|
mode = MODE_FUNCTION; |
|
|
mode = MODE_FUNCTION; |
|
|
|
|
|
function_name = -1; |
|
|
goto next_token; |
|
|
goto next_token; |
|
|
case INK_DO_KW: |
|
|
case INK_DO_KW: |
|
|
case INK_END_KW: |
|
|
case INK_END_KW: |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -26; |
|
|
default: |
|
|
default: |
|
|
executable_buffer[*executable_buffer_top] = current; |
|
|
executable_buffer[*executable_buffer_top] = current; |
|
|
*executable_buffer_top += 1; |
|
|
*executable_buffer_top += 1; |
|
@ -448,7 +480,7 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
case MODE_FUNCTION: |
|
|
case MODE_FUNCTION: |
|
|
if(current.type == INK_DO_KW) { |
|
|
if(current.type == INK_DO_KW) { |
|
|
if(function_name == -1) { |
|
|
if(function_name == -1) { |
|
|
o">// TODO: error (function name was not supplied) |
|
|
|
|
|
|
|
|
k">return -27; |
|
|
} else { |
|
|
} else { |
|
|
mode = MODE_DO; |
|
|
mode = MODE_DO; |
|
|
memset(labels, 0, sizeof(struct label)*128); |
|
|
memset(labels, 0, sizeof(struct label)*128); |
|
@ -456,10 +488,10 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if(function_name != -1) { |
|
|
if(function_name != -1) { |
|
|
o">// TODO: error (function name supplied already) |
|
|
|
|
|
|
|
|
k">return -28; |
|
|
} |
|
|
} |
|
|
if(current.type != INK_RESERVED) { |
|
|
if(current.type != INK_RESERVED) { |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -29; |
|
|
} |
|
|
} |
|
|
function_name = current.value; |
|
|
function_name = current.value; |
|
|
break; |
|
|
break; |
|
@ -467,14 +499,15 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
if(current.type == INK_END_KW) { |
|
|
if(current.type == INK_END_KW) { |
|
|
int j; |
|
|
int j; |
|
|
for(j = 0; j < function_buffer_top; j++) { |
|
|
for(j = 0; j < function_buffer_top; j++) { |
|
|
struct elem pt = function_buffer[j]; |
|
|
|
|
|
|
|
|
struct elem pt; |
|
|
|
|
|
pt = function_buffer[j]; |
|
|
if(pt.type == INK_LABEL) { |
|
|
if(pt.type == INK_LABEL) { |
|
|
int k; |
|
|
int k; |
|
|
for(k = 0; k < LABEL_BUFFER; k++) { |
|
|
for(k = 0; k < LABEL_BUFFER; k++) { |
|
|
if(labels[k].active) { |
|
|
if(labels[k].active) { |
|
|
if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) { |
|
|
if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) { |
|
|
labels[k].dest = j; |
|
|
labels[k].dest = j; |
|
|
o">// TODO: error |
|
|
|
|
|
|
|
|
k">return -30; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
@ -490,7 +523,8 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
for(j = 0; j < function_buffer_top; j++) { |
|
|
for(j = 0; j < function_buffer_top; j++) { |
|
|
struct elem pt = function_buffer[j]; |
|
|
|
|
|
|
|
|
struct elem pt; |
|
|
|
|
|
pt = function_buffer[j]; |
|
|
if(pt.type == INK_RESERVED) { |
|
|
if(pt.type == INK_RESERVED) { |
|
|
const char* str = pContext->lex_reserved_words[pt.value]; |
|
|
const char* str = pContext->lex_reserved_words[pt.value]; |
|
|
int k; |
|
|
int k; |
|
@ -507,7 +541,12 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -33; |
|
|
|
|
|
} |
|
|
function_buffer_top = 0; |
|
|
function_buffer_top = 0; |
|
|
mode = MODE_EXECUTABLE; |
|
|
mode = MODE_EXECUTABLE; |
|
|
goto next_token; |
|
|
goto next_token; |
|
@ -519,8 +558,9 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer, |
|
|
next_token: i=i; |
|
|
next_token: i=i; |
|
|
} |
|
|
} |
|
|
if(mode == MODE_FUNCTION || mode == MODE_DO) { |
|
|
if(mode == MODE_FUNCTION || mode == MODE_DO) { |
|
|
o">// error, missing an end |
|
|
|
|
|
|
|
|
k">return -32; |
|
|
} |
|
|
} |
|
|
|
|
|
return 0; |
|
|
#undef MODE_EXECUTABLE |
|
|
#undef MODE_EXECUTABLE |
|
|
#undef MODE_FUNCTION |
|
|
#undef MODE_FUNCTION |
|
|
#undef MODE_DO |
|
|
#undef MODE_DO |
|
@ -534,8 +574,13 @@ int ink_step(struct context *pContext) { |
|
|
if(pContext->panic) { |
|
|
if(pContext->panic) { |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
struct stack_frame* top = &pContext->function_stack[pContext->function_stack_top-1]; |
|
|
|
|
|
switch(top->executing.type) { |
|
|
|
|
|
|
|
|
struct stack_frame frame; |
|
|
|
|
|
struct stack_frame* top; |
|
|
|
|
|
struct elem next; |
|
|
|
|
|
int t; |
|
|
|
|
|
top = &pContext->function_stack[pContext->function_stack_top-1]; |
|
|
|
|
|
t = top->executing.type; |
|
|
|
|
|
switch(t) { |
|
|
case INK_NATIVE_FUNCTION: |
|
|
case INK_NATIVE_FUNCTION: |
|
|
if(top->index != 0) { |
|
|
if(top->index != 0) { |
|
|
ink_pop_fn(pContext); |
|
|
ink_pop_fn(pContext); |
|
@ -556,20 +601,27 @@ int ink_step(struct context *pContext) { |
|
|
if(top->index >= pContext->words[top->executing.value].size) { |
|
|
if(top->index >= pContext->words[top->executing.value].size) { |
|
|
ink_pop_fn(pContext); |
|
|
ink_pop_fn(pContext); |
|
|
} else { |
|
|
} else { |
|
|
k">struct elem next = pContext->words[top->executing.value].things[top->index]; |
|
|
|
|
|
|
|
|
next = pContext->words[top->executing.value].things[top->index]; |
|
|
if(next.type == INK_RETURN) { |
|
|
if(next.type == INK_RETURN) { |
|
|
ink_pop_fn(pContext); |
|
|
ink_pop_fn(pContext); |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
struct stack_frame frame; |
|
|
|
|
|
frame.executing = next; |
|
|
frame.executing = next; |
|
|
frame.index = 0; |
|
|
frame.index = 0; |
|
|
ink_push_fn(pContext, frame); |
|
|
|
|
|
|
|
|
t = ink_push_fn(pContext, frame); |
|
|
|
|
|
if(t < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -11; |
|
|
|
|
|
} |
|
|
top->index++; |
|
|
top->index++; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
default: |
|
|
default: |
|
|
ink_push(pContext, top->executing); |
|
|
|
|
|
|
|
|
t = ink_push(pContext, top->executing); |
|
|
|
|
|
if(t < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return -25; |
|
|
|
|
|
} |
|
|
ink_pop_fn(pContext); |
|
|
ink_pop_fn(pContext); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -581,16 +633,33 @@ void ink_run(struct context *pContext, char* buffer) { |
|
|
pContext->stack = NULL; |
|
|
pContext->stack = NULL; |
|
|
pContext->top = 0; |
|
|
pContext->top = 0; |
|
|
pContext->capacity = 0; |
|
|
pContext->capacity = 0; |
|
|
ink_lex(pContext, buffer); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_lex(pContext, buffer); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
int i = 0; |
|
|
int i = 0; |
|
|
struct elem executable_buffer[256]; |
|
|
struct elem executable_buffer[256]; |
|
|
int executable_buffer_top = 0; |
|
|
int executable_buffer_top = 0; |
|
|
ink_parse(pContext, executable_buffer, &executable_buffer_top); |
|
|
|
|
|
|
|
|
err = ink_parse(pContext, executable_buffer, &executable_buffer_top); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
struct stack_frame frame; |
|
|
struct stack_frame frame; |
|
|
frame.executing.value = ink_add_indigenous(pContext, "__-MAIN-__", executable_buffer, executable_buffer_top); |
|
|
frame.executing.value = ink_add_indigenous(pContext, "__-MAIN-__", executable_buffer, executable_buffer_top); |
|
|
|
|
|
if(frame.executing.value < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
frame.executing.type = INK_FUNCTION; |
|
|
frame.executing.type = INK_FUNCTION; |
|
|
frame.index = 0; |
|
|
frame.index = 0; |
|
|
ink_push_fn(pContext, frame); |
|
|
|
|
|
|
|
|
err = ink_push_fn(pContext, frame); |
|
|
|
|
|
if(err < 0) { |
|
|
|
|
|
pContext->panic = 1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int out; |
|
|
int out; |
|
|
do { |
|
|
do { |
|
@ -603,7 +672,8 @@ void ink_run(struct context *pContext, char* buffer) { |
|
|
static void print_stacktrace(struct context* _) { |
|
|
static void print_stacktrace(struct context* _) { |
|
|
int i = 0; |
|
|
int i = 0; |
|
|
for(; i < _->function_stack_top; ++i) { |
|
|
for(; i < _->function_stack_top; ++i) { |
|
|
struct elem thing = _->function_stack[i].executing; |
|
|
|
|
|
|
|
|
struct elem thing; |
|
|
|
|
|
thing = _->function_stack[i].executing; |
|
|
switch(thing.type) { |
|
|
switch(thing.type) { |
|
|
case INK_NATIVE_FUNCTION: { |
|
|
case INK_NATIVE_FUNCTION: { |
|
|
char *n = _->native_words[thing.value].name; |
|
|
char *n = _->native_words[thing.value].name; |
|
@ -641,8 +711,10 @@ static void add_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -656,8 +728,10 @@ static void sub_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -671,8 +745,10 @@ static void mult_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -686,8 +762,10 @@ static void div_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -701,8 +779,10 @@ static void rem_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -716,8 +796,11 @@ static void dupe_elem(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
ink_push(ctx, a); |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(ctx, a); |
|
|
|
|
|
if(err < 0) ctx->panic; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void drop_elem(struct context* ctx) { |
|
|
static void drop_elem(struct context* ctx) { |
|
@ -733,7 +816,8 @@ static void pluck_elem(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
if(a.type != INK_INTEGER) { |
|
|
if(a.type != INK_INTEGER) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -744,7 +828,9 @@ static void pluck_elem(struct context* ctx) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
ink_pop(ctx); |
|
|
ink_pop(ctx); |
|
|
ink_push(ctx, ctx->stack[position]); |
|
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
err = ink_push(ctx, ctx->stack[position]); |
|
|
|
|
|
if(err < 0) ctx->panic; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void swap_elem(struct context* ctx) { |
|
|
static void swap_elem(struct context* ctx) { |
|
@ -752,8 +838,10 @@ static void swap_elem(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
struct elem b = ctx->stack[ctx->top-2]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct elem b; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
b = ctx->stack[ctx->top-2]; |
|
|
ctx->stack[ctx->top-2] = a; |
|
|
ctx->stack[ctx->top-2] = a; |
|
|
ctx->stack[ctx->top-1] = b; |
|
|
ctx->stack[ctx->top-1] = b; |
|
|
} |
|
|
} |
|
@ -763,7 +851,8 @@ static void return_if(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
if(a.type != INK_INTEGER) { |
|
|
if(a.type != INK_INTEGER) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -781,7 +870,8 @@ static void jump_if(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
if(a.type != INK_INTEGER) { |
|
|
if(a.type != INK_INTEGER) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
@ -802,7 +892,8 @@ static void print_int(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
ink_pop(ctx); |
|
|
ink_pop(ctx); |
|
|
char* n = ink_itoa(ctx, a.value); |
|
|
char* n = ink_itoa(ctx, a.value); |
|
|
char* str = n; |
|
|
char* str = n; |
|
@ -818,7 +909,8 @@ static void print_as_utf8(struct context* ctx) { |
|
|
ctx->panic = 1; |
|
|
ctx->panic = 1; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
struct elem a = ctx->stack[ctx->top-1]; |
|
|
|
|
|
|
|
|
struct elem a; |
|
|
|
|
|
a = ctx->stack[ctx->top-1]; |
|
|
if(a.value <= 0x7F) { |
|
|
if(a.value <= 0x7F) { |
|
|
ctx->putchar(a.value); |
|
|
ctx->putchar(a.value); |
|
|
} else if(a.value <= 0x7FF) { |
|
|
} else if(a.value <= 0x7FF) { |
|
@ -840,19 +932,21 @@ static void print_as_utf8(struct context* ctx) { |
|
|
ink_pop(ctx); |
|
|
ink_pop(ctx); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ink_std_library(struct context* ctx) { |
|
|
|
|
|
ink_add_native(ctx, "trace", print_stacktrace); |
|
|
|
|
|
ink_add_native(ctx, "print_int", print_int); |
|
|
|
|
|
ink_add_native(ctx, "print_utf8", print_as_utf8); |
|
|
|
|
|
ink_add_native(ctx, "+", add_int); |
|
|
|
|
|
ink_add_native(ctx, "-", sub_int); |
|
|
|
|
|
ink_add_native(ctx, "*", mult_int); |
|
|
|
|
|
ink_add_native(ctx, "/", div_int); |
|
|
|
|
|
ink_add_native(ctx, "%", rem_int); |
|
|
|
|
|
ink_add_native(ctx, "swap", swap_elem); |
|
|
|
|
|
ink_add_native(ctx, "dup", dupe_elem); |
|
|
|
|
|
ink_add_native(ctx, "drop", drop_elem); |
|
|
|
|
|
ink_add_native(ctx, "pluck", pluck_elem); |
|
|
|
|
|
ink_add_native(ctx, "return_if", return_if); |
|
|
|
|
|
ink_add_native(ctx, "jump_if", jump_if); |
|
|
|
|
|
|
|
|
int ink_std_library(struct context* ctx) { |
|
|
|
|
|
int v; |
|
|
|
|
|
v += ink_add_native(ctx, "trace", print_stacktrace); |
|
|
|
|
|
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, "%", rem_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, "pluck", pluck_elem); |
|
|
|
|
|
v += ink_add_native(ctx, "return_if", return_if); |
|
|
|
|
|
v += ink_add_native(ctx, "jump_if", jump_if); |
|
|
|
|
|
return v; |
|
|
} |
|
|
} |