Make some unit tests pass. Fix transfer to new fiber.

This commit is contained in:
bakpakin 2018-01-12 16:25:24 -05:00
parent f8174f192c
commit 59bed71a2c
11 changed files with 100 additions and 29 deletions

View File

@ -72,7 +72,7 @@ valgrind: $(DST_TARGET)
@ valgrind --leak-check=full -v ./$(DST_TARGET)
test: $(DST_TARGET)
@ ./$(DST_TARGET) dsttest/suite0.dst
@ ./$(DST_TARGET) --gcinterval=0 dsttest/suite0.dst
valtest: $(DST_TARGET)
valgrind --leak-check=full -v ./$(DST_TARGET) dsttests/basic.dst

View File

@ -176,7 +176,7 @@ static void runfile(const uint8_t *src, int32_t len) {
}
int main(int argc, char **argv) {
int status = -1;
int status = 0;
int i;
int fileRead = 0;
uint32_t gcinterval = 0x10000;

View File

@ -491,6 +491,9 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
if (varargs) def->flags |= DST_FUNCDEF_FLAG_VARARG;
defindex = dstc_addfuncdef(c, def);
/* Ensure enough slots for vararg function. */
if (arity + varargs > def->slotcount) def->slotcount = arity + varargs;
/* Instantiate closure */
ret.flags = 0;
ret.envindex = 0;

View File

@ -45,7 +45,7 @@ DstFiber *dst_fiber_reset(DstFiber *fiber) {
fiber->frame = 0;
fiber->stackstart = DST_FRAME_SIZE;
fiber->stacktop = DST_FRAME_SIZE;
fiber->status = DST_FIBER_PENDING;
fiber->status = DST_FIBER_NEW;
fiber->parent = NULL;
return fiber;
}

View File

@ -23,6 +23,15 @@
#include <dst/dst.h>
#include <dst/dststl.h>
int dst_stl_exit(int32_t argn, Dst *argv, Dst *ret) {
(void)ret;
int32_t exitcode = 0;
if (argn > 0) {
exitcode = dst_hash(argv[0]);
}
exit(exitcode);
}
int dst_stl_print(int32_t argn, Dst *argv, Dst *ret) {
(void)ret;
@ -210,6 +219,37 @@ int dst_stl_get(int32_t argn, Dst *argv, Dst *ret) {
return 0;
}
int dst_stl_status(int32_t argn, Dst *argv, Dst *ret) {
const char *status;
if (argn != 1) {
*ret = dst_cstringv("expected 1 argument");
return 1;
}
if (!dst_checktype(argv[0], DST_FIBER)) {
*ret = dst_cstringv("expected fiber");
return 1;
}
switch(dst_unwrap_fiber(argv[0])->status) {
case DST_FIBER_PENDING:
status = "pending";
break;
case DST_FIBER_NEW:
status = "new";
break;
case DST_FIBER_ALIVE:
status = "alive";
break;
case DST_FIBER_DEAD:
status = "dead";
break;
case DST_FIBER_ERROR:
status = "error";
break;
}
*ret = dst_cstringv(status);
return 0;
}
int dst_stl_put(int32_t argn, Dst *argv, Dst *ret) {
Dst ds, key, value;
if (argn < 3) {
@ -284,6 +324,7 @@ static DstReg stl[] = {
{"tuple", dst_stl_tuple},
{"struct", dst_stl_struct},
{"fiber", dst_stl_fiber},
{"status", dst_stl_status},
{"buffer", dst_stl_buffer},
{"gensym", dst_stl_gensym},
{"asm", dst_stl_asm},
@ -325,7 +366,8 @@ static DstReg stl[] = {
{"fopen", dst_stl_fileopen},
{"fclose", dst_stl_fileclose},
{"fwrite", dst_stl_filewrite},
{"fread", dst_stl_fileread}
{"fread", dst_stl_fileread},
{"exit!", dst_stl_exit}
};
Dst dst_loadstl(int flags) {

View File

@ -121,7 +121,7 @@ static const uint8_t *real_to_string(double x) {
return dst_string(buf, real_to_string_impl(buf, x));
}
static int32_t integer_to_string_impl(uint8_t *buf, int64_t x) {
static int32_t integer_to_string_impl(uint8_t *buf, int32_t x) {
int neg = 0;
uint8_t *hi, *low;
int32_t count = 0;
@ -151,12 +151,12 @@ static int32_t integer_to_string_impl(uint8_t *buf, int64_t x) {
return count;
}
static void integer_to_string_b(DstBuffer *buffer, int64_t x) {
static void integer_to_string_b(DstBuffer *buffer, int32_t x) {
dst_buffer_extra(buffer, DST_BUFSIZE);
buffer->count += integer_to_string_impl(buffer->data + buffer->count, x);
}
static const uint8_t *integer_to_string(int64_t x) {
static const uint8_t *integer_to_string(int32_t x) {
uint8_t buf[DST_BUFSIZE];
return dst_string(buf, integer_to_string_impl(buf, x));
}
@ -641,7 +641,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
real_to_string_b(bufp, va_arg(args, double));
break;
case 'd':
integer_to_string_b(bufp, va_arg(args, int64_t));
integer_to_string_b(bufp, va_arg(args, int32_t));
break;
case 'S':
{
@ -653,7 +653,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
dst_buffer_push_cstring(bufp, va_arg(args, const char *));
break;
case 'c':
dst_buffer_push_u8(bufp, va_arg(args, int64_t));
dst_buffer_push_u8(bufp, va_arg(args, long));
break;
case 'v':
{

View File

@ -123,7 +123,8 @@ static double convert(
: ldexp(mantissa, exponent2);
}
/* Result of scanning a number source */
/* Result of scanning a number source string. Will be further processed
* depending on the desired resultant type. */
struct DstScanRes {
uint64_t mant;
int32_t ex;

View File

@ -67,9 +67,13 @@ int32_t dst_hash(Dst x) {
int32_t hash = 0;
switch (dst_type(x)) {
case DST_NIL:
hash = 0;
break;
case DST_FALSE:
hash = 1;
break;
case DST_TRUE:
hash = dst_type(x);
hash = 2;
break;
case DST_STRING:
case DST_SYMBOL:
@ -81,6 +85,8 @@ int32_t dst_hash(Dst x) {
case DST_STRUCT:
hash = dst_struct_hash(dst_unwrap_struct(x));
break;
case DST_INTEGER:
hash = dst_unwrap_integer(x);
default:
if (sizeof(double) == sizeof(void *)) {
/* Assuming 8 byte pointer */

View File

@ -532,6 +532,7 @@ static int dst_continue(Dst *returnreg) {
case DOP_TRANSFER:
{
int status;
DstFiber *nextfiber;
DstStackFrame *frame = dst_stack_frame(stack);
Dst temp = stack[oparg(2, 0xFF)];
@ -547,14 +548,31 @@ static int dst_continue(Dst *returnreg) {
*returnreg = retreg;
return 0;
}
vm_assert(nextfiber->status == DST_FIBER_PENDING, "can only transfer to pending fiber");
status = nextfiber->status;
vm_assert(status == DST_FIBER_PENDING ||
status == DST_FIBER_NEW, "can only transfer to new or pending fiber");
frame->pc = pc;
dst_vm_fiber->status = DST_FIBER_PENDING;
dst_vm_fiber = nextfiber;
vm_init_fiber_state();
stack[oparg(1, 0xFF)] = retreg;
pc++;
vm_next();
if (status == DST_FIBER_PENDING) {
/* The next fiber is currently on a transfer instruction. */
stack[oparg(1, 0xFF)] = retreg;
pc++;
} else {
/* The next fiber is new and is on the first instruction */
if ((func->def->flags & DST_FUNCDEF_FLAG_VARARG) &&
!func->def->arity) {
/* Fully var arg function */
Dst *tup = dst_tuple_begin(1);
tup[0] = retreg;
stack[0] = dst_wrap_tuple(dst_tuple_end(tup));
} else if (func->def->arity) {
/* Non zero arity function */
stack[0] = retreg;
}
}
vm_checkgc_next();
}
case DOP_PUT:
@ -569,7 +587,7 @@ static int dst_continue(Dst *returnreg) {
stack[oparg(2, 0xFF)],
oparg(3, 0xFF));
++pc;
vm_next();
vm_checkgc_next();
case DOP_GET:
stack[oparg(1, 0xFF)] = dst_get(

View File

@ -112,6 +112,13 @@
# Fiber tests
(def error (asm '{
arity 1
bytecode [
(error 0)
]
}))
(def afiber (fiber (fn [x]
(error (string "hello, " x)))))
@ -124,10 +131,10 @@
(def t (fiber (fn [] (transfer nil 1) (transfer nil 2) 3)))
(assert (= 1 (transfer t)) "initial transfer to new thread")
(assert (= 2 (transfer t)) "second transfer to thread")
(assert (= 3 (transfer t)) "return from thread")
(assert (= (status t) "dead") "finished thread is dead")
(assert (= 1 (transfer t)) "initial transfer to new fiber")
(assert (= 2 (transfer t)) "second transfer to fiber")
(assert (= 3 (transfer t)) "return from fiber")
(assert (= (status t) "dead") "finished fiber is dead")
# Var arg tests
@ -139,13 +146,6 @@
]
}))
(def error (asm '{
arity 1
bytecode [
(error 0)
]
}))
(def vargf (fn [more] (apply + more)))
(assert (= 0 (vargf [])) "var arg no arguments")
@ -169,4 +169,4 @@
# report
(print "\n" num-tests-passed " of " num-tests-run " tests passed\n")
(if (not (= num-tests-passed num-tests-run)) (exit! 1))
(if (not= num-tests-passed num-tests-run) (exit! 1))

View File

@ -319,7 +319,8 @@ struct DstFiber {
int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */
int32_t capacity;
enum {
DST_FIBER_PENDING = 0,
DST_FIBER_PENDING,
DST_FIBER_NEW,
DST_FIBER_ALIVE,
DST_FIBER_DEAD,
DST_FIBER_ERROR