1
0
mirror of https://github.com/janet-lang/janet synced 2025-11-21 17:54:49 +00:00

Compare commits

..

42 Commits

Author SHA1 Message Date
Calvin Rose
876b7f106f OpenBSD does not work with LC_*_MASK stuff. 2024-05-18 17:22:10 -05:00
Calvin Rose
809b6589a1 Put limits.h back. 2024-05-18 15:31:23 -05:00
Calvin Rose
02f53ca014 Formatting. 2024-05-18 15:21:37 -05:00
Calvin Rose
0b03ddb21b More work on setting locale for extended locale support. 2024-05-18 15:20:22 -05:00
Calvin Rose
ea5d4fd3af JANET_BSD not defined on apple. 2024-05-18 14:24:51 -05:00
Calvin Rose
e6b73f8cd1 BSD, use xlocale for thread safe functionality 2024-05-18 14:11:05 -05:00
Calvin Rose
af232ef729 windows needs a distinct implementation from posix for thread safety.
I must say, the windows solution is a lot simpler.
2024-05-18 14:02:20 -05:00
Calvin Rose
2e2f8abfc0 Work on add locales.
Need to be careful not to mess with %j formatter, or
in some other places.
2024-05-18 13:23:33 -05:00
Calvin Rose
91a583db27 Merge pull request #1448 from znley/master
Add LoongArch64 support
2024-05-18 06:33:07 -05:00
znley
c1647a74c5 Add LoongArch64 support 2024-05-18 07:18:59 +00:00
Calvin Rose
721f280966 Add with-env. 2024-05-16 21:52:49 -05:00
Calvin Rose
e914eaf055 Update CHANGELOG.md 2024-05-16 21:37:08 -05:00
Calvin Rose
fe54013679 Update naming *module-make-env* for #1447 2024-05-16 19:11:25 -05:00
Calvin Rose
fdaf2e1594 Add *module/make-env* 2024-05-16 19:10:30 -05:00
Calvin Rose
9946f3bdf4 Add buffer/format-at
Move changes over from bundle-tools branch and add testing.
2024-05-15 20:16:42 -05:00
Calvin Rose
c747e8d16c Address some compiler linter messages on openbsd 2024-05-15 18:20:20 -05:00
Calvin Rose
3e402d397e Use older openbsd build for CI. 2024-05-15 18:16:19 -05:00
Calvin Rose
0350834cd3 By default, require and import extend current env. 2024-05-15 07:40:21 -05:00
Calvin Rose
60e22d9703 Merge pull request #1445 from wishdev/defbind-alias
Add ffi/defbind-alias
2024-05-11 14:25:03 -05:00
John W Higgins
ee7362e847 Add ffi/defbind-alias 2024-05-09 21:31:22 -07:00
Calvin Rose
369f96b80e Update README to prefer Zulip. 2024-05-03 07:51:35 -05:00
Calvin Rose
7c5ed04ab1 A few minor improvements.
- Add long-form CLI options
- Update changelog.
- Use snprintf instead of sprintf for linters.
2024-05-02 09:13:29 -05:00
Calvin Rose
4779a445e0 Fix BSD/Macos issue for #1431 2024-04-26 19:32:47 -05:00
Calvin Rose
f0f1b7ce9e Address #1431 - level-trigger mode for net/accept-loop
In the edge-trigger mode before this change, if a socket
receives 2 connections before one can be handled, then only a single
connection is handle and 1 connection will never be handled in some
cases. Reverting to level-trigger mode makes this impossible.
2024-04-26 19:28:20 -05:00
Calvin Rose
7c9157a0ed Remove unneeded string functions. 2024-04-26 18:11:10 -05:00
Calvin Rose
522a6cb435 Merge pull request #1440 from ahgamut/cosmo-build
Build janet with Cosmopolitan Libc
2024-04-21 08:06:51 -05:00
Gautham
d0d551d739 remove superconfigure recipe 2024-04-21 01:16:54 -05:00
Gautham
71a123fef7 apelink 2024-04-21 01:14:58 -05:00
Gautham
3f40c8d7fb fix typo 2024-04-21 01:12:59 -05:00
Gautham
983c2e5499 simplify build to use only cosmocc 2024-04-21 01:10:06 -05:00
Gautham
eebb4c3ade remove logging 2024-04-20 22:35:04 -05:00
Gautham
50425eac72 typo 2024-04-20 22:23:29 -05:00
Gautham
382ff77bbe typo 2024-04-20 22:16:23 -05:00
Gautham
bf680fb5d3 simplify janet APE build 2024-04-20 22:09:10 -05:00
Gautham
4ed7db4f91 simplify naming 2024-04-19 10:56:46 -05:00
Calvin Rose
bf19920d65 Improve casting. 2024-04-18 03:29:45 -05:00
Gautham
174b5f6686 missing folder 2024-04-16 22:24:31 -05:00
Gautham
4173645b81 missing folder 2024-04-16 22:23:12 -05:00
Gautham
af511f1f55 patch folder location 2024-04-16 22:15:54 -05:00
Gautham
83c6080380 yml config for building with Cosmopolitan Libc 2024-04-16 22:02:31 -05:00
Calvin Rose
2f0c789ea1 More work to address #1391
Properly set read_fiber and write_fiber to NULL when unused.
This was causing extra listening in the poll implemenation leading to
busy loops where a read was accidentally listening for POLLOUT.
2024-04-15 21:32:17 -05:00
Calvin Rose
a9b8f8e8a9 Address #1391 - set fd to negative value if not used.
See https://groups.google.com/g/comp.unix.programmer/c/bNNadBIEpTo/m/G5gs1mqNhbIJ?pli=1 for a conversation and workaround.
2024-04-15 18:12:42 -05:00
22 changed files with 506 additions and 153 deletions

View File

@@ -1,4 +1,4 @@
image: openbsd/latest image: openbsd/7.4
sources: sources:
- https://git.sr.ht/~bakpakin/janet - https://git.sr.ht/~bakpakin/janet
packages: packages:

38
.github/cosmo/build vendored Normal file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
set -eux
COSMO_DIR="/sc/cosmocc"
# build x86_64
X86_64_CC="/sc/cosmocc/bin/x86_64-unknown-cosmo-cc"
X86_64_AR="/sc/cosmocc/bin/x86_64-unknown-cosmo-ar"
mkdir -p /sc/cosmocc/x86_64
make -j CC="$X86_64_CC" AR="$X86_64_AR" HAS_SHARED=0 JANET_NO_AMALG=1
cp build/janet /sc/cosmocc/x86_64/janet
make clean
# build aarch64
AARCH64_CC="/sc/cosmocc/bin/aarch64-unknown-cosmo-cc"
AARCH64_AR="/sc/cosmocc/bin/aarch64-unknown-cosmo-ar"
mkdir -p /sc/cosmocc/aarch64
make -j CC="$AARCH64_CC" AR="$AARCH64_AR" HAS_SHARED=0 JANET_NO_AMALG=1
cp build/janet /sc/cosmocc/aarch64/janet
make clean
# fat binary
apefat () {
OUTPUT="$1"
OLDNAME_X86_64="$(basename -- "$2")"
OLDNAME_AARCH64="$(basename -- "$3")"
TARG_FOLD="$(dirname "$OUTPUT")"
"$COSMO_DIR/bin/apelink" -l "$COSMO_DIR/bin/ape-x86_64.elf" \
-l "$COSMO_DIR/bin/ape-aarch64.elf" \
-M "$COSMO_DIR/bin/ape-m1.c" \
-o "$OUTPUT" \
"$2" \
"$3"
cp "$2" "$TARG_FOLD/$OLDNAME_X86_64.x86_64"
cp "$3" "$TARG_FOLD/$OLDNAME_AARCH64.aarch64"
}
apefat /sc/cosmocc/janet.com /sc/cosmocc/x86_64/janet /sc/cosmocc/aarch64/janet

21
.github/cosmo/setup vendored Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
set -e
sudo apt update
sudo apt-get install -y ca-certificates libssl-dev\
qemu qemu-utils qemu-user-static\
texinfo groff\
cmake ninja-build bison zip\
pkg-config build-essential autoconf re2c
# download cosmocc
cd /sc
wget https://github.com/jart/cosmopolitan/releases/download/3.3.3/cosmocc-3.3.3.zip
mkdir -p cosmocc
cd cosmocc
unzip ../cosmocc-3.3.3.zip
# register
cd /sc/cosmocc
sudo cp ./bin/ape-x86_64.elf /usr/bin/ape
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"

View File

