From f18ad36b1bd22a3b2a0888472b46bed9c252e65e Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 11 Oct 2023 00:58:00 -0500 Subject: [PATCH 01/11] Rework #1306 - better default for pretty printing numbers. Not perfect for serialization, but a representation that plays well with both safe integers (z where abs(z) < 2^54) and non-integer floats. --- src/core/pp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/pp.c b/src/core/pp.c index 261fca04..89ecc141 100644 --- a/src/core/pp.c +++ b/src/core/pp.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Implements a pretty printer for Janet. The pretty printer * is simple and not that flexible, but fast. */ @@ -38,11 +39,15 @@ /* Temporary buffer size */ #define BUFSIZE 64 +/* Preprocessor hacks */ +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + static void number_to_string_b(JanetBuffer *buffer, double x) { janet_buffer_ensure(buffer, buffer->count + BUFSIZE, 2); const char *fmt = (x == floor(x) && x <= JANET_INTMAX_DOUBLE && - x >= JANET_INTMIN_DOUBLE) ? "%.0f" : "%g"; + x >= JANET_INTMIN_DOUBLE) ? "%.0f" : ("%." STR(DBL_DIG) "g"); int count; if (x == 0.0) { /* Prevent printing of '-0' */ From e3f4142d2ae825ff4706ebe4970c389c8f087b77 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 12 Oct 2023 05:26:23 -0500 Subject: [PATCH 02/11] Update result value from janet_do* functions. --- .gitignore | 5 ++++- src/core/run.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 123cf5fb..b95e115b 100644 --- a/.gitignore +++ b/.gitignore @@ -34,8 +34,11 @@ local # Common test files I use. temp.janet -temp*.janet +temp.c +temp*janet +temp*.c scratch.janet +scratch.c # Emscripten *.bc diff --git a/src/core/run.c b/src/core/run.c index 9532e683..c0698231 100644 --- a/src/core/run.c +++ b/src/core/run.c @@ -32,6 +32,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char int errflags = 0, done = 0; int32_t index = 0; Janet ret = janet_wrap_nil(); + JanetFiber *fiber = NULL; const uint8_t *where = sourcePath ? janet_cstring(sourcePath) : NULL; if (where) janet_gcroot(janet_wrap_string(where)); @@ -47,7 +48,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char JanetCompileResult cres = janet_compile(form, env, where); if (cres.status == JANET_COMPILE_OK) { JanetFunction *f = janet_thunk(cres.funcdef); - JanetFiber *fiber = janet_fiber(f, 64, 0, NULL); + fiber = janet_fiber(f, 64, 0, NULL); fiber->env = env; JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret); if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) { @@ -112,9 +113,14 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char #ifdef JANET_EV /* Enter the event loop if we are not already in it */ if (janet_vm.stackn == 0) { - janet_gcroot(ret); + if (fiber) { + janet_gcroot(janet_wrap_fiber(fiber)); + } janet_loop(); - janet_gcunroot(ret); + if (fiber) { + janet_gcunroot(janet_wrap_fiber(fiber)); + ret = fiber->last_value; + } } #endif if (out) *out = ret; From 83204dc2936febf6f9b42f540d0b0fe3ef3c5faa Mon Sep 17 00:00:00 2001 From: Andriamanitra Date: Sat, 14 Oct 2023 14:21:16 +0300 Subject: [PATCH 03/11] Change Alt-f in the REPL move to next end of word instead of beginning --- src/mainclient/shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index a85b2246..696fb352 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -502,10 +502,10 @@ static void kright(void) { } static void krightw(void) { - while (gbl_pos != gbl_len && !isspace(gbl_buf[gbl_pos])) { + while (gbl_pos != gbl_len && isspace(gbl_buf[gbl_pos])) { gbl_pos++; } - while (gbl_pos != gbl_len && isspace(gbl_buf[gbl_pos])) { + while (gbl_pos != gbl_len && !isspace(gbl_buf[gbl_pos])) { gbl_pos++; } refresh(); From b5996f5f0264660abe1b45bf687df11aa40126e8 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 14 Oct 2023 19:48:20 -0500 Subject: [PATCH 04/11] Update for 1.32.0 --- CHANGELOG.md | 3 ++- Makefile | 4 ++-- meson.build | 2 +- src/conf/janetconf.h | 4 ++-- src/core/ffi.c | 8 ++++---- src/core/fiber.c | 8 ++++---- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de900ee1..91f0c5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog All notable changes to this project will be documented in this file. -## Unreleased - ??? +## 1.32.0 - 2023-10-14 +- Fix return value from C function `janet_dobytes` when called on Janet functions that yield to event loop. - Change C API for event loop interaction - get rid of JanetListener and instead use `janet_async_start` and `janet_async_end`. - Rework event loop to make fewer system calls on kqueue and epoll. - Expose atomic refcount abstraction in janet.h diff --git a/Makefile b/Makefile index 5bd9bfe4..abee818d 100644 --- a/Makefile +++ b/Makefile @@ -196,9 +196,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile ######################## ifeq ($(UNAME), Darwin) -SONAME=libjanet.1.31.dylib +SONAME=libjanet.1.32.dylib else -SONAME=libjanet.so.1.31 +SONAME=libjanet.so.1.32 endif build/c/shell.c: src/mainclient/shell.c diff --git a/meson.build b/meson.build index b58b5d96..577fa0d1 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,7 @@ project('janet', 'c', default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'], - version : '1.31.0') + version : '1.32.0') # Global settings janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet') diff --git a/src/conf/janetconf.h b/src/conf/janetconf.h index 831360fb..c4815029 100644 --- a/src/conf/janetconf.h +++ b/src/conf/janetconf.h @@ -4,10 +4,10 @@ #define JANETCONF_H #define JANET_VERSION_MAJOR 1 -#define JANET_VERSION_MINOR 31 +#define JANET_VERSION_MINOR 32 #define JANET_VERSION_PATCH 0 #define JANET_VERSION_EXTRA "" -#define JANET_VERSION "1.31.0" +#define JANET_VERSION "1.32.0" /* #define JANET_BUILD "local" */ diff --git a/src/core/ffi.c b/src/core/ffi.c index 03fccfd1..6aed7e32 100644 --- a/src/core/ffi.c +++ b/src/core/ffi.c @@ -999,13 +999,13 @@ typedef struct { uint64_t x; } sysv64_sseint_return; typedef sysv64_int_return janet_sysv64_variant_1(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, - double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); + double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); typedef sysv64_sse_return janet_sysv64_variant_2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, - double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); + double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); typedef sysv64_intsse_return janet_sysv64_variant_3(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, - double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); + double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); typedef sysv64_sseint_return janet_sysv64_variant_4(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, - double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); + double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_pointer, const Janet *argv) { union { diff --git a/src/core/fiber.c b/src/core/fiber.c index d5f51599..73871a4a 100644 --- a/src/core/fiber.c +++ b/src/core/fiber.c @@ -239,8 +239,8 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) { fiber->data + tuplehead, oldtop - tuplehead) : janet_wrap_tuple(janet_tuple_n( - fiber->data + tuplehead, - oldtop - tuplehead)); + fiber->data + tuplehead, + oldtop - tuplehead)); } } @@ -370,8 +370,8 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) { fiber->data + tuplehead, fiber->stacktop - tuplehead) : janet_wrap_tuple(janet_tuple_n( - fiber->data + tuplehead, - fiber->stacktop - tuplehead)); + fiber->data + tuplehead, + fiber->stacktop - tuplehead)); } stacksize = tuplehead - fiber->stackstart + 1; } else { From 21ebede5291a9178db9cd7d4263278431f1f614a Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 15 Oct 2023 11:03:26 -0500 Subject: [PATCH 05/11] Move posix-fork inside correct if-def Don't compile if processes are disabled. --- src/core/os.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/core/os.c b/src/core/os.c index 8d757959..425e6e73 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -1395,6 +1395,34 @@ JANET_CORE_FN(os_posix_exec, return os_execute_impl(argc, argv, JANET_EXECUTE_EXEC); } +JANET_CORE_FN(os_posix_fork, + "(os/posix-fork)", + "Make a `fork` system call and create a new process. Return nil if in the new process, otherwise a core/process object (as returned by os/spawn). " + "Not supported on all systems (POSIX only).") { + janet_sandbox_assert(JANET_SANDBOX_SUBPROCESS); + janet_fixarity(argc, 0); + (void) argv; +#ifdef JANET_WINDOWS + janet_panic("not supported"); +#else + pid_t result; + do { + result = fork(); + } while (result == -1 && errno == EINTR); + if (result == -1) { + janet_panic(strerror(errno)); + } + if (result) { + JanetProc *proc = janet_abstract(&ProcAT, sizeof(JanetProc)); + memset(proc, 0, sizeof(JanetProc)); + proc->pid = result; + proc->flags = JANET_PROC_ALLOW_ZOMBIE; + return janet_wrap_abstract(proc); + } + return janet_wrap_nil(); +#endif +} + #ifdef JANET_EV /* Runs in a separate thread */ static JanetEVGenericMessage os_shell_subr(JanetEVGenericMessage args) { @@ -2371,34 +2399,6 @@ JANET_CORE_FN(os_permission_int, return janet_wrap_integer(os_get_unix_mode(argv, 0)); } -JANET_CORE_FN(os_posix_fork, - "(os/posix-fork)", - "Make a `fork` system call and create a new process. Return nil if in the new process, otherwise a core/process object (as returned by os/spawn). " - "Not supported on all systems (POSIX only).") { - janet_sandbox_assert(JANET_SANDBOX_SUBPROCESS); - janet_fixarity(argc, 0); - (void) argv; -#ifdef JANET_WINDOWS - janet_panic("not supported"); -#else - pid_t result; - do { - result = fork(); - } while (result == -1 && errno == EINTR); - if (result == -1) { - janet_panic(strerror(errno)); - } - if (result) { - JanetProc *proc = janet_abstract(&ProcAT, sizeof(JanetProc)); - memset(proc, 0, sizeof(JanetProc)); - proc->pid = result; - proc->flags = JANET_PROC_ALLOW_ZOMBIE; - return janet_wrap_abstract(proc); - } - return janet_wrap_nil(); -#endif -} - #ifdef JANET_EV /* From a363fd926dd7adedabc9288748048b769d8e666e Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 15 Oct 2023 14:32:56 -0500 Subject: [PATCH 06/11] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f0c5f9..64c08561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog All notable changes to this project will be documented in this file. -## 1.32.0 - 2023-10-14 +## 1.32.1 - 2023-10-15 - Fix return value from C function `janet_dobytes` when called on Janet functions that yield to event loop. - Change C API for event loop interaction - get rid of JanetListener and instead use `janet_async_start` and `janet_async_end`. - Rework event loop to make fewer system calls on kqueue and epoll. From cc5beda0d26c0b91fb28540291e950392cf59fc4 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 15 Oct 2023 14:33:43 -0500 Subject: [PATCH 07/11] Update patch release. --- meson.build | 2 +- src/conf/janetconf.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 577fa0d1..aa31eba7 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,7 @@ project('janet', 'c', default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'], - version : '1.32.0') + version : '1.32.1') # Global settings janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet') diff --git a/src/conf/janetconf.h b/src/conf/janetconf.h index c4815029..4bc6046d 100644 --- a/src/conf/janetconf.h +++ b/src/conf/janetconf.h @@ -5,9 +5,9 @@ #define JANET_VERSION_MAJOR 1 #define JANET_VERSION_MINOR 32 -#define JANET_VERSION_PATCH 0 +#define JANET_VERSION_PATCH 1 #define JANET_VERSION_EXTRA "" -#define JANET_VERSION "1.32.0" +#define JANET_VERSION "1.32.1" /* #define JANET_BUILD "local" */ From 1b17e12fd6322f79aed13cd3d5ffddfe5787eb7a Mon Sep 17 00:00:00 2001 From: sogaiu <983021772@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:45:20 +0900 Subject: [PATCH 08/11] Add more + and * keywords to default-peg-grammar --- src/boot/boot.janet | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index a72b3c79..de66320f 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -2333,26 +2333,36 @@ (def default-peg-grammar `The default grammar used for pegs. This grammar defines several common patterns that should make it easier to write more complex patterns.` - ~@{:d (range "09") - :a (range "az" "AZ") + ~@{:a (range "az" "AZ") + :d (range "09") + :h (range "09" "af" "AF") :s (set " \t\r\n\0\f\v") :w (range "az" "AZ" "09") - :h (range "09" "af" "AF") - :S (if-not :s 1) - :W (if-not :w 1) :A (if-not :a 1) :D (if-not :d 1) :H (if-not :h 1) - :d+ (some :d) + :S (if-not :s 1) + :W (if-not :w 1) :a+ (some :a) + :d+ (some :d) + :h+ (some :h) :s+ (some :s) :w+ (some :w) - :h+ (some :h) - :d* (any :d) + :A+ (some :A) + :D+ (some :D) + :H+ (some :H) + :S+ (some :S) + :W+ (some :W) :a* (any :a) - :w* (any :w) + :d* (any :d) + :h* (any :h) :s* (any :s) - :h* (any :h)}) + :w* (any :w) + :A* (any :A) + :D* (any :D) + :H* (any :H) + :S* (any :S) + :W* (any :W)}) (setdyn *peg-grammar* default-peg-grammar) From 045c80869d3766004b71481cb865e97ebfd34532 Mon Sep 17 00:00:00 2001 From: Vincent Lee Date: Thu, 19 Oct 2023 23:29:51 -0700 Subject: [PATCH 09/11] Use libc strlen in janet_buffer_push_cstring Platform libc's often contains optimized assembly implementations of strlen, so take advantage of them here instead of doing a naive count. --- src/core/buffer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/buffer.c b/src/core/buffer.c index 16f20248..aee32e58 100644 --- a/src/core/buffer.c +++ b/src/core/buffer.c @@ -135,8 +135,7 @@ void janet_buffer_extra(JanetBuffer *buffer, int32_t n) { /* Push a cstring to buffer */ void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring) { - int32_t len = 0; - while (cstring[len]) ++len; + int32_t len = strlen(cstring); janet_buffer_push_bytes(buffer, (const uint8_t *) cstring, len); } From e74365fe38fa9da0e72ddcd7c9140a405e027a81 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 21 Oct 2023 09:43:28 -0500 Subject: [PATCH 10/11] Be a bit safer with reference counting. We might want to revisit some uses of refcounts in the ev module to be more efficient if we care about signal atomicity (where memory order isn't really important) or multithreading atomicity. --- src/core/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/capi.c b/src/core/capi.c index c58a2811..498ffa97 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -505,7 +505,7 @@ JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) { #ifdef JANET_WINDOWS return InterlockedDecrement(x); #else - return __atomic_add_fetch(x, -1, __ATOMIC_RELAXED); + return __atomic_add_fetch(x, -1, __ATOMIC_ACQ_REL); #endif } From 609b629c2295e7df71314dbb7b2ca2be83063bdf Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 21 Oct 2023 10:40:57 -0500 Subject: [PATCH 11/11] Add support for atomic loads in Janet's atomic abstraction. --- src/core/capi.c | 8 ++++++++ src/core/ev.c | 6 +++--- src/include/janet.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/capi.c b/src/core/capi.c index 498ffa97..0f82910b 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -509,6 +509,14 @@ JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) { #endif } +JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) { +#ifdef JANET_WINDOWS + return InterlockedOr(x, 0); +#else + return __atomic_load_n(x, __ATOMIC_ACQUIRE); +#endif +} + /* Some definitions for function-like macros */ JANET_API JanetStructHead *(janet_struct_head)(JanetStruct st) { diff --git a/src/core/ev.c b/src/core/ev.c index 2523809a..0fe1bf7f 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -1284,7 +1284,7 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout); int janet_loop_done(void) { return !((janet_vm.spawn.head != janet_vm.spawn.tail) || janet_vm.tq_count || - janet_vm.listener_count); + janet_atomic_load(&janet_vm.listener_count)); } JanetFiber *janet_loop1(void) { @@ -1346,7 +1346,7 @@ JanetFiber *janet_loop1(void) { } /* Poll for events */ - if (janet_vm.tq_count || janet_vm.listener_count) { + if (janet_vm.tq_count || janet_atomic_load(&janet_vm.listener_count)) { JanetTimeout to; memset(&to, 0, sizeof(to)); int has_timeout; @@ -1365,7 +1365,7 @@ JanetFiber *janet_loop1(void) { break; } /* Run polling implementation only if pending timeouts or pending events */ - if (janet_vm.tq_count || janet_vm.listener_count) { + if (janet_vm.tq_count || janet_atomic_load(&janet_vm.listener_count)) { janet_loop1_impl(has_timeout, to.when); } } diff --git a/src/include/janet.h b/src/include/janet.h index ea7d34db..5724af2b 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -647,6 +647,7 @@ typedef int32_t JanetAtomicInt; #endif JANET_API JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x); JANET_API JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x); +JANET_API JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x); /* We provide three possible implementations of Janets. The preferred * nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the