mirror of
https://github.com/janet-lang/janet
synced 2025-02-26 04:40:01 +00:00
Add more tests
Reuse threads on gst_run when possible change name of getline to gst_getline
This commit is contained in:
parent
7e46ead2f4
commit
21bd960865
7
Makefile
7
Makefile
@ -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
|
||||||
|
@ -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;
|
||||||
|
30
core/stl.c
30
core/stl.c
@ -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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***/
|
/***/
|
||||||
|
@ -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;
|
||||||
|
24
core/vm.c
24
core/vm.c
@ -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) {
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -489,6 +489,7 @@ 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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user