mirror of
https://github.com/janet-lang/janet
synced 2024-11-24 17:27:18 +00:00
Make some unit tests pass. Fix transfer to new fiber.
This commit is contained in:
parent
f8174f192c
commit
59bed71a2c
2
Makefile
2
Makefile
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
44
core/stl.c
44
core/stl.c
@ -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) {
|
||||
|
@ -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':
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
28
core/vm.c
28
core/vm.c
@ -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(
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user