Browse Source

Several fixes:

- Better (more) error handling
- CMakeLists clean-up
- added memset to the set of standard function I needed to ~~steal~~ borrow from OpenBSD
main
Ludovic 'Archivist' Lagouardette 3 weeks ago
parent
commit
d7610138a9
5 changed files with 198 additions and 173 deletions
  1. +7
    -5
      CMakeLists.txt
  2. +0
    -1
      README.md
  3. +4
    -4
      include/ink.h
  4. +185
    -59
      lib.c
  5. +2
    -104
      sh.c

+ 7
- 5
CMakeLists.txt View File

@ -5,7 +5,10 @@ include(CTest)
set(CMAKE_C_STANDARD 90)
add_library(ink lib.c include/ink.h)
add_library(ink-static lib.c include/ink.h)
target_include_directories(ink-static PUBLIC include)
add_library(ink SHARED lib.c include/ink.h)
target_include_directories(ink PUBLIC include)
# Uncomment to disable the redundant arithmetic
# add_definitions(-DNOEXTRAARITHMETIC)
@ -25,19 +28,18 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE)
add_executable(ink_exe main.c)
target_link_libraries(ink_exe PUBLIC ink)
target_include_directories(ink PUBLIC include)
target_link_libraries(ink_exe PUBLIC ink-static)
add_executable(inksh sh.c)
target_compile_definitions(inksh PRIVATE
"-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
target_link_libraries(inksh PUBLIC ink)
target_link_libraries(inksh PUBLIC ink-static)
# Functional tests
function(add_success_compiled_test cfile success_regex)
add_executable(${cfile} test/${cfile}.c)
target_link_libraries(${cfile} PUBLIC ink)
target_link_libraries(${cfile} PUBLIC ink-static)
add_test(NAME ${cfile} COMMAND ${cfile})
set_property (TEST ${cfile}
PROPERTY PASS_REGULAR_EXPRESSION "${success_regex}")

+ 0
- 1
README.md View File

@ -53,7 +53,6 @@ It is possible to segregate unsafe allocations (allocations that should be hidde
- Shell can import files (requires waiting for a routine in a routine)
- Waiting for another routine
- Executing other routines
- Move shell words to base implementation *iff* they do not have any external dependency (e.g.: `version`)
- Less context panics, more routine panics
## Examples

+ 4
- 4
include/ink.h View File

@ -1,6 +1,6 @@
#pragma once
#include "stddef.h";
#include "stdint.h";
#include <stddef.h>;
#include <stdint.h>;
/**
@ -290,7 +290,7 @@ int ink_compile(struct context *pContext, const char *buffer);
/**
* Includes the standard library in the specified context
* @param ctx The context
* @return 0
* @return 0 on success
*/
int ink_std_library(struct context *ctx);
@ -312,7 +312,7 @@ typedef struct ink_collection_list (*gc_fn)(struct context*,void*);
/**
* Declares a new type that can be stored within the interpreter
* @param ctx The context in which to add the file
* @param type_name The name of the type we want to add
* @param type_name The name of the type we want to add, IT WILL **NOT** BE COPIED. This string is expected to remain valid and unaltered for the runtime of the program
* @param size The size in bytes of the type to add, size of 0 mean no size, in which case the type is adjacent to C int, negative size means that the memory is not managed by the interpreter.
* @param collect A "destructor" function for the data
* @param gc A function that returns a list (allocated with the `inner_malloc`) of all the elements this element holds references to

+ 185
- 59
lib.c View File

@ -88,7 +88,7 @@ static int routine_assert(struct context* ctx, int condition, int error, const c
* @param message a message that will be printed in the output, no need to add a new line at the end :)
* @return true if the assertion failed, so as to allow for a `if(routine_assert(...)) return ...;`
*/
static int context_assert(struct context* ctx, int condition, int error, const char* message) {
static int context_assert(struct context* ctx, int condition, ">const int error, const char* message) {
condition = !condition;
if (condition) {
ctx->panic = error;
@ -102,6 +102,8 @@ static int context_assert(struct context* ctx, int condition, int error, const c
#ifdef NOSTDLIB
#define EOF ((int)(-1))
static size_t strlen(const char* c) {
size_t j;
j = 0;
@ -178,13 +180,26 @@ static int atoi(const char* c) {
return ret;
}
static int memcmp(const void *s1, const void *s2, size_t n) {
if (n != 0) {
const unsigned char *p1 = s1, *p2 = s2;
do {
if (*p1++ != *p2++) {
return (*--p1 - *--p2);
}
} while (--n != 0);
}
return 0;
}
#endif
static int utf8_consume(const char ** name, struct elem * elem) {
elem->type = INK_INTEGER;
if (**name == '\0') { return 0; }
if (!(**name & 128)) {
elem->value = **name;
elem->value = p">(unsigned char)**name;
*name += 1;
return 1;
}
@ -265,10 +280,9 @@ int ink_add_native(struct context* ctx, const char* name, void(*value)(struct co
renewed = ctx->inner_realloc(ctx, ctx->native_words, sizeof(struct native_fn) * new_count);
if(renewed == NULL) {
return -3;
} else {
ctx->native_words = renewed;
ctx->native_words_capacity = new_count;
}
ctx->native_words = renewed;
ctx->native_words_capacity = new_count;
}
name_it = name;
while (utf8_consume(&name_it, &character)) {
@ -346,10 +360,9 @@ static int ink_add_indigenous_already_array(struct context* ctx, struct elem e,
renewed = ctx->realloc(ctx, ctx->words, sizeof(struct fn) * new_count);
if(renewed == NULL) {
return -1;
} else {
ctx->words = renewed;
ctx->words_capacity = new_count;
}
ctx->words = renewed;
ctx->words_capacity = new_count;
}
for(i = 0; i < ctx->words_top; ++i) {
if(e.value == ctx->words[i].name.value) {
@ -436,10 +449,10 @@ int ink_push(struct context* ctx, struct elem value) {
int ink_push_fn(struct context* ctx, struct stack_frame value) {
struct ink_routine* current;
if(ctx->routine_current >= ctx->routines_top) return -55;
if(context_assert(ctx, ctx->routine_current >= ctx->routines_top, -55, "Trying to run in a routine that does not exist (ink_push_fn)")) return -55;
current = ctx->routines + ctx->routine_current;
if(current->panic) return -56;
if(context_assert(ctx, current->panic, -56, "Trying to run in a routine that is panicked (ink_push_fn)")) return -56;
if(current->function_stack == NULL) {
current->function_stack = ctx->malloc(ctx, sizeof(struct stack_frame) * 8);
current->function_stack_top = 0;
@ -449,12 +462,11 @@ int ink_push_fn(struct context* ctx, struct stack_frame value) {
void* renewed;
new_count = (current->function_stack_capacity + current->function_stack_capacity/2);
renewed = ctx->realloc(ctx, current->function_stack, sizeof(struct stack_frame) * new_count);
if(renewed == NULL) {
if(routine_assert(ctx, renewed == NULL, -9, "Failed to reallocate (ink_push_fn)")) {
return -9;
} else {
current->function_stack = renewed;
current->function_stack_capacity = new_count;
}
current->function_stack = renewed;
current->function_stack_capacity = new_count;
}
current->function_stack[current->function_stack_top] = value;
current->function_stack_top++;
@ -696,7 +708,7 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s
}
if(done) {
err = ink_push(pContext, value);
if(err < 0) {
if(routine_assert(pContext, err < 0, -19, "Failed to push in the context.")) {
return -19;
}
}
@ -717,7 +729,7 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s
value.value = i;
value.type = INK_FUNCTION;
err = ink_push(pContext, value);
if(err < 0) {
if(routine_assert(pContext, err < 0, -20, "Failed to push in the context.")) {
return -20;
}
done = 1;
@ -732,7 +744,7 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s
value.value = i;
value.type = INK_NATIVE_FUNCTION;
err = ink_push(pContext, value);
if(err < 0) {
if(routine_assert(pContext, err < 0, -21, "Failed to push in the context.")) {
return -21;
}
done = 1;
@ -749,7 +761,7 @@ static int ink_consume_one(int* end, struct context* pContext, char* r, int is_s
value.value = atoi(r);
value.type = INK_INTEGER;
err = ink_push(pContext, value);
if(err < 0) {
if(routine_assert(pContext, err < 0, -22, "Failed to push in the context.")) {
return -22;
}
done = 1;
@ -929,6 +941,9 @@ int ink_make_routine(struct context* ctx) {
}
}
/* FIXME: Maybe we need to abort here, this seems like quite an unsteady state */
#ifndef NOEXTRACHECKS
routine_assert(ctx, 0, -758, "FIXME reached: Maybe we need to abort here, this seems like quite an unsteady state");
#endif
return -758;
}
@ -955,6 +970,13 @@ int ink_kill_routine(struct context* ctx, int routine){
return 1;
}
#ifndef LABEL_BUFFER
#define LABEL_BUFFER 128
#endif
#ifndef FUNCTION_BUFFER
#define FUNCTION_BUFFER 256
#endif
/**
*
* @param pContext
@ -972,8 +994,6 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
int err;
#pragma GCC diagnostic pop
#define LABEL_BUFFER 128
#define FUNCTION_BUFFER 256
struct label labels[LABEL_BUFFER];
struct elem function_buffer[FUNCTION_BUFFER];
/* TODO: add checks for overflows in these arrays */
@ -1113,9 +1133,9 @@ static int ink_parse(struct context* pContext, struct elem* executable_buffer, i
err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name.value], function_buffer, function_buffer_top);
} else {
if(function_name.type == INK_NATIVE_FUNCTION) {
err = ink_add_indigenous_already_array(pContext, pContext->native_words[function_name.value].name,function_buffer, function_buffer_top);
err = ink_add_indigenous_already_array(pContext, pContext->native_words[function_name.value].name, function_buffer, function_buffer_top);
} else if(function_name.type == INK_FUNCTION) {
err = ink_add_indigenous_already_array(pContext, pContext->words[function_name.value].name,function_buffer, function_buffer_top);
err = ink_add_indigenous_already_array(pContext, pContext->words[function_name.value].name, function_buffer, function_buffer_top);
}
}
#ifndef NOEXTRACHECKS
@ -1220,7 +1240,7 @@ int ink_step(struct context *pContext) {
} else {
top->index++;
#ifndef NOEXTRACHECKS
if(pContext->native_words_top <= top->executing.value) {
if(routine_assert(pContext, pContext->native_words_top <= top->executing.value, -3438, "Bytecode contained out of bound executable word")) {
currentRoutine->runtime_error.is_set = 1;
currentRoutine->runtime_error.error_message = "Bytecode contained out of bound executable word";
pContext->panic = 1;
@ -1232,7 +1252,7 @@ int ink_step(struct context *pContext) {
break;
case INK_FUNCTION:
#ifndef NOEXTRACHECKS
if(pContext->words_top <= top->executing.value) {
if(routine_assert(pContext, pContext->words_top <= top->executing.value, -78611, "Bytecode contained out of bound artificial word")) {
currentRoutine->runtime_error.is_set = 1;
currentRoutine->runtime_error.error_message = "Bytecode contained out of bound artificial word";
pContext->panic = 1;
@ -1251,7 +1271,7 @@ int ink_step(struct context *pContext) {
frame.index = 0;
t = ink_push_fn(pContext, frame);
#ifndef NOEXTRACHECKS
if(t < 0) {
if(routine_assert(pContext, t < 0, -3583, "Instruction pointer underflow")) {
pContext->panic = 1;
currentRoutine->runtime_error.is_set = 1;
currentRoutine->runtime_error.error_message = "Instruction pointer underflow";
@ -1264,7 +1284,7 @@ int ink_step(struct context *pContext) {
default:
t = ink_push(pContext, top->executing);
#ifndef NOEXTRACHECKS
if(t < 0) {
if(routine_assert(pContext, t < 0, -25, "Literal token could not be pushed")) {
currentRoutine->runtime_error.is_set = 1;
currentRoutine->runtime_error.error_message = "Literal token could not be pushed";
pContext->panic = 1;
@ -1745,16 +1765,14 @@ static void add_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -312;
if(routine_assert(ctx, currentRoutine->top < 2, -312, "`+` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
ctx->panic = -684;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -684, "`+` requires 2 integer operands")) {
return;
}
#endif
@ -1768,16 +1786,14 @@ static void sub_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -2581;
if(routine_assert(ctx, currentRoutine->top < 2, -2581, "`-` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -821;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -821, "`-` requires 2 integer operands")) {
return;
}
#endif
@ -1791,16 +1807,14 @@ static void mult_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -8533;
if(routine_assert(ctx, currentRoutine->top < 2, -8533, "`*` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -543;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -543, "`*` requires 2 integer operands")) {
return;
}
#endif
@ -1814,16 +1828,14 @@ static void div_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -84;
if(routine_assert(ctx, currentRoutine->top < 2, -84, "`/` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1328;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -1328, "`/` requires 2 integer operands")) {
return;
}
#endif
@ -1838,8 +1850,7 @@ static void is_equal(struct context* ctx) {
struct elem ret;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -13587;
if(routine_assert(ctx, currentRoutine->top < 2, -13587, "`==` requires 2 operands")) {
return;
}
#endif
@ -1859,8 +1870,7 @@ static void is_different(struct context* ctx) {
struct elem ret;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -3873;
if(routine_assert(ctx, currentRoutine->top < 2, -3873, "`!=` requires 2 operands")) {
return;
}
#endif
@ -1881,16 +1891,14 @@ static void rem_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -218;
if(routine_assert(ctx, currentRoutine->top < 2, -218, "`%` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -8321;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -8321, "`%` requires 2 integer operands")) {
return;
}
#endif
@ -1904,16 +1912,14 @@ static void xor_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -184;
if(routine_assert(ctx, currentRoutine->top < 2, -184, "`int.xor` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -183;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -183, "`int.xor` requires 2 integer operands")) {
return;
}
#endif
@ -1927,16 +1933,14 @@ static void gt_int(struct context* ctx) {
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
#ifndef NOEXTRACHECKS
if(currentRoutine->top < 2) {
currentRoutine->panic = -132;
if(routine_assert(ctx, currentRoutine->top < 2, -132, "`>` requires 2 integer operands")) {
return;
}
#endif
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
#ifndef NOEXTRACHECKS
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1185;
if(routine_assert(ctx, !(a.type == INK_INTEGER && b.type == INK_INTEGER), -1185, "`>` requires 2 integer operands")) {
return;
}
#endif
@ -2662,6 +2666,124 @@ static void arrayify_stack(struct context* ctx) {
return;
}
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;
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;
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) {
const 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;
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 static_EOF(struct context* ctx) {
struct elem e;
e.type = INK_INTEGER;
e.value = EOF;
ink_push(ctx, e);
}
int ink_std_library(struct context* ctx) {
int v;
v = 0;
@ -2703,6 +2825,10 @@ int ink_std_library(struct context* ctx) {
v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints);
v += ink_add_native(ctx, "is.array", is_array);
v += ink_add_native(ctx, "stack.to_array", arrayify_stack);
v += ink_add_native(ctx, "words?", list_words);
v += ink_add_native(ctx, "words!", resolve_word);
v += ink_add_native(ctx, "words.call", call_word);
v += ink_add_native(ctx, "EOF", static_EOF);
return v;
}

+ 2
- 104
sh.c View File

@ -12,9 +12,7 @@
#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) {
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) {
@ -40,96 +38,7 @@ static void print_string(struct context* ctx, const struct elem string) {
}
}
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 get_type_by_name(struct context* ctx, const char* name);
static void print_releasever(struct context* ctx) {
const char * commit = GIT_COMMIT_HASH;
@ -148,25 +57,14 @@ static void read_stdin(struct context* ctx) {
ink_push(ctx, e);
}
static void static_EOF(struct context* ctx) {
struct elem e;
e.type = INK_INTEGER;
e.value = EOF;
ink_push(ctx, e);
}
int main(int argc, char** argv) {
char read_buffer[INK_SH_READ_BUFF];
struct context* ctx;
char** end_argv;
int interactive = 1;
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);
ink_add_native(ctx, "read-stdin", read_stdin);
ink_add_native(ctx, "EOF", static_EOF);
end_argv = argv + argc;
size_t cnt;
int no_exit = 1;

Loading…
Cancel
Save