@@ -60,3 +60,30 @@ jobs:
./dist/*.zip ./dist/*.zip
./*.zip ./*.zip
./*.msi ./*.msi
release-cosmo:
permissions:
contents: write # for softprops/action-gh-release to create GitHub release
name: Build release binaries for Cosmo
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@master
- name: create build folder
run: |
sudo mkdir -p /sc
sudo chmod -R 0777 /sc
- name: setup Cosmopolitan Libc
run: bash ./.github/cosmo/setup
- name: Set the version
run: echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
- name: Set the platform
run: echo "platform=cosmo" >> $GITHUB_ENV
- name: build Janet APE binary
run: bash ./.github/cosmo/build
- name: push binary to github
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
/sc/cosmocc/janet.com

3
.gitignore vendored
View File

@@ -134,6 +134,9 @@ Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
# Coverage files
*.cov
# End of https://www.gitignore.io/api/c # End of https://www.gitignore.io/api/c
# Created by https://www.gitignore.io/api/cmake # Created by https://www.gitignore.io/api/cmake

View File

@@ -1,6 +1,13 @@
# 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 - ???
- Add `with-env`
- Add *module-make-env* dynamic binding
- Add buffer/format-at
- Add long form command line options for readable CLI usage
- Fix bug with `net/accept-loop` that would sometimes miss connections.
## 1.34.0 - 2024-03-22 ## 1.34.0 - 2024-03-22
- Add a new (split) PEG special by @ianthehenry - Add a new (split) PEG special by @ianthehenry
- Add buffer/push-* sized int and float by @pnelson - Add buffer/push-* sized int and float by @pnelson

View File

@@ -315,8 +315,7 @@ See the [Embedding Section](https://janet-lang.org/capi/embedding.html) on the w
## Discussion ## Discussion
Feel free to ask questions and join the discussion on the [Janet Gitter channel](https://gitter.im/janet-language/community). Feel free to ask questions and join the discussion on the [Janet Zulip Instance](https://janet.zulipchat.com/)
Gitter provides Matrix and IRC bridges as well.
## FAQ ## FAQ

View File

@@ -55,6 +55,7 @@
(ffi/defbind sixints-fn six-ints []) (ffi/defbind sixints-fn six-ints [])
(ffi/defbind sixints-fn-2 :int [x :int s six-ints]) (ffi/defbind sixints-fn-2 :int [x :int s six-ints])
(ffi/defbind sixints-fn-3 :int [s six-ints x :int]) (ffi/defbind sixints-fn-3 :int [s six-ints x :int])
(ffi/defbind-alias int-fn int-fn-aliased :int [a :int b :int])
# #
# Struct reading and writing # Struct reading and writing
@@ -119,6 +120,7 @@
(tracev (return-struct 42)) (tracev (return-struct 42))
(tracev (double-lots 1 2 3 4 5 6 700 800 9 10)) (tracev (double-lots 1 2 3 4 5 6 700 800 9 10))
(tracev (struct-big 11 99.5)) (tracev (struct-big 11 99.5))
(tracev (int-fn-aliased 10 20))
(assert (= [10 10 12 12] (split-ret-fn 10 12))) (assert (= [10 10 12 12] (split-ret-fn 10 12)))
(assert (= [12 12 10 10] (split-flip-ret-fn 10 12))) (assert (= [12 12 10 10] (split-flip-ret-fn 10 12)))

View File

@@ -1423,6 +1423,11 @@
~(setdyn ,(bindings i) ,(bindings (+ i 1))))) ~(setdyn ,(bindings i) ,(bindings (+ i 1)))))
~(,resume (,fiber/new (fn [] ,;dyn-forms ,;body) :p))) ~(,resume (,fiber/new (fn [] ,;dyn-forms ,;body) :p)))
(defmacro with-env
`Run a block of code with a given environment table`
[env & body]
~(,resume (,fiber/new (fn [] ,;body) : ,env)))
(defmacro with-vars (defmacro with-vars
``Evaluates `body` with each var in `vars` temporarily bound. Similar signature to ``Evaluates `body` with each var in `vars` temporarily bound. Similar signature to
`let`, but each binding must be a var.`` `let`, but each binding must be a var.``
@@ -2767,10 +2772,11 @@
(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "@" x) (string/has-prefix? "." x)) x)) (defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "@" x) (string/has-prefix? "." x)) x))
(defn- check-project-relative [x] (if (string/has-prefix? "/" x) x)) (defn- check-project-relative [x] (if (string/has-prefix? "/" x) x))
(defdyn *module/cache* "Dynamic binding for overriding `module/cache`") (defdyn *module-cache* "Dynamic binding for overriding `module/cache`")
(defdyn *module/paths* "Dynamic binding for overriding `module/cache`") (defdyn *module-paths* "Dynamic binding for overriding `module/cache`")
(defdyn *module/loading* "Dynamic binding for overriding `module/cache`") (defdyn *module-loading* "Dynamic binding for overriding `module/cache`")
(defdyn *module/loaders* "Dynamic binding for overriding `module/loaders`") (defdyn *module-loaders* "Dynamic binding for overriding `module/loaders`")
(defdyn *module-make-env* "Dynamic binding for creating new environments for `import`, `require`, and `dofile`. Overrides `make-env`.")
(def module/cache (def module/cache
"A table, mapping loaded module identifiers to their environments." "A table, mapping loaded module identifiers to their environments."
@@ -2800,7 +2806,7 @@
keyword name of a loader in `module/loaders`. Returns the modified `module/paths`. keyword name of a loader in `module/loaders`. Returns the modified `module/paths`.
``` ```
[ext loader] [ext loader]
(def mp (dyn *module/paths* module/paths)) (def mp (dyn *module-paths* module/paths))
(defn- find-prefix (defn- find-prefix
[pre] [pre]
(or (find-index |(and (string? ($ 0)) (string/has-prefix? pre ($ 0))) mp) 0)) (or (find-index |(and (string? ($ 0)) (string/has-prefix? pre ($ 0))) mp) 0))
@@ -2818,7 +2824,7 @@
(module/add-paths "/init.janet" :source) (module/add-paths "/init.janet" :source)
(module/add-paths ".janet" :source) (module/add-paths ".janet" :source)
(module/add-paths ".jimage" :image) (module/add-paths ".jimage" :image)
(array/insert module/paths 0 [(fn is-cached [path] (if (in (dyn *module/cache* module/cache) path) path)) :preload check-not-relative]) (array/insert module/paths 0 [(fn is-cached [path] (if (in (dyn *module-cache* module/cache) path) path)) :preload check-not-relative])
# Version of fexists that works even with a reduced OS # Version of fexists that works even with a reduced OS
(defn- fexists (defn- fexists
@@ -2848,7 +2854,7 @@
``` ```
[path] [path]
(var ret nil) (var ret nil)
(def mp (dyn *module/paths* module/paths)) (def mp (dyn *module-paths* module/paths))
(each [p mod-kind checker] mp (each [p mod-kind checker] mp
(when (mod-filter checker path) (when (mod-filter checker path)
(if (function? p) (if (function? p)
@@ -2958,7 +2964,7 @@
:core/stream path :core/stream path
(file/open path :rb))) (file/open path :rb)))
(def path-is-file (= f path)) (def path-is-file (= f path))
(default env (make-env)) (default env ((dyn *module-make-env* make-env)))
(def spath (string path)) (def spath (string path))
(put env :source (or source (if-not path-is-file spath path))) (put env :source (or source (if-not path-is-file spath path)))
(var exit-error nil) (var exit-error nil)
@@ -3020,12 +3026,12 @@
of files as modules.`` of files as modules.``
@{:native (fn native-loader [path &] (native path (make-env))) @{:native (fn native-loader [path &] (native path (make-env)))
:source (fn source-loader [path args] :source (fn source-loader [path args]
(def ml (dyn *module/loading* module/loading)) (def ml (dyn *module-loading* module/loading))
(put ml path true) (put ml path true)
(defer (put ml path nil) (defer (put ml path nil)
(dofile path ;args))) (dofile path ;args)))
:preload (fn preload-loader [path & args] :preload (fn preload-loader [path & args]
(def mc (dyn *module/cache* module/cache)) (def mc (dyn *module-cache* module/cache))
(when-let [m (in mc path)] (when-let [m (in mc path)]
(if (function? m) (if (function? m)
(set (mc path) (m path ;args)) (set (mc path) (m path ;args))
@@ -3036,9 +3042,9 @@
[path args kargs] [path args kargs]
(def [fullpath mod-kind] (module/find path)) (def [fullpath mod-kind] (module/find path))
(unless fullpath (error mod-kind)) (unless fullpath (error mod-kind))
(def mc (dyn *module/cache* module/cache)) (def mc (dyn *module-cache* module/cache))
(def ml (dyn *module/loading* module/loading)) (def ml (dyn *module-loading* module/loading))
(def mls (dyn *module/loaders* module/loaders)) (def mls (dyn *module-loaders* module/loaders))
(if-let [check (if-not (kargs :fresh) (in mc fullpath))] (if-let [check (if-not (kargs :fresh) (in mc fullpath))]
check check
(if (ml fullpath) (if (ml fullpath)
@@ -3444,9 +3450,9 @@
(defn- print-special-form-entry (defn- print-special-form-entry
[x] [x]
(print "\n\n" (print "\n\n"
(string " special form\n\n") " special form\n\n"
(string " (" x " ...)\n\n") " (" x " ...)\n\n"
(string " See https://janet-lang.org/docs/specials.html\n\n"))) " See https://janet-lang.org/docs/specials.html\n\n"))
(defn doc* (defn doc*
"Get the documentation for a symbol in a given environment. Function form of `doc`." "Get the documentation for a symbol in a given environment. Function form of `doc`."
@@ -3853,9 +3859,11 @@
:lazy lazy :lazy lazy
:map-symbols map-symbols})) :map-symbols map-symbols}))
(defmacro ffi/defbind (defmacro ffi/defbind-alias
"Generate bindings for native functions in a convenient manner." "Generate bindings for native functions in a convenient manner.
[name ret-type & body] Similar to defbind but allows for the janet function name to be
different than the FFI function."
[name alias ret-type & body]
(def real-ret-type (eval ret-type)) (def real-ret-type (eval ret-type))
(def meta (slice body 0 -2)) (def meta (slice body 0 -2))
(def arg-pairs (partition 2 (last body))) (def arg-pairs (partition 2 (last body)))
@@ -3872,11 +3880,16 @@
(defn make-ptr [] (defn make-ptr []
(assert (ffi/lookup (if lazy (llib) lib) raw-symbol) (string "failed to find ffi symbol " raw-symbol))) (assert (ffi/lookup (if lazy (llib) lib) raw-symbol) (string "failed to find ffi symbol " raw-symbol)))
(if lazy (if lazy
~(defn ,name ,;meta [,;formal-args] ~(defn ,alias ,;meta [,;formal-args]
(,ffi/call (,(delay (make-ptr))) (,(delay (make-sig))) ,;formal-args)) (,ffi/call (,(delay (make-ptr))) (,(delay (make-sig))) ,;formal-args))
~(defn ,name ,;meta [,;formal-args] ~(defn ,alias ,;meta [,;formal-args]
(,ffi/call ,(make-ptr) ,(make-sig) ,;formal-args))))) (,ffi/call ,(make-ptr) ,(make-sig) ,;formal-args)))))
(defmacro ffi/defbind
"Generate bindings for native functions in a convenient manner."
[name ret-type & body]
~(ffi/defbind-alias ,name ,name ,ret-type ,;body))
### ###
### ###
### Flychecking ### Flychecking
@@ -4020,6 +4033,28 @@
(def x (in args (+ i 1))) (def x (in args (+ i 1)))
(or (scan-number x) (keyword x))) (or (scan-number x) (keyword x)))
(def- long-to-short
"map long options to short options"
{"-help" "h"
"-version" "v"
"-stdin" "s"
"-eval" "e"
"-expression" "E"
"-debug" "d"
"-repl" "r"
"-noprofile" "R"
"-persistent" "p"
"-quiet" "q"
"-flycheck" "k"
"-syspath" "m"
"-compile" "c"
"-image" "i"
"-nocolor" "n"
"-color" "N"
"-library" "l"
"-lint-warn" "w"
"-lint-error" "x"})
# Flag handlers # Flag handlers
(def handlers (def handlers
{"h" (fn [&] {"h" (fn [&]
@@ -4027,25 +4062,25 @@
(print (print
``` ```
Options are: Options are:
-h : Show this help --help (-h) : Show this help
-v : Print the version string --version (-v) : Print the version string
-s : Use raw stdin instead of getline like functionality --stdin (-s) : Use raw stdin instead of getline like functionality
-e code : Execute a string of janet --eval (-e) code : Execute a string of janet
-E code arguments... : Evaluate an expression as a short-fn with arguments --expression (-E) code arguments... : Evaluate an expression as a short-fn with arguments
-d : Set the debug flag in the REPL --debug (-d) : Set the debug flag in the REPL
-r : Enter the REPL after running all scripts --repl (-r) : Enter the REPL after running all scripts
-R : Disables loading profile.janet when JANET_PROFILE is present --noprofile (-R) : Disables loading profile.janet when JANET_PROFILE is present
-p : Keep on executing if there is a top-level error (persistent) --persistent (-p) : Keep on executing if there is a top-level error (persistent)
-q : Hide logo (quiet) --quiet (-q) : Hide logo (quiet)
-k : Compile scripts but do not execute (flycheck) --flycheck (-k) : Compile scripts but do not execute (flycheck)
-m syspath : Set system path for loading global modules --syspath (-m) syspath : Set system path for loading global modules
-c source output : Compile janet source code into an image --compile (-c) source output : Compile janet source code into an image
-i : Load the script argument as an image file instead of source code --image (-i) : Load the script argument as an image file instead of source code
-n : Disable ANSI color output in the REPL --nocolor (-n) : Disable ANSI color output in the REPL
-N : Enable ANSI color output in the REPL --color (-N) : Enable ANSI color output in the REPL
-l lib : Use a module before processing more arguments --library (-l) lib : Use a module before processing more arguments
-w level : Set the lint warning level - default is "normal" --lint-warn (-w) level : Set the lint warning level - default is "normal"
-x level : Set the lint error level - default is "none" --lint-error (-x) level : Set the lint error level - default is "none"
-- : Stop handling options -- : Stop handling options
```) ```)
(os/exit 0) (os/exit 0)
@@ -4090,8 +4125,8 @@
"R" (fn [&] (setdyn *profilepath* nil) 1)}) "R" (fn [&] (setdyn *profilepath* nil) 1)})
(defn- dohandler [n i &] (defn- dohandler [n i &]
(def h (in handlers n)) (def h (in handlers (get long-to-short n n)))
(if h (h i) (do (print "unknown flag -" n) ((in handlers "h"))))) (if h (h i handlers) (do (print "unknown flag -" n) ((in handlers "h")))))
# Process arguments # Process arguments
(var i 0) (var i 0)

View File

@@ -30,7 +30,7 @@
#include <string.h> #include <string.h>
static void janet_array_impl(JanetArray *array, size_t capacity) { static void janet_array_impl(JanetArray *array, int32_t capacity) {
Janet *data = NULL; Janet *data = NULL;
if (capacity > 0) { if (capacity > 0) {
janet_vm.next_collection += capacity * sizeof(Janet); janet_vm.next_collection += capacity * sizeof(Janet);
@@ -45,23 +45,21 @@ static void janet_array_impl(JanetArray *array, size_t capacity) {
} }
/* Creates a new array */ /* Creates a new array */
JanetArray *janet_array(size_t capacity) { JanetArray *janet_array(int32_t capacity) {
if (capacity > JANET_SIZEMAX) capacity = JANET_SIZEMAX;
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray)); JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
janet_array_impl(array, capacity); janet_array_impl(array, capacity);
return array; return array;
} }
/* Creates a new array with weak references */ /* Creates a new array with weak references */
JanetArray *janet_array_weak(size_t capacity) { JanetArray *janet_array_weak(int32_t capacity) {
if (capacity > JANET_SIZEMAX) capacity = JANET_SIZEMAX;
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY_WEAK, sizeof(JanetArray)); JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY_WEAK, sizeof(JanetArray));
janet_array_impl(array, capacity); janet_array_impl(array, capacity);
return array; return array;
} }
/* Creates a new array from n elements. */ /* Creates a new array from n elements. */
JanetArray *janet_array_n(const Janet *elements, size_t n) { JanetArray *janet_array_n(const Janet *elements, int32_t n) {
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray)); JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
array->capacity = n; array->capacity = n;
array->count = n; array->count = n;
@@ -74,13 +72,13 @@ JanetArray *janet_array_n(const Janet *elements, size_t n) {
} }
/* Ensure the array has enough capacity for elements */ /* Ensure the array has enough capacity for elements */
void janet_array_ensure(JanetArray *array, size_t capacity, int32_t growth) { void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth) {
Janet *newData; Janet *newData;
Janet *old = array->data; Janet *old = array->data;
if (capacity <= array->capacity) return; if (capacity <= array->capacity) return;
int64_t new_capacity = ((int64_t) capacity) * growth; int64_t new_capacity = ((int64_t) capacity) * growth;
if (new_capacity > JANET_SIZEMAX) new_capacity = JANET_SIZEMAX; if (new_capacity > INT32_MAX) new_capacity = INT32_MAX;
capacity = (size_t) new_capacity; capacity = (int32_t) new_capacity;
newData = janet_realloc(old, capacity * sizeof(Janet)); newData = janet_realloc(old, capacity * sizeof(Janet));
if (NULL == newData) { if (NULL == newData) {
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
@@ -91,10 +89,11 @@ void janet_array_ensure(JanetArray *array, size_t capacity, int32_t growth) {
} }
/* Set the count of an array. Extend with nil if needed. */ /* Set the count of an array. Extend with nil if needed. */
void janet_array_setcount(JanetArray *array, size_t count) { void janet_array_setcount(JanetArray *array, int32_t count) {
if (count > JANET_SIZEMAX) count = JANET_SIZEMAX; if (count < 0)
return;
if (count > array->count) { if (count > array->count) {
size_t i; int32_t i;
janet_array_ensure(array, count, 1); janet_array_ensure(array, count, 1);
for (i = array->count; i < count; i++) { for (i = array->count; i < count; i++) {
array->data[i] = janet_wrap_nil(); array->data[i] = janet_wrap_nil();
@@ -105,10 +104,10 @@ void janet_array_setcount(JanetArray *array, size_t count) {
/* Push a value to the top of the array */ /* Push a value to the top of the array */
void janet_array_push(JanetArray *array, Janet x) { void janet_array_push(JanetArray *array, Janet x) {
if (array->count == JANET_SIZEMAX) { if (array->count == INT32_MAX) {
janet_panic("array overflow"); janet_panic("array overflow");
} }
size_t newcount = array->count + 1; int32_t newcount = array->count + 1;
janet_array_ensure(array, newcount, 2); janet_array_ensure(array, newcount, 2);
array->data[array->count] = x; array->data[array->count] = x;
array->count = newcount; array->count = newcount;
@@ -139,7 +138,7 @@ JANET_CORE_FN(cfun_array_new,
"Creates a new empty array with a pre-allocated capacity. The same as " "Creates a new empty array with a pre-allocated capacity. The same as "
"`(array)` but can be more efficient if the maximum size of an array is known.") { "`(array)` but can be more efficient if the maximum size of an array is known.") {
janet_fixarity(argc, 1); janet_fixarity(argc, 1);
size_t cap = janet_getsize(argv, 0); int32_t cap = janet_getinteger(argv, 0);
JanetArray *array = janet_array(cap); JanetArray *array = janet_array(cap);
return janet_wrap_array(array); return janet_wrap_array(array);
} }
@@ -148,7 +147,7 @@ JANET_CORE_FN(cfun_array_weak,
"(array/weak capacity)", "(array/weak capacity)",
"Creates a new empty array with a pre-allocated capacity and support for weak references. Similar to `array/new`.") { "Creates a new empty array with a pre-allocated capacity and support for weak references. Similar to `array/new`.") {
janet_fixarity(argc, 1); janet_fixarity(argc, 1);
size_t cap = janet_getsize(argv, 0); int32_t cap = janet_getinteger(argv, 0);
JanetArray *array = janet_array_weak(cap); JanetArray *array = janet_array_weak(cap);
return janet_wrap_array(array); return janet_wrap_array(array);
} }
@@ -157,7 +156,7 @@ JANET_CORE_FN(cfun_array_new_filled,
"(array/new-filled count &opt value)", "(array/new-filled count &opt value)",
"Creates a new array of `count` elements, all set to `value`, which defaults to nil. Returns the new array.") { "Creates a new array of `count` elements, all set to `value`, which defaults to nil. Returns the new array.") {
janet_arity(argc, 1, 2); janet_arity(argc, 1, 2);
size_t count = janet_getsize(argv, 0); int32_t count = janet_getnat(argv, 0);
Janet x = (argc == 2) ? argv[1] : janet_wrap_nil(); Janet x = (argc == 2) ? argv[1] : janet_wrap_nil();
JanetArray *array = janet_array(count); JanetArray *array = janet_array(count);
for (int32_t i = 0; i < count; i++) { for (int32_t i = 0; i < count; i++) {
@@ -202,10 +201,10 @@ JANET_CORE_FN(cfun_array_push,
"Push all the elements of xs to the end of an array. Modifies the input array and returns it.") { "Push all the elements of xs to the end of an array. Modifies the input array and returns it.") {
janet_arity(argc, 1, -1); janet_arity(argc, 1, -1);
JanetArray *array = janet_getarray(argv, 0); JanetArray *array = janet_getarray(argv, 0);
if ((size_t)(INT32_MAX - argc + 1) <= array->count) { if (INT32_MAX - argc + 1 <= array->count) {
janet_panic("array overflow"); janet_panic("array overflow");
} }
size_t newcount = array->count - 1 + (size_t) argc; int32_t newcount = array->count - 1 + argc;
janet_array_ensure(array, newcount, 2); janet_array_ensure(array, newcount, 2);
if (argc > 1) memcpy(array->data + array->count, argv + 1, (size_t)(argc - 1) * sizeof(Janet)); if (argc > 1) memcpy(array->data + array->count, argv + 1, (size_t)(argc - 1) * sizeof(Janet));
array->count = newcount; array->count = newcount;
@@ -220,7 +219,7 @@ JANET_CORE_FN(cfun_array_ensure,
"Otherwise, the backing memory will be reallocated so that there is enough space.") { "Otherwise, the backing memory will be reallocated so that there is enough space.") {
janet_fixarity(argc, 3); janet_fixarity(argc, 3);
JanetArray *array = janet_getarray(argv, 0); JanetArray *array = janet_getarray(argv, 0);
size_t newcount = janet_getsize(argv, 1); int32_t newcount = janet_getinteger(argv, 1);
int32_t growth = janet_getinteger(argv, 2); int32_t growth = janet_getinteger(argv, 2);
if (newcount < 1) janet_panic("expected positive integer"); if (newcount < 1) janet_panic("expected positive integer");
janet_array_ensure(array, newcount, growth); janet_array_ensure(array, newcount, growth);
@@ -259,7 +258,7 @@ JANET_CORE_FN(cfun_array_concat,
break; break;
case JANET_ARRAY: case JANET_ARRAY:
case JANET_TUPLE: { case JANET_TUPLE: {
size_t j, len = 0; int32_t j, len = 0;
const Janet *vals = NULL; const Janet *vals = NULL;
janet_indexed_view(argv[i], &vals, &len); janet_indexed_view(argv[i], &vals, &len);
if (array->data == vals) { if (array->data == vals) {

View File

@@ -655,6 +655,27 @@ JANET_CORE_FN(cfun_buffer_format,
return argv[0]; return argv[0];
} }
JANET_CORE_FN(cfun_buffer_format_at,
"(buffer/format-at buffer at format & args)",
"Snprintf like functionality for printing values into a buffer. Returns "
"the modified buffer.") {
janet_arity(argc, 2, -1);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int32_t at = janet_getinteger(argv, 1);
if (at < 0) {
at += buffer->count + 1;
}
if (at > buffer->count || at < 0) janet_panicf("expected index at to be in range [0, %d), got %d", buffer->count, at);
int32_t oldcount = buffer->count;
buffer->count = at;
const char *strfrmt = (const char *) janet_getstring(argv, 2);
janet_buffer_format(buffer, strfrmt, 2, argc, argv);
if (buffer->count < oldcount) {
buffer->count = oldcount;
}
return argv[0];
}
void janet_lib_buffer(JanetTable *env) { 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),
@@ -681,6 +702,7 @@ void janet_lib_buffer(JanetTable *env) {
JANET_CORE_REG("buffer/bit-toggle", cfun_buffer_bittoggle), JANET_CORE_REG("buffer/bit-toggle", cfun_buffer_bittoggle),
JANET_CORE_REG("buffer/blit", cfun_buffer_blit), JANET_CORE_REG("buffer/blit", cfun_buffer_blit),
JANET_CORE_REG("buffer/format", cfun_buffer_format), JANET_CORE_REG("buffer/format", cfun_buffer_format),
JANET_CORE_REG("buffer/format-at", cfun_buffer_format_at),
JANET_REG_END JANET_REG_END
}; };
janet_core_cfuns_ext(env, NULL, buffer_cfuns); janet_core_cfuns_ext(env, NULL, buffer_cfuns);

View File

@@ -934,7 +934,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
int32_t slotchunks = (def->slotcount + 31) >> 5; int32_t slotchunks = (def->slotcount + 31) >> 5;
/* numchunks is min of slotchunks and scope->ua.count */ /* numchunks is min of slotchunks and scope->ua.count */
int32_t numchunks = slotchunks > scope->ua.count ? scope->ua.count : slotchunks; int32_t numchunks = slotchunks > scope->ua.count ? scope->ua.count : slotchunks;
uint32_t *chunks = janet_calloc(sizeof(uint32_t), slotchunks); uint32_t *chunks = janet_calloc(1, slotchunks * sizeof(uint32_t));
if (NULL == chunks) { if (NULL == chunks) {
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
} }

View File

@@ -69,7 +69,7 @@ JanetModule janet_native(const char *name, const uint8_t **error) {
host.minor < modconf.minor || host.minor < modconf.minor ||
host.bits != modconf.bits) { host.bits != modconf.bits) {
char errbuf[128]; char errbuf[128];
sprintf(errbuf, "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)", snprintf(errbuf, sizeof(errbuf), "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
host.major, host.major,
host.minor, host.minor,
host.patch, host.patch,

View File

@@ -279,8 +279,16 @@ void janet_async_in_flight(JanetFiber *fiber) {
void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state) { void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state) {
JanetFiber *fiber = janet_vm.root_fiber; JanetFiber *fiber = janet_vm.root_fiber;
janet_assert(!fiber->ev_callback, "double async on fiber"); janet_assert(!fiber->ev_callback, "double async on fiber");
if (mode & JANET_ASYNC_LISTEN_READ) stream->read_fiber = fiber; if (mode & JANET_ASYNC_LISTEN_READ) {
if (mode & JANET_ASYNC_LISTEN_WRITE) stream->write_fiber = fiber; stream->read_fiber = fiber;
} else {
stream->read_fiber = NULL;
}
if (mode & JANET_ASYNC_LISTEN_WRITE) {
stream->write_fiber = fiber;
} else {
stream->write_fiber = NULL;
}
fiber->ev_callback = callback; fiber->ev_callback = callback;
fiber->ev_stream = stream; fiber->ev_stream = stream;
janet_ev_inc_refcount(); janet_ev_inc_refcount();
@@ -462,6 +470,12 @@ static Janet janet_stream_next(void *p, Janet key) {
return janet_nextmethod(stream->methods, key); return janet_nextmethod(stream->methods, key);
} }
static void janet_stream_tostring(void *p, JanetBuffer *buffer) {
JanetStream *stream = p;
/* Let user print the file descriptor for debugging */
janet_formatb(buffer, "<core/stream handle=%d>", stream->handle);
}
const JanetAbstractType janet_stream_type = { const JanetAbstractType janet_stream_type = {
"core/stream", "core/stream",
janet_stream_gc, janet_stream_gc,
@@ -470,7 +484,7 @@ const JanetAbstractType janet_stream_type = {
NULL, NULL,
janet_stream_marshal, janet_stream_marshal,
janet_stream_unmarshal, janet_stream_unmarshal,
NULL, janet_stream_tostring,
NULL, NULL,
NULL, NULL,
janet_stream_next, janet_stream_next,
@@ -1516,6 +1530,14 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
} }
} }
void janet_stream_edge_triggered(JanetStream *stream) {
(void) stream;
}
void janet_stream_level_triggered(JanetStream *stream) {
(void) stream;
}
#elif defined(JANET_EV_EPOLL) #elif defined(JANET_EV_EPOLL)
static JanetTimestamp ts_now(void) { static JanetTimestamp ts_now(void) {
@@ -1527,15 +1549,15 @@ static JanetTimestamp ts_now(void) {
} }
/* Wait for the next event */ /* Wait for the next event */
static void janet_register_stream(JanetStream *stream) { static void janet_register_stream_impl(JanetStream *stream, int mod, int edge_trigger) {
struct epoll_event ev; struct epoll_event ev;
ev.events = EPOLLET; ev.events = edge_trigger ? EPOLLET : 0;
if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) ev.events |= EPOLLIN; if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) ev.events |= EPOLLIN;
if (stream->flags & JANET_STREAM_WRITABLE) ev.events |= EPOLLOUT; if (stream->flags & JANET_STREAM_WRITABLE) ev.events |= EPOLLOUT;
ev.data.ptr = stream; ev.data.ptr = stream;
int status; int status;
do { do {
status = epoll_ctl(janet_vm.epoll, EPOLL_CTL_ADD, stream->handle, &ev); status = epoll_ctl(janet_vm.epoll, mod ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, stream->handle, &ev);
} while (status == -1 && errno == EINTR); } while (status == -1 && errno == EINTR);
if (status == -1) { if (status == -1) {
if (errno == EPERM) { if (errno == EPERM) {
@@ -1549,6 +1571,18 @@ static void janet_register_stream(JanetStream *stream) {
} }
} }
static void janet_register_stream(JanetStream *stream) {
janet_register_stream_impl(stream, 0, 1);
}
void janet_stream_edge_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1, 1);
}
void janet_stream_level_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1, 0);
}
#define JANET_EPOLL_MAX_EVENTS 64 #define JANET_EPOLL_MAX_EVENTS 64
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) { void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
struct itimerspec its; struct itimerspec its;
@@ -1678,14 +1712,15 @@ static void timestamp2timespec(struct timespec *t, JanetTimestamp ts) {
t->tv_nsec = ts == 0 ? 0 : (ts % 1000) * 1000000; t->tv_nsec = ts == 0 ? 0 : (ts % 1000) * 1000000;
} }
void janet_register_stream(JanetStream *stream) { void janet_register_stream_impl(JanetStream *stream, int edge_trigger) {
struct kevent kevs[2]; struct kevent kevs[2];
int length = 0; int length = 0;
int clear = edge_trigger ? EV_CLEAR : 0;
if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) { if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) {
EV_SETx(&kevs[length++], stream->handle, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, stream); EV_SETx(&kevs[length++], stream->handle, EVFILT_READ, EV_ADD | EV_ENABLE | clear, 0, 0, stream);
} }
if (stream->flags & JANET_STREAM_WRITABLE) { if (stream->flags & JANET_STREAM_WRITABLE) {
EV_SETx(&kevs[length++], stream->handle, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, stream); EV_SETx(&kevs[length++], stream->handle, EVFILT_WRITE, EV_ADD | EV_ENABLE | clear, 0, 0, stream);
} }
int status; int status;
do { do {
@@ -1696,6 +1731,18 @@ void janet_register_stream(JanetStream *stream) {
} }
} }
void janet_register_stream(JanetStream *stream) {
janet_register_stream_impl(stream, 1);
}
void janet_stream_edge_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1);
}
void janet_stream_level_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 0);
}
#define JANET_KQUEUE_MAX_EVENTS 64 #define JANET_KQUEUE_MAX_EVENTS 64
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) { void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
@@ -1818,15 +1865,30 @@ void janet_register_stream(JanetStream *stream) {
janet_vm.stream_count = new_count; janet_vm.stream_count = new_count;
} }
void janet_stream_edge_triggered(JanetStream *stream) {
(void) stream;
}
void janet_stream_level_triggered(JanetStream *stream) {
(void) stream;
}
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) { void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
/* set event flags */ /* set event flags */
for (size_t i = 0; i < janet_vm.stream_count; i++) { for (size_t i = 0; i < janet_vm.stream_count; i++) {
JanetStream *stream = janet_vm.streams[i]; JanetStream *stream = janet_vm.streams[i];
janet_vm.fds[i + 1].events = 0; struct pollfd *pfd = janet_vm.fds + i + 1;
janet_vm.fds[i + 1].revents = 0; pfd->events = 0;
if (stream->read_fiber && stream->read_fiber->ev_callback) janet_vm.fds[i + 1].events |= POLLIN; pfd->revents = 0;
if (stream->write_fiber && stream->write_fiber->ev_callback) janet_vm.fds[i + 1].events |= POLLOUT; JanetFiber *rf = stream->read_fiber;
JanetFiber *wf = stream->write_fiber;
if (rf && rf->ev_callback) pfd->events |= POLLIN;
if (wf && wf->ev_callback) pfd->events |= POLLOUT;
/* Hack to ignore a file descriptor - make file descriptor negative if we want to ignore */
if (!pfd->events) {
pfd->fd = -pfd->fd;
}
} }
/* Poll for events */ /* Poll for events */
@@ -1843,6 +1905,14 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
JANET_EXIT("failed to poll events"); JANET_EXIT("failed to poll events");
} }
/* Undo negative hack */
for (size_t i = 0; i < janet_vm.stream_count; i++) {
struct pollfd *pfd = janet_vm.fds + i + 1;
if (pfd->fd < 0) {
pfd->fd = -pfd->fd;
}
}
/* Check selfpipe */ /* Check selfpipe */
if (janet_vm.fds[0].revents & POLLIN) { if (janet_vm.fds[0].revents & POLLIN) {
janet_vm.fds[0].revents = 0; janet_vm.fds[0].revents = 0;

View File

@@ -73,13 +73,13 @@ static void *int64_unmarshal(JanetMarshalContext *ctx) {
static void it_s64_tostring(void *p, JanetBuffer *buffer) { static void it_s64_tostring(void *p, JanetBuffer *buffer) {
char str[32]; char str[32];
sprintf(str, "%" PRId64, *((int64_t *)p)); snprintf(str, sizeof(str), "%" PRId64, *((int64_t *)p));
janet_buffer_push_cstring(buffer, str); janet_buffer_push_cstring(buffer, str);
} }
static void it_u64_tostring(void *p, JanetBuffer *buffer) { static void it_u64_tostring(void *p, JanetBuffer *buffer) {
char str[32]; char str[32];
sprintf(str, "%" PRIu64, *((uint64_t *)p)); snprintf(str, sizeof(str), "%" PRIu64, *((uint64_t *)p));
janet_buffer_push_cstring(buffer, str); janet_buffer_push_cstring(buffer, str);
} }

View File

@@ -349,6 +349,26 @@ JANET_CORE_FN(janet_cfun_lcm, "(math/lcm x y)",
return janet_wrap_number(janet_lcm(x, y)); return janet_wrap_number(janet_lcm(x, y));
} }
JANET_CORE_FN(janet_cfun_frexp, "(math/frexp x)",
"Returns a tuple of (mantissa, exponent) from number.") {
janet_fixarity(argc, 1);
double x = janet_getnumber(argv, 0);
int exp;
x = frexp(x, &exp);
Janet *result = janet_tuple_begin(2);
result[0] = janet_wrap_number(x);
result[1] = janet_wrap_number((double) exp);
return janet_wrap_tuple(janet_tuple_end(result));
}
JANET_CORE_FN(janet_cfun_ldexp, "(math/ldexp m e)",
"Creates a new number from a mantissa and an exponent.") {
janet_fixarity(argc, 2);
double x = janet_getnumber(argv, 0);
int32_t y = janet_getinteger(argv, 1);
return janet_wrap_number(ldexp(x, y));
}
/* Module entry point */ /* Module entry point */
void janet_lib_math(JanetTable *env) { void janet_lib_math(JanetTable *env) {
JanetRegExt math_cfuns[] = { JanetRegExt math_cfuns[] = {
@@ -395,6 +415,8 @@ void janet_lib_math(JanetTable *env) {
JANET_CORE_REG("math/next", janet_nextafter), JANET_CORE_REG("math/next", janet_nextafter),
JANET_CORE_REG("math/gcd", janet_cfun_gcd), JANET_CORE_REG("math/gcd", janet_cfun_gcd),
JANET_CORE_REG("math/lcm", janet_cfun_lcm), JANET_CORE_REG("math/lcm", janet_cfun_lcm),
JANET_CORE_REG("math/frexp", janet_cfun_frexp),
JANET_CORE_REG("math/ldexp", janet_cfun_ldexp),
JANET_REG_END JANET_REG_END
}; };
janet_core_cfuns_ext(env, NULL, math_cfuns); janet_core_cfuns_ext(env, NULL, math_cfuns);

View File

@@ -319,6 +319,7 @@ JANET_NO_RETURN static void janet_sched_accept(JanetStream *stream, JanetFunctio
NetStateAccept *state = janet_malloc(sizeof(NetStateAccept)); NetStateAccept *state = janet_malloc(sizeof(NetStateAccept));
memset(state, 0, sizeof(NetStateAccept)); memset(state, 0, sizeof(NetStateAccept));
state->function = fun; state->function = fun;
if (fun) janet_stream_level_triggered(stream);
janet_async_start(stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, state); janet_async_start(stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, state);
} }

View File

@@ -39,12 +39,22 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <signal.h> #include <signal.h>
#ifdef JANET_BSD #ifdef JANET_BSD
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(JANET_APPLE)
/* It seems only some bsds use this header for xlocale */
#include <xlocale.h>
#define JANET_EXTENDED_LOCALE
#else
#include <locale.h>
#endif
#ifdef JANET_LINUX #ifdef JANET_LINUX
#include <sched.h> #include <sched.h>
#define JANET_EXTENDED_LOCALE
#endif #endif
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
@@ -1597,13 +1607,13 @@ JANET_CORE_FN(os_clock,
JanetKeyword formatstr = janet_optkeyword(argv, argc, 1, (const uint8_t *) "double"); JanetKeyword formatstr = janet_optkeyword(argv, argc, 1, (const uint8_t *) "double");
if (janet_cstrcmp(formatstr, "double") == 0) { if (janet_cstrcmp(formatstr, "double") == 0) {
double dtime = tv.tv_sec + (tv.tv_nsec / 1E9); double dtime = (double)(tv.tv_sec + (tv.tv_nsec / 1E9));
return janet_wrap_number(dtime); return janet_wrap_number(dtime);
} else if (janet_cstrcmp(formatstr, "int") == 0) { } else if (janet_cstrcmp(formatstr, "int") == 0) {
return janet_wrap_number(tv.tv_sec); return janet_wrap_number((double)(tv.tv_sec));
} else if (janet_cstrcmp(formatstr, "tuple") == 0) { } else if (janet_cstrcmp(formatstr, "tuple") == 0) {
Janet tup[2] = {janet_wrap_integer(tv.tv_sec), Janet tup[2] = {janet_wrap_number((double)tv.tv_sec),
janet_wrap_integer(tv.tv_nsec) janet_wrap_number((double)tv.tv_nsec)
}; };
return janet_wrap_tuple(janet_tuple_n(tup, 2)); return janet_wrap_tuple(janet_tuple_n(tup, 2));
} else { } else {
@@ -1891,6 +1901,71 @@ JANET_CORE_FN(os_mktime,
#define j_symlink symlink #define j_symlink symlink
#endif #endif
JANET_CORE_FN(os_setlocale,
"(os/setlocale category &opt locale)",
"Set the system locale, which affects how dates and numbers are formatted. "
"Passing nil to locale will return the current locale.") {
janet_arity(argc, 1, 2);
const char *locale_name = janet_optcstring(argv, argc, 1, NULL);
int category_int = 0;
#ifdef JANET_EXTENDED_LOCALE
if (janet_keyeq(argv[0], "all")) {
category_int = LC_ALL_MASK;
} else if (janet_keyeq(argv[0], "collate")) {
category_int = LC_COLLATE_MASK;
} else if (janet_keyeq(argv[0], "ctype")) {
category_int = LC_CTYPE_MASK;
} else if (janet_keyeq(argv[0], "monetary")) {
category_int = LC_MONETARY_MASK;
} else if (janet_keyeq(argv[0], "numeric")) {
category_int = LC_NUMERIC_MASK;
} else if (janet_keyeq(argv[0], "time")) {
category_int = LC_TIME_MASK;
} else {
janet_panicf("expected one of :all, :collate, :ctype, :monetary, :numeric, or :time, got %v", argv[0]);
}
if (locale_name == NULL) {
const char *old = setlocale(category_int, NULL);
if (old == NULL) return janet_wrap_nil();
return janet_cstringv(old);
}
/* Use newlocale instead of setlocale for per-thread behavior */
locale_t loc = newlocale(category_int, locale_name, 0);
if (loc == 0) {
janet_panicf("failed to make locale - %s", strerror(errno));
}
locale_t old_locale = uselocale(loc);
if (old_locale == 0) {
janet_panicf("failed to set locale - %s", strerror(errno));
}
if (old_locale != LC_GLOBAL_LOCALE) {
freelocale(old_locale);
}
return janet_wrap_nil();
#else
if (janet_keyeq(argv[0], "all")) {
category_int = LC_ALL;
} else if (janet_keyeq(argv[0], "collate")) {
category_int = LC_COLLATE;
} else if (janet_keyeq(argv[0], "ctype")) {
category_int = LC_CTYPE;
} else if (janet_keyeq(argv[0], "monetary")) {
category_int = LC_MONETARY;
} else if (janet_keyeq(argv[0], "numeric")) {
category_int = LC_NUMERIC;
} else if (janet_keyeq(argv[0], "time")) {
category_int = LC_TIME;
} else {
janet_panicf("expected one of :all, :collate, :ctype, :monetary, :numeric, or :time, got %v", argv[0]);
}
const char *old = setlocale(category_int, locale_name);
if (old == NULL) {
janet_panicf("failed to set locale - %s", strerror(errno));
}
return janet_wrap_nil();
#endif
}
JANET_CORE_FN(os_link, JANET_CORE_FN(os_link,
"(os/link oldpath newpath &opt symlink)", "(os/link oldpath newpath &opt symlink)",
"Create a link at newpath that points to oldpath and returns nil. " "Create a link at newpath that points to oldpath and returns nil. "
@@ -2688,6 +2763,7 @@ void janet_lib_os(JanetTable *env) {
JANET_CORE_REG("os/strftime", os_strftime), JANET_CORE_REG("os/strftime", os_strftime),
JANET_CORE_REG("os/sleep", os_sleep), JANET_CORE_REG("os/sleep", os_sleep),
JANET_CORE_REG("os/isatty", os_isatty), JANET_CORE_REG("os/isatty", os_isatty),
JANET_CORE_REG("os/setlocale", os_setlocale),
/* env functions */ /* env functions */
JANET_CORE_REG("os/environ", os_environ), JANET_CORE_REG("os/environ", os_environ),
@@ -2744,5 +2820,8 @@ void janet_lib_os(JanetTable *env) {
#endif #endif
JANET_REG_END JANET_REG_END
}; };
#if defined(JANET_WINDOWS) && !defined(JANET_REDUCED_OS)
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
#endif
janet_core_cfuns_ext(env, NULL, os_cfuns); janet_core_cfuns_ext(env, NULL, os_cfuns);
} }

View File

@@ -380,6 +380,13 @@ static int print_jdn_one(struct pretty *S, Janet x, int depth) {
case JANET_NUMBER: case JANET_NUMBER:
janet_buffer_ensure(S->buffer, S->buffer->count + BUFSIZE, 2); janet_buffer_ensure(S->buffer, S->buffer->count + BUFSIZE, 2);
int count = snprintf((char *) S->buffer->data + S->buffer->count, BUFSIZE, "%.17g", janet_unwrap_number(x)); int count = snprintf((char *) S->buffer->data + S->buffer->count, BUFSIZE, "%.17g", janet_unwrap_number(x));
/* fix locale issues with commas */
for (int i = 0; i < count; i++) {
char c = S->buffer->data[S->buffer->count + i];
if (c == ',' || c == '\'') {
S->buffer->data[S->buffer->count + i] = '.';
}
}
S->buffer->count += count; S->buffer->count += count;
break; break;
case JANET_SYMBOL: case JANET_SYMBOL:
@@ -830,7 +837,7 @@ static const char *scanformat(
if (loc != NULL && *loc != '\0') { if (loc != NULL && *loc != '\0') {
const char *mapping = get_fmt_mapping(*p2++); const char *mapping = get_fmt_mapping(*p2++);
size_t len = strlen(mapping); size_t len = strlen(mapping);
strcpy(form, mapping); memcpy(form, mapping, len);
form += len; form += len;
} else { } else {
*(form++) = *(p2++); *(form++) = *(p2++);

View File

@@ -112,7 +112,8 @@ extern "C" {
|| defined(__s390x__) /* S390 64-bit (BE) */ \ || defined(__s390x__) /* S390 64-bit (BE) */ \
|| (defined(__ppc64__) || defined(__PPC64__)) \ || (defined(__ppc64__) || defined(__PPC64__)) \
|| defined(__aarch64__) /* ARM 64-bit */ \ || defined(__aarch64__) /* ARM 64-bit */ \
|| (defined(__riscv) && (__riscv_xlen == 64)) /* RISC-V 64-bit */ || (defined(__riscv) && (__riscv_xlen == 64)) /* RISC-V 64-bit */ \
|| defined(__loongarch64) /* LoongArch64 64-bit */
#define JANET_64 1 #define JANET_64 1
#else #else
#define JANET_32 1 #define JANET_32 1
@@ -148,12 +149,6 @@ extern "C" {
#define JANET_INTMIN_DOUBLE (-9007199254740992.0) #define JANET_INTMIN_DOUBLE (-9007199254740992.0)
#define JANET_INTMAX_INT64 9007199254740992 #define JANET_INTMAX_INT64 9007199254740992
#define JANET_INTMIN_INT64 (-9007199254740992) #define JANET_INTMIN_INT64 (-9007199254740992)
#ifdef JANET_64
#define JANET_SIZEMAX JANET_INTMAX_INT64
#else
/* Avoid loop bounds issues */
#define JANET_SIZEMAX (SIZE_MAX - 1)
#endif
/* Check emscripten */ /* Check emscripten */
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@@ -642,6 +637,12 @@ JANET_API void janet_async_end(JanetFiber *fiber);
/* Needed for windows to mark a fiber as waiting for an IOCP completion event. Noop on other platforms. */ /* Needed for windows to mark a fiber as waiting for an IOCP completion event. Noop on other platforms. */
JANET_API void janet_async_in_flight(JanetFiber *fiber); JANET_API void janet_async_in_flight(JanetFiber *fiber);
/* On some platforms, it is important to be able to control if a stream is edge-trigger or level triggered.
* For example, a server that is accepting connections might want to be level triggered or edge-triggered
* depending on expected service. */
JANET_API void janet_stream_edge_triggered(JanetStream *stream);
JANET_API void janet_stream_level_triggered(JanetStream *stream);
#endif #endif
/* Janet uses atomic integers in several places for synchronization between threads and /* Janet uses atomic integers in several places for synchronization between threads and
@@ -971,25 +972,25 @@ struct JanetStackFrame {
/* A dynamic array type. */ /* A dynamic array type. */
struct JanetArray { struct JanetArray {
JanetGCObject gc; JanetGCObject gc;
size_t count; int32_t count;
size_t capacity; int32_t capacity;
Janet *data; Janet *data;
}; };
/* A byte buffer type. Used as a mutable string or string builder. */ /* A byte buffer type. Used as a mutable string or string builder. */
struct JanetBuffer { struct JanetBuffer {
JanetGCObject gc; JanetGCObject gc;
size_t count; int32_t count;
size_t capacity; int32_t capacity;
uint8_t *data; uint8_t *data;
}; };
/* A mutable associative data type. Backed by a hashtable. */ /* A mutable associative data type. Backed by a hashtable. */
struct JanetTable { struct JanetTable {
JanetGCObject gc; JanetGCObject gc;
size_t count; int32_t count;
size_t capacity; int32_t capacity;
size_t deleted; int32_t deleted;
JanetKV *data; JanetKV *data;
JanetTable *proto; JanetTable *proto;
}; };
@@ -1003,7 +1004,7 @@ struct JanetKV {
/* Prefix for a tuple */ /* Prefix for a tuple */
struct JanetTupleHead { struct JanetTupleHead {
JanetGCObject gc; JanetGCObject gc;
size_t length; int32_t length;
int32_t hash; int32_t hash;
int32_t sm_line; int32_t sm_line;
int32_t sm_column; int32_t sm_column;
@@ -1013,9 +1014,9 @@ struct JanetTupleHead {
/* Prefix for a struct */ /* Prefix for a struct */
struct JanetStructHead { struct JanetStructHead {
JanetGCObject gc; JanetGCObject gc;
size_t length; int32_t length;
size_t capacity;
int32_t hash; int32_t hash;
int32_t capacity;
const JanetKV *proto; const JanetKV *proto;
const JanetKV data[]; const JanetKV data[];
}; };
@@ -1023,7 +1024,7 @@ struct JanetStructHead {
/* Prefix for a string */ /* Prefix for a string */
struct JanetStringHead { struct JanetStringHead {
JanetGCObject gc; JanetGCObject gc;
size_t length; int32_t length;
int32_t hash; int32_t hash;
const uint8_t data[]; const uint8_t data[];
}; };
@@ -1207,18 +1208,18 @@ struct JanetMethod {
struct JanetView { struct JanetView {
const Janet *items; const Janet *items;
size_t len; int32_t len;
}; };
struct JanetByteView { struct JanetByteView {
const uint8_t *bytes; const uint8_t *bytes;
size_t len; int32_t len;
}; };
struct JanetDictView { struct JanetDictView {
const JanetKV *kvs; const JanetKV *kvs;
size_t len; int32_t len;
size_t cap; int32_t cap;
}; };
struct JanetRange { struct JanetRange {
@@ -1582,17 +1583,17 @@ JANET_API JanetTable *janet_core_env(JanetTable *replacements);
JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements); JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements);
/* Execute strings */ /* Execute strings */
JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, size_t len, const char *sourcePath, Janet *out); JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);
JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out); JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out);
/* Run the entrypoint of a wrapped program */ /* Run the entrypoint of a wrapped program */
JANET_API int janet_loop_fiber(JanetFiber *fiber); JANET_API int janet_loop_fiber(JanetFiber *fiber);
/* Number scanning */ /* Number scanning */
JANET_API int janet_scan_number(const uint8_t *str, size_t len, double *out); JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out);
JANET_API int janet_scan_number_base(const uint8_t *str, size_t len, int32_t base, double *out); JANET_API int janet_scan_number_base(const uint8_t *str, int32_t len, int32_t base, double *out);
JANET_API int janet_scan_int64(const uint8_t *str, size_t len, int64_t *out); JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out);
JANET_API int janet_scan_uint64(const uint8_t *str, size_t len, uint64_t *out); JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out);
/* Debugging */ /* Debugging */
JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc); JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc);
@@ -1605,30 +1606,30 @@ JANET_API void janet_debug_find(
extern JANET_API const JanetAbstractType janet_rng_type; extern JANET_API const JanetAbstractType janet_rng_type;
JANET_API JanetRNG *janet_default_rng(void); JANET_API JanetRNG *janet_default_rng(void);
JANET_API void janet_rng_seed(JanetRNG *rng, uint32_t seed); JANET_API void janet_rng_seed(JanetRNG *rng, uint32_t seed);
JANET_API void janet_rng_longseed(JanetRNG *rng, const uint8_t *bytes, size_t len); JANET_API void janet_rng_longseed(JanetRNG *rng, const uint8_t *bytes, int32_t len);
JANET_API uint32_t janet_rng_u32(JanetRNG *rng); JANET_API uint32_t janet_rng_u32(JanetRNG *rng);
JANET_API double janet_rng_double(JanetRNG *rng); JANET_API double janet_rng_double(JanetRNG *rng);
/* Array functions */ /* Array functions */
JANET_API JanetArray *janet_array(size_t capacity); JANET_API JanetArray *janet_array(int32_t capacity);
JANET_API JanetArray *janet_array_weak(size_t capacity); JANET_API JanetArray *janet_array_weak(int32_t capacity);
JANET_API JanetArray *janet_array_n(const Janet *elements, size_t n); JANET_API JanetArray *janet_array_n(const Janet *elements, int32_t n);
JANET_API void janet_array_ensure(JanetArray *array, size_t capacity, int32_t growth); JANET_API void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth);
JANET_API void janet_array_setcount(JanetArray *array, size_t count); JANET_API void janet_array_setcount(JanetArray *array, int32_t count);
JANET_API void janet_array_push(JanetArray *array, Janet x); JANET_API void janet_array_push(JanetArray *array, Janet x);
JANET_API Janet janet_array_pop(JanetArray *array); JANET_API Janet janet_array_pop(JanetArray *array);
JANET_API Janet janet_array_peek(JanetArray *array); JANET_API Janet janet_array_peek(JanetArray *array);
/* Buffer functions */ /* Buffer functions */
#define JANET_BUFFER_FLAG_NO_REALLOC 0x10000 #define JANET_BUFFER_FLAG_NO_REALLOC 0x10000
JANET_API JanetBuffer *janet_buffer(size_t capacity); JANET_API JanetBuffer *janet_buffer(int32_t capacity);
JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, size_t capacity); JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity);
JANET_API JanetBuffer *janet_pointer_buffer_unsafe(void *memory, size_t capacity, size_t count); JANET_API JanetBuffer *janet_pointer_buffer_unsafe(void *memory, int32_t capacity, int32_t count);
JANET_API void janet_buffer_deinit(JanetBuffer *buffer); JANET_API void janet_buffer_deinit(JanetBuffer *buffer);
JANET_API void janet_buffer_ensure(JanetBuffer *buffer, size_t capacity, size_t growth); JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, size_t count); JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);
JANET_API void janet_buffer_extra(JanetBuffer *buffer, size_t n); JANET_API void janet_buffer_extra(JanetBuffer *buffer, int32_t n);
JANET_API void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, size_t len); JANET_API void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t len);
JANET_API void janet_buffer_push_string(JanetBuffer *buffer, JanetString string); JANET_API void janet_buffer_push_string(JanetBuffer *buffer, JanetString string);
JANET_API void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring); JANET_API void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring);
JANET_API void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x); JANET_API void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x);
@@ -1647,9 +1648,9 @@ JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x);
#define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line) #define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line)
#define janet_tuple_sm_column(t) (janet_tuple_head(t)->sm_column) #define janet_tuple_sm_column(t) (janet_tuple_head(t)->sm_column)
#define janet_tuple_flag(t) (janet_tuple_head(t)->gc.flags) #define janet_tuple_flag(t) (janet_tuple_head(t)->gc.flags)
JANET_API Janet *janet_tuple_begin(size_t length); JANET_API Janet *janet_tuple_begin(int32_t length);
JANET_API JanetTuple janet_tuple_end(Janet *tuple); JANET_API JanetTuple janet_tuple_end(Janet *tuple);
JANET_API JanetTuple janet_tuple_n(const Janet *values, size_t n); JANET_API JanetTuple janet_tuple_n(const Janet *values, int32_t n);
/* String/Symbol functions */ /* String/Symbol functions */
#define janet_string_head(s) ((JanetStringHead *)((char *)s - offsetof(JanetStringHead, data))) #define janet_string_head(s) ((JanetStringHead *)((char *)s - offsetof(JanetStringHead, data)))
@@ -1692,7 +1693,7 @@ JANET_API JanetSymbol janet_symbol_gen(void);
#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)
#define janet_struct_proto(t) (janet_struct_head(t)->proto) #define janet_struct_proto(t) (janet_struct_head(t)->proto)
JANET_API JanetKV *janet_struct_begin(size_t count); JANET_API JanetKV *janet_struct_begin(int32_t count);
JANET_API void janet_struct_put(JanetKV *st, Janet key, Janet value); JANET_API void janet_struct_put(JanetKV *st, Janet key, Janet value);
JANET_API JanetStruct janet_struct_end(JanetKV *st); JANET_API JanetStruct janet_struct_end(JanetKV *st);
JANET_API Janet janet_struct_get(JanetStruct st, Janet key); JANET_API Janet janet_struct_get(JanetStruct st, Janet key);
@@ -1702,9 +1703,9 @@ JANET_API JanetTable *janet_struct_to_table(JanetStruct st);
JANET_API const JanetKV *janet_struct_find(JanetStruct st, Janet key); JANET_API const JanetKV *janet_struct_find(JanetStruct st, Janet key);
/* Table functions */ /* Table functions */
JANET_API JanetTable *janet_table(size_t capacity); JANET_API JanetTable *janet_table(int32_t capacity);
JANET_API JanetTable *janet_table_init(JanetTable *table, size_t capacity); JANET_API JanetTable *janet_table_init(JanetTable *table, int32_t capacity);
JANET_API JanetTable *janet_table_init_raw(JanetTable *table, size_t capacity); JANET_API JanetTable *janet_table_init_raw(JanetTable *table, int32_t capacity);
JANET_API void janet_table_deinit(JanetTable *table); JANET_API void janet_table_deinit(JanetTable *table);
JANET_API Janet janet_table_get(JanetTable *t, Janet key); JANET_API Janet janet_table_get(JanetTable *t, Janet key);
JANET_API Janet janet_table_get_ex(JanetTable *t, Janet key, JanetTable **which); JANET_API Janet janet_table_get_ex(JanetTable *t, Janet key, JanetTable **which);
@@ -1719,7 +1720,7 @@ JANET_API JanetTable *janet_table_clone(JanetTable *table);
JANET_API void janet_table_clear(JanetTable *table); JANET_API void janet_table_clear(JanetTable *table);
/* Fiber */ /* Fiber */
JANET_API JanetFiber *janet_fiber(JanetFunction *callee, size_t capacity, int32_t argc, const Janet *argv); JANET_API JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity, int32_t argc, const Janet *argv);
JANET_API JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t argc, const Janet *argv); JANET_API JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t argc, const Janet *argv);
JANET_API JanetFiberStatus janet_fiber_status(JanetFiber *fiber); JANET_API JanetFiberStatus janet_fiber_status(JanetFiber *fiber);
JANET_API int janet_fiber_can_resume(JanetFiber *fiber); JANET_API int janet_fiber_can_resume(JanetFiber *fiber);
@@ -1727,11 +1728,11 @@ JANET_API JanetFiber *janet_current_fiber(void);
JANET_API JanetFiber *janet_root_fiber(void); JANET_API JanetFiber *janet_root_fiber(void);
/* Treat similar types through uniform interfaces for iteration */ /* Treat similar types through uniform interfaces for iteration */
JANET_API int janet_indexed_view(Janet seq, const Janet **data, size_t *len); JANET_API int janet_indexed_view(Janet seq, const Janet **data, int32_t *len);
JANET_API int janet_bytes_view(Janet str, const uint8_t **data, size_t *len); JANET_API int janet_bytes_view(Janet str, const uint8_t **data, int32_t *len);
JANET_API int janet_dictionary_view(Janet tab, const JanetKV **data, size_t *len, size_t *cap); JANET_API int janet_dictionary_view(Janet tab, const JanetKV **data, int32_t *len, int32_t *cap);
JANET_API Janet janet_dictionary_get(const JanetKV *data, size_t cap, Janet key); JANET_API Janet janet_dictionary_get(const JanetKV *data, int32_t cap, Janet key);
JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, size_t cap, const JanetKV *kv); JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, int32_t cap, const JanetKV *kv);
/* Abstract */ /* Abstract */
#define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data))) #define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data)))
@@ -1807,17 +1808,17 @@ JANET_API int janet_cstrcmp(JanetString str, const char *other);
JANET_API Janet janet_in(Janet ds, Janet key); JANET_API Janet janet_in(Janet ds, Janet key);
JANET_API Janet janet_get(Janet ds, Janet key); JANET_API Janet janet_get(Janet ds, Janet key);
JANET_API Janet janet_next(Janet ds, Janet key); JANET_API Janet janet_next(Janet ds, Janet key);
JANET_API Janet janet_getindex(Janet ds, size_t index); JANET_API Janet janet_getindex(Janet ds, int32_t index);
JANET_API size_t janet_length(Janet x); JANET_API int32_t janet_length(Janet x);
JANET_API Janet janet_lengthv(Janet x); JANET_API Janet janet_lengthv(Janet x);
JANET_API void janet_put(Janet ds, Janet key, Janet value); JANET_API void janet_put(Janet ds, Janet key, Janet value);
JANET_API void janet_putindex(Janet ds, size_t index, Janet value); JANET_API void janet_putindex(Janet ds, int32_t index, Janet value);
#define janet_flag_at(F, I) ((F) & ((1ULL) << (I))) #define janet_flag_at(F, I) ((F) & ((1ULL) << (I)))
JANET_API Janet janet_wrap_number_safe(double x); JANET_API Janet janet_wrap_number_safe(double x);
JANET_API int janet_keyeq(Janet x, const char *cstring); JANET_API int janet_keyeq(Janet x, const char *cstring);
JANET_API int janet_streq(Janet x, const char *cstring); JANET_API int janet_streq(Janet x, const char *cstring);
JANET_API int janet_symeq(Janet x, const char *cstring); JANET_API int janet_symeq(Janet x, const char *cstring);
JANET_API int32_t janet_sorted_keys(const JanetKV *dict, size_t cap, size_t *index_buffer); JANET_API int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer);
/* VM functions */ /* VM functions */
JANET_API int janet_init(void); JANET_API int janet_init(void);
@@ -2177,6 +2178,8 @@ JANET_API Janet janet_wrap_s64(int64_t x);
JANET_API Janet janet_wrap_u64(uint64_t x); JANET_API Janet janet_wrap_u64(uint64_t x);
JANET_API int64_t janet_unwrap_s64(Janet x); JANET_API int64_t janet_unwrap_s64(Janet x);
JANET_API uint64_t janet_unwrap_u64(Janet x); JANET_API uint64_t janet_unwrap_u64(Janet x);
JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out);
JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out);
#endif #endif

