1
0
mirror of https://github.com/janet-lang/janet synced 2025-11-23 18:54:50 +00:00

Compare commits

...

41 Commits

Author SHA1 Message Date
Calvin Rose
ca4c1e4259 Try to use atomics inside signal handler for ref count. 2023-08-20 08:49:49 -05:00
Calvin Rose
91712add3d Fix threaded abstracts in min build. 2023-08-19 20:19:05 -05:00
Calvin Rose
7198dcb416 Add sanboxing for signal handling. 2023-08-19 17:44:04 -05:00
Calvin Rose
08e20e912d Use pthread_sigmask when adding signal handlers. 2023-08-19 17:30:55 -05:00
Calvin Rose
f45571033c Add os/sigaction for signal handling.
Also improve interrupts to work better with busy loops
and signals.
2023-08-19 13:26:29 -05:00
Calvin Rose
2ac36a0572 Merge pull request #1257 from primo-ppcg/any-every
Update `any?`, `every?`
2023-08-18 07:20:44 -05:00
Calvin Rose
3df1d54847 Merge pull request #1258 from primo-ppcg/each
Update `each` keys before body
2023-08-18 07:16:19 -05:00
Calvin Rose
f3969b6066 Merge pull request #1259 from primo-ppcg/buffer-from-bytes
Add `buffer/from-bytes`
2023-08-18 07:15:08 -05:00
primo-ppcg
6222f35bc8 add buffer/from-bytes 2023-08-18 12:35:12 +07:00
primo-ppcg
2f178963c0 update each keys before body 2023-08-18 10:32:24 +07:00
primo-ppcg
15760b0950 update any?, every?
Updates `any?` and `every?` to be exact functional analogues to `or` and `and`.
2023-08-18 07:39:30 +07:00
Calvin Rose
43a6a70e1e Merge pull request #1255 from primo-ppcg/sort
Special case common `sort` usages
2023-08-16 20:34:17 -05:00
Calvin Rose
cd36f1ef5f Distinguish between threaded channels and non-threaded when marshalling.
Threaded channels _can_ be marshalled, just not for communication
between threads. This is a special case since the same abstract type
is used for both threaded and non-threaded channels.
2023-08-16 14:26:52 -05:00
primo-ppcg
cdd7083c86 special case common sort usages 2023-08-15 11:58:22 +07:00
Calvin Rose
8df7364319 Quick fix for discussion #1253
Protect against garbage collection during connect.
2023-08-13 12:00:54 -05:00
Calvin Rose
63023722d1 Merge pull request #1246 from wooosh/use-object-typedefs
Use typedefs for strings, symbols, keywords, tuples, structs, and abstracts.
2023-08-13 08:33:19 -05:00
Calvin Rose
79c12e5116 Merge pull request #1252 from primo-ppcg/reverse
Rework `reverse`, again
2023-08-12 14:29:23 -05:00
primo-ppcg
53e16944a1 rework reverse, again 2023-08-13 00:54:17 +07:00
Calvin Rose
7475362c85 Merge pull request #1249 from primo-ppcg/compare
Speed up `compare` functions
2023-08-11 19:27:42 -05:00
primo-ppcg
9238b82cde speed up compare 2023-08-11 23:48:29 +07:00
Calvin Rose
7049f658ec Merge pull request #1244 from primo-ppcg/bytes-indexed-dictionary
Move `bytes?`, `indexed?`, `dictionary?` to corelib
2023-08-09 17:56:35 -05:00
wooosh
701913fb19 Use typedefs for strings, symbols, keywords, tuples, structs, and abstracts. 2023-08-09 16:09:34 -04:00
primo-ppcg
831f41a62b move bytes?, indexed?, dictionary? to corelib 2023-08-08 10:00:05 +07:00
Calvin Rose
0ea1da80e7 Merge pull request #1242 from primo-ppcg/reverse
Rework `reverse`
2023-08-06 08:10:56 -05:00
Calvin Rose
06eea74b98 Merge pull request #1241 from primo-ppcg/keys-values-pairs
Rework `keys`, `values`, `pairs`
2023-08-06 08:10:43 -05:00
primo-ppcg
c8c0e112bc rework reverse 2023-08-06 16:16:41 +07:00
primo-ppcg
7417e82c51 rework keys, values, pairs 2023-08-06 15:39:16 +07:00
Calvin Rose
ecc4d80a5a Prepare for 1.30.0 release. 2023-08-05 18:58:04 -05:00
Calvin Rose
3df24c52f4 Merge pull request #1236 from primo-ppcg/range
Move `range` to corelib
2023-08-05 18:05:37 -05:00
primo-ppcg
8a70fb95b5 slight refactoring 2023-08-05 11:00:23 +07:00
primo-ppcg
d8b45ecd61 better test coverage 2023-08-03 20:39:32 +07:00
primo-ppcg
61712bae9c speed up range creation 2023-08-02 01:26:03 +07:00
Calvin Rose
4ff81a5a25 Add strip in release process instead of local builds - Address #1233 2023-07-27 21:40:07 -05:00
Calvin Rose
08f0e55d8f Add strip in release process instead of local builds - Address #1233 2023-07-27 21:37:48 -05:00
Calvin Rose
080b37cb31 Update CHANGELOG. 2023-07-25 17:51:21 -05:00
Calvin Rose
bbdcd035ba Merge pull request #1231 from sogaiu/tweak-file-open-doc 2023-07-23 23:20:09 -05:00
sogaiu
f9233ef90b Add fopen reference to file/open docstring 2023-07-23 18:39:20 +09:00
Calvin Rose
cd3573a4d2 Merge pull request #1224 from primo-ppcg/array-remove 2023-07-15 06:42:15 -05:00
Calvin Rose
738fe24e6d Allow buffer/blit to take explicit nils for default args.
Also small changes for range checking code.
2023-07-14 20:04:10 -05:00
primo-ppcg
c2e55b5486 update docstrings for string/slice and tuple/slice 2023-07-15 00:52:12 +07:00
primo-ppcg
bdefd3ba1e update final array index to be -1 2023-07-14 17:34:55 +07:00
25 changed files with 479 additions and 236 deletions

View File

@@ -1,7 +1,8 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Unreleased - ??? ## 1.30.0 - 2023-08-05
- Change indexing of `array/remove` to start from -1 at the end instead of -2.
- Add new string escape sequences `\\a`, `\\b`, `\\?`, and `\\'`. - Add new string escape sequences `\\a`, `\\b`, `\\?`, and `\\'`.
- Fix bug with marshalling channels - Fix bug with marshalling channels
- Add `div` for floored division - Add `div` for floored division

View File

@@ -48,6 +48,7 @@ SONAME_SETTER=-Wl,-soname,
# For cross compilation # For cross compilation
HOSTCC?=$(CC) HOSTCC?=$(CC)
HOSTAR?=$(AR) HOSTAR?=$(AR)
# Symbols are (optionally) removed later, keep -g as default!
CFLAGS?=-O2 -g CFLAGS?=-O2 -g
LDFLAGS?=-rdynamic LDFLAGS?=-rdynamic
RUN:=$(RUN) RUN:=$(RUN)
@@ -195,9 +196,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile
######################## ########################
ifeq ($(UNAME), Darwin) ifeq ($(UNAME), Darwin)
SONAME=libjanet.1.29.dylib SONAME=libjanet.1.30.dylib
else else
SONAME=libjanet.so.1.29 SONAME=libjanet.so.1.30
endif endif
build/c/shell.c: src/mainclient/shell.c build/c/shell.c: src/mainclient/shell.c
@@ -266,6 +267,7 @@ build/janet-%.tar.gz: $(JANET_TARGET) \
README.md build/c/janet.c build/c/shell.c README.md build/c/janet.c build/c/shell.c
mkdir -p build/$(JANET_DIST_DIR)/bin mkdir -p build/$(JANET_DIST_DIR)/bin
cp $(JANET_TARGET) build/$(JANET_DIST_DIR)/bin/ cp $(JANET_TARGET) build/$(JANET_DIST_DIR)/bin/
strip -x -S 'build/$(JANET_DIST_DIR)/bin/janet'
mkdir -p build/$(JANET_DIST_DIR)/include mkdir -p build/$(JANET_DIST_DIR)/include
cp build/janet.h build/$(JANET_DIST_DIR)/include/ cp build/janet.h build/$(JANET_DIST_DIR)/include/
mkdir -p build/$(JANET_DIST_DIR)/lib/ mkdir -p build/$(JANET_DIST_DIR)/lib/
@@ -364,7 +366,7 @@ build/janet.tmLanguage: tools/tm_lang_gen.janet $(JANET_TARGET)
$(RUN) $(JANET_TARGET) $< > $@ $(RUN) $(JANET_TARGET) $< > $@
compile-commands: compile-commands:
# Requires pip install copmiledb # Requires pip install compiledb
compiledb make compiledb make
clean: clean:

10
examples/sigaction.janet Normal file
View File

@@ -0,0 +1,10 @@
(defn action []
(print "Handled SIGHUP!")
(flush))
(defn main [_]
# Set the interrupt-interpreter argument to `true` to allow
# interrupting the busy loop `(forever)`. By default, will not
# interrupt the interpreter.
(os/sigaction :hup action true)
(forever))

View File

@@ -20,7 +20,7 @@
project('janet', 'c', project('janet', 'c',
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'], default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.29.1') version : '1.30.0')
# Global settings # Global settings
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet') janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')

View File

