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)
|
@ valgrind --leak-check=full -v ./$(DST_TARGET)
|
||||||
|
|
||||||
test: $(DST_TARGET)
|
test: $(DST_TARGET)
|
||||||
@ ./$(DST_TARGET) dsttest/suite0.dst
|
@ ./$(DST_TARGET) --gcinterval=0 dsttest/suite0.dst
|
||||||
|
|
||||||
valtest: $(DST_TARGET)
|
valtest: $(DST_TARGET)
|
||||||
valgrind --leak-check=full -v ./$(DST_TARGET) dsttests/basic.dst
|
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 main(int argc, char **argv) {
|
||||||
int status = -1;
|
int status = 0;
|
||||||
int i;
|
int i;
|
||||||
int fileRead = 0;
|
int fileRead = 0;
|
||||||
uint32_t gcinterval = 0x10000;
|
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;
|
if (varargs) def->flags |= DST_FUNCDEF_FLAG_VARARG;
|
||||||
defindex = dstc_addfuncdef(c, def);
|
defindex = dstc_addfuncdef(c, def);
|
||||||
|
|
||||||
|
/* Ensure enough slots for vararg function. */
|
||||||
|
if (arity + varargs > def->slotcount) def->slotcount = arity + varargs;
|
||||||
|
|
||||||
/* Instantiate closure */
|
/* Instantiate closure */
|
||||||
ret.flags = 0;
|
ret.flags = 0;
|
||||||
ret.envindex = 0;
|
ret.envindex = 0;
|
||||||
|
@ -45,7 +45,7 @@ DstFiber *dst_fiber_reset(DstFiber *fiber) {
|
|||||||
fiber->frame = 0;
|
fiber->frame = 0;
|
||||||
fiber->stackstart = DST_FRAME_SIZE;
|
fiber->stackstart = DST_FRAME_SIZE;
|
||||||
fiber->stacktop = DST_FRAME_SIZE;
|
fiber->stacktop = DST_FRAME_SIZE;
|
||||||
fiber->status = DST_FIBER_PENDING;
|
fiber->status = DST_FIBER_NEW;
|
||||||
fiber->parent = NULL;
|
fiber->parent = NULL;
|
||||||
return fiber;
|
return fiber;
|
||||||
}
|
}
|
||||||
|
44
core/stl.c
44
core/stl.c
@ -23,6 +23,15 @@
|
|||||||
#include <dst/dst.h>
|
#include <dst/dst.h>
|
||||||
#include <dst/dststl.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) {
|
int dst_stl_print(int32_t argn, Dst *argv, Dst *ret) {
|
||||||
(void)ret;
|
(void)ret;
|
||||||
|
|
||||||
@ -210,6 +219,37 @@ int dst_stl_get(int32_t argn, Dst *argv, Dst *ret) {
|
|||||||
return 0;
|
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) {
|
int dst_stl_put(int32_t argn, Dst *argv, Dst *ret) {
|
||||||
Dst ds, key, value;
|
Dst ds, key, value;
|
||||||
if (argn < 3) {
|
if (argn < 3) {
|
||||||
@ -284,6 +324,7 @@ static DstReg stl[] = {
|
|||||||
{"tuple", dst_stl_tuple},
|
{"tuple", dst_stl_tuple},
|
||||||
{"struct", dst_stl_struct},
|
{"struct", dst_stl_struct},
|
||||||
{"fiber", dst_stl_fiber},
|
{"fiber", dst_stl_fiber},
|
||||||
|
{"status", dst_stl_status},
|
||||||
{"buffer", dst_stl_buffer},
|
{"buffer", dst_stl_buffer},
|
||||||
{"gensym", dst_stl_gensym},
|
{"gensym", dst_stl_gensym},
|
||||||
{"asm", dst_stl_asm},
|
{"asm", dst_stl_asm},
|
||||||
@ -325,7 +366,8 @@ static DstReg stl[] = {
|
|||||||
{"fopen", dst_stl_fileopen},
|
{"fopen", dst_stl_fileopen},
|
||||||
{"fclose", dst_stl_fileclose},
|
{"fclose", dst_stl_fileclose},
|
||||||
{"fwrite", dst_stl_filewrite},
|
{"fwrite", dst_stl_filewrite},
|
||||||
{"fread", dst_stl_fileread}
|
{"fread", dst_stl_fileread},
|
||||||
|
{"exit!", dst_stl_exit}
|
||||||
};
|
};
|
||||||
|
|
||||||
Dst dst_loadstl(int flags) {
|
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));
|
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;
|
int neg = 0;
|
||||||
uint8_t *hi, *low;
|
uint8_t *hi, *low;
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
@ -151,12 +151,12 @@ static int32_t integer_to_string_impl(uint8_t *buf, int64_t x) {
|
|||||||
return count;
|
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);
|
dst_buffer_extra(buffer, DST_BUFSIZE);
|
||||||
buffer->count += integer_to_string_impl(buffer->data + buffer->count, x);
|
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];
|
uint8_t buf[DST_BUFSIZE];
|
||||||
return dst_string(buf, integer_to_string_impl(buf, x));
|
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));
|
real_to_string_b(bufp, va_arg(args, double));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
integer_to_string_b(bufp, va_arg(args, int64_t));
|
integer_to_string_b(bufp, va_arg(args, int32_t));
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
{
|
||||||
@ -653,7 +653,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
|||||||
dst_buffer_push_cstring(bufp, va_arg(args, const char *));
|
dst_buffer_push_cstring(bufp, va_arg(args, const char *));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
dst_buffer_push_u8(bufp, va_arg(args, int64_t));
|
dst_buffer_push_u8(bufp, va_arg(args, long));
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
{
|
{
|
||||||
|
@ -123,7 +123,8 @@ static double convert(
|
|||||||
: ldexp(mantissa, exponent2);
|
: 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 {
|
struct DstScanRes {
|
||||||
uint64_t mant;
|
uint64_t mant;
|
||||||
int32_t ex;
|
int32_t ex;
|
||||||
|
@ -67,9 +67,13 @@ int32_t dst_hash(Dst x) {
|
|||||||
int32_t hash = 0;
|
int32_t hash = 0;
|
||||||
switch (dst_type(x)) {
|
switch (dst_type(x)) {
|
||||||
case DST_NIL:
|
case DST_NIL:
|
||||||
|
hash = 0;
|
||||||
|
break;
|
||||||
case DST_FALSE:
|
case DST_FALSE:
|
||||||
|
hash = 1;
|
||||||
|
break;
|
||||||
case DST_TRUE:
|
case DST_TRUE:
|
||||||
hash = dst_type(x);
|
hash = 2;
|
||||||
break;
|
break;
|
||||||
case DST_STRING:
|
case DST_STRING:
|
||||||
case DST_SYMBOL:
|
case DST_SYMBOL:
|
||||||
@ -81,6 +85,8 @@ int32_t dst_hash(Dst x) {
|
|||||||
case DST_STRUCT:
|
case DST_STRUCT:
|
||||||
hash = dst_struct_hash(dst_unwrap_struct(x));
|
hash = dst_struct_hash(dst_unwrap_struct(x));
|
||||||
break;
|
break;
|
||||||
|
case DST_INTEGER:
|
||||||
|
hash = dst_unwrap_integer(x);
|
||||||
default:
|
default:
|
||||||
if (sizeof(double) == sizeof(void *)) {
|
if (sizeof(double) == sizeof(void *)) {
|
||||||
/* Assuming 8 byte pointer */
|
/* Assuming 8 byte pointer */
|
||||||
|
24
core/vm.c
24
core/vm.c
@ -532,6 +532,7 @@ static int dst_continue(Dst *returnreg) {
|
|||||||
|
|
||||||
case DOP_TRANSFER:
|
case DOP_TRANSFER:
|
||||||
{
|
{
|
||||||
|
int status;
|
||||||
DstFiber *nextfiber;
|
DstFiber *nextfiber;
|
||||||
DstStackFrame *frame = dst_stack_frame(stack);
|
DstStackFrame *frame = dst_stack_frame(stack);
|
||||||
Dst temp = stack[oparg(2, 0xFF)];
|
Dst temp = stack[oparg(2, 0xFF)];
|
||||||
@ -547,14 +548,31 @@ static int dst_continue(Dst *returnreg) {
|
|||||||
*returnreg = retreg;
|
*returnreg = retreg;
|
||||||
return 0;
|
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;
|
frame->pc = pc;
|
||||||
dst_vm_fiber->status = DST_FIBER_PENDING;
|
dst_vm_fiber->status = DST_FIBER_PENDING;
|
||||||
dst_vm_fiber = nextfiber;
|
dst_vm_fiber = nextfiber;
|
||||||
vm_init_fiber_state();
|
vm_init_fiber_state();
|
||||||
|
if (status == DST_FIBER_PENDING) {
|
||||||
|
/* The next fiber is currently on a transfer instruction. */
|
||||||
stack[oparg(1, 0xFF)] = retreg;
|
stack[oparg(1, 0xFF)] = retreg;
|
||||||
pc++;
|
pc++;
|
||||||
vm_next();
|
} 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:
|
case DOP_PUT:
|
||||||
@ -569,7 +587,7 @@ static int dst_continue(Dst *returnreg) {
|
|||||||
stack[oparg(2, 0xFF)],
|
stack[oparg(2, 0xFF)],
|
||||||
oparg(3, 0xFF));
|
oparg(3, 0xFF));
|
||||||
++pc;
|
++pc;
|
||||||
vm_next();
|
vm_checkgc_next();
|
||||||
|
|
||||||
case DOP_GET:
|
case DOP_GET:
|
||||||
stack[oparg(1, 0xFF)] = dst_get(
|
stack[oparg(1, 0xFF)] = dst_get(
|
||||||
|
@ -112,6 +112,13 @@
|
|||||||
|
|
||||||
# Fiber tests
|
# Fiber tests
|
||||||
|
|
||||||
|
(def error (asm '{
|
||||||
|
arity 1
|
||||||
|
bytecode [
|
||||||
|
(error 0)
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
|
||||||
(def afiber (fiber (fn [x]
|
(def afiber (fiber (fn [x]
|
||||||
(error (string "hello, " x)))))
|
(error (string "hello, " x)))))
|
||||||
|
|
||||||
@ -124,10 +131,10 @@
|
|||||||
|
|
||||||
(def t (fiber (fn [] (transfer nil 1) (transfer nil 2) 3)))
|
(def t (fiber (fn [] (transfer nil 1) (transfer nil 2) 3)))
|
||||||
|
|
||||||
(assert (= 1 (transfer t)) "initial transfer to new thread")
|
(assert (= 1 (transfer t)) "initial transfer to new fiber")
|
||||||
(assert (= 2 (transfer t)) "second transfer to thread")
|
(assert (= 2 (transfer t)) "second transfer to fiber")
|
||||||
(assert (= 3 (transfer t)) "return from thread")
|
(assert (= 3 (transfer t)) "return from fiber")
|
||||||
(assert (= (status t) "dead") "finished thread is dead")
|
(assert (= (status t) "dead") "finished fiber is dead")
|
||||||
|
|
||||||
# Var arg tests
|
# Var arg tests
|
||||||
|
|
||||||
@ -139,13 +146,6 @@
|
|||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(def error (asm '{
|
|
||||||
arity 1
|
|
||||||
bytecode [
|
|
||||||
(error 0)
|
|
||||||
]
|
|
||||||
}))
|
|
||||||
|
|
||||||
(def vargf (fn [more] (apply + more)))
|
(def vargf (fn [more] (apply + more)))
|
||||||
|
|
||||||
(assert (= 0 (vargf [])) "var arg no arguments")
|
(assert (= 0 (vargf [])) "var arg no arguments")
|
||||||
@ -169,4 +169,4 @@
|
|||||||
# report
|
# report
|
||||||
|
|
||||||
(print "\n" num-tests-passed " of " num-tests-run " tests passed\n")
|
(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 stacktop; /* Top of stack. Where values are pushed and popped from. */
|
||||||
int32_t capacity;
|
int32_t capacity;
|
||||||
enum {
|
enum {
|
||||||
DST_FIBER_PENDING = 0,
|
DST_FIBER_PENDING,
|
||||||
|
DST_FIBER_NEW,
|
||||||
DST_FIBER_ALIVE,
|
DST_FIBER_ALIVE,
|
||||||
DST_FIBER_DEAD,
|
DST_FIBER_DEAD,
|
||||||
DST_FIBER_ERROR
|
DST_FIBER_ERROR
|
||||||
|
Loading…
Reference in New Issue
Block a user