View File

@@ -976,4 +976,7 @@
(assert (= () '() (macex '())) "macex ()") (assert (= () '() (macex '())) "macex ()")
(assert (= '[] (macex '[])) "macex []") (assert (= '[] (macex '[])) "macex []")
(assert (= :a (with-env @{:b :a} (dyn :b))) "with-env dyn")
(assert-error "unknown symbol +" (with-env @{} (eval '(+ 1 2))))
(end-suite) (end-suite)

View File

@@ -162,5 +162,20 @@
(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")
# buffer/format-at
(def start-buf (buffer/new-filled 100 (chr "x")))
(buffer/format-at start-buf 50 "aa%dbb" 32)
(assert (= (string start-buf) (string (string/repeat "x" 50) "aa32bb" (string/repeat "x" 44)))
"buffer/format-at 1")
(assert
(deep=
(buffer/format @"" "%j" [1 2 3 :a :b :c])
(buffer/format-at @"" 0 "%j" [1 2 3 :a :b :c]))
"buffer/format-at empty buffer")
(def buf @"xxxyyy")
(buffer/format-at buf -4 "xxx")
(assert (= (string buf) "xxxxxx") "buffer/format-at negative index")
(assert-error "expected index at to be in range [0, 0), got 1" (buffer/format-at @"" 1 "abc"))
(end-suite) (end-suite)