@@ -103,23 +103,13 @@
(defn symbol? "Check if x is a symbol." [x] (= (type x) :symbol)) (defn symbol? "Check if x is a symbol." [x] (= (type x) :symbol))
(defn keyword? "Check if x is a keyword." [x] (= (type x) :keyword)) (defn keyword? "Check if x is a keyword." [x] (= (type x) :keyword))
(defn buffer? "Check if x is a buffer." [x] (= (type x) :buffer)) (defn buffer? "Check if x is a buffer." [x] (= (type x) :buffer))
(defn function? "Check if x is a function (not a cfunction)." [x] (defn function? "Check if x is a function (not a cfunction)." [x] (= (type x) :function))
(= (type x) :function))
(defn cfunction? "Check if x a cfunction." [x] (= (type x) :cfunction)) (defn cfunction? "Check if x a cfunction." [x] (= (type x) :cfunction))
(defn table? "Check if x a table." [x] (= (type x) :table)) (defn table? "Check if x a table." [x] (= (type x) :table))
(defn struct? "Check if x a struct." [x] (= (type x) :struct)) (defn struct? "Check if x a struct." [x] (= (type x) :struct))
(defn array? "Check if x is an array." [x] (= (type x) :array)) (defn array? "Check if x is an array." [x] (= (type x) :array))
(defn tuple? "Check if x is a tuple." [x] (= (type x) :tuple)) (defn tuple? "Check if x is a tuple." [x] (= (type x) :tuple))
(defn boolean? "Check if x is a boolean." [x] (= (type x) :boolean)) (defn boolean? "Check if x is a boolean." [x] (= (type x) :boolean))
(defn bytes? "Check if x is a string, symbol, keyword, or buffer." [x]
(def t (type x))
(if (= t :string) true (if (= t :symbol) true (if (= t :keyword) true (= t :buffer)))))
(defn dictionary? "Check if x is a table or struct." [x]
(def t (type x))
(if (= t :table) true (= t :struct)))
(defn indexed? "Check if x is an array or tuple." [x]
(def t (type x))
(if (= t :array) true (= t :tuple)))
(defn truthy? "Check if x is truthy." [x] (if x true false)) (defn truthy? "Check if x is truthy." [x] (if x true false))
(defn true? "Check if x is true." [x] (= x true)) (defn true? "Check if x is true." [x] (= x true))
(defn false? "Check if x is false." [x] (= x false)) (defn false? "Check if x is false." [x] (= x false))
@@ -446,8 +436,8 @@
:each ~(,in ,ds ,k) :each ~(,in ,ds ,k)
:keys k :keys k
:pairs ~[,k (,in ,ds ,k)])) :pairs ~[,k (,in ,ds ,k)]))
,;body (set ,k (,next ,ds ,k))
(set ,k (,next ,ds ,k)))))) ,;body))))
(defn- iterate-template (defn- iterate-template
[binding expr body] [binding expr body]
@@ -749,6 +739,14 @@
## Polymorphic comparisons ## Polymorphic comparisons
(defmacro- do-compare
[x y]
~(if (def f (get ,x :compare))
(f ,x ,y)
(if (def f (get ,y :compare))
(- (f ,y ,x))
(cmp ,x ,y))))
(defn compare (defn compare
``Polymorphic compare. Returns -1, 0, 1 for x < y, x = y, x > y respectively. ``Polymorphic compare. Returns -1, 0, 1 for x < y, x = y, x > y respectively.
Differs from the primitive comparators in that it first checks to Differs from the primitive comparators in that it first checks to
@@ -756,20 +754,18 @@
compare x and y. If so, it uses that method. If not, it compare x and y. If so, it uses that method. If not, it
delegates to the primitive comparators.`` delegates to the primitive comparators.``
[x y] [x y]
(or (do-compare x y))
(when-let [f (get x :compare)] (f x y))
(when-let [f (get y :compare)] (- (f y x)))
(cmp x y)))
(defn- compare-reduce [op xs] (defmacro- compare-reduce [op xs]
(var r true) ~(do
(loop [i :range [0 (- (length xs) 1)] (var res true)
:let [c (compare (xs i) (xs (+ i 1))) (var x (get ,xs 0))
ok (op c 0)] (forv i 1 (length ,xs)
:when (not ok)] (let [y (in ,xs i)]
(set r false) (if (,op (do-compare x y) 0)
(break)) (set x y)
r) (do (set res false) (break)))))
res))
(defn compare= (defn compare=
``Equivalent of `=` but using polymorphic `compare` instead of primitive comparator.`` ``Equivalent of `=` but using polymorphic `compare` instead of primitive comparator.``
@@ -809,21 +805,31 @@
### ###
### ###
(defn- median-of-three [a b c] (defmacro- median-of-three
(if (not= (> a b) (> a c)) [x y z]
a ~(if (<= ,x ,y)
(if (not= (> b a) (> b c)) b c))) (if (<= ,y ,z) ,y (if (<= ,z ,x) ,x ,z))
(if (<= ,z ,y) ,y (if (<= ,x ,z) ,x ,z))))
(defmacro- sort-partition-template
[ind before? left right pivot]
~(do
(while (,before? (in ,ind ,left) ,pivot) (++ ,left))
(while (,before? ,pivot (in ,ind ,right)) (-- ,right))))
(defn- sort-help [a lo hi before?] (defn- sort-help [a lo hi before?]
(when (< lo hi) (when (< lo hi)
(def pivot (def [x y z] [(in a lo)
(median-of-three (in a hi) (in a lo) (in a (div (+ lo hi) 2))
(in a (math/floor (/ (+ lo hi) 2))))) (in a hi)])
(def pivot (median-of-three x y z))
(var left lo) (var left lo)
(var right hi) (var right hi)
(while true (while true
(while (before? (in a left) pivot) (++ left)) (case before?
(while (before? pivot (in a right)) (-- right)) < (sort-partition-template a < left right pivot)
> (sort-partition-template a > left right pivot)
(sort-partition-template a before? left right pivot))
(when (<= left right) (when (<= left right)
(def tmp (in a left)) (def tmp (in a left))
(set (a left) (in a right)) (set (a left) (in a right))
@@ -831,8 +837,10 @@
(++ left) (++ left)
(-- right)) (-- right))
(if (>= left right) (break))) (if (>= left right) (break)))
(sort-help a lo right before?) (if (< lo right)
(sort-help a left hi before?)) (sort-help a lo right before?))
(if (< left hi)
(sort-help a left hi before?)))
a) a)
(defn sort (defn sort
@@ -840,7 +848,8 @@
If a `before?` comparator function is provided, sorts elements using that, If a `before?` comparator function is provided, sorts elements using that,
otherwise uses `<`.`` otherwise uses `<`.``
[ind &opt before?] [ind &opt before?]
(sort-help ind 0 (- (length ind) 1) (or before? <))) (default before? <)
(sort-help ind 0 (- (length ind) 1) before?))
(defn sort-by (defn sort-by
``Sorts `ind` in-place by calling a function `f` on each element and ``Sorts `ind` in-place by calling a function `f` on each element and
@@ -1007,30 +1016,6 @@
(map-template :keep res pred ind inds) (map-template :keep res pred ind inds)
res) res)
(defn range
`Create an array of values [start, end) with a given step.
With one argument, returns a range [0, end). With two arguments, returns
a range [start, end). With three, returns a range with optional step size.`
[& args]
(case (length args)
1 (do
(def [n] args)
(def arr (array/new n))
(forv i 0 n (put arr i i))
arr)
2 (do
(def [n m] args)
(def arr (array/new (- m n)))
(forv i n m (put arr (- i n) i))
arr)
3 (do
(def [n m s] args)
(cond
(zero? s) @[]
(neg? s) (seq [i :down [n m (- s)]] i)
(seq [i :range [n m s]] i)))
(error "expected 1 to 3 arguments to range")))
(defn find-index (defn find-index
``Find the index of indexed type for which `pred` is true. Returns `dflt` if not found.`` ``Find the index of indexed type for which `pred` is true. Returns `dflt` if not found.``
[pred ind &opt dflt] [pred ind &opt dflt]
@@ -1439,20 +1424,21 @@
(fn [& r] (f ;more ;r)))) (fn [& r] (f ;more ;r))))
(defn every? (defn every?
``Returns true if each value in `ind` is truthy, otherwise returns the first ``Evaluates to the last element of `ind` if all preceding elements are truthy,
falsey value.`` otherwise evaluates to the first falsey argument.``
[ind] [ind]
(var res true) (var res true)
(loop [x :in ind :while res] (loop [x :in ind :while res]
(if x nil (set res x))) (set res x))
res) res)
(defn any? (defn any?
``Returns the first truthy value in `ind`, otherwise nil.`` ``Evaluates to the last element of `ind` if all preceding elements are falsey,
otherwise evaluates to the first truthy element.``
[ind] [ind]
(var res nil) (var res nil)
(loop [x :in ind :until res] (loop [x :in ind :until res]
(if x (set res x))) (set res x))
res) res)
(defn reverse! (defn reverse!
@@ -1474,12 +1460,12 @@
a new array. If a string or buffer is provided, returns an array of its a new array. If a string or buffer is provided, returns an array of its
byte values, reversed.` byte values, reversed.`
[t] [t]
(def len (length t)) (var n (length t))
(var n (- len 1)) (def ret (if (bytes? t)
(def ret (array/new len)) (buffer/new-filled n)
(while (>= n 0) (array/new-filled n)))
(array/push ret (in t n)) (each v t
(-- n)) (put ret (-- n) v))
ret) ret)
(defn invert (defn invert
@@ -1590,31 +1576,31 @@
(defn keys (defn keys
"Get the keys of an associative data structure." "Get the keys of an associative data structure."
[x] [x]
(def arr @[]) (def arr (array/new-filled (length x)))
(var k (next x nil)) (var i 0)
(while (not= nil k) (eachk k x
(array/push arr k) (put arr i k)
(set k (next x k))) (++ i))
arr) arr)
(defn values (defn values
"Get the values of an associative data structure." "Get the values of an associative data structure."
[x] [x]
(def arr @[]) (def arr (array/new-filled (length x)))
(var k (next x nil)) (var i 0)
(while (not= nil k) (each v x
(array/push arr (in x k)) (put arr i v)
(set k (next x k))) (++ i))
arr) arr)
(defn pairs (defn pairs
"Get the key-value pairs of an associative data structure." "Get the key-value pairs of an associative data structure."
[x] [x]
(def arr @[]) (def arr (array/new-filled (length x)))
(var k (next x nil)) (var i 0)
(while (not= nil k) (eachp p x
(array/push arr (tuple k (in x k))) (put arr i p)
(set k (next x k))) (++ i))
arr) arr)
(defn frequencies (defn frequencies

View File

@@ -4,10 +4,10 @@
#define JANETCONF_H #define JANETCONF_H
#define JANET_VERSION_MAJOR 1 #define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 29 #define JANET_VERSION_MINOR 30
#define JANET_VERSION_PATCH 1 #define JANET_VERSION_PATCH 0
#define JANET_VERSION_EXTRA "" #define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.29.1" #define JANET_VERSION "1.30.0"
/* #define JANET_BUILD "local" */ /* #define JANET_BUILD "local" */

View File

@@ -211,7 +211,7 @@ JANET_CORE_FN(cfun_array_slice,
"Takes a slice of array or tuple from `start` to `end`. The range is half open, " "Takes a slice of array or tuple from `start` to `end`. The range is half open, "
"[start, end). Indexes can also be negative, indicating indexing from the " "[start, end). Indexes can also be negative, indicating indexing from the "
"end of the array. By default, `start` is 0 and `end` is the length of the array. " "end of the array. By default, `start` is 0 and `end` is the length of the array. "
"Note that index -1 is synonymous with index `(length arrtup)` to allow a full " "Note that if the range is negative, it is taken as (start, end] to allow a full "
"negative slice range. Returns a new array.") { "negative slice range. Returns a new array.") {
JanetView view = janet_getindexed(argv, 0); JanetView view = janet_getindexed(argv, 0);
JanetRange range = janet_getslice(argc, argv); JanetRange range = janet_getslice(argc, argv);
@@ -259,8 +259,8 @@ JANET_CORE_FN(cfun_array_insert,
"(array/insert arr at & xs)", "(array/insert arr at & xs)",
"Insert all `xs` into array `arr` at index `at`. `at` should be an integer between " "Insert all `xs` into array `arr` at index `at`. `at` should be an integer between "
"0 and the length of the array. A negative value for `at` will index backwards from " "0 and the length of the array. A negative value for `at` will index backwards from "
"the end of the array, such that inserting at -1 appends to the array. " "the end of the array, inserting after the index such that inserting at -1 appends to "
"Returns the array.") { "the array. Returns the array.") {
size_t chunksize, restsize; size_t chunksize, restsize;
janet_arity(argc, 2, -1); janet_arity(argc, 2, -1);
JanetArray *array = janet_getarray(argv, 0); JanetArray *array = janet_getarray(argv, 0);
@@ -297,7 +297,7 @@ JANET_CORE_FN(cfun_array_remove,
int32_t at = janet_getinteger(argv, 1); int32_t at = janet_getinteger(argv, 1);
int32_t n = 1; int32_t n = 1;
if (at < 0) { if (at < 0) {
at = array->count + at + 1; at = array->count + at;
} }
if (at < 0 || at > array->count) if (at < 0 || at > array->count)
janet_panicf("removal index %d out of range [0,%d]", at, array->count); janet_panicf("removal index %d out of range [0,%d]", at, array->count);

View File

@@ -221,6 +221,20 @@ JANET_CORE_FN(cfun_buffer_new_filled,
return janet_wrap_buffer(buffer); return janet_wrap_buffer(buffer);
} }
JANET_CORE_FN(cfun_buffer_frombytes,
"(buffer/from-bytes & byte-vals)",
"Creates a buffer from integer parameters with byte values. All integers "
"will be coerced to the range of 1 byte 0-255.") {
int32_t i;
JanetBuffer *buffer = janet_buffer(argc);
for (i = 0; i < argc; i++) {
int32_t c = janet_getinteger(argv, i);
buffer->data[i] = c & 0xFF;
}
buffer->count = argc;
return janet_wrap_buffer(buffer);
}
JANET_CORE_FN(cfun_buffer_fill, JANET_CORE_FN(cfun_buffer_fill,
"(buffer/fill buffer &opt byte)", "(buffer/fill buffer &opt byte)",
"Fill up a buffer with bytes, defaulting to 0s. Does not change the buffer's length. " "Fill up a buffer with bytes, defaulting to 0s. Does not change the buffer's length. "
@@ -462,13 +476,15 @@ JANET_CORE_FN(cfun_buffer_blit,
int same_buf = src.bytes == dest->data; int same_buf = src.bytes == dest->data;
int32_t offset_dest = 0; int32_t offset_dest = 0;
int32_t offset_src = 0; int32_t offset_src = 0;
if (argc > 2) if (argc > 2 && !janet_checktype(argv[2], JANET_NIL))
offset_dest = janet_gethalfrange(argv, 2, dest->count, "dest-start"); offset_dest = janet_gethalfrange(argv, 2, dest->count, "dest-start");
if (argc > 3) if (argc > 3 && !janet_checktype(argv[3], JANET_NIL))
offset_src = janet_gethalfrange(argv, 3, src.len, "src-start"); offset_src = janet_gethalfrange(argv, 3, src.len, "src-start");
int32_t length_src; int32_t length_src;
if (argc > 4) { if (argc > 4) {
int32_t src_end = janet_gethalfrange(argv, 4, src.len, "src-end"); int32_t src_end = src.len;
if (!janet_checktype(argv[4], JANET_NIL))
src_end = janet_gethalfrange(argv, 4, src.len, "src-end");
length_src = src_end - offset_src; length_src = src_end - offset_src;
if (length_src < 0) length_src = 0; if (length_src < 0) length_src = 0;
} else { } else {
@@ -507,6 +523,7 @@ void janet_lib_buffer(JanetTable *env) {
JanetRegExt buffer_cfuns[] = { JanetRegExt buffer_cfuns[] = {
JANET_CORE_REG("buffer/new", cfun_buffer_new), JANET_CORE_REG("buffer/new", cfun_buffer_new),
JANET_CORE_REG("buffer/new-filled", cfun_buffer_new_filled), JANET_CORE_REG("buffer/new-filled", cfun_buffer_new_filled),
JANET_CORE_REG("buffer/from-bytes", cfun_buffer_frombytes),
JANET_CORE_REG("buffer/fill", cfun_buffer_fill), JANET_CORE_REG("buffer/fill", cfun_buffer_fill),
JANET_CORE_REG("buffer/trim", cfun_buffer_trim), JANET_CORE_REG("buffer/trim", cfun_buffer_trim),
JANET_CORE_REG("buffer/push-byte", cfun_buffer_u8), JANET_CORE_REG("buffer/push-byte", cfun_buffer_u8),

View File

@@ -342,6 +342,20 @@ int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const c
return not_raw; return not_raw;
} }
int32_t janet_getstartrange(const Janet *argv, int32_t argc, int32_t n, int32_t length) {
if (n >= argc || janet_checktype(argv[n], JANET_NIL)) {
return 0;
}
return janet_gethalfrange(argv, n, length, "start");
}
int32_t janet_getendrange(const Janet *argv, int32_t argc, int32_t n, int32_t length) {
if (n >= argc || janet_checktype(argv[n], JANET_NIL)) {
return length;
}
return janet_gethalfrange(argv, n, length, "end");
}
int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which) { int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which) {
int32_t raw = janet_getinteger(argv, n); int32_t raw = janet_getinteger(argv, n);
int32_t not_raw = raw; int32_t not_raw = raw;
@@ -394,24 +408,10 @@ JanetRange janet_getslice(int32_t argc, const Janet *argv) {
janet_arity(argc, 1, 3); janet_arity(argc, 1, 3);
JanetRange range; JanetRange range;
int32_t length = janet_length(argv[0]); int32_t length = janet_length(argv[0]);
if (argc == 1) { range.start = janet_getstartrange(argv, argc, 1, length);
range.start = 0; range.end = janet_getendrange(argv, argc, 2, length);
range.end = length;
} else if (argc == 2) {
range.start = janet_checktype(argv[1], JANET_NIL)
? 0
: janet_gethalfrange(argv, 1, length, "start");
range.end = length;
} else {
range.start = janet_checktype(argv[1], JANET_NIL)
? 0
: janet_gethalfrange(argv, 1, length, "start");
range.end = janet_checktype(argv[2], JANET_NIL)
? length
: janet_gethalfrange(argv, 2, length, "end");
if (range.end < range.start) if (range.end < range.start)
range.end = range.start; range.end = range.start;
}
return range; return range;
} }
@@ -493,7 +493,7 @@ void *janet_optabstract(const Janet *argv, int32_t argc, int32_t n, const JanetA
/* Some definitions for function-like macros */ /* Some definitions for function-like macros */
JANET_API JanetStructHead *(janet_struct_head)(const JanetKV *st) { JANET_API JanetStructHead *(janet_struct_head)(JanetStruct st) {
return janet_struct_head(st); return janet_struct_head(st);
} }
@@ -501,10 +501,10 @@ JANET_API JanetAbstractHead *(janet_abstract_head)(const void *abstract) {
return janet_abstract_head(abstract); return janet_abstract_head(abstract);
} }
JANET_API JanetStringHead *(janet_string_head)(const uint8_t *s) { JANET_API JanetStringHead *(janet_string_head)(JanetString s) {
return janet_string_head(s); return janet_string_head(s);
} }
JANET_API JanetTupleHead *(janet_tuple_head)(const Janet *tuple) { JANET_API JanetTupleHead *(janet_tuple_head)(JanetTuple tuple) {
return janet_tuple_head(tuple); return janet_tuple_head(tuple);
} }

View File

@@ -426,6 +426,36 @@ JANET_CORE_FN(janet_core_slice,
} }
} }
JANET_CORE_FN(janet_core_range,
"(range & args)",
"Create an array of values [start, end) with a given step. "
"With one argument, returns a range [0, end). With two arguments, returns "
"a range [start, end). With three, returns a range with optional step size.") {
janet_arity(argc, 1, 3);
int32_t start = 0, stop = 0, step = 1, count = 0;
if (argc == 3) {
start = janet_getinteger(argv, 0);
stop = janet_getinteger(argv, 1);
step = janet_getinteger(argv, 2);
count = (step > 0) ? (stop - start - 1) / step + 1 :
((step < 0) ? (stop - start + 1) / step + 1 : 0);
} else if (argc == 2) {
start = janet_getinteger(argv, 0);
stop = janet_getinteger(argv, 1);
count = stop - start;
} else {
stop = janet_getinteger(argv, 0);
count = stop;
}
count = (count > 0) ? count : 0;
JanetArray *array = janet_array(count);
for (int32_t i = 0; i < count; i++) {
array->data[i] = janet_wrap_number(start + i * step);
}
array->count = count;
return janet_wrap_array(array);
}
JANET_CORE_FN(janet_core_table, JANET_CORE_FN(janet_core_table,
"(table & kvs)", "(table & kvs)",
"Creates a new table from a variadic number of keys and values. " "Creates a new table from a variadic number of keys and values. "
@@ -629,6 +659,27 @@ ret_false:
return janet_wrap_false(); return janet_wrap_false();
} }
JANET_CORE_FN(janet_core_is_bytes,
"(bytes? x)",
"Check if x is a string, symbol, keyword, or buffer.") {
janet_fixarity(argc, 1);
return janet_wrap_boolean(janet_checktypes(argv[0], JANET_TFLAG_BYTES));
}
JANET_CORE_FN(janet_core_is_indexed,
"(indexed? x)",
"Check if x is an array or tuple.") {
janet_fixarity(argc, 1);
return janet_wrap_boolean(janet_checktypes(argv[0], JANET_TFLAG_INDEXED));
}
JANET_CORE_FN(janet_core_is_dictionary,
"(dictionary? x)",
"Check if x is a table or struct.") {
janet_fixarity(argc, 1);
return janet_wrap_boolean(janet_checktypes(argv[0], JANET_TFLAG_DICTIONARY));
}
JANET_CORE_FN(janet_core_signal, JANET_CORE_FN(janet_core_signal,
"(signal what x)", "(signal what x)",
"Raise a signal with payload x. ") { "Raise a signal with payload x. ") {
@@ -690,6 +741,7 @@ static const SandboxOption sandbox_options[] = {
{"net-connect", JANET_SANDBOX_NET_CONNECT}, {"net-connect", JANET_SANDBOX_NET_CONNECT},
{"net-listen", JANET_SANDBOX_NET_LISTEN}, {"net-listen", JANET_SANDBOX_NET_LISTEN},
{"sandbox", JANET_SANDBOX_SANDBOX}, {"sandbox", JANET_SANDBOX_SANDBOX},
{"signal", JANET_SANDBOX_SIGNAL},
{"subprocess", JANET_SANDBOX_SUBPROCESS}, {"subprocess", JANET_SANDBOX_SUBPROCESS},
{NULL, 0} {NULL, 0}
}; };
@@ -714,6 +766,7 @@ JANET_CORE_FN(janet_core_sandbox,
"* :net-connect - disallow making outbound network connections\n" "* :net-connect - disallow making outbound network connections\n"
"* :net-listen - disallow accepting inbound network connections\n" "* :net-listen - disallow accepting inbound network connections\n"
"* :sandbox - disallow calling this function\n" "* :sandbox - disallow calling this function\n"
"* :signal - disallow adding or removing signal handlers\n"
"* :subprocess - disallow running subprocesses") { "* :subprocess - disallow running subprocesses") {
uint32_t flags = 0; uint32_t flags = 0;
for (int32_t i = 0; i < argc; i++) { for (int32_t i = 0; i < argc; i++) {
@@ -1023,7 +1076,11 @@ static void janet_load_libs(JanetTable *env) {
JANET_CORE_REG("module/expand-path", janet_core_expand_path), JANET_CORE_REG("module/expand-path", janet_core_expand_path),
JANET_CORE_REG("int?", janet_core_check_int), JANET_CORE_REG("int?", janet_core_check_int),
JANET_CORE_REG("nat?", janet_core_check_nat), JANET_CORE_REG("nat?", janet_core_check_nat),
JANET_CORE_REG("bytes?", janet_core_is_bytes),
JANET_CORE_REG("indexed?", janet_core_is_indexed),
JANET_CORE_REG("dictionary?", janet_core_is_dictionary),
JANET_CORE_REG("slice", janet_core_slice), JANET_CORE_REG("slice", janet_core_slice),
JANET_CORE_REG("range", janet_core_range),
JANET_CORE_REG("signal", janet_core_signal), JANET_CORE_REG("signal", janet_core_signal),
JANET_CORE_REG("memcmp", janet_core_memcmp), JANET_CORE_REG("memcmp", janet_core_memcmp),
JANET_CORE_REG("getproto", janet_core_getproto), JANET_CORE_REG("getproto", janet_core_getproto),

View File

@@ -562,6 +562,7 @@ void janet_ev_init_common(void) {
janet_vm.tq_capacity = 0; janet_vm.tq_capacity = 0;
janet_table_init_raw(&janet_vm.threaded_abstracts, 0); janet_table_init_raw(&janet_vm.threaded_abstracts, 0);
janet_table_init_raw(&janet_vm.active_tasks, 0); janet_table_init_raw(&janet_vm.active_tasks, 0);
janet_table_init_raw(&janet_vm.signal_handlers, 0);
janet_rng_seed(&janet_vm.ev_rng, 0); janet_rng_seed(&janet_vm.ev_rng, 0);
#ifndef JANET_WINDOWS #ifndef JANET_WINDOWS
pthread_attr_init(&janet_vm.new_thread_attr); pthread_attr_init(&janet_vm.new_thread_attr);
@@ -577,6 +578,7 @@ void janet_ev_deinit_common(void) {
janet_vm.listeners = NULL; janet_vm.listeners = NULL;
janet_table_deinit(&janet_vm.threaded_abstracts); janet_table_deinit(&janet_vm.threaded_abstracts);
janet_table_deinit(&janet_vm.active_tasks); janet_table_deinit(&janet_vm.active_tasks);
janet_table_deinit(&janet_vm.signal_handlers);
#ifndef JANET_WINDOWS #ifndef JANET_WINDOWS
pthread_attr_destroy(&janet_vm.new_thread_attr); pthread_attr_destroy(&janet_vm.new_thread_attr);
#endif #endif
@@ -601,11 +603,19 @@ void janet_addtimeout(double sec) {
} }
void janet_ev_inc_refcount(void) { void janet_ev_inc_refcount(void) {
janet_vm.extra_listeners++; #ifdef JANET_WINDOWS
InterlockedIncrement(&janet_vm.extra_listeners);
#else
__atomic_add_fetch(&janet_vm.extra_listeners, 1, __ATOMIC_RELAXED);
#endif
} }
void janet_ev_dec_refcount(void) { void janet_ev_dec_refcount(void) {
janet_vm.extra_listeners--; #ifdef JANET_WINDOWS
InterlockedDecrement(&janet_vm.extra_listeners);
#else
__atomic_add_fetch(&janet_vm.extra_listeners, -1, __ATOMIC_RELAXED);
#endif
} }
/* Channels */ /* Channels */
@@ -1224,6 +1234,7 @@ static Janet janet_chanat_next(void *p, Janet key) {
static void janet_chanat_marshal(void *p, JanetMarshalContext *ctx) { static void janet_chanat_marshal(void *p, JanetMarshalContext *ctx) {
JanetChannel *channel = (JanetChannel *)p; JanetChannel *channel = (JanetChannel *)p;
janet_marshal_byte(ctx, channel->is_threaded);
janet_marshal_abstract(ctx, channel); janet_marshal_abstract(ctx, channel);
janet_marshal_byte(ctx, channel->closed); janet_marshal_byte(ctx, channel->closed);
janet_marshal_int(ctx, channel->limit); janet_marshal_int(ctx, channel->limit);
@@ -1243,7 +1254,13 @@ static void janet_chanat_marshal(void *p, JanetMarshalContext *ctx) {
} }
static void *janet_chanat_unmarshal(JanetMarshalContext *ctx) { static void *janet_chanat_unmarshal(JanetMarshalContext *ctx) {
JanetChannel *abst = janet_unmarshal_abstract(ctx, sizeof(JanetChannel)); uint8_t is_threaded = janet_unmarshal_byte(ctx);
JanetChannel *abst;
if (is_threaded) {
abst = janet_unmarshal_abstract_threaded(ctx, sizeof(JanetChannel));
} else {
abst = janet_unmarshal_abstract(ctx, sizeof(JanetChannel));
}
uint8_t is_closed = janet_unmarshal_byte(ctx); uint8_t is_closed = janet_unmarshal_byte(ctx);
int32_t limit = janet_unmarshal_int(ctx); int32_t limit = janet_unmarshal_int(ctx);
int32_t count = janet_unmarshal_int(ctx); int32_t count = janet_unmarshal_int(ctx);
@@ -1283,6 +1300,33 @@ int janet_loop_done(void) {
janet_vm.extra_listeners); janet_vm.extra_listeners);
} }
static void janet_loop1_poll(void) {
/* Poll for events */
if (janet_vm.listener_count || janet_vm.tq_count || janet_vm.extra_listeners) {
JanetTimeout to;
memset(&to, 0, sizeof(to));
int has_timeout;
/* Drop timeouts that are no longer needed */
while ((has_timeout = peek_timeout(&to))) {
if (to.curr_fiber != NULL) {
if (!janet_fiber_can_resume(to.curr_fiber)) {
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
pop_timeout(0);
continue;
}
} else if (to.fiber->sched_id != to.sched_id) {
pop_timeout(0);
continue;
}
break;
}
/* Run polling implementation only if pending timeouts or pending events */
if (janet_vm.tq_count || janet_vm.listener_count || janet_vm.extra_listeners) {
janet_loop1_impl(has_timeout, to.when);
}
}
}
JanetFiber *janet_loop1(void) { JanetFiber *janet_loop1(void) {
/* Schedule expired timers */ /* Schedule expired timers */
JanetTimeout to; JanetTimeout to;
@@ -1340,30 +1384,7 @@ JanetFiber *janet_loop1(void) {
} }
} }
/* Poll for events */ janet_loop1_poll();
if (janet_vm.listener_count || janet_vm.tq_count || janet_vm.extra_listeners) {
JanetTimeout to;
memset(&to, 0, sizeof(to));
int has_timeout;
/* Drop timeouts that are no longer needed */
while ((has_timeout = peek_timeout(&to))) {
if (to.curr_fiber != NULL) {
if (!janet_fiber_can_resume(to.curr_fiber)) {
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
pop_timeout(0);
continue;
}
} else if (to.fiber->sched_id != to.sched_id) {
pop_timeout(0);
continue;
}
break;
}
/* Run polling implementation only if pending timeouts or pending events */
if (janet_vm.tq_count || janet_vm.listener_count || janet_vm.extra_listeners) {
janet_loop1_impl(has_timeout, to.when);
}
}
/* No fiber was interrupted */ /* No fiber was interrupted */
return NULL; return NULL;
@@ -1384,6 +1405,12 @@ void janet_loop(void) {
while (!janet_loop_done()) { while (!janet_loop_done()) {
JanetFiber *interrupted_fiber = janet_loop1(); JanetFiber *interrupted_fiber = janet_loop1();
if (NULL != interrupted_fiber) { if (NULL != interrupted_fiber) {
/* Allow an extra poll before rescheduling to allow posted events to be handled
* before entering a possibly infinite, blocking loop. */
Janet x = janet_wrap_fiber(interrupted_fiber);
janet_gcroot(x);
janet_loop1_poll();
janet_gcunroot(x);
janet_schedule(interrupted_fiber, janet_wrap_nil()); janet_schedule(interrupted_fiber, janet_wrap_nil());
} }
} }
@@ -2525,14 +2552,17 @@ JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event)
switch (event) { switch (event) {
default: default:
break; break;
case JANET_ASYNC_EVENT_MARK: case JANET_ASYNC_EVENT_MARK: {
if (state->mode != JANET_ASYNC_WRITEMODE_CONNECT) {
janet_mark(state->is_buffer janet_mark(state->is_buffer
? janet_wrap_buffer(state->src.buf) ? janet_wrap_buffer(state->src.buf)
: janet_wrap_string(state->src.str)); : janet_wrap_string(state->src.str));
}
if (state->mode == JANET_ASYNC_WRITEMODE_SENDTO) { if (state->mode == JANET_ASYNC_WRITEMODE_SENDTO) {
janet_mark(janet_wrap_abstract(state->dest_abst)); janet_mark(janet_wrap_abstract(state->dest_abst));
} }
break; break;
}
case JANET_ASYNC_EVENT_CLOSE: case JANET_ASYNC_EVENT_CLOSE:
janet_cancel(s->fiber, janet_cstringv("stream closed")); janet_cancel(s->fiber, janet_cstringv("stream closed"));
return JANET_ASYNC_STATUS_DONE; return JANET_ASYNC_STATUS_DONE;

View File

@@ -143,7 +143,8 @@ JANET_CORE_FN(cfun_io_fopen,
"Following one of the initial flags, 0 or more of the following flags can be appended:\n\n" "Following one of the initial flags, 0 or more of the following flags can be appended:\n\n"
"* b - open the file in binary mode (rather than text mode)\n\n" "* b - open the file in binary mode (rather than text mode)\n\n"
"* + - append to the file instead of overwriting it\n\n" "* + - append to the file instead of overwriting it\n\n"
"* n - error if the file cannot be opened instead of returning nil") { "* n - error if the file cannot be opened instead of returning nil\n\n"
"See fopen (<stdio.h>, C99) for further details.") {
janet_arity(argc, 1, 2); janet_arity(argc, 1, 2);
const uint8_t *fname = janet_getstring(argv, 0); const uint8_t *fname = janet_getstring(argv, 0);
const uint8_t *fmode; const uint8_t *fmode;

View File

@@ -1245,6 +1245,18 @@ void *janet_unmarshal_abstract(JanetMarshalContext *ctx, size_t size) {
return p; return p;
} }
void *janet_unmarshal_abstract_threaded(JanetMarshalContext *ctx, size_t size) {
#ifdef JANET_THREADS
void *p = janet_abstract_threaded(ctx->at, size);
janet_unmarshal_abstract_reuse(ctx, p);
return p;
#else
(void) ctx;
(void) size;
janet_panic("threaded abstracts not supported");
#endif
}
static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) { static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) {
Janet key; Janet key;
data = unmarshal_one(st, data, &key, flags + 1); data = unmarshal_one(st, data, &key, flags + 1);

View File

@@ -706,6 +706,18 @@ static const struct keyword_signal signal_keywords[] = {
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static int get_signal_kw(const Janet *argv, int32_t n) {
JanetKeyword signal_kw = janet_getkeyword(argv, n);
const struct keyword_signal *ptr = signal_keywords;
while (ptr->keyword) {
if (!janet_cstrcmp(signal_kw, ptr->keyword)) {
return ptr->signal;
}
ptr++;
}
janet_panicf("undefined signal %v", argv[n]);
}
#endif #endif
JANET_CORE_FN(os_proc_kill, JANET_CORE_FN(os_proc_kill,
@@ -731,18 +743,7 @@ JANET_CORE_FN(os_proc_kill,
#else #else
int signal = -1; int signal = -1;
if (argc == 3) { if (argc == 3) {
JanetKeyword signal_kw = janet_getkeyword(argv, 2); signal = get_signal_kw(argv, 2);
const struct keyword_signal *ptr = signal_keywords;
while (ptr->keyword) {
if (!janet_cstrcmp(signal_kw, ptr->keyword)) {
signal = ptr->signal;
break;
}
ptr++;
}
if (signal == -1) {
janet_panic("undefined signal");
}
} }
int status = kill(proc->pid, signal == -1 ? SIGKILL : signal); int status = kill(proc->pid, signal == -1 ? SIGKILL : signal);
if (status) { if (status) {
@@ -803,6 +804,102 @@ static void close_handle(JanetHandle handle) {
#endif #endif
} }
#ifdef JANET_EV
#ifndef JANET_WINDOWS
static void janet_signal_callback(JanetEVGenericMessage msg) {
int sig = msg.tag;
Janet handlerv = janet_table_get(&janet_vm.signal_handlers, janet_wrap_integer(sig));
if (!janet_checktype(handlerv, JANET_FUNCTION)) {
/* Let another thread/process try to handle this */
sigset_t set;
sigemptyset(&set);
sigaddset(&set, sig);
#ifdef JANET_THREADS
pthread_sigmask(SIG_BLOCK, &set, NULL);
#else
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
raise(sig);
return;
}
JanetFunction *handler = janet_unwrap_function(handlerv);
JanetFiber *fiber = janet_fiber(handler, 64, 0, NULL);
janet_schedule(fiber, janet_wrap_nil());
if (msg.argi) {
janet_ev_dec_refcount();
}
}
static void janet_signal_trampoline_no_interrupt(int sig) {
/* Do not interact with global janet state here except for janet_ev_post_event, unsafe! */
JanetEVGenericMessage msg;
memset(&msg, 0, sizeof(msg));
msg.tag = sig;
janet_ev_post_event(&janet_vm, janet_signal_callback, msg);
}
static void janet_signal_trampoline(int sig) {
/* Do not interact with global janet state here except for janet_ev_post_event, unsafe! */
JanetEVGenericMessage msg;
memset(&msg, 0, sizeof(msg));
msg.tag = sig;
msg.argi = 1;
janet_ev_post_event(&janet_vm, janet_signal_callback, msg);
janet_ev_inc_refcount();
janet_interpreter_interrupt(NULL);
}
#endif
JANET_CORE_FN(os_sigaction,
"(os/sigaction which &opt handler interrupt-interpreter)",
"Add a signal handler for a given action. Use nil for the `handler` argument to remove a signal handler.") {
janet_sandbox_assert(JANET_SANDBOX_SIGNAL);
janet_arity(argc, 1, 3);
#ifdef JANET_WINDOWS
janet_panic("unsupported on this platform");
#else
/* TODO - per thread signal masks */
int rc;
int sig = get_signal_kw(argv, 0);
JanetFunction *handler = janet_optfunction(argv, argc, 1, NULL);
int can_interrupt = janet_optboolean(argv, argc, 2, 0);
Janet oldhandler = janet_table_get(&janet_vm.signal_handlers, janet_wrap_integer(sig));
if (!janet_checktype(oldhandler, JANET_NIL)) {
janet_gcunroot(oldhandler);
}
if (NULL != handler) {
Janet handlerv = janet_wrap_function(handler);
janet_gcroot(handlerv);
janet_table_put(&janet_vm.signal_handlers, janet_wrap_integer(sig), handlerv);
} else {
janet_table_put(&janet_vm.signal_handlers, janet_wrap_integer(sig), janet_wrap_nil());
}
struct sigaction action;
sigset_t mask;
sigfillset(&mask);
memset(&action, 0, sizeof(action));
if (can_interrupt) {
action.sa_handler = janet_signal_trampoline;
} else {
action.sa_handler = janet_signal_trampoline_no_interrupt;
}
action.sa_mask = mask;
RETRY_EINTR(rc, sigaction(sig, &action, NULL));
sigset_t set;
sigemptyset(&set);
sigaddset(&set, sig);
#ifdef JANET_THREADS
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
#else
sigprocmask(SIG_UNBLOCK, &set, NULL);
#endif
return janet_wrap_nil();
#endif
}
#endif
/* Create piped file for os/execute and os/spawn. Need to be careful that we mark /* Create piped file for os/execute and os/spawn. Need to be careful that we mark
the error flag if we can't create pipe and don't leak handles. *handle will be cleaned the error flag if we can't create pipe and don't leak handles. *handle will be cleaned
up by the calling function. If everything goes well, *handle is owned by the calling function, up by the calling function. If everything goes well, *handle is owned by the calling function,
@@ -2536,6 +2633,7 @@ void janet_lib_os(JanetTable *env) {
#ifdef JANET_EV #ifdef JANET_EV
JANET_CORE_REG("os/open", os_open), /* fs read and write */ JANET_CORE_REG("os/open", os_open), /* fs read and write */
JANET_CORE_REG("os/pipe", os_pipe), JANET_CORE_REG("os/pipe", os_pipe),
JANET_CORE_REG("os/sigaction", os_sigaction),
#endif #endif
#endif #endif
JANET_REG_END JANET_REG_END

View File

@@ -89,7 +89,7 @@ struct JanetVM {
/* If this flag is true, suspend on function calls and backwards jumps. /* If this flag is true, suspend on function calls and backwards jumps.
* When this occurs, this flag will be reset to 0. */ * When this occurs, this flag will be reset to 0. */
int auto_suspend; volatile int auto_suspend;
/* The current running fiber on the current thread. /* The current running fiber on the current thread.
* Set and unset by functions in vm.c */ * Set and unset by functions in vm.c */
@@ -157,9 +157,10 @@ struct JanetVM {
JanetListenerState **listeners; JanetListenerState **listeners;
size_t listener_count; size_t listener_count;
size_t listener_cap; size_t listener_cap;
size_t extra_listeners; volatile size_t extra_listeners; /* used in signal handler, must be volatile */
JanetTable threaded_abstracts; /* All abstract types that can be shared between threads (used in this thread) */ JanetTable threaded_abstracts; /* All abstract types that can be shared between threads (used in this thread) */
JanetTable active_tasks; /* All possibly live task fibers - used just for tracking */ JanetTable active_tasks; /* All possibly live task fibers - used just for tracking */
JanetTable signal_handlers;
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
void **iocp; void **iocp;
#elif defined(JANET_EV_EPOLL) #elif defined(JANET_EV_EPOLL)

View File

@@ -175,8 +175,9 @@ JANET_CORE_FN(cfun_string_slice,
"Returns a substring from a byte sequence. The substring is from " "Returns a substring from a byte sequence. The substring is from "
"index `start` inclusive to index `end`, exclusive. All indexing " "index `start` inclusive to index `end`, exclusive. All indexing "
"is from 0. `start` and `end` can also be negative to indicate indexing " "is from 0. `start` and `end` can also be negative to indicate indexing "
"from the end of the string. Note that index -1 is synonymous with " "from the end of the string. Note that if `start` is negative it is "
"index `(length bytes)` to allow a full negative slice range. ") { "exclusive, and if `end` is negative it is inclusive, to allow a full "
"negative slice range.") {
JanetByteView view = janet_getbytes(argv, 0); JanetByteView view = janet_getbytes(argv, 0);
JanetRange range = janet_getslice(argc, argv); JanetRange range = janet_getslice(argc, argv);
return janet_stringv(view.bytes + range.start, range.end - range.start); return janet_stringv(view.bytes + range.start, range.end - range.start);

View File

@@ -69,9 +69,9 @@ JANET_CORE_FN(cfun_tuple_slice,
"inclusive to index `end` exclusive. If `start` or `end` are not provided, " "inclusive to index `end` exclusive. If `start` or `end` are not provided, "
"they default to 0 and the length of `arrtup`, respectively. " "they default to 0 and the length of `arrtup`, respectively. "
"`start` and `end` can also be negative to indicate indexing " "`start` and `end` can also be negative to indicate indexing "
"from the end of the input. Note that index -1 is synonymous with " "from the end of the input. Note that if `start` is negative it is "
"index `(length arrtup)` to allow a full negative slice range. " "exclusive, and if `end` is negative it is inclusive, to allow a full "
"Returns the new tuple.") { "negative slice range. Returns the new tuple.") {
JanetView view = janet_getindexed(argv, 0); JanetView view = janet_getindexed(argv, 0);
JanetRange range = janet_getslice(argc, argv); JanetRange range = janet_getslice(argc, argv);
return janet_wrap_tuple(janet_tuple_n(view.items + range.start, range.end - range.start)); return janet_wrap_tuple(janet_tuple_n(view.items + range.start, range.end - range.start));

View File

@@ -800,13 +800,13 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
VM_OP(JOP_JUMP) VM_OP(JOP_JUMP)
pc += DS; pc += DS;
vm_maybe_auto_suspend(DS < 0); vm_maybe_auto_suspend(DS <= 0);
vm_next(); vm_next();
VM_OP(JOP_JUMP_IF) VM_OP(JOP_JUMP_IF)
if (janet_truthy(stack[A])) { if (janet_truthy(stack[A])) {
pc += ES; pc += ES;
vm_maybe_auto_suspend(ES < 0); vm_maybe_auto_suspend(ES <= 0);
} else { } else {
pc++; pc++;
} }
@@ -817,14 +817,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
pc++; pc++;
} else { } else {
pc += ES; pc += ES;
vm_maybe_auto_suspend(ES < 0); vm_maybe_auto_suspend(ES <= 0);
} }
vm_next(); vm_next();
VM_OP(JOP_JUMP_IF_NIL) VM_OP(JOP_JUMP_IF_NIL)
if (janet_checktype(stack[A], JANET_NIL)) { if (janet_checktype(stack[A], JANET_NIL)) {
pc += ES; pc += ES;
vm_maybe_auto_suspend(ES < 0); vm_maybe_auto_suspend(ES <= 0);
} else { } else {
pc++; pc++;
} }
@@ -835,7 +835,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
pc++; pc++;
} else { } else {
pc += ES; pc += ES;
vm_maybe_auto_suspend(ES < 0); vm_maybe_auto_suspend(ES <= 0);
} }
vm_next(); vm_next();

View File

@@ -43,10 +43,10 @@ int (janet_truthy)(Janet x) {
return janet_truthy(x); return janet_truthy(x);
} }
const JanetKV *(janet_unwrap_struct)(Janet x) { JanetStruct(janet_unwrap_struct)(Janet x) {
return janet_unwrap_struct(x); return janet_unwrap_struct(x);
} }
const Janet *(janet_unwrap_tuple)(Janet x) { JanetTuple(janet_unwrap_tuple)(Janet x) {
return janet_unwrap_tuple(x); return janet_unwrap_tuple(x);
} }
JanetFiber *(janet_unwrap_fiber)(Janet x) { JanetFiber *(janet_unwrap_fiber)(Janet x) {
@@ -61,16 +61,16 @@ JanetTable *(janet_unwrap_table)(Janet x) {
JanetBuffer *(janet_unwrap_buffer)(Janet x) { JanetBuffer *(janet_unwrap_buffer)(Janet x) {
return janet_unwrap_buffer(x); return janet_unwrap_buffer(x);
} }
const uint8_t *(janet_unwrap_string)(Janet x) { JanetString(janet_unwrap_string)(Janet x) {
return janet_unwrap_string(x); return janet_unwrap_string(x);
} }
const uint8_t *(janet_unwrap_symbol)(Janet x) { JanetSymbol(janet_unwrap_symbol)(Janet x) {
return janet_unwrap_symbol(x); return janet_unwrap_symbol(x);
} }
const uint8_t *(janet_unwrap_keyword)(Janet x) { JanetKeyword(janet_unwrap_keyword)(Janet x) {
return janet_unwrap_keyword(x); return janet_unwrap_keyword(x);
} }
void *(janet_unwrap_abstract)(Janet x) { JanetAbstract(janet_unwrap_abstract)(Janet x) {
return janet_unwrap_abstract(x); return janet_unwrap_abstract(x);
} }
void *(janet_unwrap_pointer)(Janet x) { void *(janet_unwrap_pointer)(Janet x) {
@@ -102,22 +102,22 @@ Janet(janet_wrap_false)(void) {
Janet(janet_wrap_boolean)(int x) { Janet(janet_wrap_boolean)(int x) {
return janet_wrap_boolean(x); return janet_wrap_boolean(x);
} }
Janet(janet_wrap_string)(const uint8_t *x) { Janet(janet_wrap_string)(JanetString x) {
return janet_wrap_string(x); return janet_wrap_string(x);
} }
Janet(janet_wrap_symbol)(const uint8_t *x) { Janet(janet_wrap_symbol)(JanetSymbol x) {
return janet_wrap_symbol(x); return janet_wrap_symbol(x);
} }
Janet(janet_wrap_keyword)(const uint8_t *x) { Janet(janet_wrap_keyword)(JanetKeyword x) {
return janet_wrap_keyword(x); return janet_wrap_keyword(x);
} }
Janet(janet_wrap_array)(JanetArray *x) { Janet(janet_wrap_array)(JanetArray *x) {
return janet_wrap_array(x); return janet_wrap_array(x);
} }
Janet(janet_wrap_tuple)(const Janet *x) { Janet(janet_wrap_tuple)(JanetTuple x) {
return janet_wrap_tuple(x); return janet_wrap_tuple(x);
} }
Janet(janet_wrap_struct)(const JanetKV *x) { Janet(janet_wrap_struct)(JanetStruct x) {
return janet_wrap_struct(x); return janet_wrap_struct(x);
} }
Janet(janet_wrap_fiber)(JanetFiber *x) { Janet(janet_wrap_fiber)(JanetFiber *x) {
@@ -135,7 +135,7 @@ Janet(janet_wrap_cfunction)(JanetCFunction x) {
Janet(janet_wrap_table)(JanetTable *x) { Janet(janet_wrap_table)(JanetTable *x) {
return janet_wrap_table(x); return janet_wrap_table(x);
} }
Janet(janet_wrap_abstract)(void *x) { Janet(janet_wrap_abstract)(JanetAbstract x) {
return janet_wrap_abstract(x); return janet_wrap_abstract(x);
} }
Janet(janet_wrap_pointer)(void *x) { Janet(janet_wrap_pointer)(void *x) {
@@ -317,4 +317,3 @@ JANET_WRAP_DEFINE(pointer, void *, JANET_POINTER, pointer)
#undef JANET_WRAP_DEFINE #undef JANET_WRAP_DEFINE
#endif #endif

View File

@@ -653,10 +653,10 @@ struct JanetListenerState {
* external bindings, we should prefer using the Head structs directly, and * external bindings, we should prefer using the Head structs directly, and
* use the host language to add sugar around the manipulation of the Janet types. */ * use the host language to add sugar around the manipulation of the Janet types. */
JANET_API JanetStructHead *janet_struct_head(const JanetKV *st); JANET_API JanetStructHead *janet_struct_head(JanetStruct st);
JANET_API JanetAbstractHead *janet_abstract_head(const void *abstract); JANET_API JanetAbstractHead *janet_abstract_head(const void *abstract);
JANET_API JanetStringHead *janet_string_head(const uint8_t *s); JANET_API JanetStringHead *janet_string_head(JanetString s);
JANET_API JanetTupleHead *janet_tuple_head(const Janet *tuple); JANET_API JanetTupleHead *janet_tuple_head(JanetTuple tuple);
/* Some language bindings won't have access to the macro versions. */ /* Some language bindings won't have access to the macro versions. */
@@ -665,16 +665,16 @@ JANET_API int janet_checktype(Janet x, JanetType type);
JANET_API int janet_checktypes(Janet x, int typeflags); JANET_API int janet_checktypes(Janet x, int typeflags);
JANET_API int janet_truthy(Janet x); JANET_API int janet_truthy(Janet x);
JANET_API const JanetKV *janet_unwrap_struct(Janet x); JANET_API JanetStruct janet_unwrap_struct(Janet x);
JANET_API const Janet *janet_unwrap_tuple(Janet x); JANET_API JanetTuple janet_unwrap_tuple(Janet x);
JANET_API JanetFiber *janet_unwrap_fiber(Janet x); JANET_API JanetFiber *janet_unwrap_fiber(Janet x);
JANET_API JanetArray *janet_unwrap_array(Janet x); JANET_API JanetArray *janet_unwrap_array(Janet x);
JANET_API JanetTable *janet_unwrap_table(Janet x); JANET_API JanetTable *janet_unwrap_table(Janet x);
JANET_API JanetBuffer *janet_unwrap_buffer(Janet x); JANET_API JanetBuffer *janet_unwrap_buffer(Janet x);
JANET_API const uint8_t *janet_unwrap_string(Janet x); JANET_API JanetString janet_unwrap_string(Janet x);
JANET_API const uint8_t *janet_unwrap_symbol(Janet x); JANET_API JanetSymbol janet_unwrap_symbol(Janet x);
JANET_API const uint8_t *janet_unwrap_keyword(Janet x); JANET_API JanetKeyword janet_unwrap_keyword(Janet x);
JANET_API void *janet_unwrap_abstract(Janet x); JANET_API JanetAbstract janet_unwrap_abstract(Janet x);
JANET_API void *janet_unwrap_pointer(Janet x); JANET_API void *janet_unwrap_pointer(Janet x);
JANET_API JanetFunction *janet_unwrap_function(Janet x); JANET_API JanetFunction *janet_unwrap_function(Janet x);
JANET_API JanetCFunction janet_unwrap_cfunction(Janet x); JANET_API JanetCFunction janet_unwrap_cfunction(Janet x);
@@ -687,18 +687,18 @@ JANET_API Janet janet_wrap_number(double x);
JANET_API Janet janet_wrap_true(void); JANET_API Janet janet_wrap_true(void);
JANET_API Janet janet_wrap_false(void); JANET_API Janet janet_wrap_false(void);
JANET_API Janet janet_wrap_boolean(int x); JANET_API Janet janet_wrap_boolean(int x);
JANET_API Janet janet_wrap_string(const uint8_t *x); JANET_API Janet janet_wrap_string(JanetString x);
JANET_API Janet janet_wrap_symbol(const uint8_t *x); JANET_API Janet janet_wrap_symbol(JanetSymbol x);
JANET_API Janet janet_wrap_keyword(const uint8_t *x); JANET_API Janet janet_wrap_keyword(JanetKeyword x);
JANET_API Janet janet_wrap_array(JanetArray *x); JANET_API Janet janet_wrap_array(JanetArray *x);
JANET_API Janet janet_wrap_tuple(const Janet *x); JANET_API Janet janet_wrap_tuple(JanetTuple x);
JANET_API Janet janet_wrap_struct(const JanetKV *x); JANET_API Janet janet_wrap_struct(JanetStruct x);
JANET_API Janet janet_wrap_fiber(JanetFiber *x); JANET_API Janet janet_wrap_fiber(JanetFiber *x);
JANET_API Janet janet_wrap_buffer(JanetBuffer *x); JANET_API Janet janet_wrap_buffer(JanetBuffer *x);
JANET_API Janet janet_wrap_function(JanetFunction *x); JANET_API Janet janet_wrap_function(JanetFunction *x);
JANET_API Janet janet_wrap_cfunction(JanetCFunction x); JANET_API Janet janet_wrap_cfunction(JanetCFunction x);
JANET_API Janet janet_wrap_table(JanetTable *x); JANET_API Janet janet_wrap_table(JanetTable *x);
JANET_API Janet janet_wrap_abstract(void *x); JANET_API Janet janet_wrap_abstract(JanetAbstract x);
JANET_API Janet janet_wrap_pointer(void *x); JANET_API Janet janet_wrap_pointer(void *x);
JANET_API Janet janet_wrap_integer(int32_t x); JANET_API Janet janet_wrap_integer(int32_t x);
@@ -776,14 +776,14 @@ JANET_API Janet janet_nanbox_from_bits(uint64_t bits);
#define janet_wrap_pointer(s) janet_nanbox_wrap_((s), JANET_POINTER) #define janet_wrap_pointer(s) janet_nanbox_wrap_((s), JANET_POINTER)
/* Unwrap the pointer types */ /* Unwrap the pointer types */
#define janet_unwrap_struct(x) ((const JanetKV *)janet_nanbox_to_pointer(x)) #define janet_unwrap_struct(x) ((JanetStruct)janet_nanbox_to_pointer(x))
#define janet_unwrap_tuple(x) ((const Janet *)janet_nanbox_to_pointer(x)) #define janet_unwrap_tuple(x) ((JanetTuple)janet_nanbox_to_pointer(x))
#define janet_unwrap_fiber(x) ((JanetFiber *)janet_nanbox_to_pointer(x)) #define janet_unwrap_fiber(x) ((JanetFiber *)janet_nanbox_to_pointer(x))
#define janet_unwrap_array(x) ((JanetArray *)janet_nanbox_to_pointer(x)) #define janet_unwrap_array(x) ((JanetArray *)janet_nanbox_to_pointer(x))
#define janet_unwrap_table(x) ((JanetTable *)janet_nanbox_to_pointer(x)) #define janet_unwrap_table(x) ((JanetTable *)janet_nanbox_to_pointer(x))
#define janet_unwrap_buffer(x) ((JanetBuffer *)janet_nanbox_to_pointer(x)) #define janet_unwrap_buffer(x) ((JanetBuffer *)janet_nanbox_to_pointer(x))
#define janet_unwrap_string(x) ((const uint8_t *)janet_nanbox_to_pointer(x)) #define janet_unwrap_string(x) ((JanetString)janet_nanbox_to_pointer(x))
#define janet_unwrap_symbol(x) ((const uint8_t *)janet_nanbox_to_pointer(x)) #define janet_unwrap_symbol(x) ((JanetSymbol)janet_nanbox_to_pointer(x))
#define janet_unwrap_keyword(x) ((const uint8_t *)janet_nanbox_to_pointer(x)) #define janet_unwrap_keyword(x) ((const uint8_t *)janet_nanbox_to_pointer(x))
#define janet_unwrap_abstract(x) (janet_nanbox_to_pointer(x)) #define janet_unwrap_abstract(x) (janet_nanbox_to_pointer(x))
#define janet_unwrap_pointer(x) (janet_nanbox_to_pointer(x)) #define janet_unwrap_pointer(x) (janet_nanbox_to_pointer(x))
@@ -825,15 +825,15 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer);
#define janet_wrap_cfunction(s) janet_nanbox32_from_tagp(JANET_CFUNCTION, (void *)(s)) #define janet_wrap_cfunction(s) janet_nanbox32_from_tagp(JANET_CFUNCTION, (void *)(s))
#define janet_wrap_pointer(s) janet_nanbox32_from_tagp(JANET_POINTER, (void *)(s)) #define janet_wrap_pointer(s) janet_nanbox32_from_tagp(JANET_POINTER, (void *)(s))
#define janet_unwrap_struct(x) ((const JanetKV *)(x).tagged.payload.pointer) #define janet_unwrap_struct(x) ((JanetStruct)(x).tagged.payload.pointer)
#define janet_unwrap_tuple(x) ((const Janet *)(x).tagged.payload.pointer) #define janet_unwrap_tuple(x) ((JanetTuple)(x).tagged.payload.pointer)
#define janet_unwrap_fiber(x) ((JanetFiber *)(x).tagged.payload.pointer) #define janet_unwrap_fiber(x) ((JanetFiber *)(x).tagged.payload.pointer)
#define janet_unwrap_array(x) ((JanetArray *)(x).tagged.payload.pointer) #define janet_unwrap_array(x) ((JanetArray *)(x).tagged.payload.pointer)
#define janet_unwrap_table(x) ((JanetTable *)(x).tagged.payload.pointer) #define janet_unwrap_table(x) ((JanetTable *)(x).tagged.payload.pointer)
#define janet_unwrap_buffer(x) ((JanetBuffer *)(x).tagged.payload.pointer) #define janet_unwrap_buffer(x) ((JanetBuffer *)(x).tagged.payload.pointer)
#define janet_unwrap_string(x) ((const uint8_t *)(x).tagged.payload.pointer) #define janet_unwrap_string(x) ((JanetString)(x).tagged.payload.pointer)
#define janet_unwrap_symbol(x) ((const uint8_t *)(x).tagged.payload.pointer) #define janet_unwrap_symbol(x) ((JanetSymbol)(x).tagged.payload.pointer)
#define janet_unwrap_keyword(x) ((const uint8_t *)(x).tagged.payload.pointer) #define janet_unwrap_keyword(x) ((JanetKeyword)(x).tagged.payload.pointer)
#define janet_unwrap_abstract(x) ((x).tagged.payload.pointer) #define janet_unwrap_abstract(x) ((x).tagged.payload.pointer)
#define janet_unwrap_pointer(x) ((x).tagged.payload.pointer) #define janet_unwrap_pointer(x) ((x).tagged.payload.pointer)
#define janet_unwrap_function(x) ((JanetFunction *)(x).tagged.payload.pointer) #define janet_unwrap_function(x) ((JanetFunction *)(x).tagged.payload.pointer)
@@ -848,15 +848,15 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer);
#define janet_truthy(x) \ #define janet_truthy(x) \
((x).type != JANET_NIL && ((x).type != JANET_BOOLEAN || ((x).as.u64 & 0x1))) ((x).type != JANET_NIL && ((x).type != JANET_BOOLEAN || ((x).as.u64 & 0x1)))
#define janet_unwrap_struct(x) ((const JanetKV *)(x).as.pointer) #define janet_unwrap_struct(x) ((JanetStruct)(x).as.pointer)
#define janet_unwrap_tuple(x) ((const Janet *)(x).as.pointer) #define janet_unwrap_tuple(x) ((JanetTuple)(x).as.pointer)
#define janet_unwrap_fiber(x) ((JanetFiber *)(x).as.pointer) #define janet_unwrap_fiber(x) ((JanetFiber *)(x).as.pointer)
#define janet_unwrap_array(x) ((JanetArray *)(x).as.pointer) #define janet_unwrap_array(x) ((JanetArray *)(x).as.pointer)
#define janet_unwrap_table(x) ((JanetTable *)(x).as.pointer) #define janet_unwrap_table(x) ((JanetTable *)(x).as.pointer)
#define janet_unwrap_buffer(x) ((JanetBuffer *)(x).as.pointer) #define janet_unwrap_buffer(x) ((JanetBuffer *)(x).as.pointer)
#define janet_unwrap_string(x) ((const uint8_t *)(x).as.pointer) #define janet_unwrap_string(x) ((JanetString)(x).as.pointer)
#define janet_unwrap_symbol(x) ((const uint8_t *)(x).as.pointer) #define janet_unwrap_symbol(x) ((JanetSymbol)(x).as.pointer)
#define janet_unwrap_keyword(x) ((const uint8_t *)(x).as.pointer) #define janet_unwrap_keyword(x) ((JanetKeyword)(x).as.pointer)
#define janet_unwrap_abstract(x) ((x).as.pointer) #define janet_unwrap_abstract(x) ((x).as.pointer)
#define janet_unwrap_pointer(x) ((x).as.pointer) #define janet_unwrap_pointer(x) ((x).as.pointer)
#define janet_unwrap_function(x) ((JanetFunction *)(x).as.pointer) #define janet_unwrap_function(x) ((JanetFunction *)(x).as.pointer)
@@ -1612,7 +1612,7 @@ JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x);
#define JANET_TUPLE_FLAG_BRACKETCTOR 0x10000 #define JANET_TUPLE_FLAG_BRACKETCTOR 0x10000
#define janet_tuple_head(t) ((JanetTupleHead *)((char *)t - offsetof(JanetTupleHead, data))) #define janet_tuple_head(t) ((JanetTupleHead *)((char *)t - offsetof(JanetTupleHead, data)))
#define janet_tuple_from_head(gcobject) ((const Janet *)((char *)gcobject + offsetof(JanetTupleHead, data))) #define janet_tuple_from_head(gcobject) ((JanetTuple)((char *)gcobject + offsetof(JanetTupleHead, data)))
#define janet_tuple_length(t) (janet_tuple_head(t)->length) #define janet_tuple_length(t) (janet_tuple_head(t)->length)
#define janet_tuple_hash(t) (janet_tuple_head(t)->hash) #define janet_tuple_hash(t) (janet_tuple_head(t)->hash)
#define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line) #define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line)
@@ -1658,7 +1658,7 @@ JANET_API JanetSymbol janet_symbol_gen(void);
/* Structs */ /* Structs */
#define janet_struct_head(t) ((JanetStructHead *)((char *)t - offsetof(JanetStructHead, data))) #define janet_struct_head(t) ((JanetStructHead *)((char *)t - offsetof(JanetStructHead, data)))
#define janet_struct_from_head(t) ((const JanetKV *)((char *)gcobject + offsetof(JanetStructHead, data))) #define janet_struct_from_head(t) ((JanetStruct)((char *)gcobject + offsetof(JanetStructHead, data)))
#define janet_struct_length(t) (janet_struct_head(t)->length) #define janet_struct_length(t) (janet_struct_head(t)->length)
#define janet_struct_capacity(t) (janet_struct_head(t)->capacity) #define janet_struct_capacity(t) (janet_struct_head(t)->capacity)
#define janet_struct_hash(t) (janet_struct_head(t)->hash) #define janet_struct_hash(t) (janet_struct_head(t)->hash)
@@ -1822,6 +1822,7 @@ JANET_API void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *pr
#define JANET_SANDBOX_FS_TEMP 1024 #define JANET_SANDBOX_FS_TEMP 1024
#define JANET_SANDBOX_FFI_USE 2048 #define JANET_SANDBOX_FFI_USE 2048
#define JANET_SANDBOX_FFI_JIT 4096 #define JANET_SANDBOX_FFI_JIT 4096
#define JANET_SANDBOX_SIGNAL 8192
#define JANET_SANDBOX_FFI (JANET_SANDBOX_FFI_DEFINE | JANET_SANDBOX_FFI_USE | JANET_SANDBOX_FFI_JIT) #define JANET_SANDBOX_FFI (JANET_SANDBOX_FFI_DEFINE | JANET_SANDBOX_FFI_USE | JANET_SANDBOX_FFI_JIT)
#define JANET_SANDBOX_FS (JANET_SANDBOX_FS_WRITE | JANET_SANDBOX_FS_READ | JANET_SANDBOX_FS_TEMP) #define JANET_SANDBOX_FS (JANET_SANDBOX_FS_WRITE | JANET_SANDBOX_FS_READ | JANET_SANDBOX_FS_TEMP)
#define JANET_SANDBOX_NET (JANET_SANDBOX_NET_CONNECT | JANET_SANDBOX_NET_LISTEN) #define JANET_SANDBOX_NET (JANET_SANDBOX_NET_CONNECT | JANET_SANDBOX_NET_LISTEN)
@@ -1997,6 +1998,8 @@ JANET_API JanetDictView janet_getdictionary(const Janet *argv, int32_t n);
JANET_API void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstractType *at); JANET_API void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstractType *at);
JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv); JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv);
JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which);
JANET_API int32_t janet_getstartrange(const Janet *argv, int32_t argc, int32_t n, int32_t length);
JANET_API int32_t janet_getendrange(const Janet *argv, int32_t argc, int32_t n, int32_t length);
JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which);
JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags); JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags);
@@ -2070,6 +2073,7 @@ JANET_API uint8_t janet_unmarshal_byte(JanetMarshalContext *ctx);
JANET_API void janet_unmarshal_bytes(JanetMarshalContext *ctx, uint8_t *dest, size_t len); JANET_API void janet_unmarshal_bytes(JanetMarshalContext *ctx, uint8_t *dest, size_t len);
JANET_API Janet janet_unmarshal_janet(JanetMarshalContext *ctx); JANET_API Janet janet_unmarshal_janet(JanetMarshalContext *ctx);
JANET_API JanetAbstract janet_unmarshal_abstract(JanetMarshalContext *ctx, size_t size); JANET_API JanetAbstract janet_unmarshal_abstract(JanetMarshalContext *ctx, size_t size);
JANET_API JanetAbstract janet_unmarshal_abstract_threaded(JanetMarshalContext *ctx, size_t size);
JANET_API void janet_unmarshal_abstract_reuse(JanetMarshalContext *ctx, void *p); JANET_API void janet_unmarshal_abstract_reuse(JanetMarshalContext *ctx, void *p);
JANET_API void janet_register_abstract_type(const JanetAbstractType *at); JANET_API void janet_register_abstract_type(const JanetAbstractType *at);

View File

@@ -44,7 +44,7 @@
(assert (deep= (array/remove @[1 2 3 4 5] 2) @[1 2 4 5]) "array/remove 1") (assert (deep= (array/remove @[1 2 3 4 5] 2) @[1 2 4 5]) "array/remove 1")
(assert (deep= (array/remove @[1 2 3 4 5] 2 2) @[1 2 5]) "array/remove 2") (assert (deep= (array/remove @[1 2 3 4 5] 2 2) @[1 2 5]) "array/remove 2")
(assert (deep= (array/remove @[1 2 3 4 5] 2 200) @[1 2]) "array/remove 3") (assert (deep= (array/remove @[1 2 3 4 5] 2 200) @[1 2]) "array/remove 3")
(assert (deep= (array/remove @[1 2 3 4 5] -3 200) @[1 2 3]) "array/remove 4") (assert (deep= (array/remove @[1 2 3 4 5] -2 200) @[1 2 3]) "array/remove 4")
# array/peek # array/peek

View File

@@ -113,13 +113,22 @@
# 7478ad11 # 7478ad11
(assert (= nil (any? [])) "any? 1") (assert (= nil (any? [])) "any? 1")
(assert (= nil (any? [false nil])) "any? 2") (assert (= nil (any? [false nil])) "any? 2")
(assert (= nil (any? [nil false])) "any? 3") (assert (= false (any? [nil false])) "any? 3")
(assert (= 1 (any? [1])) "any? 4") (assert (= 1 (any? [1])) "any? 4")
(assert (nan? (any? [nil math/nan nil])) "any? 5") (assert (nan? (any? [nil math/nan nil])) "any? 5")
(assert (= true (assert (= true
(any? [nil nil false nil nil true nil nil nil nil false :a nil])) (any? [nil nil false nil nil true nil nil nil nil false :a nil]))
"any? 6") "any? 6")
(assert (= true (every? [])) "every? 1")
(assert (= true (every? [1 true])) "every? 2")
(assert (= 1 (every? [true 1])) "every? 3")
(assert (= nil (every? [nil])) "every? 4")
(assert (= 2 (every? [1 math/nan 2])) "every? 5")
(assert (= false
(every? [1 1 true 1 1 false 1 1 1 1 true :a nil]))
"every? 6")
# Some higher order functions and macros # Some higher order functions and macros
# 5e2de33 # 5e2de33
(def my-array @[1 2 3 4 5 6]) (def my-array @[1 2 3 4 5 6])
@@ -362,14 +371,7 @@
(assert (= false (and false false)) "and 1") (assert (= false (and false false)) "and 1")
(assert (= false (or false false)) "or 1") (assert (= false (or false false)) "or 1")
# Range
# a982f351d
(assert (deep= (range 10) @[0 1 2 3 4 5 6 7 8 9]) "range 1 argument")
(assert (deep= (range 5 10) @[5 6 7 8 9]) "range 2 arguments")
(assert (deep= (range 5 10 2) @[5 7 9]) "range 3 arguments")
# 11cd1279d # 11cd1279d
(assert (= (length (range 10)) 10) "(range 10)")
(assert (= (length (range 1 10)) 9) "(range 1 10)")
(assert (deep= @{:a 1 :b 2 :c 3} (zipcoll '[:a :b :c] '[1 2 3])) "zipcoll") (assert (deep= @{:a 1 :b 2 :c 3} (zipcoll '[:a :b :c] '[1 2 3])) "zipcoll")
# bc8be266f # bc8be266f

View File

@@ -77,6 +77,14 @@
(buffer/push-string b5 "456" @"789") (buffer/push-string b5 "456" @"789")
(assert (= "123456789" (string b5)) "buffer/push-buffer 2") (assert (= "123456789" (string b5)) "buffer/push-buffer 2")
# Buffer from bytes
(assert (deep= @"" (buffer/from-bytes)) "buffer/from-bytes 1")
(assert (deep= @"ABC" (buffer/from-bytes 65 66 67)) "buffer/from-bytes 2")
(assert (deep= @"0123456789" (buffer/from-bytes ;(range 48 58))) "buffer/from-bytes 3")
(assert (= 0 (length (buffer/from-bytes))) "buffer/from-bytes 4")
(assert (= 5 (length (buffer/from-bytes ;(range 5)))) "buffer/from-bytes 5")
(assert-error "bad slot #1, expected 32 bit signed integer" (buffer/from-bytes :abc))
# some tests for buffer/format # some tests for buffer/format
# 029394d # 029394d
(assert (= (string (buffer/format @"" "pi = %6.3f" math/pi)) "pi = 3.142") (assert (= (string (buffer/format @"" "pi = %6.3f" math/pi)) "pi = 3.142")
@@ -103,6 +111,7 @@
(assert (deep= @"bcde" (buffer/blit @"" a -1 1 5)) "buffer/blit 3") (assert (deep= @"bcde" (buffer/blit @"" a -1 1 5)) "buffer/blit 3")
(assert (deep= @"cde" (buffer/blit @"" a -1 2 5)) "buffer/blit 4") (assert (deep= @"cde" (buffer/blit @"" a -1 2 5)) "buffer/blit 4")
(assert (deep= @"de" (buffer/blit @"" a -1 3 5)) "buffer/blit 5") (assert (deep= @"de" (buffer/blit @"" a -1 3 5)) "buffer/blit 5")
(assert (deep= @"de" (buffer/blit @"" a nil 3 5)) "buffer/blit 6")
# buffer/push-at # buffer/push-at
# c55d93512 # c55d93512
@@ -113,8 +122,5 @@
(assert (deep= @"abc423" (buffer/push-at @"abc123" 3 "4")) (assert (deep= @"abc423" (buffer/push-at @"abc123" 3 "4"))
"buffer/push-at 3") "buffer/push-at 3")
# 4782a76
(assert (= 10 (do (var x 10) (def y x) (++ x) y)) "no invalid aliasing")
(end-suite) (end-suite)

View File

@@ -159,5 +159,18 @@
(assert-error "invalid offset-a: 1" (memcmp "a" "b" 1 1 0)) (assert-error "invalid offset-a: 1" (memcmp "a" "b" 1 1 0))
(assert-error "invalid offset-b: 1" (memcmp "a" "b" 1 0 1)) (assert-error "invalid offset-b: 1" (memcmp "a" "b" 1 0 1))
# Range
# a982f351d
(assert (deep= (range 10) @[0 1 2 3 4 5 6 7 8 9]) "(range 10)")
(assert (deep= (range 5 10) @[5 6 7 8 9]) "(range 5 10)")
(assert (deep= (range 0 16 4) @[0 4 8 12]) "(range 0 16 4)")
(assert (deep= (range 0 17 4) @[0 4 8 12 16]) "(range 0 17 4)")
(assert (deep= (range 16 0 -4) @[16 12 8 4]) "(range 16 0 -4)")
(assert (deep= (range 17 0 -4) @[17 13 9 5 1]) "(range 17 0 -4)")
(assert (= (length (range 10)) 10) "(range 10)")
(assert (= (length (range -10)) 0) "(range -10)")
(assert (= (length (range 1 10)) 9) "(range 1 10)")
(end-suite) (end-suite)

View File

@@ -292,5 +292,8 @@
[2 6 4 'z]]) [2 6 4 'z]])
"arg & inner symbolmap") "arg & inner symbolmap")
# 4782a76
(assert (= 10 (do (var x 10) (def y x) (++ x) y)) "no invalid aliasing")
(end-suite) (end-suite)