diff --git a/CMakeLists.txt b/CMakeLists.txt index 28ab24ef..d86ba004 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,14 +69,15 @@ src/core/wrap.c src/core/gc.h src/core/fiber.h src/core/symcache.h +src/core/state.h src/core/util.h ) set(MAINCLIENT_SOURCES +clientinit.h src/mainclient/main.c src/mainclient/line.c src/mainclient/line.h -clientinit.h ) set(PARSER_SOURCES @@ -105,7 +106,6 @@ src/include/dst/dstcompile.h src/include/dst/dstconfig.h src/include/dst/dstopcodes.h src/include/dst/dstparse.h -src/include/dst/dststate.h src/include/dst/dstcorelib.h src/include/dst/dsttypes.h ) diff --git a/src/assembler/asm.c b/src/assembler/asm.c index 14ea0384..9dd443c4 100644 --- a/src/assembler/asm.c +++ b/src/assembler/asm.c @@ -139,7 +139,7 @@ static const DstInstructionDef dst_ops[] = { /* Check a dst string against a bunch of test_strings. Return the * index of the matching test_string, or -1 if not found. */ -static int32_t strsearch(const uint8_t *str, const char **test_strings) { +static int32_t strsearch(const uint8_t *str, const char *const *test_strings) { int32_t len = dst_string_length(str); int index; for (index = 0; ; index++) { diff --git a/src/core/corelib.c b/src/core/corelib.c index 60572871..76c80378 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -22,6 +22,7 @@ #include #include +#include "state.h" int dst_core_print(DstArgs args) { int32_t i; diff --git a/src/core/gc.c b/src/core/gc.c index e593a7ab..abc313ff 100644 --- a/src/core/gc.c +++ b/src/core/gc.c @@ -21,6 +21,7 @@ */ #include +#include "state.h" #include "symcache.h" #include "gc.h" @@ -382,3 +383,7 @@ void dst_clear_memory(void) { } dst_vm_blocks = NULL; } + +/* Primitives for suspending GC. */ +int dst_gclock() { return dst_vm_gc_suspend++; } +void dst_gcunlock(int handle) { dst_vm_gc_suspend = handle; } diff --git a/src/core/gc.h b/src/core/gc.h index 491523b9..e68cb48c 100644 --- a/src/core/gc.h +++ b/src/core/gc.h @@ -39,6 +39,8 @@ #define dst_gc_unmark(m) (dst_gc_header(m)->flags &= ~DST_MEM_COLOR) #define dst_gc_reachable(m) (dst_gc_header(m)->flags & DST_MEM_REACHABLE) +// #define dst_gclock() (dst_vm_gc_suspend++) +// #define dst_gcunlock(lock) (dst_vm_gc_suspend = lock) /* Memory header struct. Node of a linked list of memory blocks. */ typedef struct DstGCMemoryHeader DstGCMemoryHeader; diff --git a/src/include/dst/dststate.h b/src/core/state.h similarity index 94% rename from src/include/dst/dststate.h rename to src/core/state.h index e4b1dc84..d3d5da65 100644 --- a/src/include/dst/dststate.h +++ b/src/core/state.h @@ -28,11 +28,8 @@ extern "C" { #endif #include -#include "dstconfig.h" -#include "dsttypes.h" - -/* Names of all of the types */ -extern const char *dst_type_names[16]; +#include +#include /* The VM state. Rather than a struct that is passed * around, the vm state is global for simplicity. */ @@ -40,18 +37,18 @@ extern const char *dst_type_names[16]; /* How many VM stacks have been entered */ extern DST_THREAD_LOCAL int dst_vm_stackn; -/* Garbage collection */ -extern DST_THREAD_LOCAL void *dst_vm_blocks; -extern DST_THREAD_LOCAL uint32_t dst_vm_gc_interval; -extern DST_THREAD_LOCAL uint32_t dst_vm_next_collection; -extern DST_THREAD_LOCAL int dst_vm_gc_suspend; - /* Immutable value cache */ extern DST_THREAD_LOCAL const uint8_t **dst_vm_cache; extern DST_THREAD_LOCAL uint32_t dst_vm_cache_capacity; extern DST_THREAD_LOCAL uint32_t dst_vm_cache_count; extern DST_THREAD_LOCAL uint32_t dst_vm_cache_deleted; +/* Garbage collection */ +extern DST_THREAD_LOCAL void *dst_vm_blocks; +extern DST_THREAD_LOCAL uint32_t dst_vm_gc_interval; +extern DST_THREAD_LOCAL uint32_t dst_vm_next_collection; +extern DST_THREAD_LOCAL int dst_vm_gc_suspend; + /* GC roots */ extern DST_THREAD_LOCAL Dst *dst_vm_roots; extern DST_THREAD_LOCAL uint32_t dst_vm_root_count; diff --git a/src/core/symcache.c b/src/core/symcache.c index de1c9183..f4101807 100644 --- a/src/core/symcache.c +++ b/src/core/symcache.c @@ -26,6 +26,7 @@ * whole program. Equality is then just a pointer check. */ #include +#include "state.h" #include "gc.h" #include "util.h" diff --git a/src/core/util.c b/src/core/util.c index c251704d..db3780a9 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -33,7 +33,7 @@ const char dst_base64[65] = /* The DST value types in order. These types can be used as * mnemonics instead of a bit pattern for type checking */ -const char *dst_type_names[16] = { +const char *const dst_type_names[16] = { ":nil", ":false", ":true", diff --git a/src/core/vm.c b/src/core/vm.c index 24771ab4..d99bb115 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -22,6 +22,7 @@ #include #include +#include "state.h" #include "fiber.h" #include "gc.h" #include "symcache.h" @@ -29,6 +30,10 @@ /* VM state */ DST_THREAD_LOCAL int dst_vm_stackn = 0; +/* Maybe collect garbage */ +#define dst_maybe_collect() do {\ + if (dst_vm_next_collection >= dst_vm_gc_interval) dst_collect(); } while (0) + /* Start running the VM from where it left off. */ Dst dst_run(DstFiber *fiber) { diff --git a/src/include/dst/dst.h b/src/include/dst/dst.h index ebb390b6..da6ff46f 100644 --- a/src/include/dst/dst.h +++ b/src/include/dst/dst.h @@ -35,7 +35,6 @@ extern "C" { #include #include "dsttypes.h" -#include "dststate.h" /* Array functions */ DstArray *dst_array(int32_t capacity); @@ -154,10 +153,8 @@ void dst_clear_memory(void); void dst_gcroot(Dst root); int dst_gcunroot(Dst root); int dst_gcunrootall(Dst root); -#define dst_maybe_collect() do {\ - if (dst_vm_next_collection >= dst_vm_gc_interval) dst_collect(); } while (0) -#define dst_gclock() (dst_vm_gc_suspend++) -#define dst_gcunlock(lock) (dst_vm_gc_suspend = lock) +int dst_gclock(); +void dst_gcunlock(int handle); /* Functions */ DstFuncDef *dst_funcdef_alloc(void); diff --git a/src/include/dst/dstconfig.h b/src/include/dst/dstconfig.h index 77247f0f..2c7ad118 100644 --- a/src/include/dst/dstconfig.h +++ b/src/include/dst/dstconfig.h @@ -49,7 +49,9 @@ extern "C" { || defined(unix) || defined(__unix) || defined(__unix__) #define DST_UNIX 1 /* Enable certain posix features */ +#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L +#endif #elif defined(__EMSCRIPTEN__) #define DST_WEB 1 #elif defined(WIN32) || defined(_WIN32) diff --git a/src/include/dst/dstcorelib.h b/src/include/dst/dstcorelib.h index 5e6a7400..838d362a 100644 --- a/src/include/dst/dstcorelib.h +++ b/src/include/dst/dstcorelib.h @@ -32,7 +32,7 @@ extern "C" { /* Native */ int dst_core_native(DstArgs args); -/* Math functions */ +/* Arithmetic */ int dst_int(DstArgs args); int dst_real(DstArgs args); int dst_add(DstArgs args); @@ -62,6 +62,8 @@ int dst_lshift(DstArgs args); int dst_rshift(DstArgs args); int dst_lshiftu(DstArgs args); int dst_not(DstArgs args); + +/* Math */ int dst_cos(DstArgs args); int dst_sin(DstArgs args); int dst_tan(DstArgs args); @@ -94,14 +96,16 @@ int dst_core_rawget(DstArgs args); int dst_core_getproto(DstArgs args); int dst_core_setproto(DstArgs args); int dst_core_put(DstArgs args); -int dst_core_gccollect(DstArgs args); -int dst_core_gcsetinterval(DstArgs args); -int dst_core_gcinterval(DstArgs args); int dst_core_type(DstArgs args); int dst_core_next(DstArgs args); int dst_core_hash(DstArgs args); int dst_core_string_slice(DstArgs args); +/* GC */ +int dst_core_gccollect(DstArgs args); +int dst_core_gcsetinterval(DstArgs args); +int dst_core_gcinterval(DstArgs args); + /* Initialize builtin libraries */ int dst_lib_io(DstArgs args); int dst_lib_math(DstArgs args); diff --git a/src/include/dst/dsttypes.h b/src/include/dst/dsttypes.h index feb519e5..806cba47 100644 --- a/src/include/dst/dsttypes.h +++ b/src/include/dst/dsttypes.h @@ -29,6 +29,9 @@ extern "C" { #include "dstconfig.h" +/* Names of all of the types */ +extern const char *const dst_type_names[16]; + #ifdef DST_NANBOX typedef union Dst Dst; #else diff --git a/test/suite1.dst b/test/suite1.dst index efb6a42b..5c317d90 100644 --- a/test/suite1.dst +++ b/test/suite1.dst @@ -1,4 +1,5 @@ # Copyright (c) 2017 Calvin Rose + # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -40,4 +41,30 @@ (assert (= (myfun true) 8) "check do form regression") (assert (= (myfun false) 9) "check do form regression") +(defn assert-many [f n e] + (var good true) + (for [i 0 n] + (if (not (f i)) + (:= good false))) + (assert good e)) + +(assert-many (fn [] (>= 1 (random) 0)) 200 "(random) between 0 and 1") + +## Table prototypes + +(def roottab @{ + :parentprop 123 +}) + +(def childtab @{ + :childprop 456 +}) + +(setproto childtab roottab) + +(assert (= 123 (get roottab :parentprop)), "table get 1") +(assert (= 123 (get childtab :parentprop)), "table get proto") +(assert (= nil (get roottab :childprop)), "table get 2") +(assert (= 456 (get childtab :childprop)), "proto no effect") + (end-suite)