|
@ -514,7 +514,7 @@ int ink_make_routine(struct context* ctx) { |
|
|
int new_count; |
|
|
int new_count; |
|
|
void* renewed; |
|
|
void* renewed; |
|
|
new_count = (ctx->routines_capacity + ctx->routines_capacity/2); |
|
|
new_count = (ctx->routines_capacity + ctx->routines_capacity/2); |
|
|
renewed = ctx->inner_realloc(ctx->routines, sizeof(struct stack_frame) * new_count); |
|
|
|
|
|
|
|
|
renewed = ctx->inner_realloc(ctx->routines, sizeof(struct ink_routine) * new_count); |
|
|
if(renewed == NULL) { |
|
|
if(renewed == NULL) { |
|
|
return -99; |
|
|
return -99; |
|
|
} else { |
|
|
} else { |
|
@ -770,7 +770,7 @@ int ink_step(struct context *pContext) { |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ink_compile(struct context *pContext, char* buffer) { |
|
|
|
|
|
|
|
|
void ink_compile(struct context *pContext, ">const char* buffer) { |
|
|
int routine, saved, executable_buffer_top; |
|
|
int routine, saved, executable_buffer_top; |
|
|
/* Main function has a size limit of 256 (need to know that for REPL */ |
|
|
/* Main function has a size limit of 256 (need to know that for REPL */ |
|
|
struct elem executable_buffer[256]; |
|
|
struct elem executable_buffer[256]; |
|
@ -1012,6 +1012,8 @@ void ink_gc(struct context* ctx) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* TODO: Mark objects contained within function code */ |
|
|
|
|
|
|
|
|
/* Mark the rest of the data */ |
|
|
/* Mark the rest of the data */ |
|
|
do { |
|
|
do { |
|
|
marked = 0; |
|
|
marked = 0; |
|
@ -1171,6 +1173,46 @@ static void div_int(struct context* ctx) { |
|
|
currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value; |
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifndef NOEXTRAARITHMETIC |
|
|
|
|
|
|
|
|
static void rem_int(struct context* ctx) { |
|
|
static void rem_int(struct context* ctx) { |
|
|
struct ink_routine* currentRoutine; |
|
|
struct ink_routine* currentRoutine; |
|
|
struct elem a; |
|
|
struct elem a; |
|
@ -1190,6 +1232,84 @@ static void rem_int(struct context* ctx) { |
|
|
currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value; |
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
a = currentRoutine->stack[currentRoutine->top-1]; |
|
|
|
|
|
b = currentRoutine->stack[currentRoutine->top-2]; |
|
|
|
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
a = currentRoutine->stack[currentRoutine->top-1]; |
|
|
|
|
|
b = currentRoutine->stack[currentRoutine->top-2]; |
|
|
|
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
a = currentRoutine->stack[currentRoutine->top-1]; |
|
|
|
|
|
b = currentRoutine->stack[currentRoutine->top-2]; |
|
|
|
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
if(currentRoutine->top < 2) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
a = currentRoutine->stack[currentRoutine->top-1]; |
|
|
|
|
|
b = currentRoutine->stack[currentRoutine->top-2]; |
|
|
|
|
|
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
ink_pop(ctx); |
|
|
|
|
|
currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void dupe_elem(struct context* ctx) { |
|
|
static void dupe_elem(struct context* ctx) { |
|
|
struct ink_routine* currentRoutine; |
|
|
struct ink_routine* currentRoutine; |
|
|
struct elem a; |
|
|
struct elem a; |
|
@ -1348,12 +1468,6 @@ static void print_as_utf8(struct context* ctx) { |
|
|
ink_pop(ctx); |
|
|
ink_pop(ctx); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct ink_array { |
|
|
|
|
|
int top; |
|
|
|
|
|
int capacity; |
|
|
|
|
|
struct elem* elements; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static int get_type_by_name(struct context* ctx, const char* name) { |
|
|
static int get_type_by_name(struct context* ctx, const char* name) { |
|
|
int i; |
|
|
int i; |
|
|
for(i = 0; i < ctx->types_top; ++i) { |
|
|
for(i = 0; i < ctx->types_top; ++i) { |
|
@ -1364,20 +1478,50 @@ static int get_type_by_name(struct context* ctx, const char* name) { |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void run_gc(struct context* 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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void collect_noop(struct context* _1, void* _2) {} |
|
|
|
|
|
|
|
|
|
|
|
static struct ink_collection_list gc_noop(struct context* _1, void* _2) { |
|
|
|
|
|
struct ink_collection_list c; |
|
|
|
|
|
c.elements = NULL; |
|
|
|
|
|
c.count = 0; |
|
|
|
|
|
return c; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifndef NOARRAYLIB |
|
|
|
|
|
|
|
|
|
|
|
struct ink_array { |
|
|
|
|
|
int top; |
|
|
|
|
|
int capacity; |
|
|
|
|
|
struct elem* elements; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
static void collect_array(struct context* ctx, void* array) { |
|
|
static void collect_array(struct context* ctx, void* array) { |
|
|
struct ink_array* ary; |
|
|
|
|
|
|
|
|
struct ink_array* ary; |
|
|
ary = array; |
|
|
ary = array; |
|
|
if(ary->elements != NULL) ctx->free(ary->elements); |
|
|
|
|
|
|
|
|
if(ary->elements != NULL) ctx->free(ary->elements); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static struct ink_collection_list gc_array(struct context* ctx, void* array) { |
|
|
static struct ink_collection_list gc_array(struct context* ctx, void* array) { |
|
|
struct ink_array* ary; |
|
|
|
|
|
struct ink_collection_list c; |
|
|
|
|
|
|
|
|
struct ink_array* ary; |
|
|
|
|
|
struct ink_collection_list c; |
|
|
ary = array; |
|
|
ary = array; |
|
|
c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top); |
|
|
|
|
|
c.count = ary->top; |
|
|
|
|
|
memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top); |
|
|
|
|
|
return c; |
|
|
|
|
|
|
|
|
c.elements = ctx->inner_malloc(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) { |
|
|
static void new_array(struct context* ctx) { |
|
@ -1527,6 +1671,33 @@ static void index_array(struct context* ctx) { |
|
|
ink_push(ctx, ary->elements[idx.value]); |
|
|
ink_push(ctx, ary->elements[idx.value]); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void get_size_array(struct context* ctx) { |
|
|
|
|
|
int tid; |
|
|
|
|
|
struct ink_routine *currentRoutine; |
|
|
|
|
|
struct elem a; |
|
|
|
|
|
struct ink_array *ary; |
|
|
|
|
|
struct elem sz; |
|
|
|
|
|
|
|
|
|
|
|
tid = get_type_by_name(ctx, "array"); |
|
|
|
|
|
currentRoutine = ctx->routines + ctx->routine_current; |
|
|
|
|
|
if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
a = currentRoutine->stack[currentRoutine->top - 1]; |
|
|
|
|
|
ary = ink_get_value(ctx, a); |
|
|
|
|
|
if (ary == NULL) { |
|
|
|
|
|
currentRoutine->panic = -1; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
ink_pop(ctx); |
|
|
|
|
|
|
|
|
|
|
|
sz.type = INK_INTEGER; |
|
|
|
|
|
sz.value = ary->top; |
|
|
|
|
|
|
|
|
|
|
|
ink_push(ctx, sz); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void print_array_of_codepoints(struct context* ctx) { |
|
|
static void print_array_of_codepoints(struct context* ctx) { |
|
|
int tid, i; |
|
|
int tid, i; |
|
|
struct ink_routine *currentRoutine; |
|
|
struct ink_routine *currentRoutine; |
|
@ -1556,19 +1727,6 @@ static void print_array_of_codepoints(struct context* ctx) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void run_gc(struct context* 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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void arrayify_stack(struct context* ctx) { |
|
|
static void arrayify_stack(struct context* ctx) { |
|
|
struct ink_routine* currentRoutine; |
|
|
struct ink_routine* currentRoutine; |
|
|
struct elem array_ref; |
|
|
struct elem array_ref; |
|
@ -1594,27 +1752,11 @@ static void arrayify_stack(struct context* ctx) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void collect_noop(struct context*, void*) {} |
|
|
|
|
|
|
|
|
|
|
|
static struct ink_collection_list gc_noop(struct context*, void*) { |
|
|
|
|
|
struct ink_collection_list c; |
|
|
|
|
|
c.elements = NULL; |
|
|
|
|
|
c.count = 0; |
|
|
|
|
|
return c; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#endif // NOARRAYLIB |
|
|
|
|
|
|
|
|
int ink_std_library(struct context* ctx) { |
|
|
int ink_std_library(struct context* ctx) { |
|
|
int v; |
|
|
int v; |
|
|
v = 0; |
|
|
v = 0; |
|
|
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.print_utf8", print_array_of_codepoints); |
|
|
|
|
|
v += ink_add_native(ctx, "sys.trace", print_stacktrace); |
|
|
v += ink_add_native(ctx, "sys.trace", print_stacktrace); |
|
|
v += ink_add_native(ctx, "sys.gc", run_gc); |
|
|
v += ink_add_native(ctx, "sys.gc", run_gc); |
|
|
v += ink_add_native(ctx, "print_int", print_int); |
|
|
v += ink_add_native(ctx, "print_int", print_int); |
|
@ -1623,14 +1765,35 @@ int ink_std_library(struct context* ctx) { |
|
|
v += ink_add_native(ctx, "-", sub_int); |
|
|
v += ink_add_native(ctx, "-", sub_int); |
|
|
v += ink_add_native(ctx, "*", mult_int); |
|
|
v += ink_add_native(ctx, "*", mult_int); |
|
|
v += ink_add_native(ctx, "/", div_int); |
|
|
v += ink_add_native(ctx, "/", div_int); |
|
|
v += ink_add_native(ctx, "%", rem_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, "swap", swap_elem); |
|
|
v += ink_add_native(ctx, "dup", dupe_elem); |
|
|
v += ink_add_native(ctx, "dup", dupe_elem); |
|
|
v += ink_add_native(ctx, "drop", drop_elem); |
|
|
v += ink_add_native(ctx, "drop", drop_elem); |
|
|
v += ink_add_native(ctx, "stack.clear", clear_stack); |
|
|
v += ink_add_native(ctx, "stack.clear", clear_stack); |
|
|
v += ink_add_native(ctx, "stack.to_array", arrayify_stack); |
|
|
|
|
|
v += ink_add_native(ctx, "pluck", pluck_elem); |
|
|
v += ink_add_native(ctx, "pluck", pluck_elem); |
|
|
v += ink_add_native(ctx, "return_if", return_if); |
|
|
v += ink_add_native(ctx, "return_if", return_if); |
|
|
v += ink_add_native(ctx, "jump_if", jump_if); |
|
|
v += ink_add_native(ctx, "jump_if", jump_if); |
|
|
|
|
|
#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); |
|
|
|
|
|
#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.size", get_size_array); |
|
|
|
|
|
v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints); |
|
|
|
|
|
v += ink_add_native(ctx, "stack.to_array", arrayify_stack); |
|
|
|
|
|
#endif // NOARRAYLIB |
|
|
|
|
|
|
|
|
return v; |
|
|
return v; |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|