#include "ink.h"
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#ifndef INK_SH_READ_BUFF
|
|
#define INK_SH_READ_BUFF 32768
|
|
#endif // INK_SH_READ_BUFF
|
|
|
|
int get_type_by_name(struct context* ctx, const char* name);
|
|
|
|
static void list_words(struct context* ctx) {
|
|
struct native_fn* nit;
|
|
struct fn* dit;
|
|
int i;
|
|
for(nit = ctx->native_words; nit != ctx->native_words + ctx->native_words_top; ++nit) {
|
|
const struct ink_array* name = ink_get_value(ctx, nit->name);
|
|
for (i = 0; i < name->top; ++i) {
|
|
const struct elem a = name->elements[i];
|
|
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 = -9472;
|
|
return;
|
|
}
|
|
}
|
|
ctx->putchar(ctx, '\n');
|
|
}
|
|
for(dit = ctx->words; dit != ctx->words + ctx->words_top; ++dit) {
|
|
const struct ink_array* name = ink_get_value(ctx, dit->name);
|
|
for (i = 0; i < name->top; ++i) {
|
|
const struct elem a = name->elements[i];
|
|
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 = -9472;
|
|
return;
|
|
}
|
|
}
|
|
ctx->putchar(ctx, '\n');
|
|
}
|
|
}
|
|
|
|
static void resolve_word(struct context* ctx) {
|
|
struct native_fn* nit;
|
|
struct fn* dit;
|
|
int i;
|
|
struct ink_routine *currentRoutine;
|
|
struct elem a;
|
|
struct ink_array *ary;
|
|
unsigned char* name;
|
|
int it;
|
|
int found = 0;
|
|
|
|
#ifndef NOEXTRACHECKS
|
|
int tid;
|
|
tid = get_type_by_name(ctx, "array");
|
|
#endif
|
|
currentRoutine = ctx->routines + ctx->routine_current;
|
|
#ifndef NOEXTRACHECKS
|
|
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);
|
|
|
|
#ifndef NOEXTRACHECKS
|
|
for(i = 0; i < ary->top; ++i) {
|
|
if(ary->elements[i].type != INK_INTEGER) {
|
|
currentRoutine->panic = -1;
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
ink_pop(ctx);
|
|
|
|
for(nit = ctx->native_words; (!found) && nit != ctx->native_words + ctx->native_words_top; ++nit) {
|
|
struct ink_array* inner_name = ink_get_value(ctx, nit->name);
|
|
if(ary->top == inner_name->top && memcmp(ary->elements, inner_name->elements, sizeof(struct elem)*ary->top) == 0) {
|
|
struct elem fn;
|
|
fn.type = INK_NATIVE_FUNCTION;
|
|
fn.value = nit - ctx->native_words;
|
|
ink_push(ctx, fn);
|
|
found = 1;
|
|
}
|
|
}
|
|
for(dit = ctx->words; (!found) && dit != ctx->words + ctx->words_top; ++dit) {
|
|
struct ink_array* inner_name = ink_get_value(ctx, dit->name);
|
|
if(ary->top == inner_name->top && memcmp(ary->elements, inner_name->elements, sizeof(struct elem)*ary->top) == 0) {
|
|
struct elem fn;
|
|
fn.type = INK_FUNCTION;
|
|
fn.value = dit - ctx->words;
|
|
ink_push(ctx, fn);
|
|
found = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void call_word(struct context* ctx) {
|
|
struct ink_routine *currentRoutine;
|
|
unsigned char* name;
|
|
int it;
|
|
int found = 0;
|
|
struct stack_frame frame;
|
|
|
|
currentRoutine = ctx->routines + ctx->routine_current;
|
|
#ifndef NOEXTRACHECKS
|
|
if (currentRoutine->top < 1 || (currentRoutine->stack[currentRoutine->top - 1].type != INK_FUNCTION && currentRoutine->stack[currentRoutine->top - 1].type != INK_NATIVE_FUNCTION)) {
|
|
currentRoutine->panic = -1;
|
|
return;
|
|
}
|
|
#endif
|
|
frame.executing = currentRoutine->stack[currentRoutine->top - 1];
|
|
frame.index = 0;
|
|
ink_pop(ctx);
|
|
ink_push_fn(ctx, frame);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
char read_buffer[INK_SH_READ_BUFF];
|
|
struct context* ctx;
|
|
char** end_argv;
|
|
ctx = ink_make_default_context();
|
|
ink_add_native(ctx, "words?", list_words);
|
|
ink_add_native(ctx, "words!", resolve_word);
|
|
ink_add_native(ctx, "words.call", call_word);
|
|
end_argv = argv + argc;
|
|
size_t cnt;
|
|
int no_exit = 1;
|
|
for(argv+=1; argv != end_argv; argv++) {
|
|
FILE* file;
|
|
file = fopen(*argv, "r");
|
|
cnt = fread(read_buffer, 1, INK_SH_READ_BUFF - 1, file);
|
|
if(cnt == 0) {
|
|
fprintf(stderr, "Can't read file !! -> %s\n", *argv);
|
|
}
|
|
read_buffer[cnt] = 0;
|
|
ink_compile(ctx, read_buffer);
|
|
|
|
if(ctx->panic) {
|
|
fprintf(stderr, "Panicked !! -> %d\n", ctx->panic);
|
|
}
|
|
|
|
while (ink_can_run(ctx)) {
|
|
ink_step_everyone(ctx);
|
|
}
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
char* it = read_buffer;
|
|
do {
|
|
int line_on = 0;
|
|
int routine;
|
|
struct ink_routine* rt;
|
|
// cnt = fread(read_buffer, 1, INK_SH_READ_BUFF - 1, stdin);
|
|
fputc('%', stdout);
|
|
fputc(' ', stdout);
|
|
cnt = 0;
|
|
|
|
while(!line_on) {
|
|
int c = fgetc(stdin);
|
|
if (c == EOF) {
|
|
read_buffer[cnt] = 0;
|
|
line_on = 1;
|
|
no_exit = 0;
|
|
} else if(c == '\n'){
|
|
read_buffer[cnt] = 0;
|
|
line_on = 1;
|
|
} else {
|
|
read_buffer[cnt] = c;
|
|
++cnt;
|
|
}
|
|
}
|
|
if(cnt > 0) {
|
|
read_buffer[cnt] = 0;
|
|
routine = ink_compile(ctx, read_buffer);
|
|
|
|
if (ctx->panic) {
|
|
fprintf(stderr, "Panicked ctx !! -> %d\n", ctx->panic);
|
|
}
|
|
if (ctx->routines[routine].panic) {
|
|
fprintf(stderr, "Panicked routine !! -> %d\n", ctx->routines[routine].panic);
|
|
}
|
|
if (ctx->routines[routine].runtime_error.is_set) {
|
|
fprintf(stderr, "Panicked !! -> %s\n", ctx->routines[routine].runtime_error.error_message);
|
|
}
|
|
|
|
while (ink_can_run(ctx)) {
|
|
ink_step_everyone(ctx);
|
|
}
|
|
rt = ctx->routines + routine;
|
|
if(rt->top) {
|
|
if(rt->stack[rt->top - 1].type == INK_INTEGER) {
|
|
fprintf(stdout, "%u\n", rt->stack[rt->top - 1].value);
|
|
}
|
|
if(rt->stack[rt->top - 1].type == get_type_by_name(ctx, "array")) {
|
|
struct elem* ary_it;
|
|
int print_as_string = 1;
|
|
struct ink_array* ary = ink_get_value(ctx, rt->stack[rt->top - 1]);
|
|
|
|
|
|
for(ary_it = ary->elements; ary_it != ary->elements + ary->top; ++ary_it) {
|
|
print_as_string = print_as_string && (isprint(ary_it->value) || isspace(ary_it->value)) && (ary_it->type == INK_INTEGER);
|
|
}
|
|
|
|
if(print_as_string) {
|
|
for (ary_it = ary->elements; ary_it != ary->elements + ary->top; ++ary_it) {
|
|
fputc(ary_it->value, stdout);
|
|
}
|
|
fputc('\n', stdout);
|
|
} else {
|
|
fputc('[', stdout);
|
|
for (ary_it = ary->elements; ary_it != ary->elements + ary->top; ++ary_it) {
|
|
fprintf(stdout, "%u", ary_it->value);
|
|
if (ary_it + 1 != ary->elements + ary->top) fputc(',', stdout);
|
|
}
|
|
fputc(']', stdout);
|
|
fputc('\n', stdout);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while(no_exit);
|
|
fputc('\n', stdout);
|
|
return ink_destroy(ctx);
|
|
}
|