1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-25 22:53:16 +00:00

Add more tests

Reuse threads on gst_run when possible
change name of getline to gst_getline
This commit is contained in:
Calvin Rose 2017-06-29 21:57:09 -04:00
parent 7e46ead2f4
commit 21bd960865
7 changed files with 73 additions and 26 deletions

View File

@ -39,7 +39,7 @@ debug: $(GST_TARGET)
gdb $(GST_TARGET) gdb $(GST_TARGET)
valgrind: $(GST_TARGET) valgrind: $(GST_TARGET)
valgrind --leak-check=full ./$(GST_TARGET) valgrind --leak-check=full -v ./$(GST_TARGET)
clean: clean:
rm $(GST_TARGET) || true rm $(GST_TARGET) || true
@ -51,4 +51,7 @@ clean:
test: $(GST_TARGET) test: $(GST_TARGET)
$(GST_TARGET) gsttests/basic.gst $(GST_TARGET) gsttests/basic.gst
.PHONY: clean install run debug valgrind valtest: $(GST_TARGET)
valgrind --leak-check=full -v ./$(GST_TARGET) gsttests/basic.gst
.PHONY: clean install run debug valgrind test valtest

View File

@ -25,7 +25,7 @@
#include <gst/gst.h> #include <gst/gst.h>
/* Simple read line functionality */ /* Simple read line functionality */
char *getline() { static char *gst_getline() {
char *line = malloc(100); char *line = malloc(100);
char *linep = line; char *linep = line;
size_t lenmax = 100; size_t lenmax = 100;
@ -55,7 +55,7 @@ char *getline() {
} }
/* Compile and run an ast */ /* Compile and run an ast */
int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { static int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
GstCompiler c; GstCompiler c;
GstValue func; GstValue func;
/* Try to compile generated AST */ /* Try to compile generated AST */
@ -80,7 +80,7 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
} }
/* Parse a file and execute it */ /* Parse a file and execute it */
int debug_run(Gst *vm, FILE *in) { static int debug_run(Gst *vm, FILE *in) {
char buffer[2048] = {0}; char buffer[2048] = {0};
const char *reader = buffer; const char *reader = buffer;
GstParser p; GstParser p;
@ -123,7 +123,7 @@ int debug_run(Gst *vm, FILE *in) {
} }
/* A simple repl */ /* A simple repl */
int debug_repl(Gst *vm) { static int debug_repl(Gst *vm) {
char *buffer, *reader; char *buffer, *reader;
GstParser p; GstParser p;
buffer = reader = NULL; buffer = reader = NULL;
@ -138,7 +138,7 @@ int debug_repl(Gst *vm) {
printf("\x1B[32m>>\x1B[0m "); printf("\x1B[32m>>\x1B[0m ");
if (buffer) if (buffer)
free(buffer); free(buffer);
buffer = getline(); buffer = gst_getline();
if (!buffer || *buffer == '\0') if (!buffer || *buffer == '\0')
return 0; return 0;
reader = buffer; reader = buffer;

View File

@ -450,13 +450,16 @@ int gst_stl_thread(Gst *vm) {
t->parent = parent.data.thread; t->parent = parent.data.thread;
} else if (parent.type != GST_NIL) { } else if (parent.type != GST_NIL) {
gst_c_throwc(vm, "expected thread/nil as parent"); gst_c_throwc(vm, "expected thread/nil as parent");
} else {
t->parent = vm->thread;
} }
if (errorParent.type == GST_THREAD) { if (errorParent.type == GST_THREAD) {
t->errorParent = errorParent.data.thread; t->errorParent = errorParent.data.thread;
} else if (errorParent.type != GST_NIL) { } else if (errorParent.type != GST_NIL) {
gst_c_throwc(vm, "expected thread/nil as error parent"); gst_c_throwc(vm, "expected thread/nil as error parent");
} else {
t->errorParent = vm->thread;
} }
t->parent = vm->thread;
gst_c_return(vm, gst_wrap_thread(t)); gst_c_return(vm, gst_wrap_thread(t));
} }
@ -830,9 +833,12 @@ int gst_stl_gcollect(Gst *vm) {
} }
/* Static debug print helper */ /* Static debug print helper */
static GstInteger gst_stl_debugp_helper(Gst *vm, GstBuffer *b, GstTable *seen, GstValue x, GstInteger next) { static GstInteger gst_stl_debugp_helper(Gst *vm, GstBuffer *b, GstTable *seen, GstValue x, GstInteger next, int depth) {
GstValue check = gst_table_get(seen, x); GstValue check = gst_table_get(seen, x);
const uint8_t *str; const uint8_t *str;
/* Prevent a stack overflow */
if (depth++ > GST_RECURSION_GUARD)
return -1;
if (check.type == GST_INTEGER) { if (check.type == GST_INTEGER) {
str = gst_to_string(vm, check); str = gst_to_string(vm, check);
gst_buffer_append_cstring(vm, b, "<visited "); gst_buffer_append_cstring(vm, b, "<visited ");
@ -870,14 +876,20 @@ static GstInteger gst_stl_debugp_helper(Gst *vm, GstBuffer *b, GstTable *seen, G
isfirst = 0; isfirst = 0;
else else
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
next = gst_stl_debugp_helper(vm, b, seen, data[i], next); next = gst_stl_debugp_helper(vm, b, seen, data[i], next, depth);
if (next == -1)
return -1;
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
next = gst_stl_debugp_helper(vm, b, seen, data[i + 1], next); next = gst_stl_debugp_helper(vm, b, seen, data[i + 1], next, depth);
if (next == -1)
return -1;
} }
} }
} else if (gst_seq_view(x, &data, &len)) { } else if (gst_seq_view(x, &data, &len)) {
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
next = gst_stl_debugp_helper(vm, b, seen, data[i], next); next = gst_stl_debugp_helper(vm, b, seen, data[i], next, depth);
if (next == -1)
return -1;
if (i != len - 1) if (i != len - 1)
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
} }
@ -891,8 +903,12 @@ static GstInteger gst_stl_debugp_helper(Gst *vm, GstBuffer *b, GstTable *seen, G
int gst_stl_debugp(Gst *vm) { int gst_stl_debugp(Gst *vm) {
GstValue x = gst_arg(vm, 0); GstValue x = gst_arg(vm, 0);
GstBuffer *buf = gst_buffer(vm, 10); GstBuffer *buf = gst_buffer(vm, 10);
gst_stl_debugp_helper(vm, buf, gst_table(vm, 10), x, 0); GstInteger res = gst_stl_debugp_helper(vm, buf, gst_table(vm, 10), x, 0, 0);
gst_c_return(vm, gst_wrap_string(gst_buffer_to_string(vm, buf))); if (res == -1) {
gst_c_throwc(vm, "recursed too deeply in debugp");
} else {
gst_c_return(vm, gst_wrap_string(gst_buffer_to_string(vm, buf)));
}
} }
/***/ /***/

View File

@ -25,14 +25,18 @@
/* Create a new thread */ /* Create a new thread */
GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) {
GstThread *thread = gst_alloc(vm, sizeof(GstThread)); GstThread *thread = gst_alloc(vm, sizeof(GstThread));
GstValue *data, *stack;
if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE;
data = gst_alloc(vm, sizeof(GstValue) * capacity); thread->data = gst_alloc(vm, sizeof(GstValue) * capacity);
thread->capacity = capacity; thread->capacity = capacity;
return gst_thread_reset(vm, thread, callee);
}
/* Clear a thread (reset it) */
GstThread *gst_thread_reset(Gst *vm, GstThread *thread, GstValue callee) {
GstValue *stack;
thread->count = GST_FRAME_SIZE; thread->count = GST_FRAME_SIZE;
thread->data = data;
thread->status = GST_THREAD_PENDING; thread->status = GST_THREAD_PENDING;
stack = data + GST_FRAME_SIZE; stack = thread->data + GST_FRAME_SIZE;
gst_frame_size(stack) = 0; gst_frame_size(stack) = 0;
gst_frame_prevsize(stack) = 0; gst_frame_prevsize(stack) = 0;
gst_frame_ret(stack) = 0; gst_frame_ret(stack) = 0;

View File

@ -299,7 +299,6 @@ int gst_continue(Gst *vm) {
temp = vm->ret; temp = vm->ret;
goto vm_return; goto vm_return;
} else { } else {
stack = gst_thread_popframe(vm, vm->thread);
goto vm_error; goto vm_error;
} }
} else { } else {
@ -377,7 +376,9 @@ int gst_continue(Gst *vm) {
/* Handle returning from stack frame. Expect return value in temp. */ /* Handle returning from stack frame. Expect return value in temp. */
vm_return: vm_return:
stack = gst_thread_popframe(vm, vm->thread); stack = gst_thread_popframe(vm, vm->thread);
while (vm->thread->count < GST_FRAME_SIZE) { while (vm->thread->count < GST_FRAME_SIZE ||
vm->thread->status == GST_THREAD_DEAD ||
vm->thread->status == GST_THREAD_ERROR) {
vm->thread->status = GST_THREAD_DEAD; vm->thread->status = GST_THREAD_DEAD;
if (vm->thread->parent) { if (vm->thread->parent) {
vm->thread = vm->thread->parent; vm->thread = vm->thread->parent;
@ -387,6 +388,7 @@ int gst_continue(Gst *vm) {
return GST_RETURN_OK; return GST_RETURN_OK;
} }
} }
vm->thread->status = GST_THREAD_ALIVE;
pc = gst_frame_pc(stack); pc = gst_frame_pc(stack);
stack[gst_frame_ret(stack)] = temp; stack[gst_frame_ret(stack)] = temp;
continue; continue;
@ -394,9 +396,14 @@ int gst_continue(Gst *vm) {
/* Handle errors from c functions and vm opcodes */ /* Handle errors from c functions and vm opcodes */
vm_error: vm_error:
vm->thread->status = GST_THREAD_ERROR; vm->thread->status = GST_THREAD_ERROR;
if (vm->thread->errorParent == NULL) while (vm->thread->count < GST_FRAME_SIZE ||
return GST_RETURN_ERROR; vm->thread->status == GST_THREAD_DEAD ||
vm->thread = vm->thread->errorParent; vm->thread->status == GST_THREAD_ERROR) {
if (vm->thread->errorParent == NULL)
return GST_RETURN_ERROR;
vm->thread = vm->thread->errorParent;
}
vm->thread->status = GST_THREAD_ALIVE;
stack = vm->thread->data + vm->thread->count; stack = vm->thread->data + vm->thread->count;
stack[gst_frame_ret(stack)] = vm->ret; stack[gst_frame_ret(stack)] = vm->ret;
pc = gst_frame_pc(stack); pc = gst_frame_pc(stack);
@ -416,7 +423,12 @@ int gst_continue(Gst *vm) {
/* Run the vm with a given function. This function is /* Run the vm with a given function. This function is
* called to start the vm. */ * called to start the vm. */
int gst_run(Gst *vm, GstValue callee) { int gst_run(Gst *vm, GstValue callee) {
vm->thread = gst_thread(vm, callee, 64); if (vm->thread == NULL) {
vm->thread = gst_thread(vm, callee, 64);
} else {
/* Reuse old thread */
gst_thread_reset(vm, vm->thread, callee);
}
if (vm->thread == NULL) if (vm->thread == NULL)
return GST_RETURN_CRASH; return GST_RETURN_CRASH;
if (callee.type == GST_CFUNCTION) { if (callee.type == GST_CFUNCTION) {

View File

@ -48,6 +48,8 @@
(assert (= accum 65536) "loop") (assert (= accum 65536) "loop")
(assert (= (struct 1 2 3 4 5 6 7 8) (struct 7 8 5 6 3 4 1 2)) "struct order does not matter")
"Serialization tests" "Serialization tests"
(def scheck (fn [x] (def scheck (fn [x]
(def dat (serialize x)) (def dat (serialize x))
@ -64,7 +66,16 @@
(scheck (tuple 1 2 3)) (scheck (tuple 1 2 3))
(scheck 123412.12) (scheck 123412.12)
(scheck (struct (struct 1 2 3 "a") (struct 1 2 3 "a") false 1 "asdasd" (tuple "a" "b"))) (scheck (struct (struct 1 2 3 "a") (struct 1 2 3 "a") false 1 "asdasd" (tuple "a" "b")))
(scheck "psdafoilasdfbiusbdfliasbldfiubaslidufbliausdbfiluasbdfiulbasldiufbalisudhfiasudbfaisuldfbl") (scheck "qwertyuiopasdfghjklzxcvbnm123456789")
(scheck "qwertyuiopasdfghjklzxcvbnm1234567890!@#$%^&*()")
(def athread (thread (fn [x]
(error (string "hello, " x)))))
(def athread-result (tran athread "world!"))
(assert (= athread-result "hello, world!") "thread error result")
(assert (= (status athread) "error") "thread error status")
"All tests passed" "All tests passed"

View File

@ -488,7 +488,8 @@ GstValue gst_table_next(GstTable *o, GstValue key);
/****/ /****/
#define gst_thread_stack(t) ((t)->data + (t)->count) #define gst_thread_stack(t) ((t)->data + (t)->count)
GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity); GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity);
GstThread *gst_thread_reset(Gst *vm, GstThread *thread, GstValue callee);
void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra); void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra);
void gst_thread_push(Gst *vm, GstThread *thread, GstValue x); void gst_thread_push(Gst *vm, GstThread *thread, GstValue x);
void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n); void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n);