From 52d3470cbe31d2c9ceb643efea377070db29eaae Mon Sep 17 00:00:00 2001 From: Christopher Chambers Date: Fri, 9 Jun 2023 12:32:14 -0400 Subject: [PATCH 01/15] Fix order in which *macro-lints* is set during expansion Previously, `*macro-lints*` was set after the `macroexpand1` fiber was resumed, rather than just before. And, `*macro-lints*` was never cleared. This behavior was typically fine since the main users of `compile` pass the same lint array repeatedly, and the first macro expansion (somewhere in boot.janet) never produces a lint. But, when compiling with a fresh lint array, if the first macro invocation produced a lint, the lint was always lost. --- src/core/compile.c | 8 +++++--- test/suite-boot.janet | 8 +++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/core/compile.c b/src/core/compile.c index 8ab0e3a2..4f45ff1f 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -746,12 +746,14 @@ static int macroexpand1( int lock = janet_gclock(); Janet mf_kw = janet_ckeywordv("macro-form"); janet_table_put(c->env, mf_kw, x); + Janet ml_kw = janet_ckeywordv("macro-lints"); + if (c->lints) { + janet_table_put(c->env, ml_kw, janet_wrap_array(c->lints)); + } Janet tempOut; JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &tempOut); janet_table_put(c->env, mf_kw, janet_wrap_nil()); - if (c->lints) { - janet_table_put(c->env, janet_ckeywordv("macro-lints"), janet_wrap_array(c->lints)); - } + janet_table_put(c->env, ml_kw, janet_wrap_nil()); janet_gcunlock(lock); if (status != JANET_SIGNAL_OK) { const uint8_t *es = janet_formatc("(macro) %V", tempOut); diff --git a/test/suite-boot.janet b/test/suite-boot.janet index 49a022cb..6282a212 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -877,5 +877,11 @@ (assert (= (thunk) 1) "delay 3") (assert (= counter 1) "delay 4") -(end-suite) +# maclintf +(def env (table/clone (curenv))) +((compile '(defmacro foo [] (maclintf :strict "oops")) env :anonymous)) +(def lints @[]) +(compile (tuple/setmap '(foo) 1 2) env :anonymous lints) +(assert (deep= lints @[[:strict 1 2 "oops"]]) "maclintf 1") +(end-suite) From 163f7ee85d6f07af92b6d899a605a5587dd42bd9 Mon Sep 17 00:00:00 2001 From: Christopher Chambers Date: Sat, 10 Jun 2023 16:52:20 -0400 Subject: [PATCH 02/15] Add test for maclintf in nested macro invocations --- test/suite-boot.janet | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/suite-boot.janet b/test/suite-boot.janet index 6282a212..af4320b3 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -884,4 +884,15 @@ (compile (tuple/setmap '(foo) 1 2) env :anonymous lints) (assert (deep= lints @[[:strict 1 2 "oops"]]) "maclintf 1") +(def env (table/clone (curenv))) +((compile '(defmacro foo [& body] (maclintf :strict "foo-oops") ~(do ,;body)) env :anonymous)) +((compile '(defmacro bar [] (maclintf :strict "bar-oops")) env :anonymous)) +(def lints @[]) +# Compile (foo (bar)), but with explicit source map values +(def bar-invoke (tuple/setmap '(bar) 3 4)) +(compile (tuple/setmap ~(foo ,bar-invoke) 1 2) env :anonymous lints) +(assert (deep= lints @[[:strict 1 2 "foo-oops"] + [:strict 3 4 "bar-oops"]]) + "maclintf 2") + (end-suite) From f9ab91511d42fe817bd409f928e9158ec65f84b9 Mon Sep 17 00:00:00 2001 From: Chloe Kudryavtsev Date: Sun, 11 Jun 2023 10:44:39 +0200 Subject: [PATCH 03/15] peg: add support for "true" and "false" primitives to always/never match The use cases involve user-expandable grammars. For example, consider the IRC nickname specification. > They SHOULD NOT contain any dot character ('.', 0x2E). > Servers MAY have additional implementation-specific nickname restrictions. To implement this, we can do something along these lines: ```janet (def nickname @{:main '(some :allowed) :allowed (! (+ :forbidden/dot :forbidden/user)) # for lax mode, (put nickname :forbidden/dot false) :forbidden/dot "." # to add your own requirements # (put nickname :forbidden/user 'something) :forbidden/user false}) ``` Additionally, it's common in parsing theory to allow matches of the empty string (epsilon). `true` essentially allows for this. Note that this does not strictly add new functionality, you could emulate this previously using `0` and `(! 0)` respectively, but this should be faster and more intuitive. The speed improvement primarily comes from `(! 0)` which is now a single step. --- src/core/peg.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/peg.c b/src/core/peg.c index a814e65f..a087ddfa 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -735,6 +735,12 @@ static const uint8_t *peg_getrange(Builder *b, Janet x) { return str; } +static int32_t peg_getboolean(Builder *b, Janet x) { + if (!janet_checktype(x, JANET_BOOLEAN)) + peg_panicf(b, "expected boolean, got %v", x); + return janet_unwrap_boolean(x); +} + static int32_t peg_getinteger(Builder *b, Janet x) { if (!janet_checkint(x)) peg_panicf(b, "expected integer, got %v", x); @@ -1261,6 +1267,13 @@ static uint32_t peg_compile1(Builder *b, Janet peg) { default: peg_panic(b, "unexpected peg source"); return 0; + + case JANET_BOOLEAN: { + int n = peg_getboolean(b, peg); + Reserve r = reserve(b, 2); + emit_1(r, n ? RULE_NCHAR : RULE_NOTNCHAR, 0); + break; + } case JANET_NUMBER: { int32_t n = peg_getinteger(b, peg); Reserve r = reserve(b, 2); From 1077efd03a9699132735f6c1b543106070a18d24 Mon Sep 17 00:00:00 2001 From: primo-ppcg Date: Sun, 11 Jun 2023 16:38:04 +0700 Subject: [PATCH 04/15] update if-let Fixes #1189 --- src/boot/boot.janet | 6 +++++- test/suite-boot.janet | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 602c8a2e..4c158f44 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -674,7 +674,11 @@ (do (def bl (in bindings i)) (def br (in bindings (+ 1 i))) - (tuple 'if (tuple 'def bl br) (aux (+ 2 i)) fal)))) + (if (symbol? bl) + (tuple 'if (tuple 'def bl br) (aux (+ 2 i)) fal) + (tuple 'if (tuple 'def (def sym (gensym)) br) + (tuple 'do (tuple 'def bl sym) (aux (+ 2 i))) + fal))))) (aux 0)) (defmacro when-let diff --git a/test/suite-boot.janet b/test/suite-boot.janet index 17cdb0d5..18a3074c 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -129,6 +129,8 @@ (assert (= (if-let [a my-array k (next a 5)] :t :f) :f) "if-let 4") (assert (= (if-let [[a b] my-array] a) 1) "if-let 5") (assert (= (if-let [{:a a :b b} {:a 1 :b 2}] b) 2) "if-let 6") +(assert (= (if-let [[a b] nil] :t :f) :f) "if-let 7") +(assert (= (if-let [a true b false] b a) true) "if-let 8") (assert (= 14 (sum (map inc @[1 2 3 4]))) "sum map") (def myfun (juxt + - * /)) From e54ea7a1d8ffeb03a81d96461dd152e744d4f884 Mon Sep 17 00:00:00 2001 From: Chloe Kudryavtsev Date: Sun, 11 Jun 2023 12:38:40 +0200 Subject: [PATCH 05/15] fixup! peg: add support for "true" and "false" primitives to always/never match --- src/core/peg.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/peg.c b/src/core/peg.c index a087ddfa..fa7aef20 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -736,9 +736,9 @@ static const uint8_t *peg_getrange(Builder *b, Janet x) { } static int32_t peg_getboolean(Builder *b, Janet x) { - if (!janet_checktype(x, JANET_BOOLEAN)) - peg_panicf(b, "expected boolean, got %v", x); - return janet_unwrap_boolean(x); + if (!janet_checktype(x, JANET_BOOLEAN)) + peg_panicf(b, "expected boolean, got %v", x); + return janet_unwrap_boolean(x); } static int32_t peg_getinteger(Builder *b, Janet x) { @@ -1268,12 +1268,12 @@ static uint32_t peg_compile1(Builder *b, Janet peg) { peg_panic(b, "unexpected peg source"); return 0; - case JANET_BOOLEAN: { - int n = peg_getboolean(b, peg); - Reserve r = reserve(b, 2); - emit_1(r, n ? RULE_NCHAR : RULE_NOTNCHAR, 0); - break; - } + case JANET_BOOLEAN: { + int n = peg_getboolean(b, peg); + Reserve r = reserve(b, 2); + emit_1(r, n ? RULE_NCHAR : RULE_NOTNCHAR, 0); + break; + } case JANET_NUMBER: { int32_t n = peg_getinteger(b, peg); Reserve r = reserve(b, 2); From 32c5b816ae888c346a3525cc2729950d26831a02 Mon Sep 17 00:00:00 2001 From: primo-ppcg Date: Sun, 11 Jun 2023 18:38:20 +0700 Subject: [PATCH 06/15] use unquotes instead --- src/boot/boot.janet | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 4c158f44..43699aa6 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -675,10 +675,10 @@ (def bl (in bindings i)) (def br (in bindings (+ 1 i))) (if (symbol? bl) - (tuple 'if (tuple 'def bl br) (aux (+ 2 i)) fal) - (tuple 'if (tuple 'def (def sym (gensym)) br) - (tuple 'do (tuple 'def bl sym) (aux (+ 2 i))) - fal))))) + ~(if (def ,bl ,br) ,(aux (+ 2 i)) ,fal) + ~(if (def ,(def sym (gensym)) ,br) + (do (def ,bl ,sym) ,(aux (+ 2 i))) + ,fal))))) (aux 0)) (defmacro when-let From 2a7ea27bb73e5fb2285cab5eee53bf4b9e118140 Mon Sep 17 00:00:00 2001 From: primo-ppcg Date: Sun, 11 Jun 2023 19:15:48 +0700 Subject: [PATCH 07/15] do not expand false branch more than once Fixes #1191 --- src/boot/boot.janet | 12 +++++++----- test/suite-boot.janet | 7 ++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 43699aa6..c6c1ff27 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -668,18 +668,20 @@ (def len (length bindings)) (if (= 0 len) (error "expected at least 1 binding")) (if (odd? len) (error "expected an even number of bindings")) + (def res (gensym)) (defn aux [i] (if (>= i len) - tru + ~(do (set ,res ,tru) true) (do (def bl (in bindings i)) (def br (in bindings (+ 1 i))) (if (symbol? bl) - ~(if (def ,bl ,br) ,(aux (+ 2 i)) ,fal) + ~(if (def ,bl ,br) ,(aux (+ 2 i))) ~(if (def ,(def sym (gensym)) ,br) - (do (def ,bl ,sym) ,(aux (+ 2 i))) - ,fal))))) - (aux 0)) + (do (def ,bl ,sym) ,(aux (+ 2 i)))))))) + ~(do + (var ,res nil) + (if ,(aux 0) ,res ,fal))) (defmacro when-let "Same as `(if-let bindings (do ;body))`." diff --git a/test/suite-boot.janet b/test/suite-boot.janet index 18a3074c..77a2bc92 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -130,7 +130,12 @@ (assert (= (if-let [[a b] my-array] a) 1) "if-let 5") (assert (= (if-let [{:a a :b b} {:a 1 :b 2}] b) 2) "if-let 6") (assert (= (if-let [[a b] nil] :t :f) :f) "if-let 7") -(assert (= (if-let [a true b false] b a) true) "if-let 8") + +# #1191 +(var cnt 0) +(defmacro upcnt [] (++ cnt)) +(assert (= (if-let [a true b true c true] nil (upcnt)) nil) "issue #1191") +(assert (= cnt 1) "issue #1191") (assert (= 14 (sum (map inc @[1 2 3 4]))) "sum map") (def myfun (juxt + - * /)) From 2fde34b51915f27e849195d111ffc55a94747e78 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 18 Jun 2023 09:41:53 -0500 Subject: [PATCH 08/15] Remove extra function call that cannot ever trigger. --- src/core/peg.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/peg.c b/src/core/peg.c index fa7aef20..11504cda 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -735,12 +735,6 @@ static const uint8_t *peg_getrange(Builder *b, Janet x) { return str; } -static int32_t peg_getboolean(Builder *b, Janet x) { - if (!janet_checktype(x, JANET_BOOLEAN)) - peg_panicf(b, "expected boolean, got %v", x); - return janet_unwrap_boolean(x); -} - static int32_t peg_getinteger(Builder *b, Janet x) { if (!janet_checkint(x)) peg_panicf(b, "expected integer, got %v", x); @@ -1269,7 +1263,7 @@ static uint32_t peg_compile1(Builder *b, Janet peg) { return 0; case JANET_BOOLEAN: { - int n = peg_getboolean(b, peg); + int n = janet_unwrap_boolean(peg); Reserve r = reserve(b, 2); emit_1(r, n ? RULE_NCHAR : RULE_NOTNCHAR, 0); break; From 5a39a04a79cfb3b64b79462819340a4168e357dc Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 19 Jun 2023 06:48:33 -0500 Subject: [PATCH 09/15] Prepare for 1.29.0 release. --- CHANGELOG.md | 3 ++- Makefile | 4 ++-- src/conf/janetconf.h | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06f9105c..b2c7bbce 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.29.0 - 2023-06-19 +- Add support for passing booleans to PEGs for "always" and "never" matching. - Allow dictionary types for `take` and `drop` - Fix bug with closing channels while other fibers were waiting on them - `ev/take`, `ev/give`, and `ev/select` will now return the correct (documented) value when another fiber closes the channel. - Add `ffi/calling-conventions` to show all available calling conventions for FFI. diff --git a/Makefile b/Makefile index 404f76f2..85b2a7ba 100644 --- a/Makefile +++ b/Makefile @@ -195,9 +195,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile ######################## ifeq ($(UNAME), Darwin) -SONAME=libjanet.1.28.dylib +SONAME=libjanet.1.29.dylib else -SONAME=libjanet.so.1.28 +SONAME=libjanet.so.1.29 endif build/c/shell.c: src/mainclient/shell.c diff --git a/src/conf/janetconf.h b/src/conf/janetconf.h index 73e39d55..be917286 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 28 +#define JANET_VERSION_MINOR 29 #define JANET_VERSION_PATCH 0 -#define JANET_VERSION_EXTRA "-dev" -#define JANET_VERSION "1.28.0-dev" +#define JANET_VERSION_EXTRA "" +#define JANET_VERSION "1.29.0" /* #define JANET_BUILD "local" */ From 63bb93fc0788d6edc09af7549d8251ad763ec7ae Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 19 Jun 2023 07:14:56 -0500 Subject: [PATCH 10/15] Fix isatty code to not use functions only defined if ev is enabled. --- src/core/os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/os.c b/src/core/os.c index e4ec5cd6..70f0449c 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -1437,11 +1437,11 @@ JANET_CORE_FN(os_isatty, FILE *f = (argc == 1) ? janet_getfile(argv, 0, NULL) : stdout; #ifdef JANET_WINDOWS int fd = _fileno(f); - if (fd == -1) janet_panicv(janet_ev_lasterr()); + if (fd == -1) janet_panic("not a valid stream"); return janet_wrap_boolean(_isatty(fd)); #else int fd = fileno(f); - if (fd == -1) janet_panicv(janet_ev_lasterr()); + if (fd == -1) janet_panic(strerror(errno)); return janet_wrap_boolean(isatty(fd)); #endif } From 3a4d56afca2eee0e4dbca9a6400757d198e6d6f3 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 19 Jun 2023 07:18:35 -0500 Subject: [PATCH 11/15] Patch release. --- CHANGELOG.md | 2 +- meson.build | 2 +- src/conf/janetconf.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c7bbce..7ccc67c8 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.29.0 - 2023-06-19 +## 1.29.1 - 2023-06-19 - Add support for passing booleans to PEGs for "always" and "never" matching. - Allow dictionary types for `take` and `drop` - Fix bug with closing channels while other fibers were waiting on them - `ev/take`, `ev/give`, and `ev/select` will now return the correct (documented) value when another fiber closes the channel. diff --git a/meson.build b/meson.build index 4b75e0b7..f0bcd709 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.28.0') + version : '1.29.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 be917286..d4786eb3 100644 --- a/src/conf/janetconf.h +++ b/src/conf/janetconf.h @@ -5,9 +5,9 @@ #define JANET_VERSION_MAJOR 1 #define JANET_VERSION_MINOR 29 -#define JANET_VERSION_PATCH 0 +#define JANET_VERSION_PATCH 1 #define JANET_VERSION_EXTRA "" -#define JANET_VERSION "1.29.0" +#define JANET_VERSION "1.29.1" /* #define JANET_BUILD "local" */ From 78eed9b11c6b48f21e60b1d1ef169b69478a5cfb Mon Sep 17 00:00:00 2001 From: sogaiu <983021772@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:23:07 +0900 Subject: [PATCH 12/15] Use vm_commit --- src/core/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/vm.c b/src/core/vm.c index 444f8d79..ab73499d 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -980,7 +980,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) { if (func->gc.flags & JANET_FUNCFLAG_TRACE) { vm_do_trace(func, fiber->stacktop - fiber->stackstart, fiber->data + fiber->stackstart); } - janet_stack_frame(stack)->pc = pc; + vm_commit(); if (janet_fiber_funcframe(fiber, func)) { int32_t n = fiber->stacktop - fiber->stackstart; janet_panicf("%v called with %d argument%s, expected %d", From f977ace7f8c75f698e468cd4f5add09082dcdaf8 Mon Sep 17 00:00:00 2001 From: Michael Camilleri Date: Fri, 23 Jun 2023 15:50:19 +0900 Subject: [PATCH 13/15] Avoid prematurely closing file descriptors when redirecting IO --- src/core/os.c | 6 ++++-- test/suite-os.janet | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/core/os.c b/src/core/os.c index 70f0449c..65afdce9 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -1145,14 +1145,16 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) { posix_spawn_file_actions_addclose(&actions, pipe_in); } else if (new_in != JANET_HANDLE_NONE && new_in != 0) { posix_spawn_file_actions_adddup2(&actions, new_in, 0); - posix_spawn_file_actions_addclose(&actions, new_in); + if (new_in != new_out && new_in != new_err) + posix_spawn_file_actions_addclose(&actions, new_in); } if (pipe_out != JANET_HANDLE_NONE) { posix_spawn_file_actions_adddup2(&actions, pipe_out, 1); posix_spawn_file_actions_addclose(&actions, pipe_out); } else if (new_out != JANET_HANDLE_NONE && new_out != 1) { posix_spawn_file_actions_adddup2(&actions, new_out, 1); - posix_spawn_file_actions_addclose(&actions, new_out); + if (new_out != new_err) + posix_spawn_file_actions_addclose(&actions, new_out); } if (pipe_err != JANET_HANDLE_NONE) { posix_spawn_file_actions_adddup2(&actions, pipe_err, 2); diff --git a/test/suite-os.janet b/test/suite-os.janet index f88c997d..1af75674 100644 --- a/test/suite-os.janet +++ b/test/suite-os.janet @@ -94,9 +94,9 @@ (assert (= (length buf) 2) "cryptorand appends to buffer")) # 80db68210 -(assert-no-error (os/clock :realtime) "realtime clock") -(assert-no-error (os/clock :cputime) "cputime clock") -(assert-no-error (os/clock :monotonic) "monotonic clock") +(assert-no-error "realtime clock" (os/clock :realtime)) +(assert-no-error "cputime clock" (os/clock :cputime)) +(assert-no-error "monotonic clock" (os/clock :monotonic)) (def before (os/clock :monotonic)) (def after (os/clock :monotonic)) @@ -129,5 +129,16 @@ (string/format "(os/exit %d)" i)] :p)) (string "os/execute " i))) +# os/execute IO redirection +(assert-no-error "IO redirection" + (defn devnull [] + (def os (os/which)) + (def path (if (or (= os :mingw) (= os :windows)) + "NUL" + "/dev/null")) + (os/open path :w)) + (with [dn (devnull)] + (os/execute ["ls"] :px {:out dn :err dn}))) + (end-suite) From 1ccd8799166f65f3a87407d440c33bcda3f9149d Mon Sep 17 00:00:00 2001 From: Michael Camilleri Date: Sat, 24 Jun 2023 10:56:47 +0900 Subject: [PATCH 14/15] Make test cross-platform --- test/suite-os.janet | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/suite-os.janet b/test/suite-os.janet index 1af75674..881f24cf 100644 --- a/test/suite-os.janet +++ b/test/suite-os.janet @@ -138,7 +138,11 @@ "/dev/null")) (os/open path :w)) (with [dn (devnull)] - (os/execute ["ls"] :px {:out dn :err dn}))) + (os/execute [(dyn :executable) + "-e" + "(print :foo) (eprint :bar)"] + :px + {:out dn :err dn}))) (end-suite) From ff90b81ec3c0e79ce13bf616c5362d9c14d0f09e Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 24 Jun 2023 10:38:35 -0500 Subject: [PATCH 15/15] Add some utilitites for dealing with unsigned integers in janet.h --- src/core/capi.c | 10 +++++++++- src/core/util.c | 9 ++++++++- src/core/vm.c | 8 ++++---- src/include/janet.h | 3 +++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/core/capi.c b/src/core/capi.c index 6984d3ad..c1109c5f 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -273,6 +273,14 @@ int32_t janet_getinteger(const Janet *argv, int32_t n) { return janet_unwrap_integer(x); } +uint32_t janet_getuinteger(const Janet *argv, int32_t n) { + Janet x = argv[n]; + if (!janet_checkuint(x)) { + janet_panicf("bad slot #%d, expected 32 bit signed integer, got %v", n, x); + } + return janet_unwrap_integer(x); +} + int64_t janet_getinteger64(const Janet *argv, int32_t n) { #ifdef JANET_INT_TYPES return janet_unwrap_s64(argv[n]); @@ -290,7 +298,7 @@ uint64_t janet_getuinteger64(const Janet *argv, int32_t n) { return janet_unwrap_u64(argv[n]); #else Janet x = argv[n]; - if (!janet_checkint64(x)) { + if (!janet_checkuint64(x)) { janet_panicf("bad slot #%d, expected 64 bit unsigned integer, got %v", n, x); } return (uint64_t) janet_unwrap_number(x); diff --git a/src/core/util.c b/src/core/util.c index c0e3e564..2dfd11e3 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -805,6 +805,13 @@ int janet_checkint(Janet x) { return janet_checkintrange(dval); } +int janet_checkuint(Janet x) { + if (!janet_checktype(x, JANET_NUMBER)) + return 0; + double dval = janet_unwrap_number(x); + return janet_checkuintrange(dval); +} + int janet_checkint64(Janet x) { if (!janet_checktype(x, JANET_NUMBER)) return 0; @@ -816,7 +823,7 @@ int janet_checkuint64(Janet x) { if (!janet_checktype(x, JANET_NUMBER)) return 0; double dval = janet_unwrap_number(x); - return dval >= 0 && dval <= JANET_INTMAX_DOUBLE && dval == (uint64_t) dval; + return janet_checkuint64range(dval); } int janet_checksize(Janet x) { diff --git a/src/core/vm.c b/src/core/vm.c index ab73499d..dd8b7e57 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -147,8 +147,8 @@ stack[A] = janet_mcall(#op, 2, _argv);\ vm_checkgc_pcnext();\ } else {\ - type1 x1 = (type1) janet_unwrap_integer(op1);\ - stack[A] = janet_wrap_integer(x1 op CS);\ + type1 x1 = (type1) janet_unwrap_number(op1);\ + stack[A] = janet_wrap_number((type1) (x1 op CS));\ vm_pcnext();\ }\ } @@ -175,9 +175,9 @@ Janet op1 = stack[B];\ Janet op2 = stack[C];\ if (janet_checktype(op1, JANET_NUMBER) && janet_checktype(op2, JANET_NUMBER)) {\ - type1 x1 = (type1) janet_unwrap_integer(op1);\ + type1 x1 = (type1) janet_unwrap_number(op1);\ int32_t x2 = janet_unwrap_integer(op2);\ - stack[A] = janet_wrap_integer(x1 op x2);\ + stack[A] = janet_wrap_number((type1) (x1 op x2));\ vm_pcnext();\ } else {\ vm_commit();\ diff --git a/src/include/janet.h b/src/include/janet.h index 509b194e..3f6b8982 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -868,12 +868,15 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer); #endif JANET_API int janet_checkint(Janet x); +JANET_API int janet_checkuint(Janet x); JANET_API int janet_checkint64(Janet x); JANET_API int janet_checkuint64(Janet x); JANET_API int janet_checksize(Janet x); JANET_API JanetAbstract janet_checkabstract(Janet x, const JanetAbstractType *at); #define janet_checkintrange(x) ((x) >= INT32_MIN && (x) <= INT32_MAX && (x) == (int32_t)(x)) +#define janet_checkuintrange(x) ((x) >= 0 && (x) <= UINT32_MAX && (x) == (uint32_t)(x)) #define janet_checkint64range(x) ((x) >= JANET_INTMIN_DOUBLE && (x) <= JANET_INTMAX_DOUBLE && (x) == (int64_t)(x)) +#define janet_checkuint64range(x) ((x) >= 0 && (x) <= JANET_INTMAX_DOUBLE && (x) == (uint64_t)(x)) #define janet_unwrap_integer(x) ((int32_t) janet_unwrap_number(x)) #define janet_wrap_integer(x) janet_wrap_number((int32_t)(x))