Browse Source

Fixed a bug where routine list was not properly resized

main
Ludovic 'Archivist' Lagouardette 3 months ago
parent
commit
df8b2a7f05
10 changed files with 232 additions and 83 deletions
  1. +2
    -1
      .gitignore
  2. +0
    -8
      .idea/.gitignore
  3. +0
    -2
      .idea/ink.iml
  4. +0
    -4
      .idea/misc.xml
  5. +0
    -8
      .idea/modules.xml
  6. +0
    -6
      .idea/vcs.xml
  7. +10
    -0
      CMakeLists.txt
  8. +4
    -4
      README.md
  9. +4
    -1
      ink.h
  10. +212
    -49
      lib.c

+ 2
- 1
.gitignore View File

@ -1 +1,2 @@
cmake-build-*
cmake-build-*
.idea/*

+ 0
- 8
.idea/.gitignore View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

+ 0
- 2
.idea/ink.iml View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

+ 0
- 4
.idea/misc.xml View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

+ 0
- 8
.idea/modules.xml View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ink.iml" filepath="$PROJECT_DIR$/.idea/ink.iml" />
</modules>
</component>
</project>

+ 0
- 6
.idea/vcs.xml View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

+ 10
- 0
CMakeLists.txt View File

@ -4,6 +4,16 @@ project(ink C)
set(CMAKE_C_STANDARD 90)
add_library(ink lib.c ink.h)
# Uncomment to disable the redundant arithmetic
# add_definitions(-DNOEXTRAARITHMETIC)
# Uncomment to disable array types
# add_definitions(-DNOARRAYLIB)
# Ensures the interpreter doesn't use the standard C library functions
# add_definitions(-DNOSTDLIB)
add_executable(ink_exe main.c)
target_link_libraries(ink_exe PUBLIC ink)

+ 4
- 4
README.md View File

@ -1,7 +1,7 @@
# `ink`
`ink` is a minimalistic interpreted programming language, tentatively implemented exclusively in C98. It features
coroutines and can currently only manipulate integers. Part of the code may not be compliant with C98 and I will try to
`ink` is a minimalistic interpreted programming language, tentatively implemented exclusively in C89. It features
coroutines and can currently only manipulate integers. Part of the code may not be compliant with C89 and I will try to
fix that in time.
It is fully self-contained and doesn't rely on a working standard library beyond the following:
@ -13,8 +13,8 @@ It is fully self-contained and doesn't rely on a working standard library beyond
To make the library not use the standard library, build it with `NOSTDLIB` defined as a preprocessor directive.
All of these functions need to work for `ink` to work. It is easy to add new functions to the interpreter. In the
future, I will add a garbage collector to handle cleaning dynamically allocated resources.
All of these functions need to work for `ink` to work. It is easy to add new functions to the interpreter. I added a
garbage collector to handle cleaning dynamically allocated resources.
It is possible to segregate unsafe allocations (allocations that should be hidden from the interpreter) by setting the
`inner_` versions of the library functions to different allocation functions.

+ 4
- 1
ink.h View File

@ -94,6 +94,9 @@ struct ink_collection_list {
int count;
};
/**
* Contains the data and metadata of an embedded element including the pointer to the element
*/
struct element_slab {
void* data;
int uses;
@ -247,7 +250,7 @@ int ink_step_everyone(struct context *pContext);
* @param pContext The context to execute the code in
* @param buffer The buffer that contains the source as a NULL terminated string
*/
void ink_compile(struct context *pContext, char *buffer);
void ink_compile(struct context *pContext, ">const char *buffer);
/**
* Includes the standard library in the specified context

+ 212
- 49
lib.c View File

@ -514,7 +514,7 @@ int ink_make_routine(struct context* ctx) {
int new_count;
void* renewed;
new_count = (ctx->routines_capacity + ctx->routines_capacity/2);
renewed = ctx->inner_realloc(ctx->routines, sizeof(struct stack_frame) * new_count);
renewed = ctx->inner_realloc(ctx->routines, sizeof(struct ink_routine) * new_count);
if(renewed == NULL) {
return -99;
} else {
@ -770,7 +770,7 @@ int ink_step(struct context *pContext) {
return 1;
}
void ink_compile(struct context *pContext, char* buffer) {
void ink_compile(struct context *pContext, ">const char* buffer) {
int routine, saved, executable_buffer_top;
/* Main function has a size limit of 256 (need to know that for REPL */
struct elem executable_buffer[256];
@ -1012,6 +1012,8 @@ void ink_gc(struct context* ctx) {
}
}
/* TODO: Mark objects contained within function code */
/* Mark the rest of the data */
do {
marked = 0;
@ -1171,6 +1173,46 @@ static void div_int(struct context* ctx) {
currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value;
}
static void is_equal(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
struct elem ret;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
ink_pop(ctx);
ink_pop(ctx);
ret.type = INK_INTEGER;
ret.value = a.value == b.value && a.type == b.type;
}
static void is_different(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
struct elem ret;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
ink_pop(ctx);
ink_pop(ctx);
ret.type = INK_INTEGER;
ret.value = !(a.value == b.value && a.type == b.type);
}
#ifndef NOEXTRAARITHMETIC
static void rem_int(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
@ -1190,6 +1232,84 @@ static void rem_int(struct context* ctx) {
currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value;
}
static void gt_int(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1;
return;
}
ink_pop(ctx);
currentRoutine->stack[currentRoutine->top-1].value = b.value > a.value;
}
static void gte_int(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1;
return;
}
ink_pop(ctx);
currentRoutine->stack[currentRoutine->top-1].value = b.value >= a.value;
}
static void lte_int(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1;
return;
}
ink_pop(ctx);
currentRoutine->stack[currentRoutine->top-1].value = b.value <= a.value;
}
#endif // NOEXTRAARITHMETIC
static void lt_int(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
struct elem b;
currentRoutine = ctx->routines + ctx->routine_current;
if(currentRoutine->top < 2) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top-1];
b = currentRoutine->stack[currentRoutine->top-2];
if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
currentRoutine->panic = -1;
return;
}
ink_pop(ctx);
currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value;
}
static void dupe_elem(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem a;
@ -1348,12 +1468,6 @@ static void print_as_utf8(struct context* ctx) {
ink_pop(ctx);
}
struct ink_array {
int top;
int capacity;
struct elem* elements;
};
static int get_type_by_name(struct context* ctx, const char* name) {
int i;
for(i = 0; i < ctx->types_top; ++i) {
@ -1364,20 +1478,50 @@ static int get_type_by_name(struct context* ctx, const char* name) {
return -1;
}
static void run_gc(struct context* ctx) {
ink_gc(ctx);
}
static void clear_stack(struct context* ctx) {
struct ink_routine* currentRoutine;
currentRoutine = ctx->routines + ctx->routine_current;
while (currentRoutine->top >= 1) {
ink_pop(ctx);
}
return;
}
static void collect_noop(struct context* _1, void* _2) {}
static struct ink_collection_list gc_noop(struct context* _1, void* _2) {
struct ink_collection_list c;
c.elements = NULL;
c.count = 0;
return c;
}
#ifndef NOARRAYLIB
struct ink_array {
int top;
int capacity;
struct elem* elements;
};
static void collect_array(struct context* ctx, void* array) {
struct ink_array* ary;
struct ink_array* ary;
ary = array;
if(ary->elements != NULL) ctx->free(ary->elements);
if(ary->elements != NULL) ctx->free(ary->elements);
}
static struct ink_collection_list gc_array(struct context* ctx, void* array) {
struct ink_array* ary;
struct ink_collection_list c;
struct ink_array* ary;
struct ink_collection_list c;
ary = array;
c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
c.count = ary->top;
memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
return c;
c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
c.count = ary->top;
memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
return c;
}
static void new_array(struct context* ctx) {
@ -1527,6 +1671,33 @@ static void index_array(struct context* ctx) {
ink_push(ctx, ary->elements[idx.value]);
}
static void get_size_array(struct context* ctx) {
int tid;
struct ink_routine *currentRoutine;
struct elem a;
struct ink_array *ary;
struct elem sz;
tid = get_type_by_name(ctx, "array");
currentRoutine = ctx->routines + ctx->routine_current;
if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) {
currentRoutine->panic = -1;
return;
}
a = currentRoutine->stack[currentRoutine->top - 1];
ary = ink_get_value(ctx, a);
if (ary == NULL) {
currentRoutine->panic = -1;
return;
}
ink_pop(ctx);
sz.type = INK_INTEGER;
sz.value = ary->top;
ink_push(ctx, sz);
}
static void print_array_of_codepoints(struct context* ctx) {
int tid, i;
struct ink_routine *currentRoutine;
@ -1556,19 +1727,6 @@ static void print_array_of_codepoints(struct context* ctx) {
}
}
static void run_gc(struct context* ctx) {
ink_gc(ctx);
}
static void clear_stack(struct context* ctx) {
struct ink_routine* currentRoutine;
currentRoutine = ctx->routines + ctx->routine_current;
while (currentRoutine->top >= 1) {
ink_pop(ctx);
}
return;
}
static void arrayify_stack(struct context* ctx) {
struct ink_routine* currentRoutine;
struct elem array_ref;
@ -1594,27 +1752,11 @@ static void arrayify_stack(struct context* ctx) {
return;
}
static void collect_noop(struct context*, void*) {}
static struct ink_collection_list gc_noop(struct context*, void*) {
struct ink_collection_list c;
c.elements = NULL;
c.count = 0;
return c;
}
#endif // NOARRAYLIB
int ink_std_library(struct context* ctx) {
int v;
v = 0;
ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop);
v += ink_add_native(ctx, "[", push_array_stack_delim);
v += ink_add_native(ctx, "]", push_delimited_array);
v += ink_add_native(ctx, "array.new", new_array);
v += ink_add_native(ctx, "array.push", push_array);
v += ink_add_native(ctx, "array.index", index_array);
v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints);
v += ink_add_native(ctx, "sys.trace", print_stacktrace);
v += ink_add_native(ctx, "sys.gc", run_gc);
v += ink_add_native(ctx, "print_int", print_int);
@ -1623,14 +1765,35 @@ int ink_std_library(struct context* ctx) {
v += ink_add_native(ctx, "-", sub_int);
v += ink_add_native(ctx, "*", mult_int);
v += ink_add_native(ctx, "/", div_int);
v += ink_add_native(ctx, "%", rem_int);
v += ink_add_native(ctx, "==", is_equal);
v += ink_add_native(ctx, "!=", is_different);
v += ink_add_native(ctx, "<", lt_int);
v += ink_add_native(ctx, "swap", swap_elem);
v += ink_add_native(ctx, "dup", dupe_elem);
v += ink_add_native(ctx, "drop", drop_elem);
v += ink_add_native(ctx, "stack.clear", clear_stack);
v += ink_add_native(ctx, "stack.to_array", arrayify_stack);
v += ink_add_native(ctx, "pluck", pluck_elem);
v += ink_add_native(ctx, "return_if", return_if);
v += ink_add_native(ctx, "jump_if", jump_if);
#ifndef NOEXTRAARITHMETIC
v += ink_add_native(ctx, ">", gt_int);
v += ink_add_native(ctx, ">=", gte_int);
v += ink_add_native(ctx, "=<", lte_int);
v += ink_add_native(ctx, "%", rem_int);
#endif // NOEXTRAARITHMETIC
#ifndef NOARRAYLIB
ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop);
v += ink_add_native(ctx, "[", push_array_stack_delim);
v += ink_add_native(ctx, "]", push_delimited_array);
v += ink_add_native(ctx, "array.new", new_array);
v += ink_add_native(ctx, "array.push", push_array);
v += ink_add_native(ctx, "array.index", index_array);
v += ink_add_native(ctx, "array.size", get_size_array);
v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints);
v += ink_add_native(ctx, "stack.to_array", arrayify_stack);
#endif // NOARRAYLIB
return v;
}
}

Loading…
Cancel
Save