#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 print_string(struct context* ctx, const struct elem string) {
							 | 
						|
								    int i;
							 | 
						|
								    const struct ink_array* name = ink_get_value(ctx, string);
							 | 
						|
								    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;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								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) {
							 | 
						|
								        print_string(ctx, nit->name);
							 | 
						|
								        ctx->putchar(ctx, '\n');
							 | 
						|
								    }
							 | 
						|
								    for(dit = ctx->words; dit != ctx->words + ctx->words_top; ++dit) {
							 | 
						|
								        print_string(ctx, dit->name);
							 | 
						|
								        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) {
							 | 
						|
								                        print_string(ctx, rt->stack[rt->top - 1]);
							 | 
						|
								                        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);
							 | 
						|
								}
							 |