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) set(CMAKE_C_STANDARD 90)
add_library(ink lib.c ink.h) 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) add_executable(ink_exe main.c)
target_link_libraries(ink_exe PUBLIC ink) target_link_libraries(ink_exe PUBLIC ink)

+ 4
- 4
README.md View File

@ -1,7 +1,7 @@
# `ink` # `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. fix that in time.
It is fully self-contained and doesn't rely on a working standard library beyond the following: 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. 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 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. `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; int count;
}; };
/**
* Contains the data and metadata of an embedded element including the pointer to the element
*/
struct element_slab { struct element_slab {
void* data; void* data;
int uses; int uses;
@ -247,7 +250,7 @@ int ink_step_everyone(struct context *pContext);
* @param pContext The context to execute the code in * @param pContext The context to execute the code in
* @param buffer The buffer that contains the source as a NULL terminated string * @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 * 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; int new_count;
void* renewed; void* renewed;
new_count = (ctx->routines_capacity + ctx->routines_capacity/2); 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) { if(renewed == NULL) {
return -99; return -99;
} else { } else {
@ -770,7 +770,7 @@ int ink_step(struct context *pContext) {
return 1; 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; int routine, saved, executable_buffer_top;
/* Main function has a size limit of 256 (need to know that for REPL */ /* Main function has a size limit of 256 (need to know that for REPL */
struct elem executable_buffer[256]; 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 */ /* Mark the rest of the data */
do { do {
marked = 0; marked = 0;
@ -1171,6 +1173,46 @@ static void div_int(struct context* ctx) {
currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value; 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) { static void rem_int(struct context* ctx) {
struct ink_routine* currentRoutine; struct ink_routine* currentRoutine;
struct elem a; struct elem a;
@ -1190,6 +1232,84 @@ static void rem_int(struct context* ctx) {
currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value; 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) { static void dupe_elem(struct context* ctx) {
struct ink_routine* currentRoutine; struct ink_routine* currentRoutine;
struct elem a; struct elem a;
@ -1348,12 +1468,6 @@ static void print_as_utf8(struct context* ctx) {
ink_pop(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) { static int get_type_by_name(struct context* ctx, const char* name) {
int i; int i;
for(i = 0; i < ctx->types_top; ++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; 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) { static void collect_array(struct context* ctx, void* array) {
struct ink_array* ary;
struct ink_array* ary;
ary = array; 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) { 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; 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) { 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]); 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) { static void print_array_of_codepoints(struct context* ctx) {
int tid, i; int tid, i;
struct ink_routine *currentRoutine; 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) { static void arrayify_stack(struct context* ctx) {
struct ink_routine* currentRoutine; struct ink_routine* currentRoutine;
struct elem array_ref; struct elem array_ref;
@ -1594,27 +1752,11 @@ static void arrayify_stack(struct context* ctx) {
return; 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 ink_std_library(struct context* ctx) {
int v; int v;
v = 0; 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.trace", print_stacktrace);
v += ink_add_native(ctx, "sys.gc", run_gc); v += ink_add_native(ctx, "sys.gc", run_gc);
v += ink_add_native(ctx, "print_int", print_int); 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, "-", sub_int);
v += ink_add_native(ctx, "*", mult_int); v += ink_add_native(ctx, "*", mult_int);
v += ink_add_native(ctx, "/", div_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, "swap", swap_elem);
v += ink_add_native(ctx, "dup", dupe_elem); v += ink_add_native(ctx, "dup", dupe_elem);
v += ink_add_native(ctx, "drop", drop_elem); v += ink_add_native(ctx, "drop", drop_elem);
v += ink_add_native(ctx, "stack.clear", clear_stack); 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, "pluck", pluck_elem);
v += ink_add_native(ctx, "return_if", return_if); v += ink_add_native(ctx, "return_if", return_if);
v += ink_add_native(ctx, "jump_if", jump_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; return v;
}
}

Loading…
Cancel
Save