A minimalistic programming language written in C89.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

251 lignes
8.0 KiB

#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
#ifndef GIT_COMMIT_HASH
#define GIT_COMMIT_HASH "?"
#endif
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);
}
static void print_releasever(struct context* ctx) {
const char * commit = GIT_COMMIT_HASH;
while (*commit) {
ctx->putchar(ctx, *commit++);
}
ctx->putchar(ctx, '\n');
}
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);
ink_add_native(ctx, "version", print_releasever);
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);
}