|
@ -355,11 +355,43 @@ struct context* ink_make_default_context(void) { |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
static int ink_consume_one(int* end, struct context* pContext, char* r) { |
|
|
|
|
|
|
|
|
#ifndef NOSTRINGLITERALS |
|
|
|
|
|
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 i; |
|
|
int done; |
|
|
int done; |
|
|
struct elem value; |
|
|
struct elem value; |
|
|
int err; |
|
|
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); |
|
|
|
|
|
if(ary == NULL) { |
|
|
|
|
|
pContext->panic = -1; |
|
|
|
|
|
return -8747; |
|
|
|
|
|
} |
|
|
|
|
|
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) { |
|
|
if(*end == 0) { |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
@ -460,9 +492,46 @@ static int ink_lex(struct context *pContext, const char* buffer) { |
|
|
char r[128]; |
|
|
char r[128]; |
|
|
int end; |
|
|
int end; |
|
|
int err; |
|
|
int err; |
|
|
|
|
|
#ifndef NOSTRINGLITERALS |
|
|
|
|
|
int parses_string; |
|
|
|
|
|
#endif |
|
|
end = 0; |
|
|
end = 0; |
|
|
restart_after_comment: |
|
|
restart_after_comment: |
|
|
|
|
|
#ifndef NOSTRINGLITERALS |
|
|
|
|
|
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 /* ... */ |
|
|
|
|
|
#endif |
|
|
if(isspace(*buffer)) { |
|
|
if(isspace(*buffer)) { |
|
|
if(end == 1 && r[0] == '#') { |
|
|
if(end == 1 && r[0] == '#') { |
|
|
while(*buffer != '\n' && *buffer != 0) { |
|
|
while(*buffer != '\n' && *buffer != 0) { |
|
@ -471,18 +540,24 @@ restart_after_comment: |
|
|
end = 0; |
|
|
end = 0; |
|
|
goto restart_after_comment; |
|
|
goto restart_after_comment; |
|
|
} |
|
|
} |
|
|
err = ink_consume_one(&end, pContext, r); |
|
|
|
|
|
|
|
|
err = ink_consume_one(&end, pContext, r, 0); |
|
|
if(err < 0) { |
|
|
if(err < 0) { |
|
|
pContext->panic = 1; |
|
|
pContext->panic = 1; |
|
|
return -8; |
|
|
return -8; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
|
|
|
} else /* ... */ |
|
|
|
|
|
#ifndef NOSTRINGLITERALS |
|
|
|
|
|
if(end == 0 && *buffer == '"' && !parses_string) { |
|
|
|
|
|
parses_string = 1; |
|
|
|
|
|
} else /* ... */ |
|
|
|
|
|
#endif |
|
|
|
|
|
{ |
|
|
r[end] = *buffer; |
|
|
r[end] = *buffer; |
|
|
++end; |
|
|
++end; |
|
|
} |
|
|
} |
|
|
++buffer; |
|
|
++buffer; |
|
|
} |
|
|
} |
|
|
err = ink_consume_one(&end, pContext, r); |
|
|
|
|
|
|
|
|
err = ink_consume_one(&end, pContext, r, 0); |
|
|
if(err < 0) { |
|
|
if(err < 0) { |
|
|
pContext->panic = 1; |
|
|
pContext->panic = 1; |
|
|
return -9; |
|
|
return -9; |
|
@ -930,7 +1005,7 @@ void* ink_get_value(struct context* ctx, struct elem ref) { |
|
|
return s->data; |
|
|
return s->data; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct elem ink_make_native(struct context* ctx, int type, void* ptr) { |
|
|
|
|
|
|
|
|
struct elem ink_make_native_unsafe(struct context* ctx, int type, void* ptr, int is_protected) { |
|
|
int type_id; |
|
|
int type_id; |
|
|
struct elem ret; |
|
|
struct elem ret; |
|
|
int g, i; |
|
|
int g, i; |
|
@ -982,7 +1057,8 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { |
|
|
for(i = 0; i < g; ++i) { |
|
|
for(i = 0; i < g; ++i) { |
|
|
if(! ctx->types[type_id].elements[i].in_use) { |
|
|
if(! ctx->types[type_id].elements[i].in_use) { |
|
|
ctx->types[type_id].elements[i].in_use = 1; |
|
|
ctx->types[type_id].elements[i].in_use = 1; |
|
|
ctx->types[type_id].elements[i].uses = 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) { |
|
|
if(ctx->types[type_id].element_size < 0) { |
|
|
ctx->types[type_id].elements[i].data = ptr; |
|
|
ctx->types[type_id].elements[i].data = ptr; |
|
|
} else { |
|
|
} else { |
|
@ -1006,6 +1082,10 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct elem ink_make_native(struct context* ctx, int type, void* ptr) { |
|
|
|
|
|
return ink_make_native_unsafe(ctx, type, ptr, 0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void ink_gc(struct context* ctx) { |
|
|
void ink_gc(struct context* ctx) { |
|
|
int i, j, k; |
|
|
int i, j, k; |
|
|
int marked; |
|
|
int marked; |
|
@ -1041,7 +1121,7 @@ void ink_gc(struct context* ctx) { |
|
|
for (i = 0; i < ctx->types_top; ++i) { |
|
|
for (i = 0; i < ctx->types_top; ++i) { |
|
|
for (j = 0; j < ctx->types[i].elements_top; ++j) { |
|
|
for (j = 0; j < ctx->types[i].elements_top; ++j) { |
|
|
/* Only mark from things that are active and detected as in use */ |
|
|
/* 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].uses) { |
|
|
|
|
|
|
|
|
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; |
|
|
struct ink_collection_list c; |
|
|
c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); |
|
|
c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); |
|
|
for (k = 0; k < c.count; ++k) { |
|
|
for (k = 0; k < c.count; ++k) { |
|
@ -1061,7 +1141,7 @@ void ink_gc(struct context* ctx) { |
|
|
/* Sweep phase: explore any allocated data and sweep the unused away */ |
|
|
/* Sweep phase: explore any allocated data and sweep the unused away */ |
|
|
for(i = 0; i < ctx->types_top; ++i) { |
|
|
for(i = 0; i < ctx->types_top; ++i) { |
|
|
for(j = 0; j < ctx->types[i].elements_top; ++j) { |
|
|
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) { |
|
|
|
|
|
|
|
|
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->collections++; |
|
|
ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); |
|
|
ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); |
|
|
if(ctx->types[i].element_size > 0) { |
|
|
if(ctx->types[i].element_size > 0) { |
|
@ -1598,6 +1678,20 @@ static void new_array(struct context* ctx) { |
|
|
ink_push(ctx, e); |
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
static void push_array_stack_delim(struct context* ctx) { |
|
|
static void push_array_stack_delim(struct context* ctx) { |
|
|
int tid; |
|
|
int tid; |
|
|
struct elem e; |
|
|
struct elem e; |
|
|