mirror of
https://github.com/janet-lang/janet
synced 2026-04-20 13:51:28 +00:00
Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa163093d2 | ||
|
|
e70f64e23d | ||
|
|
6f605f8141 | ||
|
|
d9419ef994 | ||
|
|
7e8639a682 | ||
|
|
452b303b4c | ||
|
|
b0f1a4967d | ||
|
|
9eb4c59c04 | ||
|
|
0d42506cde | ||
|
|
c8a13ce475 | ||
|
|
05e3467d09 | ||
|
|
90639e5068 | ||
|
|
73c7711c78 | ||
|
|
78f6b6a507 | ||
|
|
84f0ab5356 | ||
|
|
546437d799 | ||
|
|
0f05aec563 | ||
|
|
c9097623d6 | ||
|
|
6392b37c47 | ||
|
|
4fcc8075d4 | ||
|
|
b2d6a55335 | ||
|
|
1fea5f8fe7 | ||
|
|
d3e52a2afb | ||
|
|
d6ea1989cc | ||
|
|
96513665d6 | ||
|
|
b795d13f61 | ||
|
|
970f9b3981 | ||
|
|
be7dab4d17 | ||
|
|
0e44ce5cba | ||
|
|
1f8c2781dd | ||
|
|
f381a9c773 | ||
|
|
855a9a01fc | ||
|
|
a5f237993d | ||
|
|
c68264802a | ||
|
|
742469a8bc | ||
|
|
92928d5c4f | ||
|
|
8320e25d64 | ||
|
|
c16a9d8463 | ||
|
|
f1819c916a | ||
|
|
dd14b24d2a | ||
|
|
050d7c12a3 | ||
|
|
7e2c433abc | ||
|
|
6713b23a65 | ||
|
|
60078e7950 | ||
|
|
69095fbb48 | ||
|
|
c88a3c64e3 | ||
|
|
771b0d0ab1 | ||
|
|
c85310578b | ||
|
|
60e2992158 | ||
|
|
2795e8a8b7 | ||
|
|
bdf14170a4 | ||
|
|
10dcbc639a | ||
|
|
6a9bb0f4e4 | ||
|
|
c941e5a8f4 | ||
|
|
be91414c7a | ||
|
|
6839b603c8 | ||
|
|
926b68d62e | ||
|
|
d374e90033 | ||
|
|
b168b0758a | ||
|
|
54c66ecfc0 | ||
|
|
1c158bd4ff | ||
|
|
ff24143f54 | ||
|
|
dd117e81c2 | ||
|
|
f4744a18c6 | ||
|
|
259d5fabd9 | ||
|
|
d122a75efd | ||
|
|
c9ea3ac304 | ||
|
|
c63fe6ef8a | ||
|
|
72ec89dfe9 | ||
|
|
04805d106e | ||
|
|
9aed578466 | ||
|
|
77c5279296 | ||
|
|
af75bf3b64 | ||
|
|
a5157e868b | ||
|
|
01a3d8f932 | ||
|
|
f22472a644 | ||
|
|
5cac8bcf9f | ||
|
|
a2801fbef9 | ||
|
|
0b14e913da | ||
|
|
85155bb2b4 | ||
|
|
dd8de1e9ac | ||
|
|
c909835b0a | ||
|
|
a18aafedfd | ||
|
|
317ab6df6b | ||
|
|
1fcaffe6b0 | ||
|
|
3ae5c410dc | ||
|
|
381128364e | ||
|
|
0acf167e84 | ||
|
|
f7ca6deeb0 | ||
|
|
251486e4aa | ||
|
|
c6467be60d | ||
|
|
4dd512ad28 | ||
|
|
28076b9385 |
@@ -4,12 +4,20 @@ sources:
|
|||||||
packages:
|
packages:
|
||||||
- meson
|
- meson
|
||||||
tasks:
|
tasks:
|
||||||
- build: |
|
- with-epoll: |
|
||||||
cd janet
|
cd janet
|
||||||
meson setup build --buildtype=release
|
meson setup with-epoll --buildtype=release
|
||||||
cd build
|
cd with-epoll
|
||||||
|
meson configure -Depoll=true
|
||||||
|
ninja
|
||||||
|
ninja test
|
||||||
|
- no-epoll: |
|
||||||
|
cd janet
|
||||||
|
meson setup no-epoll --buildtype=release
|
||||||
|
cd no-epoll
|
||||||
meson configure -Depoll=false
|
meson configure -Depoll=false
|
||||||
ninja
|
ninja
|
||||||
ninja test
|
ninja test
|
||||||
sudo ninja install
|
sudo ninja install
|
||||||
sudo jpm --verbose install circlet
|
sudo jpm --verbose install circlet
|
||||||
|
sudo jpm --verbose install spork
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -140,3 +140,6 @@ compile_commands.json
|
|||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/cmake
|
# End of https://www.gitignore.io/api/cmake
|
||||||
|
|
||||||
|
# Astyle
|
||||||
|
*.orig
|
||||||
|
|||||||
36
CHANGELOG.md
36
CHANGELOG.md
@@ -1,6 +1,42 @@
|
|||||||
# 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 - ???
|
||||||
|
- Increase default nesting depth of pretty printing to `JANET_RECURSION_GUARD`
|
||||||
|
- Update meson.build
|
||||||
|
- Add option to automatically add shebang line in installed scripts with `jpm`.
|
||||||
|
- Add `partition-by` and `group-by` to the core.
|
||||||
|
- Sort keys in pretty printing output.
|
||||||
|
|
||||||
|
## 1.15.3 - 2021-02-28
|
||||||
|
- Fix a fiber bug that occured in deeply nested fibers
|
||||||
|
- Add `unref` combinator to pegs.
|
||||||
|
- Small docstring changes.
|
||||||
|
|
||||||
|
## 1.15.2 - 2021-02-15
|
||||||
|
- Fix bug in windows version of `os/spawn` and `os/execute` with setting environment variables.
|
||||||
|
- Fix documentation typos.
|
||||||
|
- Fix peg integer reading combinators when used with capture tags.
|
||||||
|
|
||||||
|
## 1.15.0 - 2021-02-08
|
||||||
|
- Fix `gtim` and `ltim` bytecode instructions on non-integer values.
|
||||||
|
- Clean up output of flychecking to be the same as the repl.
|
||||||
|
- Change behavior of `debug/stacktrace` with a nil error value.
|
||||||
|
- Add optional argument to `parser/produce`.
|
||||||
|
- Add `no-core` option to creating standalone binaries to make execution faster.
|
||||||
|
- Fix bug where a buffer overflow could be confused with an out of memory error.
|
||||||
|
- Change error output to `file:line:column: message`. Column is in bytes - tabs
|
||||||
|
are considered to have width 1 (instead of 8).
|
||||||
|
|
||||||
|
## 1.14.2 - 2021-01-23
|
||||||
|
- Allow `JANET_PROFILE` env variable to load a profile before loading the repl.
|
||||||
|
- Update `tracev` macro to allow `def` and `var` inside to work as expected.
|
||||||
|
- Use `(dyn :peg-grammar)` for passing a default grammar to `peg/compile` instead of loading
|
||||||
|
`default-peg-grammar` directly from the root environment.
|
||||||
|
- Add `ev/thread` for combining threading with the event loop.
|
||||||
|
- Add `ev/do-thread` to make `ev/thread` easier to use.
|
||||||
|
- Automatically set supervisor channel in `net/accept-loop` and `net/server` correctly.
|
||||||
|
|
||||||
## 1.14.1 - 2021-01-18
|
## 1.14.1 - 2021-01-18
|
||||||
- Add `doc-of` for reverse documentation lookup.
|
- Add `doc-of` for reverse documentation lookup.
|
||||||
- Add `ev/give-supervsior` to send a message to the supervising channel.
|
- Add `ev/give-supervsior` to send a message to the supervising channel.
|
||||||
|
|||||||
20
Makefile
20
Makefile
@@ -27,7 +27,7 @@ PREFIX?=/usr/local
|
|||||||
INCLUDEDIR?=$(PREFIX)/include
|
INCLUDEDIR?=$(PREFIX)/include
|
||||||
BINDIR?=$(PREFIX)/bin
|
BINDIR?=$(PREFIX)/bin
|
||||||
LIBDIR?=$(PREFIX)/lib
|
LIBDIR?=$(PREFIX)/lib
|
||||||
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 2> /dev/null || echo local)\""
|
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 1 2> /dev/null || echo local)\""
|
||||||
CLIBS=-lm -lpthread
|
CLIBS=-lm -lpthread
|
||||||
JANET_TARGET=build/janet
|
JANET_TARGET=build/janet
|
||||||
JANET_LIBRARY=build/libjanet.so
|
JANET_LIBRARY=build/libjanet.so
|
||||||
@@ -66,7 +66,7 @@ ifeq ($(UNAME), Haiku)
|
|||||||
LDFLAGS=-Wl,--export-dynamic
|
LDFLAGS=-Wl,--export-dynamic
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(shell mkdir -p build/core build/mainclient build/webclient build/boot)
|
$(shell mkdir -p build/core build/c build/boot)
|
||||||
all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.h
|
all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.h
|
||||||
|
|
||||||
######################
|
######################
|
||||||
@@ -149,7 +149,7 @@ build/janet_boot: $(JANET_BOOT_OBJECTS)
|
|||||||
$(CC) $(BOOT_CFLAGS) -o $@ $(JANET_BOOT_OBJECTS) $(CLIBS)
|
$(CC) $(BOOT_CFLAGS) -o $@ $(JANET_BOOT_OBJECTS) $(CLIBS)
|
||||||
|
|
||||||
# Now the reason we bootstrap in the first place
|
# Now the reason we bootstrap in the first place
|
||||||
build/janet.c: build/janet_boot src/boot/boot.janet
|
build/c/janet.c: build/janet_boot src/boot/boot.janet
|
||||||
build/janet_boot . JANET_PATH '$(JANET_PATH)' > $@
|
build/janet_boot . JANET_PATH '$(JANET_PATH)' > $@
|
||||||
cksum $@
|
cksum $@
|
||||||
|
|
||||||
@@ -157,9 +157,9 @@ build/janet.c: build/janet_boot src/boot/boot.janet
|
|||||||
##### Amalgamation #####
|
##### Amalgamation #####
|
||||||
########################
|
########################
|
||||||
|
|
||||||
SONAME=libjanet.so.1.14
|
SONAME=libjanet.so.1.15
|
||||||
|
|
||||||
build/shell.c: src/mainclient/shell.c
|
build/c/shell.c: src/mainclient/shell.c
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
build/janet.h: $(JANET_TARGET) src/include/janet.h src/conf/janetconf.h
|
build/janet.h: $(JANET_TARGET) src/include/janet.h src/conf/janetconf.h
|
||||||
@@ -168,11 +168,11 @@ build/janet.h: $(JANET_TARGET) src/include/janet.h src/conf/janetconf.h
|
|||||||
build/janetconf.h: src/conf/janetconf.h
|
build/janetconf.h: src/conf/janetconf.h
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
build/janet.o: build/janet.c src/include/janet.h src/conf/janetconf.h
|
build/janet.o: build/c/janet.c src/conf/janetconf.h src/include/janet.h
|
||||||
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@ -I build
|
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
build/shell.o: build/shell.c src/include/janet.h src/conf/janetconf.h
|
build/shell.o: build/c/shell.c src/conf/janetconf.h src/include/janet.h
|
||||||
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@ -I build
|
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
$(JANET_TARGET): build/janet.o build/shell.o
|
$(JANET_TARGET): build/janet.o build/shell.o
|
||||||
$(HOSTCC) $(LDFLAGS) $(BUILD_CFLAGS) -o $@ $^ $(CLIBS)
|
$(HOSTCC) $(LDFLAGS) $(BUILD_CFLAGS) -o $@ $^ $(CLIBS)
|
||||||
@@ -224,7 +224,7 @@ dist: build/janet-dist.tar.gz
|
|||||||
build/janet-%.tar.gz: $(JANET_TARGET) \
|
build/janet-%.tar.gz: $(JANET_TARGET) \
|
||||||
build/janet.h \
|
build/janet.h \
|
||||||
jpm.1 janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) \
|
jpm.1 janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) \
|
||||||
build/doc.html README.md build/janet.c build/shell.c jpm
|
build/doc.html README.md build/c/janet.c build/c/shell.c jpm
|
||||||
$(eval JANET_DIST_DIR = "janet-$(shell basename $*)")
|
$(eval JANET_DIST_DIR = "janet-$(shell basename $*)")
|
||||||
mkdir -p build/$(JANET_DIST_DIR)
|
mkdir -p build/$(JANET_DIST_DIR)
|
||||||
cp -r $^ build/$(JANET_DIST_DIR)/
|
cp -r $^ build/$(JANET_DIST_DIR)/
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ Documentation is also available locally in the REPL.
|
|||||||
Use the `(doc symbol-name)` macro to get API
|
Use the `(doc symbol-name)` macro to get API
|
||||||
documentation for symbols in the core library. For example,
|
documentation for symbols in the core library. For example,
|
||||||
```
|
```
|
||||||
(doc doc)
|
(doc apply)
|
||||||
```
|
```
|
||||||
Shows documentation for the doc macro.
|
Shows documentation for the `apply` function.
|
||||||
|
|
||||||
To get a list of all bindings in the default
|
To get a list of all bindings in the default
|
||||||
environment, use the `(all-bindings)` function. You
|
environment, use the `(all-bindings)` function. You
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ if not "%JANET_BUILD%" == "" (
|
|||||||
|
|
||||||
if not exist build mkdir build
|
if not exist build mkdir build
|
||||||
if not exist build\core mkdir build\core
|
if not exist build\core mkdir build\core
|
||||||
if not exist build\mainclient mkdir build\mainclient
|
if not exist build\c mkdir build\c
|
||||||
if not exist build\boot mkdir build\boot
|
if not exist build\boot mkdir build\boot
|
||||||
|
|
||||||
@rem Build the bootstrap interpreter
|
@rem Build the bootstrap interpreter
|
||||||
@@ -44,10 +44,10 @@ for %%f in (src\boot\*.c) do (
|
|||||||
)
|
)
|
||||||
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
build\janet_boot . > build\janet.c
|
build\janet_boot . > build\c\janet.c
|
||||||
|
|
||||||
@rem Build the sources
|
@rem Build the sources
|
||||||
%JANET_COMPILE% /Fobuild\janet.obj build\janet.c
|
%JANET_COMPILE% /Fobuild\janet.obj build\c\janet.c
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
%JANET_COMPILE% /Fobuild\shell.obj src\mainclient\shell.c
|
%JANET_COMPILE% /Fobuild\shell.obj src\mainclient\shell.c
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
@@ -102,9 +102,9 @@ exit /b 0
|
|||||||
mkdir dist
|
mkdir dist
|
||||||
janet.exe tools\gendoc.janet > dist\doc.html
|
janet.exe tools\gendoc.janet > dist\doc.html
|
||||||
janet.exe tools\removecr.janet dist\doc.html
|
janet.exe tools\removecr.janet dist\doc.html
|
||||||
janet.exe tools\removecr.janet build\janet.c
|
janet.exe tools\removecr.janet build\c\janet.c
|
||||||
|
|
||||||
copy build\janet.c dist\janet.c
|
copy build\c\janet.c dist\janet.c
|
||||||
copy src\mainclient\shell.c dist\shell.c
|
copy src\mainclient\shell.c dist\shell.c
|
||||||
copy janet.exe dist\janet.exe
|
copy janet.exe dist\janet.exe
|
||||||
copy LICENSE dist\LICENSE
|
copy LICENSE dist\LICENSE
|
||||||
|
|||||||
126
jpm
126
jpm
@@ -23,12 +23,12 @@
|
|||||||
|
|
||||||
# Overriden on some installs.
|
# Overriden on some installs.
|
||||||
# To configure this script, replace the code between
|
# To configure this script, replace the code between
|
||||||
# the START and END comments and define a function
|
# the START and END comments and define a function
|
||||||
# (install-paths) that gives the the default paths
|
# (install-paths) that gives the the default paths
|
||||||
# to use. Trailing directory separator not expected.
|
# to use. Trailing directory separator not expected.
|
||||||
#
|
#
|
||||||
# Example.
|
# Example.
|
||||||
#
|
#
|
||||||
# (defn- install-paths []
|
# (defn- install-paths []
|
||||||
# {:headerpath "/usr/local/include/janet"
|
# {:headerpath "/usr/local/include/janet"
|
||||||
# :libpath "/usr/local/lib/janet"
|
# :libpath "/usr/local/lib/janet"
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
(defn- try-real [path]
|
(defn- try-real [path]
|
||||||
"If os/realpath fails just use normal path."
|
"If os/realpath fails just use normal path."
|
||||||
(try (os/realpath) ([_] path)))
|
(try (os/realpath path) ([_] path)))
|
||||||
|
|
||||||
(defn- install-paths []
|
(defn- install-paths []
|
||||||
{:headerpath (try-real (string exe-dir "/../include/janet"))
|
{:headerpath (try-real (string exe-dir "/../include/janet"))
|
||||||
@@ -169,9 +169,7 @@
|
|||||||
[& args]
|
[& args]
|
||||||
(if (dyn :verbose)
|
(if (dyn :verbose)
|
||||||
(print ;(interpose " " args)))
|
(print ;(interpose " " args)))
|
||||||
(def res (os/execute args :p))
|
(os/execute args :px))
|
||||||
(unless (zero? res)
|
|
||||||
(error (string "command exited with status " res))))
|
|
||||||
|
|
||||||
(defn copy
|
(defn copy
|
||||||
"Copy a file or directory recursively from one location to another."
|
"Copy a file or directory recursively from one location to another."
|
||||||
@@ -602,7 +600,7 @@
|
|||||||
(string (string/slice path 0 (- -1 (length modext))) statext))
|
(string (string/slice path 0 (- -1 (length modext))) statext))
|
||||||
|
|
||||||
(defn- make-bin-source
|
(defn- make-bin-source
|
||||||
[declarations lookup-into-invocations]
|
[declarations lookup-into-invocations no-core]
|
||||||
(string
|
(string
|
||||||
declarations
|
declarations
|
||||||
```
|
```
|
||||||
@@ -627,15 +625,22 @@ int main(int argc, const char **argv) {
|
|||||||
|
|
||||||
janet_init();
|
janet_init();
|
||||||
|
|
||||||
|
```
|
||||||
|
(if no-core
|
||||||
|
```
|
||||||
|
/* Get core env */
|
||||||
|
JanetTable *env = janet_table(8);
|
||||||
|
JanetTable *lookup = janet_core_lookup_table(NULL);
|
||||||
|
JanetTable *temptab;
|
||||||
|
int handle = janet_gclock();
|
||||||
|
```
|
||||||
|
```
|
||||||
/* Get core env */
|
/* Get core env */
|
||||||
JanetTable *env = janet_core_env(NULL);
|
JanetTable *env = janet_core_env(NULL);
|
||||||
JanetTable *lookup = janet_env_lookup(env);
|
JanetTable *lookup = janet_env_lookup(env);
|
||||||
JanetTable *temptab;
|
JanetTable *temptab;
|
||||||
int handle = janet_gclock();
|
int handle = janet_gclock();
|
||||||
|
```)
|
||||||
/* Load natives into unmarshalling dictionary */
|
|
||||||
|
|
||||||
```
|
|
||||||
lookup-into-invocations
|
lookup-into-invocations
|
||||||
```
|
```
|
||||||
/* Unmarshal bytecode */
|
/* Unmarshal bytecode */
|
||||||
@@ -663,7 +668,6 @@ int main(int argc, const char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create enviornment */
|
/* Create enviornment */
|
||||||
temptab = janet_table(0);
|
|
||||||
temptab = env;
|
temptab = env;
|
||||||
janet_table_put(temptab, janet_ckeywordv("args"), janet_wrap_array(args));
|
janet_table_put(temptab, janet_ckeywordv("args"), janet_wrap_array(args));
|
||||||
janet_gcroot(janet_wrap_table(temptab));
|
janet_gcroot(janet_wrap_table(temptab));
|
||||||
@@ -674,6 +678,14 @@ int main(int argc, const char **argv) {
|
|||||||
/* Run everything */
|
/* Run everything */
|
||||||
JanetFiber *fiber = janet_fiber(jfunc, 64, argc, argc ? args->data : NULL);
|
JanetFiber *fiber = janet_fiber(jfunc, 64, argc, argc ? args->data : NULL);
|
||||||
fiber->env = temptab;
|
fiber->env = temptab;
|
||||||
|
#ifdef JANET_EV
|
||||||
|
janet_gcroot(janet_wrap_fiber(fiber));
|
||||||
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
|
janet_loop();
|
||||||
|
int status = janet_fiber_status(fiber);
|
||||||
|
janet_deinit();
|
||||||
|
return status;
|
||||||
|
#else
|
||||||
Janet out;
|
Janet out;
|
||||||
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
|
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||||
if (result != JANET_SIGNAL_OK && result != JANET_SIGNAL_EVENT) {
|
if (result != JANET_SIGNAL_OK && result != JANET_SIGNAL_EVENT) {
|
||||||
@@ -681,11 +693,9 @@ int main(int argc, const char **argv) {
|
|||||||
janet_deinit();
|
janet_deinit();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#ifdef JANET_NET
|
|
||||||
janet_loop();
|
|
||||||
#endif
|
|
||||||
janet_deinit();
|
janet_deinit();
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
```))
|
```))
|
||||||
@@ -694,7 +704,7 @@ int main(int argc, const char **argv) {
|
|||||||
"Links an image with libjanet.a (or .lib) to produce an
|
"Links an image with libjanet.a (or .lib) to produce an
|
||||||
executable. Also will try to link native modules into the
|
executable. Also will try to link native modules into the
|
||||||
final executable as well."
|
final executable as well."
|
||||||
[opts source dest]
|
[opts source dest no-core]
|
||||||
|
|
||||||
# Create executable's janet image
|
# Create executable's janet image
|
||||||
(def cimage_dest (string dest ".c"))
|
(def cimage_dest (string dest ".c"))
|
||||||
@@ -710,7 +720,16 @@ int main(int argc, const char **argv) {
|
|||||||
(def dep-ldflags @[])
|
(def dep-ldflags @[])
|
||||||
|
|
||||||
# Create marshalling dictionary
|
# Create marshalling dictionary
|
||||||
(def mdict (invert (env-lookup root-env)))
|
(def mdict1 (invert (env-lookup root-env)))
|
||||||
|
(def mdict
|
||||||
|
(if no-core
|
||||||
|
(let [temp @{}]
|
||||||
|
(eachp [k v] mdict1
|
||||||
|
(if (or (cfunction? k) (abstract? k))
|
||||||
|
(put temp k v)))
|
||||||
|
temp)
|
||||||
|
mdict1))
|
||||||
|
|
||||||
# Load all native modules
|
# Load all native modules
|
||||||
(def prefixes @{})
|
(def prefixes @{})
|
||||||
(def static-libs @[])
|
(def static-libs @[])
|
||||||
@@ -755,7 +774,7 @@ int main(int argc, const char **argv) {
|
|||||||
# Make image byte buffer
|
# Make image byte buffer
|
||||||
(create-buffer-c-impl image cimage_dest "janet_payload_image")
|
(create-buffer-c-impl image cimage_dest "janet_payload_image")
|
||||||
# Append main function
|
# Append main function
|
||||||
(spit cimage_dest (make-bin-source declarations lookup-into-invocations) :ab)
|
(spit cimage_dest (make-bin-source declarations lookup-into-invocations no-core) :ab)
|
||||||
(def oimage_dest (out-path cimage_dest ".c" ".o"))
|
(def oimage_dest (out-path cimage_dest ".c" ".o"))
|
||||||
# Compile and link final exectable
|
# Compile and link final exectable
|
||||||
(unless no-compile
|
(unless no-compile
|
||||||
@@ -959,7 +978,7 @@ int main(int argc, const char **argv) {
|
|||||||
(let [op (out-path src ".c" objext)]
|
(let [op (out-path src ".c" objext)]
|
||||||
(compile-c opts src op)
|
(compile-c opts src op)
|
||||||
op)
|
op)
|
||||||
(errorf "unknown source file type: %s, expected .c or .cpp"))))
|
(errorf "unknown source file type: %s, expected .c or .cpp" src))))
|
||||||
|
|
||||||
(when-let [embedded (opts :embedded)]
|
(when-let [embedded (opts :embedded)]
|
||||||
(loop [src :in embedded]
|
(loop [src :in embedded]
|
||||||
@@ -1044,10 +1063,10 @@ int main(int argc, const char **argv) {
|
|||||||
This executable can be installed as well to the --binpath given."
|
This executable can be installed as well to the --binpath given."
|
||||||
[&keys {:install install :name name :entry entry :headers headers
|
[&keys {:install install :name name :entry entry :headers headers
|
||||||
:cflags cflags :lflags lflags :deps deps :ldflags ldflags
|
:cflags cflags :lflags lflags :deps deps :ldflags ldflags
|
||||||
:no-compile no-compile}]
|
:no-compile no-compile :no-core no-core}]
|
||||||
(def name (if is-win (string name ".exe") name))
|
(def name (if is-win (string name ".exe") name))
|
||||||
(def dest (string "build" sep name))
|
(def dest (string "build" sep name))
|
||||||
(create-executable @{:cflags cflags :lflags lflags :ldflags ldflags :no-compile no-compile} entry dest)
|
(create-executable @{:cflags cflags :lflags lflags :ldflags ldflags :no-compile no-compile} entry dest no-core)
|
||||||
(if no-compile
|
(if no-compile
|
||||||
(let [cdest (string dest ".c")]
|
(let [cdest (string dest ".c")]
|
||||||
(add-dep "build" cdest))
|
(add-dep "build" cdest))
|
||||||
@@ -1061,12 +1080,15 @@ int main(int argc, const char **argv) {
|
|||||||
(install-rule dest (dyn :binpath JANET_BINPATH))))))
|
(install-rule dest (dyn :binpath JANET_BINPATH))))))
|
||||||
|
|
||||||
(defn declare-binscript
|
(defn declare-binscript
|
||||||
"Declare a janet file to be installed as an executable script. Creates
|
``Declare a janet file to be installed as an executable script. Creates
|
||||||
a shim on windows. If hardcode is true, will insert code into the script
|
a shim on windows. If hardcode is true, will insert code into the script
|
||||||
such that it will run correctly even when JANET_PATH is changed."
|
such that it will run correctly even when JANET_PATH is changed. if auto-shebang
|
||||||
[&keys {:main main :hardcode-syspath hardcode}]
|
is truthy, will also automatically insert a correct shebang line.
|
||||||
|
``
|
||||||
|
[&keys {:main main :hardcode-syspath hardcode :is-janet is-janet}]
|
||||||
(def binpath (dyn :binpath JANET_BINPATH))
|
(def binpath (dyn :binpath JANET_BINPATH))
|
||||||
(if hardcode
|
(def auto-shebang (and is-janet (dyn :auto-shebang)))
|
||||||
|
(if (or auto-shebang hardcode)
|
||||||
(let [syspath (dyn :modpath JANET_MODPATH)]
|
(let [syspath (dyn :modpath JANET_MODPATH)]
|
||||||
(def parts (peg/match path-splitter main))
|
(def parts (peg/match path-splitter main))
|
||||||
(def name (last parts))
|
(def name (last parts))
|
||||||
@@ -1078,7 +1100,9 @@ int main(int argc, const char **argv) {
|
|||||||
(def first-line (:read f :line))
|
(def first-line (:read f :line))
|
||||||
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
|
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
|
||||||
(def rest (:read f :all))
|
(def rest (:read f :all))
|
||||||
(string first-line second-line rest)))
|
(string (if auto-shebang
|
||||||
|
(string "#!" (dyn :binpath JANET_BINPATH) "/janet\n"))
|
||||||
|
first-line (if hardcode second-line) rest)))
|
||||||
(create-dirs path)
|
(create-dirs path)
|
||||||
(spit path contents)
|
(spit path contents)
|
||||||
(unless is-win (shell "chmod" "+x" path))))
|
(unless is-win (shell "chmod" "+x" path))))
|
||||||
@@ -1354,7 +1378,9 @@ Flags are:
|
|||||||
|
|
||||||
(defn quickbin
|
(defn quickbin
|
||||||
[input output]
|
[input output]
|
||||||
(create-executable @{} input output)
|
(if (= (os/stat output :mode) :file)
|
||||||
|
(print "output " output " exists."))
|
||||||
|
(create-executable @{:no-compile (dyn :no-compile)} input output (dyn :no-core))
|
||||||
(do-rule output))
|
(do-rule output))
|
||||||
|
|
||||||
(defn jpm-debug-repl
|
(defn jpm-debug-repl
|
||||||
@@ -1401,26 +1427,30 @@ Flags are:
|
|||||||
"load-lockfile" load-lockfile
|
"load-lockfile" load-lockfile
|
||||||
"quickbin" quickbin})
|
"quickbin" quickbin})
|
||||||
|
|
||||||
(def- args (tuple/slice (dyn :args) 1))
|
(defn- main
|
||||||
(def- len (length args))
|
"Script entry."
|
||||||
(var i :private 0)
|
[& argv]
|
||||||
|
|
||||||
# Get flags
|
(def- args (tuple/slice argv 1))
|
||||||
(while (< i len)
|
(def- len (length args))
|
||||||
(if-let [m (peg/match argpeg (args i))]
|
(var i :private 0)
|
||||||
(if (= 2 (length m))
|
|
||||||
(let [[key value] m]
|
|
||||||
(setdyn (keyword key) value))
|
|
||||||
(setdyn (keyword (m 0)) true))
|
|
||||||
(break))
|
|
||||||
(++ i))
|
|
||||||
|
|
||||||
# Run subcommand
|
# Get flags
|
||||||
(if (= i len)
|
(while (< i len)
|
||||||
(help)
|
(if-let [m (peg/match argpeg (args i))]
|
||||||
(do
|
(if (= 2 (length m))
|
||||||
(if-let [com (subcommands (args i))]
|
(let [[key value] m]
|
||||||
(com ;(tuple/slice args (+ i 1)))
|
(setdyn (keyword key) value))
|
||||||
(do
|
(setdyn (keyword (m 0)) true))
|
||||||
(print "invalid command " (args i))
|
(break))
|
||||||
(help)))))
|
(++ i))
|
||||||
|
|
||||||
|
# Run subcommand
|
||||||
|
(if (= i len)
|
||||||
|
(help)
|
||||||
|
(do
|
||||||
|
(if-let [com (subcommands (args i))]
|
||||||
|
(com ;(tuple/slice args (+ i 1)))
|
||||||
|
(do
|
||||||
|
(print "invalid command " (args i))
|
||||||
|
(help))))))
|
||||||
|
|||||||
4
jpm.1
4
jpm.1
@@ -42,6 +42,10 @@ Prevents jpm from going to network to get dependencies - all dependencies should
|
|||||||
Use this flag with the deps and update-pkgs subcommands. This is not a surefire way to prevent a build script from accessing
|
Use this flag with the deps and update-pkgs subcommands. This is not a surefire way to prevent a build script from accessing
|
||||||
the network, for example, a build script that invokes curl will still have network access.
|
the network, for example, a build script that invokes curl will still have network access.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR \-\-auto\-shebang
|
||||||
|
Prepends installed scripts with a generated shebang line, such that they will use a janet binary located in JANET_BINPATH.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
# IN THE SOFTWARE.
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
project('janet', 'c',
|
project('janet', 'c',
|
||||||
default_options : ['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.14.1')
|
version : '1.15.3')
|
||||||
|
|
||||||
# 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')
|
||||||
@@ -33,7 +33,7 @@ dl_dep = cc.find_library('dl', required : false)
|
|||||||
thread_dep = dependency('threads')
|
thread_dep = dependency('threads')
|
||||||
|
|
||||||
# Link options
|
# Link options
|
||||||
if build_machine.system() != 'windows'
|
if get_option('default_library') != 'static' and build_machine.system() != 'windows'
|
||||||
add_project_link_arguments('-rdynamic', language : 'c')
|
add_project_link_arguments('-rdynamic', language : 'c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -244,6 +244,7 @@ janet_dep = declare_dependency(include_directories : incdir,
|
|||||||
# pkgconfig
|
# pkgconfig
|
||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
pkg.generate(libjanet,
|
pkg.generate(libjanet,
|
||||||
|
subdirs: 'janet',
|
||||||
description: 'Library for the Janet programming language.')
|
description: 'Library for the Janet programming language.')
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|||||||
1976
src/boot/boot.janet
1976
src/boot/boot.janet
File diff suppressed because it is too large
Load Diff
@@ -4,10 +4,10 @@
|
|||||||
#define JANETCONF_H
|
#define JANETCONF_H
|
||||||
|
|
||||||
#define JANET_VERSION_MAJOR 1
|
#define JANET_VERSION_MAJOR 1
|
||||||
#define JANET_VERSION_MINOR 14
|
#define JANET_VERSION_MINOR 15
|
||||||
#define JANET_VERSION_PATCH 1
|
#define JANET_VERSION_PATCH 3
|
||||||
#define JANET_VERSION_EXTRA ""
|
#define JANET_VERSION_EXTRA ""
|
||||||
#define JANET_VERSION "1.14.1"
|
#define JANET_VERSION "1.15.3"
|
||||||
|
|
||||||
/* #define JANET_BUILD "local" */
|
/* #define JANET_BUILD "local" */
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ void janet_buffer_extra(JanetBuffer *buffer, int32_t n) {
|
|||||||
}
|
}
|
||||||
int32_t new_size = buffer->count + n;
|
int32_t new_size = buffer->count + n;
|
||||||
if (new_size > buffer->capacity) {
|
if (new_size > buffer->capacity) {
|
||||||
int32_t new_capacity = new_size * 2;
|
int32_t new_capacity = (new_size > (INT32_MAX / 2)) ? INT32_MAX : (new_size * 2);
|
||||||
uint8_t *new_data = realloc(buffer->data, new_capacity * sizeof(uint8_t));
|
uint8_t *new_data = realloc(buffer->data, new_capacity * sizeof(uint8_t));
|
||||||
janet_gcpressure(new_capacity - buffer->capacity);
|
janet_gcpressure(new_capacity - buffer->capacity);
|
||||||
if (NULL == new_data) {
|
if (NULL == new_data) {
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
|
|||||||
void janet_signalv(JanetSignal sig, Janet message) {
|
void janet_signalv(JanetSignal sig, Janet message) {
|
||||||
if (janet_vm_return_reg != NULL) {
|
if (janet_vm_return_reg != NULL) {
|
||||||
*janet_vm_return_reg = message;
|
*janet_vm_return_reg = message;
|
||||||
janet_vm_fiber->flags |= JANET_FIBER_DID_LONGJUMP;
|
if (NULL != janet_vm_fiber) {
|
||||||
|
janet_vm_fiber->flags |= JANET_FIBER_DID_LONGJUMP;
|
||||||
|
}
|
||||||
#if defined(JANET_BSD) || defined(JANET_APPLE)
|
#if defined(JANET_BSD) || defined(JANET_APPLE)
|
||||||
_longjmp(*janet_vm_jmp_buf, sig);
|
_longjmp(*janet_vm_jmp_buf, sig);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -872,8 +872,12 @@ static Janet cfun(int32_t argc, Janet *argv) {
|
|||||||
} else {
|
} else {
|
||||||
JanetTable *t = janet_table(4);
|
JanetTable *t = janet_table(4);
|
||||||
janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error));
|
janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error));
|
||||||
janet_table_put(t, janet_ckeywordv("line"), janet_wrap_integer(res.error_mapping.line));
|
if (res.error_mapping.line > 0) {
|
||||||
janet_table_put(t, janet_ckeywordv("column"), janet_wrap_integer(res.error_mapping.column));
|
janet_table_put(t, janet_ckeywordv("line"), janet_wrap_integer(res.error_mapping.line));
|
||||||
|
}
|
||||||
|
if (res.error_mapping.column > 0) {
|
||||||
|
janet_table_put(t, janet_ckeywordv("column"), janet_wrap_integer(res.error_mapping.column));
|
||||||
|
}
|
||||||
if (res.macrofiber) {
|
if (res.macrofiber) {
|
||||||
janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber));
|
janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1206,7 +1206,8 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
"if native modules are compatible with the host program."));
|
"if native modules are compatible with the host program."));
|
||||||
|
|
||||||
/* Allow references to the environment */
|
/* Allow references to the environment */
|
||||||
janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope."));
|
janet_def(env, "root-env", janet_wrap_table(env),
|
||||||
|
JDOC("The root environment used to create environments with (make-env)."));
|
||||||
|
|
||||||
janet_load_libs(env);
|
janet_load_libs(env);
|
||||||
janet_gcroot(janet_wrap_table(env));
|
janet_gcroot(janet_wrap_table(env));
|
||||||
@@ -1221,22 +1222,7 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
return janet_vm_core_env;
|
return janet_vm_core_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load core cfunctions (and some built in janet assembly functions) */
|
JanetTable *dict = janet_core_lookup_table(replacements);
|
||||||
JanetTable *dict = janet_table(512);
|
|
||||||
janet_load_libs(dict);
|
|
||||||
|
|
||||||
/* Add replacements */
|
|
||||||
if (replacements != NULL) {
|
|
||||||
for (int32_t i = 0; i < replacements->capacity; i++) {
|
|
||||||
JanetKV kv = replacements->data[i];
|
|
||||||
if (!janet_checktype(kv.key, JANET_NIL)) {
|
|
||||||
janet_table_put(dict, kv.key, kv.value);
|
|
||||||
if (janet_checktype(kv.value, JANET_CFUNCTION)) {
|
|
||||||
janet_table_put(janet_vm_registry, kv.value, kv.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshal bytecode */
|
/* Unmarshal bytecode */
|
||||||
Janet marsh_out = janet_unmarshal(
|
Janet marsh_out = janet_unmarshal(
|
||||||
@@ -1270,3 +1256,23 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
JanetTable *janet_core_lookup_table(JanetTable *replacements) {
|
||||||
|
JanetTable *dict = janet_table(512);
|
||||||
|
janet_load_libs(dict);
|
||||||
|
|
||||||
|
/* Add replacements */
|
||||||
|
if (replacements != NULL) {
|
||||||
|
for (int32_t i = 0; i < replacements->capacity; i++) {
|
||||||
|
JanetKV kv = replacements->data[i];
|
||||||
|
if (!janet_checktype(kv.key, JANET_NIL)) {
|
||||||
|
janet_table_put(dict, kv.key, kv.value);
|
||||||
|
if (janet_checktype(kv.value, JANET_CFUNCTION)) {
|
||||||
|
janet_table_put(janet_vm_registry, kv.value, kv.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) {
|
|||||||
int32_t fi;
|
int32_t fi;
|
||||||
const char *errstr = (const char *)janet_to_string(err);
|
const char *errstr = (const char *)janet_to_string(err);
|
||||||
JanetFiber **fibers = NULL;
|
JanetFiber **fibers = NULL;
|
||||||
int wrote_error = 0;
|
|
||||||
|
/* Don't print error line if it is nil. */
|
||||||
|
int wrote_error = janet_checktype(err, JANET_NIL);
|
||||||
|
|
||||||
int print_color = janet_truthy(janet_dyn("err-color"));
|
int print_color = janet_truthy(janet_dyn("err-color"));
|
||||||
if (print_color) janet_eprintf("\x1b[31m");
|
if (print_color) janet_eprintf("\x1b[31m");
|
||||||
@@ -302,7 +304,6 @@ static Janet cfun_debug_stacktrace(int32_t argc, Janet *argv) {
|
|||||||
janet_arity(argc, 1, 2);
|
janet_arity(argc, 1, 2);
|
||||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||||
Janet x = argc == 1 ? janet_wrap_nil() : argv[1];
|
Janet x = argc == 1 ? janet_wrap_nil() : argv[1];
|
||||||
x = janet_checktype(x, JANET_NIL) ? fiber->last_value : x;
|
|
||||||
janet_stacktrace(fiber, x);
|
janet_stacktrace(fiber, x);
|
||||||
return argv[0];
|
return argv[0];
|
||||||
}
|
}
|
||||||
@@ -382,7 +383,7 @@ static const JanetReg debug_cfuns[] = {
|
|||||||
JDOC("(debug/stacktrace fiber &opt err)\n\n"
|
JDOC("(debug/stacktrace fiber &opt err)\n\n"
|
||||||
"Prints a nice looking stacktrace for a fiber. Can optionally provide "
|
"Prints a nice looking stacktrace for a fiber. Can optionally provide "
|
||||||
"an error value to print the stack trace with. If `err` is nil or not "
|
"an error value to print the stack trace with. If `err` is nil or not "
|
||||||
"provided, will default to `(fiber/last-value fiber)`. Returns the fiber.")
|
"provided, will skipp the error line. Returns the fiber.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"debug/lineage", cfun_debug_lineage,
|
"debug/lineage", cfun_debug_lineage,
|
||||||
|
|||||||
@@ -393,7 +393,20 @@ static void janet_stream_marshal(void *p, JanetMarshalContext *ctx) {
|
|||||||
* while in transit, and it's value gets reused. DuplicateHandle does not work
|
* while in transit, and it's value gets reused. DuplicateHandle does not work
|
||||||
* for network sockets, and in general for winsock it is better to nipt duplicate
|
* for network sockets, and in general for winsock it is better to nipt duplicate
|
||||||
* unless there is a need to. */
|
* unless there is a need to. */
|
||||||
janet_marshal_int64(ctx, (int64_t)(s->handle));
|
HANDLE duph = INVALID_HANDLE_VALUE;
|
||||||
|
if (s->flags & JANET_STREAM_SOCKET) {
|
||||||
|
duph = s->handle;
|
||||||
|
} else {
|
||||||
|
DuplicateHandle(
|
||||||
|
GetCurrentProcess(),
|
||||||
|
s->handle,
|
||||||
|
GetCurrentProcess(),
|
||||||
|
&duph,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
}
|
||||||
|
janet_marshal_int64(ctx, (int64_t)(duph));
|
||||||
#else
|
#else
|
||||||
/* Marshal after dup becuse it is easier than maintaining our own ref counting. */
|
/* Marshal after dup becuse it is easier than maintaining our own ref counting. */
|
||||||
int duph = dup(s->handle);
|
int duph = dup(s->handle);
|
||||||
@@ -1614,8 +1627,7 @@ JanetAsyncStatus ev_machine_read(JanetListenerState *s, JanetAsyncEvent event) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case JANET_ASYNC_EVENT_ERR:
|
case JANET_ASYNC_EVENT_ERR: {
|
||||||
case JANET_ASYNC_EVENT_HUP: {
|
|
||||||
if (state->bytes_read) {
|
if (state->bytes_read) {
|
||||||
janet_schedule(s->fiber, janet_wrap_buffer(state->buf));
|
janet_schedule(s->fiber, janet_wrap_buffer(state->buf));
|
||||||
} else {
|
} else {
|
||||||
@@ -1623,6 +1635,7 @@ JanetAsyncStatus ev_machine_read(JanetListenerState *s, JanetAsyncEvent event) {
|
|||||||
}
|
}
|
||||||
return JANET_ASYNC_STATUS_DONE;
|
return JANET_ASYNC_STATUS_DONE;
|
||||||
}
|
}
|
||||||
|
case JANET_ASYNC_EVENT_HUP:
|
||||||
case JANET_ASYNC_EVENT_READ: {
|
case JANET_ASYNC_EVENT_READ: {
|
||||||
JanetBuffer *buffer = state->buf;
|
JanetBuffer *buffer = state->buf;
|
||||||
int32_t bytes_left = state->bytes_left;
|
int32_t bytes_left = state->bytes_left;
|
||||||
@@ -2033,6 +2046,64 @@ static Janet cfun_ev_go(int32_t argc, Janet *argv) {
|
|||||||
return argv[0];
|
return argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For ev/thread - Run an interpreter in the new thread. */
|
||||||
|
static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) {
|
||||||
|
JanetBuffer *buffer = (JanetBuffer *) args.argp;
|
||||||
|
const uint8_t *nextbytes = buffer->data;
|
||||||
|
const uint8_t *endbytes = nextbytes + buffer->count;
|
||||||
|
janet_init();
|
||||||
|
JanetTryState tstate;
|
||||||
|
JanetSignal signal = janet_try(&tstate);
|
||||||
|
if (!signal) {
|
||||||
|
Janet aregv = janet_unmarshal(nextbytes, endbytes - nextbytes,
|
||||||
|
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
|
||||||
|
if (!janet_checktype(aregv, JANET_TABLE)) janet_panic("expected table for abstract registry");
|
||||||
|
janet_vm_abstract_registry = janet_unwrap_table(aregv);
|
||||||
|
Janet regv = janet_unmarshal(nextbytes, endbytes - nextbytes,
|
||||||
|
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
|
||||||
|
if (!janet_checktype(regv, JANET_TABLE)) janet_panic("expected table for cfunction registry");
|
||||||
|
janet_vm_registry = janet_unwrap_table(regv);
|
||||||
|
Janet fiberv = janet_unmarshal(nextbytes, endbytes - nextbytes,
|
||||||
|
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
|
||||||
|
Janet value = janet_unmarshal(nextbytes, endbytes - nextbytes,
|
||||||
|
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
|
||||||
|
if (!janet_checktype(fiberv, JANET_FIBER)) janet_panic("expected fiber");
|
||||||
|
JanetFiber *fiber = janet_unwrap_fiber(fiberv);
|
||||||
|
janet_schedule(fiber, value);
|
||||||
|
janet_loop();
|
||||||
|
args.tag = JANET_EV_TCTAG_NIL;
|
||||||
|
} else {
|
||||||
|
if (janet_checktype(tstate.payload, JANET_STRING)) {
|
||||||
|
args.tag = JANET_EV_TCTAG_ERR_STRINGF;
|
||||||
|
args.argp = strdup((const char *) janet_unwrap_string(tstate.payload));
|
||||||
|
} else {
|
||||||
|
args.tag = JANET_EV_TCTAG_ERR_STRING;
|
||||||
|
args.argp = "failed to start thread";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
janet_buffer_deinit(buffer);
|
||||||
|
janet_restore(&tstate);
|
||||||
|
janet_deinit();
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Janet cfun_ev_thread(int32_t argc, Janet *argv) {
|
||||||
|
janet_arity(argc, 1, 3);
|
||||||
|
janet_getfiber(argv, 0);
|
||||||
|
Janet value = argc == 2 ? argv[1] : janet_wrap_nil();
|
||||||
|
/* Marshal arguments for the new thread. */
|
||||||
|
JanetBuffer *buffer = malloc(sizeof(JanetBuffer));
|
||||||
|
if (NULL == buffer) {
|
||||||
|
JANET_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
janet_buffer_init(buffer, 0);
|
||||||
|
janet_marshal(buffer, janet_wrap_table(janet_vm_abstract_registry), NULL, JANET_MARSHAL_UNSAFE);
|
||||||
|
janet_marshal(buffer, janet_wrap_table(janet_vm_registry), NULL, JANET_MARSHAL_UNSAFE);
|
||||||
|
janet_marshal(buffer, argv[0], NULL, JANET_MARSHAL_UNSAFE);
|
||||||
|
janet_marshal(buffer, value, NULL, JANET_MARSHAL_UNSAFE);
|
||||||
|
janet_ev_threaded_await(janet_go_thread_subr, 0, argc, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static Janet cfun_ev_give_supervisor(int32_t argc, Janet *argv) {
|
static Janet cfun_ev_give_supervisor(int32_t argc, Janet *argv) {
|
||||||
janet_arity(argc, 1, -1);
|
janet_arity(argc, 1, -1);
|
||||||
JanetChannel *chan = janet_vm_root_fiber->supervisor_channel;
|
JanetChannel *chan = janet_vm_root_fiber->supervisor_channel;
|
||||||
@@ -2146,6 +2217,14 @@ static const JanetReg ev_cfuns[] = {
|
|||||||
"events occur in the newly scheduled fiber, an event will be pushed to the supervisor. "
|
"events occur in the newly scheduled fiber, an event will be pushed to the supervisor. "
|
||||||
"If not provided, the new fiber will inherit the current supervisor.")
|
"If not provided, the new fiber will inherit the current supervisor.")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ev/thread", cfun_ev_thread,
|
||||||
|
JDOC("(ev/thread fiber &opt value flags)\n\n"
|
||||||
|
"Resume a (copy of a) `fiber` in a new operating system thread, optionally passing `value` "
|
||||||
|
"to resume with. "
|
||||||
|
"Unlike `ev/go`, this function will suspend the current fiber until the thread is complete. "
|
||||||
|
"The the final result.")
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ev/give-supervisor", cfun_ev_give_supervisor,
|
"ev/give-supervisor", cfun_ev_give_supervisor,
|
||||||
JDOC("(ev/give-supervsior tag & payload)\n\n"
|
JDOC("(ev/give-supervsior tag & payload)\n\n"
|
||||||
@@ -2248,6 +2327,7 @@ static const JanetReg ev_cfuns[] = {
|
|||||||
|
|
||||||
void janet_lib_ev(JanetTable *env) {
|
void janet_lib_ev(JanetTable *env) {
|
||||||
janet_core_cfuns(env, NULL, ev_cfuns);
|
janet_core_cfuns(env, NULL, ev_cfuns);
|
||||||
|
janet_register_abstract_type(&janet_stream_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -746,6 +746,7 @@ static const JanetReg io_cfuns[] = {
|
|||||||
"* r - allow reading from the file\n\n"
|
"* r - allow reading from the file\n\n"
|
||||||
"* w - allow writing to the file\n\n"
|
"* w - allow writing to the file\n\n"
|
||||||
"* a - append to the file\n\n"
|
"* a - append to the file\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")
|
||||||
|
|||||||
@@ -938,6 +938,7 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
#ifdef JANET_EV
|
#ifdef JANET_EV
|
||||||
fiber->waiting = NULL;
|
fiber->waiting = NULL;
|
||||||
fiber->sched_id = 0;
|
fiber->sched_id = 0;
|
||||||
|
fiber->supervisor_channel = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Push fiber to seen stack */
|
/* Push fiber to seen stack */
|
||||||
@@ -1427,9 +1428,9 @@ static const JanetReg marsh_cfuns[] = {
|
|||||||
"marshal", cfun_marshal,
|
"marshal", cfun_marshal,
|
||||||
JDOC("(marshal x &opt reverse-lookup buffer)\n\n"
|
JDOC("(marshal x &opt reverse-lookup buffer)\n\n"
|
||||||
"Marshal a value into a buffer and return the buffer. The buffer "
|
"Marshal a value into a buffer and return the buffer. The buffer "
|
||||||
"can the later be unmarshalled to reconstruct the initial value. "
|
"can then later be unmarshalled to reconstruct the initial value. "
|
||||||
"Optionally, one can pass in a reverse lookup table to not marshal "
|
"Optionally, one can pass in a reverse lookup table to not marshal "
|
||||||
"aliased values that are found in the table. Then a forward"
|
"aliased values that are found in the table. Then a forward "
|
||||||
"lookup table can be used to recover the original value when "
|
"lookup table can be used to recover the original value when "
|
||||||
"unmarshalling.")
|
"unmarshalling.")
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ JanetAsyncStatus net_machine_accept(JanetListenerState *s, JanetAsyncEvent event
|
|||||||
if (state->function) {
|
if (state->function) {
|
||||||
/* Schedule worker */
|
/* Schedule worker */
|
||||||
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
|
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
|
||||||
|
fiber->supervisor_channel = s->fiber->supervisor_channel;
|
||||||
janet_schedule(fiber, janet_wrap_nil());
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
/* Now listen again for next connection */
|
/* Now listen again for next connection */
|
||||||
Janet err;
|
Janet err;
|
||||||
@@ -222,6 +223,7 @@ JanetAsyncStatus net_machine_accept(JanetListenerState *s, JanetAsyncEvent event
|
|||||||
Janet streamv = janet_wrap_abstract(stream);
|
Janet streamv = janet_wrap_abstract(stream);
|
||||||
if (state->function) {
|
if (state->function) {
|
||||||
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
|
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
|
||||||
|
fiber->supervisor_channel = s->fiber->supervisor_channel;
|
||||||
janet_schedule(fiber, janet_wrap_nil());
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
} else {
|
} else {
|
||||||
janet_schedule(s->fiber, streamv);
|
janet_schedule(s->fiber, streamv);
|
||||||
@@ -263,12 +265,11 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
|
|||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
if (janet_keyeq(argv[offset], "unix")) {
|
if (janet_keyeq(argv[offset], "unix")) {
|
||||||
const char *path = janet_getcstring(argv, offset + 1);
|
const char *path = janet_getcstring(argv, offset + 1);
|
||||||
struct sockaddr_un *saddr = malloc(sizeof(struct sockaddr_un));
|
struct sockaddr_un *saddr = calloc(1, sizeof(struct sockaddr_un));
|
||||||
if (saddr == NULL) {
|
if (saddr == NULL) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
saddr->sun_family = AF_UNIX;
|
saddr->sun_family = AF_UNIX;
|
||||||
memset(&saddr->sun_path, 0, 108);
|
|
||||||
#ifdef JANET_LINUX
|
#ifdef JANET_LINUX
|
||||||
if (path[0] == '@') {
|
if (path[0] == '@') {
|
||||||
saddr->sun_path[0] = '\0';
|
saddr->sun_path[0] = '\0';
|
||||||
|
|||||||
101
src/core/os.c
101
src/core/os.c
@@ -187,49 +187,71 @@ static Janet os_exit(int32_t argc, Janet *argv) {
|
|||||||
#ifndef JANET_NO_PROCESSES
|
#ifndef JANET_NO_PROCESSES
|
||||||
|
|
||||||
/* Get env for os_execute */
|
/* Get env for os_execute */
|
||||||
static char **os_execute_env(int32_t argc, const Janet *argv) {
|
#ifdef JANET_WINDOWS
|
||||||
char **envp = NULL;
|
typedef char *EnvBlock;
|
||||||
if (argc > 2) {
|
#else
|
||||||
JanetDictView dict = janet_getdictionary(argv, 2);
|
typedef char **EnvBlock;
|
||||||
envp = janet_smalloc(sizeof(char *) * ((size_t)dict.len + 1));
|
#endif
|
||||||
int32_t j = 0;
|
|
||||||
for (int32_t i = 0; i < dict.cap; i++) {
|
/* Get env for os_execute */
|
||||||
const JanetKV *kv = dict.kvs + i;
|
static EnvBlock os_execute_env(int32_t argc, const Janet *argv) {
|
||||||
if (!janet_checktype(kv->key, JANET_STRING)) continue;
|
if (argc <= 2) return NULL;
|
||||||
if (!janet_checktype(kv->value, JANET_STRING)) continue;
|
JanetDictView dict = janet_getdictionary(argv, 2);
|
||||||
const uint8_t *keys = janet_unwrap_string(kv->key);
|
#ifdef JANET_WINDOWS
|
||||||
const uint8_t *vals = janet_unwrap_string(kv->value);
|
JanetBuffer *temp = janet_buffer(10);
|
||||||
int32_t klen = janet_string_length(keys);
|
for (int32_t i = 0; i < dict.cap; i++) {
|
||||||
int32_t vlen = janet_string_length(vals);
|
const JanetKV *kv = dict.kvs + i;
|
||||||
/* Check keys has no embedded 0s or =s. */
|
if (!janet_checktype(kv->key, JANET_STRING)) continue;
|
||||||
int skip = 0;
|
if (!janet_checktype(kv->value, JANET_STRING)) continue;
|
||||||
for (int32_t k = 0; k < klen; k++) {
|
const uint8_t *keys = janet_unwrap_string(kv->key);
|
||||||
if (keys[k] == '\0' || keys[k] == '=') {
|
const uint8_t *vals = janet_unwrap_string(kv->value);
|
||||||
skip = 1;
|
janet_buffer_push_bytes(temp, keys, janet_string_length(keys));
|
||||||
break;
|
janet_buffer_push_u8(temp, '=');
|
||||||
}
|
janet_buffer_push_bytes(temp, vals, janet_string_length(vals));
|
||||||
}
|
janet_buffer_push_u8(temp, '\0');
|
||||||
if (skip) continue;
|
|
||||||
char *envitem = janet_smalloc((size_t) klen + (size_t) vlen + 2);
|
|
||||||
memcpy(envitem, keys, klen);
|
|
||||||
envitem[klen] = '=';
|
|
||||||
memcpy(envitem + klen + 1, vals, vlen);
|
|
||||||
envitem[klen + vlen + 1] = 0;
|
|
||||||
envp[j++] = envitem;
|
|
||||||
}
|
|
||||||
envp[j] = NULL;
|
|
||||||
}
|
}
|
||||||
|
janet_buffer_push_u8(temp, '\0');
|
||||||
|
char *ret = janet_smalloc(temp->count);
|
||||||
|
memcpy(ret, temp->data, temp->count);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
char **envp = janet_smalloc(sizeof(char *) * ((size_t)dict.len + 1));
|
||||||
|
int32_t j = 0;
|
||||||
|
for (int32_t i = 0; i < dict.cap; i++) {
|
||||||
|
const JanetKV *kv = dict.kvs + i;
|
||||||
|
if (!janet_checktype(kv->key, JANET_STRING)) continue;
|
||||||
|
if (!janet_checktype(kv->value, JANET_STRING)) continue;
|
||||||
|
const uint8_t *keys = janet_unwrap_string(kv->key);
|
||||||
|
const uint8_t *vals = janet_unwrap_string(kv->value);
|
||||||
|
int32_t klen = janet_string_length(keys);
|
||||||
|
int32_t vlen = janet_string_length(vals);
|
||||||
|
/* Check keys has no embedded 0s or =s. */
|
||||||
|
int skip = 0;
|
||||||
|
for (int32_t k = 0; k < klen; k++) {
|
||||||
|
if (keys[k] == '\0' || keys[k] == '=') {
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
char *envitem = janet_smalloc((size_t) klen + (size_t) vlen + 2);
|
||||||
|
memcpy(envitem, keys, klen);
|
||||||
|
envitem[klen] = '=';
|
||||||
|
memcpy(envitem + klen + 1, vals, vlen);
|
||||||
|
envitem[klen + vlen + 1] = 0;
|
||||||
|
envp[j++] = envitem;
|
||||||
|
}
|
||||||
|
envp[j] = NULL;
|
||||||
return envp;
|
return envp;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free memory from os_execute. Not actually needed, but doesn't pressure the GC
|
static void os_execute_cleanup(EnvBlock envp, const char **child_argv) {
|
||||||
in the happy path. */
|
|
||||||
static void os_execute_cleanup(char **envp, const char **child_argv) {
|
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
(void) child_argv;
|
(void) child_argv;
|
||||||
|
if (NULL != envp) janet_sfree(envp);
|
||||||
#else
|
#else
|
||||||
janet_sfree((void *)child_argv);
|
janet_sfree((void *)child_argv);
|
||||||
#endif
|
|
||||||
if (NULL != envp) {
|
if (NULL != envp) {
|
||||||
char **envitem = envp;
|
char **envitem = envp;
|
||||||
while (*envitem != NULL) {
|
while (*envitem != NULL) {
|
||||||
@@ -238,6 +260,7 @@ static void os_execute_cleanup(char **envp, const char **child_argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
janet_sfree(envp);
|
janet_sfree(envp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
@@ -730,12 +753,11 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
|||||||
uint64_t flags = 0;
|
uint64_t flags = 0;
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
flags = janet_getflags(argv, 1, "epx");
|
flags = janet_getflags(argv, 1, "epx");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get environment */
|
/* Get environment */
|
||||||
int use_environ = !janet_flag_at(flags, 0);
|
int use_environ = !janet_flag_at(flags, 0);
|
||||||
char **envp = os_execute_env(argc, argv);
|
EnvBlock envp = os_execute_env(argc, argv);
|
||||||
|
|
||||||
/* Get arguments */
|
/* Get arguments */
|
||||||
JanetView exargs = janet_getindexed(argv, 0);
|
JanetView exargs = janet_getindexed(argv, 0);
|
||||||
@@ -919,7 +941,6 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
|||||||
janet_unlock_environ();
|
janet_unlock_environ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for child */
|
|
||||||
os_execute_cleanup(envp, child_argv);
|
os_execute_cleanup(envp, child_argv);
|
||||||
if (status) {
|
if (status) {
|
||||||
janet_panicf("%p: %s", argv[0], strerror(errno));
|
janet_panicf("%p: %s", argv[0], strerror(errno));
|
||||||
@@ -2064,7 +2085,7 @@ static const JanetReg os_cfuns[] = {
|
|||||||
#ifndef JANET_NO_PROCESSES
|
#ifndef JANET_NO_PROCESSES
|
||||||
{
|
{
|
||||||
"os/execute", os_execute,
|
"os/execute", os_execute,
|
||||||
JDOC("(os/execute args &opts flags env)\n\n"
|
JDOC("(os/execute args &opt flags env)\n\n"
|
||||||
"Execute a program on the system and pass it string arguments. `flags` "
|
"Execute a program on the system and pass it string arguments. `flags` "
|
||||||
"is a keyword that modifies how the program will execute.\n\n"
|
"is a keyword that modifies how the program will execute.\n\n"
|
||||||
"* :e - enables passing an environment to the program. Without :e, the "
|
"* :e - enables passing an environment to the program. Without :e, the "
|
||||||
@@ -2084,7 +2105,7 @@ static const JanetReg os_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"os/spawn", os_spawn,
|
"os/spawn", os_spawn,
|
||||||
JDOC("(os/spawn args &opts flags env)\n\n"
|
JDOC("(os/spawn args &opt flags env)\n\n"
|
||||||
"Execute a program on the system and return a handle to the process. Otherwise, the "
|
"Execute a program on the system and return a handle to the process. Otherwise, the "
|
||||||
"same arguments as os/execute. Does not wait for the process.")
|
"same arguments as os/execute. Does not wait for the process.")
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -175,7 +175,14 @@ static void popstate(JanetParser *p, Janet val) {
|
|||||||
if (newtop->flags & PFLAG_CONTAINER) {
|
if (newtop->flags & PFLAG_CONTAINER) {
|
||||||
newtop->argn++;
|
newtop->argn++;
|
||||||
/* Keep track of number of values in the root state */
|
/* Keep track of number of values in the root state */
|
||||||
if (p->statecount == 1) p->pending++;
|
if (p->statecount == 1) {
|
||||||
|
p->pending++;
|
||||||
|
/* Root items are always wrapped in a tuple for source map info. */
|
||||||
|
const Janet *tup = janet_tuple_n(&val, 1);
|
||||||
|
janet_tuple_sm_line(tup) = (int32_t) top.line;
|
||||||
|
janet_tuple_sm_column(tup) = (int32_t) top.column;
|
||||||
|
val = janet_wrap_tuple(tup);
|
||||||
|
}
|
||||||
push_arg(p, val);
|
push_arg(p, val);
|
||||||
return;
|
return;
|
||||||
} else if (newtop->flags & PFLAG_READERMAC) {
|
} else if (newtop->flags & PFLAG_READERMAC) {
|
||||||
@@ -730,6 +737,19 @@ const char *janet_parser_error(JanetParser *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Janet janet_parser_produce(JanetParser *parser) {
|
Janet janet_parser_produce(JanetParser *parser) {
|
||||||
|
Janet ret;
|
||||||
|
size_t i;
|
||||||
|
if (parser->pending == 0) return janet_wrap_nil();
|
||||||
|
ret = janet_unwrap_tuple(parser->args[0])[0];
|
||||||
|
for (i = 1; i < parser->argcount; i++) {
|
||||||
|
parser->args[i - 1] = parser->args[i];
|
||||||
|
}
|
||||||
|
parser->pending--;
|
||||||
|
parser->argcount--;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Janet janet_parser_produce_wrapped(JanetParser *parser) {
|
||||||
Janet ret;
|
Janet ret;
|
||||||
size_t i;
|
size_t i;
|
||||||
if (parser->pending == 0) return janet_wrap_nil();
|
if (parser->pending == 0) return janet_wrap_nil();
|
||||||
@@ -910,8 +930,13 @@ static Janet cfun_parse_insert(int32_t argc, Janet *argv) {
|
|||||||
if (s->flags & PFLAG_COMMENT) s--;
|
if (s->flags & PFLAG_COMMENT) s--;
|
||||||
if (s->flags & PFLAG_CONTAINER) {
|
if (s->flags & PFLAG_CONTAINER) {
|
||||||
s->argn++;
|
s->argn++;
|
||||||
if (p->statecount == 1) p->pending++;
|
if (p->statecount == 1) {
|
||||||
push_arg(p, argv[1]);
|
p->pending++;
|
||||||
|
Janet tup = janet_wrap_tuple(janet_tuple_n(argv + 1, 1));
|
||||||
|
push_arg(p, tup);
|
||||||
|
} else {
|
||||||
|
push_arg(p, argv[1]);
|
||||||
|
}
|
||||||
} else if (s->flags & (PFLAG_STRING | PFLAG_LONGSTRING)) {
|
} else if (s->flags & (PFLAG_STRING | PFLAG_LONGSTRING)) {
|
||||||
const uint8_t *str = janet_to_string(argv[1]);
|
const uint8_t *str = janet_to_string(argv[1]);
|
||||||
int32_t slen = janet_string_length(str);
|
int32_t slen = janet_string_length(str);
|
||||||
@@ -980,9 +1005,13 @@ static Janet cfun_parse_error(int32_t argc, Janet *argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Janet cfun_parse_produce(int32_t argc, Janet *argv) {
|
static Janet cfun_parse_produce(int32_t argc, Janet *argv) {
|
||||||
janet_fixarity(argc, 1);
|
janet_arity(argc, 1, 2);
|
||||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parser_type);
|
JanetParser *p = janet_getabstract(argv, 0, &janet_parser_type);
|
||||||
return janet_parser_produce(p);
|
if (argc == 2 && janet_truthy(argv[1])) {
|
||||||
|
return janet_parser_produce_wrapped(p);
|
||||||
|
} else {
|
||||||
|
return janet_parser_produce(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Janet cfun_parse_flush(int32_t argc, Janet *argv) {
|
static Janet cfun_parse_flush(int32_t argc, Janet *argv) {
|
||||||
@@ -1217,10 +1246,12 @@ static const JanetReg parse_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"parser/produce", cfun_parse_produce,
|
"parser/produce", cfun_parse_produce,
|
||||||
JDOC("(parser/produce parser)\n\n"
|
JDOC("(parser/produce parser &opt wrap)\n\n"
|
||||||
"Dequeue the next value in the parse queue. Will return nil if "
|
"Dequeue the next value in the parse queue. Will return nil if "
|
||||||
"no parsed values are in the queue, otherwise will dequeue the "
|
"no parsed values are in the queue, otherwise will dequeue the "
|
||||||
"next value.")
|
"next value. If `wrap` is truthy, will return a 1-element tuple that "
|
||||||
|
"wraps the result. This tuple can be used for source-mapping "
|
||||||
|
"purposes.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"parser/consume", cfun_parse_consume,
|
"parser/consume", cfun_parse_consume,
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ tail:
|
|||||||
const uint8_t *next_text;
|
const uint8_t *next_text;
|
||||||
CapState cs = cap_save(s);
|
CapState cs = cap_save(s);
|
||||||
down1(s);
|
down1(s);
|
||||||
while (text < s->text_end) {
|
while (text <= s->text_end) {
|
||||||
CapState cs2 = cap_save(s);
|
CapState cs2 = cap_save(s);
|
||||||
next_text = peg_rule(s, rule_a, text);
|
next_text = peg_rule(s, rule_a, text);
|
||||||
if (next_text) {
|
if (next_text) {
|
||||||
@@ -296,7 +296,7 @@ tail:
|
|||||||
text++;
|
text++;
|
||||||
}
|
}
|
||||||
up1(s);
|
up1(s);
|
||||||
if (text >= s->text_end) {
|
if (text > s->text_end) {
|
||||||
cap_load(s, cs);
|
cap_load(s, cs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -596,6 +596,30 @@ tail:
|
|||||||
return text + width;
|
return text + width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case RULE_UNREF: {
|
||||||
|
int32_t tcap = s->tags->count;
|
||||||
|
down1(s);
|
||||||
|
const uint8_t *result = peg_rule(s, s->bytecode + rule[1], text);
|
||||||
|
up1(s);
|
||||||
|
if (!result) return NULL;
|
||||||
|
int32_t final_tcap = s->tags->count;
|
||||||
|
/* Truncate tagged captures to not include items of the given tag */
|
||||||
|
int32_t w = tcap;
|
||||||
|
/* If no tag is given, drop ALL tagged captures */
|
||||||
|
if (rule[2]) {
|
||||||
|
for (int32_t i = tcap; i < final_tcap; i++) {
|
||||||
|
if (s->tags->data[i] != (0xFF & rule[2])) {
|
||||||
|
s->tags->data[w] = s->tags->data[i];
|
||||||
|
s->tagged_captures->data[w] = s->tagged_captures->data[i];
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->tags->count = w;
|
||||||
|
s->tagged_captures->count = w;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -919,15 +943,15 @@ static void spec_error(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
spec_onerule(b, argc, argv, RULE_ERROR);
|
spec_onerule(b, argc, argv, RULE_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void spec_drop(Builder *b, int32_t argc, const Janet *argv) {
|
|
||||||
spec_onerule(b, argc, argv, RULE_DROP);
|
|
||||||
}
|
|
||||||
static void spec_to(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_to(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_onerule(b, argc, argv, RULE_TO);
|
spec_onerule(b, argc, argv, RULE_TO);
|
||||||
}
|
}
|
||||||
static void spec_thru(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_thru(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_onerule(b, argc, argv, RULE_THRU);
|
spec_onerule(b, argc, argv, RULE_THRU);
|
||||||
}
|
}
|
||||||
|
static void spec_drop(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
|
spec_onerule(b, argc, argv, RULE_DROP);
|
||||||
|
}
|
||||||
|
|
||||||
/* Rule of the form [rule, tag] */
|
/* Rule of the form [rule, tag] */
|
||||||
static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
|
static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
|
||||||
@@ -947,6 +971,9 @@ static void spec_accumulate(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
static void spec_group(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_group(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_cap1(b, argc, argv, RULE_GROUP);
|
spec_cap1(b, argc, argv, RULE_GROUP);
|
||||||
}
|
}
|
||||||
|
static void spec_unref(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
|
spec_cap1(b, argc, argv, RULE_UNREF);
|
||||||
|
}
|
||||||
|
|
||||||
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
peg_arity(b, argc, 1, 2);
|
peg_arity(b, argc, 1, 2);
|
||||||
@@ -1027,7 +1054,7 @@ static void spec_matchtime(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
static void spec_readint(Builder *b, int32_t argc, const Janet *argv, uint32_t mask) {
|
static void spec_readint(Builder *b, int32_t argc, const Janet *argv, uint32_t mask) {
|
||||||
peg_arity(b, argc, 1, 2);
|
peg_arity(b, argc, 1, 2);
|
||||||
Reserve r = reserve(b, 3);
|
Reserve r = reserve(b, 3);
|
||||||
uint32_t tag = (argc == 2) ? emit_tag(b, argv[3]) : 0;
|
uint32_t tag = (argc == 2) ? emit_tag(b, argv[1]) : 0;
|
||||||
int32_t width = peg_getnat(b, argv[0]);
|
int32_t width = peg_getnat(b, argv[0]);
|
||||||
if ((width < 0) || (width > JANET_MAX_READINT_WIDTH)) {
|
if ((width < 0) || (width > JANET_MAX_READINT_WIDTH)) {
|
||||||
peg_panicf(b, "width must be between 0 and %d, got %d", JANET_MAX_READINT_WIDTH, width);
|
peg_panicf(b, "width must be between 0 and %d, got %d", JANET_MAX_READINT_WIDTH, width);
|
||||||
@@ -1104,6 +1131,7 @@ static const SpecialPair peg_specials[] = {
|
|||||||
{"to", spec_to},
|
{"to", spec_to},
|
||||||
{"uint", spec_uint_le},
|
{"uint", spec_uint_le},
|
||||||
{"uint-be", spec_uint_be},
|
{"uint-be", spec_uint_be},
|
||||||
|
{"unref", spec_unref},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Compile a janet value into a rule and return the rule index. */
|
/* Compile a janet value into a rule and return the rule index. */
|
||||||
@@ -1392,6 +1420,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
|||||||
case RULE_ACCUMULATE:
|
case RULE_ACCUMULATE:
|
||||||
case RULE_GROUP:
|
case RULE_GROUP:
|
||||||
case RULE_CAPTURE:
|
case RULE_CAPTURE:
|
||||||
|
case RULE_UNREF:
|
||||||
/* [rule, tag] */
|
/* [rule, tag] */
|
||||||
if (rule[1] >= blen) goto bad;
|
if (rule[1] >= blen) goto bad;
|
||||||
op_flags[rule[1]] |= 0x01;
|
op_flags[rule[1]] |= 0x01;
|
||||||
@@ -1486,7 +1515,13 @@ static JanetPeg *make_peg(Builder *b) {
|
|||||||
static JanetPeg *compile_peg(Janet x) {
|
static JanetPeg *compile_peg(Janet x) {
|
||||||
Builder builder;
|
Builder builder;
|
||||||
builder.grammar = janet_table(0);
|
builder.grammar = janet_table(0);
|
||||||
builder.default_grammar = janet_get_core_table("default-peg-grammar");
|
builder.default_grammar = NULL;
|
||||||
|
{
|
||||||
|
Janet default_grammarv = janet_dyn("peg-grammar");
|
||||||
|
if (janet_checktype(default_grammarv, JANET_TABLE)) {
|
||||||
|
builder.default_grammar = janet_unwrap_table(default_grammarv);
|
||||||
|
}
|
||||||
|
}
|
||||||
builder.tags = janet_table(0);
|
builder.tags = janet_table(0);
|
||||||
builder.constants = NULL;
|
builder.constants = NULL;
|
||||||
builder.bytecode = NULL;
|
builder.bytecode = NULL;
|
||||||
@@ -1656,7 +1691,8 @@ static const JanetReg peg_cfuns[] = {
|
|||||||
"peg/compile", cfun_peg_compile,
|
"peg/compile", cfun_peg_compile,
|
||||||
JDOC("(peg/compile peg)\n\n"
|
JDOC("(peg/compile peg)\n\n"
|
||||||
"Compiles a peg source data structure into a <core/peg>. This will speed up matching "
|
"Compiles a peg source data structure into a <core/peg>. This will speed up matching "
|
||||||
"if the same peg will be used multiple times.")
|
"if the same peg will be used multiple times. Will also use `(dyn :peg-grammar)` to suppliment "
|
||||||
|
"the grammar of the peg for otherwise undefined peg keywords.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"peg/match", cfun_peg_match,
|
"peg/match", cfun_peg_match,
|
||||||
|
|||||||
@@ -351,6 +351,9 @@ struct pretty {
|
|||||||
int indent;
|
int indent;
|
||||||
int flags;
|
int flags;
|
||||||
int32_t bufstartlen;
|
int32_t bufstartlen;
|
||||||
|
int32_t *keysort_buffer;
|
||||||
|
int32_t keysort_capacity;
|
||||||
|
int32_t keysort_start;
|
||||||
JanetTable seen;
|
JanetTable seen;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -594,31 +597,55 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
|||||||
janet_buffer_push_cstring(S->buffer, "...");
|
janet_buffer_push_cstring(S->buffer, "...");
|
||||||
} else {
|
} else {
|
||||||
int32_t i = 0, len = 0, cap = 0;
|
int32_t i = 0, len = 0, cap = 0;
|
||||||
int first_kv_pair = 1;
|
|
||||||
const JanetKV *kvs = NULL;
|
const JanetKV *kvs = NULL;
|
||||||
int counter = 0;
|
|
||||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||||
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
||||||
janet_buffer_push_u8(S->buffer, ' ');
|
janet_buffer_push_u8(S->buffer, ' ');
|
||||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||||
for (i = 0; i < cap; i++) {
|
int32_t ks_start = S->keysort_start;
|
||||||
if (!janet_checktype(kvs[i].key, JANET_NIL)) {
|
|
||||||
if (counter == JANET_PRETTY_DICT_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
/* Ensure buffer is large enough to sort keys. */
|
||||||
print_newline(S, 0);
|
int truncated = 0;
|
||||||
janet_buffer_push_cstring(S->buffer, "...");
|
int64_t mincap = (int64_t) len + (int64_t) ks_start;
|
||||||
break;
|
if (mincap > INT32_MAX) {
|
||||||
}
|
truncated = 1;
|
||||||
if (first_kv_pair) {
|
len = 0;
|
||||||
first_kv_pair = 0;
|
mincap = ks_start;
|
||||||
} else {
|
}
|
||||||
print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
|
||||||
}
|
if (S->keysort_capacity < mincap) {
|
||||||
janet_pretty_one(S, kvs[i].key, 0);
|
if (mincap >= INT32_MAX / 2) {
|
||||||
janet_buffer_push_u8(S->buffer, ' ');
|
S->keysort_capacity = INT32_MAX;
|
||||||
janet_pretty_one(S, kvs[i].value, 1);
|
} else {
|
||||||
counter++;
|
S->keysort_capacity = mincap * 2;
|
||||||
|
}
|
||||||
|
S->keysort_buffer = janet_srealloc(S->keysort_buffer, sizeof(int32_t) * S->keysort_capacity);
|
||||||
|
if (NULL == S->keysort_buffer) {
|
||||||
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
janet_sorted_keys(kvs, cap, S->keysort_buffer + ks_start);
|
||||||
|
S->keysort_start += len;
|
||||||
|
if (!(S->flags & JANET_PRETTY_NOTRUNC) && (len > JANET_PRETTY_DICT_LIMIT)) {
|
||||||
|
len = JANET_PRETTY_DICT_LIMIT;
|
||||||
|
truncated = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (i) print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
||||||
|
int32_t j = S->keysort_buffer[i + ks_start];
|
||||||
|
janet_pretty_one(S, kvs[j].key, 0);
|
||||||
|
janet_buffer_push_u8(S->buffer, ' ');
|
||||||
|
janet_pretty_one(S, kvs[j].value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (truncated) {
|
||||||
|
print_newline(S, 0);
|
||||||
|
janet_buffer_push_cstring(S->buffer, "...");
|
||||||
|
}
|
||||||
|
|
||||||
|
S->keysort_start = ks_start;
|
||||||
}
|
}
|
||||||
S->indent -= 2;
|
S->indent -= 2;
|
||||||
S->depth++;
|
S->depth++;
|
||||||
@@ -641,6 +668,9 @@ static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Jan
|
|||||||
S.indent = 0;
|
S.indent = 0;
|
||||||
S.flags = flags;
|
S.flags = flags;
|
||||||
S.bufstartlen = startlen;
|
S.bufstartlen = startlen;
|
||||||
|
S.keysort_capacity = 0;
|
||||||
|
S.keysort_buffer = NULL;
|
||||||
|
S.keysort_start = 0;
|
||||||
janet_table_init(&S.seen, 10);
|
janet_table_init(&S.seen, 10);
|
||||||
janet_pretty_one(&S, x, 0);
|
janet_pretty_one(&S, x, 0);
|
||||||
janet_table_deinit(&S.seen);
|
janet_table_deinit(&S.seen);
|
||||||
@@ -663,6 +693,9 @@ static JanetBuffer *janet_jdn_(JanetBuffer *buffer, int depth, Janet x, int32_t
|
|||||||
S.indent = 0;
|
S.indent = 0;
|
||||||
S.flags = 0;
|
S.flags = 0;
|
||||||
S.bufstartlen = startlen;
|
S.bufstartlen = startlen;
|
||||||
|
S.keysort_capacity = 0;
|
||||||
|
S.keysort_buffer = NULL;
|
||||||
|
S.keysort_start = 0;
|
||||||
janet_table_init(&S.seen, 10);
|
janet_table_init(&S.seen, 10);
|
||||||
int res = print_jdn_one(&S, x, depth);
|
int res = print_jdn_one(&S, x, depth);
|
||||||
janet_table_deinit(&S.seen);
|
janet_table_deinit(&S.seen);
|
||||||
@@ -822,7 +855,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
|||||||
case 'P':
|
case 'P':
|
||||||
case 'p': { /* janet pretty , precision = depth */
|
case 'p': { /* janet pretty , precision = depth */
|
||||||
int depth = atoi(precision);
|
int depth = atoi(precision);
|
||||||
if (depth < 1) depth = 4;
|
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
||||||
char d = c[-1];
|
char d = c[-1];
|
||||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||||
@@ -974,7 +1007,7 @@ void janet_buffer_format(
|
|||||||
case 'P':
|
case 'P':
|
||||||
case 'p': { /* janet pretty , precision = depth */
|
case 'p': { /* janet pretty , precision = depth */
|
||||||
int depth = atoi(precision);
|
int depth = atoi(precision);
|
||||||
if (depth < 1) depth = 4;
|
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
||||||
char d = strfrmt[-1];
|
char d = strfrmt[-1];
|
||||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ static JANET_THREAD_LOCAL JanetTable *janet_vm_thread_decode = NULL;
|
|||||||
static JanetTable *janet_thread_get_decode(void) {
|
static JanetTable *janet_thread_get_decode(void) {
|
||||||
if (janet_vm_thread_decode == NULL) {
|
if (janet_vm_thread_decode == NULL) {
|
||||||
janet_vm_thread_decode = janet_get_core_table("load-image-dict");
|
janet_vm_thread_decode = janet_get_core_table("load-image-dict");
|
||||||
|
if (NULL == janet_vm_thread_decode) {
|
||||||
|
janet_vm_thread_decode = janet_table(0);
|
||||||
|
}
|
||||||
janet_gcroot(janet_wrap_table(janet_vm_thread_decode));
|
janet_gcroot(janet_wrap_table(janet_vm_thread_decode));
|
||||||
}
|
}
|
||||||
return janet_vm_thread_decode;
|
return janet_vm_thread_decode;
|
||||||
@@ -520,7 +523,7 @@ static int thread_worker(JanetMailboxPair *pair) {
|
|||||||
janet_stacktrace(fiber, out);
|
janet_stacktrace(fiber, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JANET_NET
|
#ifdef JANET_EV
|
||||||
janet_loop();
|
janet_loop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -602,6 +602,38 @@ JanetTable *janet_get_core_table(const char *name) {
|
|||||||
return janet_unwrap_table(out);
|
return janet_unwrap_table(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sort keys of a dictionary type */
|
||||||
|
int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer) {
|
||||||
|
|
||||||
|
/* First, put populated indices into index_buffer */
|
||||||
|
int32_t next_index = 0;
|
||||||
|
for (int32_t i = 0; i < cap; i++) {
|
||||||
|
if (!janet_checktype(dict[i].key, JANET_NIL)) {
|
||||||
|
index_buffer[next_index++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, sort those (simple insertion sort here for now) */
|
||||||
|
for (int32_t i = 1; i < next_index; i++) {
|
||||||
|
int32_t index_to_insert = index_buffer[i];
|
||||||
|
Janet lhs = dict[index_to_insert].key;
|
||||||
|
for (int32_t j = i - 1; j >= 0; j--) {
|
||||||
|
index_buffer[j + 1] = index_buffer[j];
|
||||||
|
Janet rhs = dict[index_buffer[j]].key;
|
||||||
|
if (janet_compare(lhs, rhs) >= 0) {
|
||||||
|
index_buffer[j + 1] = index_to_insert;
|
||||||
|
break;
|
||||||
|
} else if (j == 0) {
|
||||||
|
index_buffer[0] = index_to_insert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return number of indices found */
|
||||||
|
return next_index;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Clock shims for various platforms */
|
/* Clock shims for various platforms */
|
||||||
#ifdef JANET_GETTIME
|
#ifdef JANET_GETTIME
|
||||||
/* For macos */
|
/* For macos */
|
||||||
|
|||||||
@@ -108,6 +108,11 @@ void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cf
|
|||||||
int janet_gettime(struct timespec *spec);
|
int janet_gettime(struct timespec *spec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* strdup */
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
#define strdup(x) _strdup(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR)
|
#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR)
|
||||||
|
|
||||||
/* Initialize builtin libraries */
|
/* Initialize builtin libraries */
|
||||||
|
|||||||
@@ -307,18 +307,14 @@ int32_t janet_hash(Janet x) {
|
|||||||
hash = janet_struct_hash(janet_unwrap_struct(x));
|
hash = janet_struct_hash(janet_unwrap_struct(x));
|
||||||
break;
|
break;
|
||||||
case JANET_NUMBER: {
|
case JANET_NUMBER: {
|
||||||
double num = janet_unwrap_number(x);
|
union {
|
||||||
if (isnan(num) || isinf(num) || num == 0) {
|
double d;
|
||||||
hash = 0;
|
uint64_t u;
|
||||||
} else {
|
} as;
|
||||||
hash = (int32_t)num;
|
as.d = janet_unwrap_number(x);
|
||||||
hash = ((hash >> 16) ^ hash) * 0x45d9f3b;
|
uint32_t lo = (uint32_t)(as.u & 0xFFFFFFFF);
|
||||||
hash = ((hash >> 16) ^ hash) * 0x45d9f3b;
|
uint32_t hi = (uint32_t)(as.u >> 32);
|
||||||
hash = (hash >> 16) ^ hash;
|
hash = (int32_t)(hi ^ (lo >> 3));
|
||||||
|
|
||||||
uint32_t lo = (uint32_t)(janet_u64(x) & 0xFFFFFFFF);
|
|
||||||
hash ^= lo + 0x9e3779b9 + (hash << 6) + (hash >> 2);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JANET_ABSTRACT: {
|
case JANET_ABSTRACT: {
|
||||||
|
|||||||
@@ -202,6 +202,20 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
|||||||
vm_checkgc_pcnext();\
|
vm_checkgc_pcnext();\
|
||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
|
#define vm_compop_imm(op) \
|
||||||
|
{\
|
||||||
|
Janet op1 = stack[B];\
|
||||||
|
if (janet_checktype(op1, JANET_NUMBER)) {\
|
||||||
|
double x1 = janet_unwrap_number(op1);\
|
||||||
|
double x2 = (double) CS; \
|
||||||
|
stack[A] = janet_wrap_boolean(x1 op x2);\
|
||||||
|
vm_pcnext();\
|
||||||
|
} else {\
|
||||||
|
vm_commit();\
|
||||||
|
stack[A] = janet_wrap_boolean(janet_compare(op1, janet_wrap_integer(CS)) op 0);\
|
||||||
|
vm_checkgc_pcnext();\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
/* Trace a function call */
|
/* Trace a function call */
|
||||||
static void vm_do_trace(JanetFunction *func, int32_t argc, const Janet *argv) {
|
static void vm_do_trace(JanetFunction *func, int32_t argc, const Janet *argv) {
|
||||||
@@ -780,8 +794,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_compop( <=);
|
vm_compop( <=);
|
||||||
|
|
||||||
VM_OP(JOP_LESS_THAN_IMMEDIATE)
|
VM_OP(JOP_LESS_THAN_IMMEDIATE)
|
||||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) < CS);
|
vm_compop_imm( <);
|
||||||
vm_pcnext();
|
|
||||||
|
|
||||||
VM_OP(JOP_GREATER_THAN)
|
VM_OP(JOP_GREATER_THAN)
|
||||||
vm_compop( >);
|
vm_compop( >);
|
||||||
@@ -790,15 +803,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_compop( >=);
|
vm_compop( >=);
|
||||||
|
|
||||||
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
|
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
|
||||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) > CS);
|
vm_compop_imm( >);
|
||||||
vm_pcnext();
|
|
||||||
|
|
||||||
VM_OP(JOP_EQUALS)
|
VM_OP(JOP_EQUALS)
|
||||||
stack[A] = janet_wrap_boolean(janet_equals(stack[B], stack[C]));
|
stack[A] = janet_wrap_boolean(janet_equals(stack[B], stack[C]));
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_EQUALS_IMMEDIATE)
|
VM_OP(JOP_EQUALS_IMMEDIATE)
|
||||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) == CS);
|
stack[A] = janet_wrap_boolean(janet_unwrap_number(stack[B]) == (double) CS);
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_NOT_EQUALS)
|
VM_OP(JOP_NOT_EQUALS)
|
||||||
@@ -806,7 +818,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_NOT_EQUALS_IMMEDIATE)
|
VM_OP(JOP_NOT_EQUALS_IMMEDIATE)
|
||||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) != CS);
|
stack[A] = janet_wrap_boolean(janet_unwrap_number(stack[B]) != (double) CS);
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_COMPARE)
|
VM_OP(JOP_COMPARE)
|
||||||
@@ -1276,7 +1288,14 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
|||||||
/* Push frame */
|
/* Push frame */
|
||||||
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
||||||
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
||||||
janet_panicf("arity mismatch in %v", janet_wrap_function(fun));
|
int32_t min = fun->def->min_arity;
|
||||||
|
int32_t max = fun->def->max_arity;
|
||||||
|
Janet funv = janet_wrap_function(fun);
|
||||||
|
if (min == max && min != argc)
|
||||||
|
janet_panicf("arity mismatch in %v, expected %d, got %d", funv, min, argc);
|
||||||
|
if (min >= 0 && argc < min)
|
||||||
|
janet_panicf("arity mismatch in %v, expected at least %d, got %d", funv, min, argc);
|
||||||
|
janet_panicf("arity mismatch in %v, expected at most %d, got %d", funv, max, argc);
|
||||||
}
|
}
|
||||||
janet_fiber_frame(janet_vm_fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
janet_fiber_frame(janet_vm_fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
||||||
|
|
||||||
@@ -1359,6 +1378,7 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
|
|||||||
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
||||||
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
||||||
*out = in;
|
*out = in;
|
||||||
|
janet_fiber_set_status(fiber, sig);
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
/* Check if we need any special handling for certain opcodes */
|
/* Check if we need any special handling for certain opcodes */
|
||||||
@@ -1398,23 +1418,23 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
|
|||||||
|
|
||||||
/* Save global state */
|
/* Save global state */
|
||||||
JanetTryState tstate;
|
JanetTryState tstate;
|
||||||
JanetSignal signal = janet_try(&tstate);
|
JanetSignal sig = janet_try(&tstate);
|
||||||
if (!signal) {
|
if (!sig) {
|
||||||
/* Normal setup */
|
/* Normal setup */
|
||||||
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
|
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
|
||||||
janet_vm_fiber = fiber;
|
janet_vm_fiber = fiber;
|
||||||
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
||||||
signal = run_vm(fiber, in);
|
sig = run_vm(fiber, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore */
|
/* Restore */
|
||||||
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
||||||
janet_fiber_set_status(fiber, signal);
|
janet_fiber_set_status(fiber, sig);
|
||||||
janet_restore(&tstate);
|
janet_restore(&tstate);
|
||||||
fiber->last_value = tstate.payload;
|
fiber->last_value = tstate.payload;
|
||||||
*out = tstate.payload;
|
*out = tstate.payload;
|
||||||
|
|
||||||
return signal;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter the main vm loop */
|
/* Enter the main vm loop */
|
||||||
|
|||||||
@@ -1367,6 +1367,7 @@ JANET_API void janet_parser_deinit(JanetParser *parser);
|
|||||||
JANET_API void janet_parser_consume(JanetParser *parser, uint8_t c);
|
JANET_API void janet_parser_consume(JanetParser *parser, uint8_t c);
|
||||||
JANET_API enum JanetParserStatus janet_parser_status(JanetParser *parser);
|
JANET_API enum JanetParserStatus janet_parser_status(JanetParser *parser);
|
||||||
JANET_API Janet janet_parser_produce(JanetParser *parser);
|
JANET_API Janet janet_parser_produce(JanetParser *parser);
|
||||||
|
JANET_API Janet janet_parser_produce_wrapped(JanetParser *parser);
|
||||||
JANET_API const char *janet_parser_error(JanetParser *parser);
|
JANET_API const char *janet_parser_error(JanetParser *parser);
|
||||||
JANET_API void janet_parser_flush(JanetParser *parser);
|
JANET_API void janet_parser_flush(JanetParser *parser);
|
||||||
JANET_API void janet_parser_eof(JanetParser *parser);
|
JANET_API void janet_parser_eof(JanetParser *parser);
|
||||||
@@ -1406,6 +1407,7 @@ JANET_API JanetCompileResult janet_compile(Janet source, JanetTable *env, JanetS
|
|||||||
|
|
||||||
/* Get the default environment for janet */
|
/* Get the default environment for janet */
|
||||||
JANET_API JanetTable *janet_core_env(JanetTable *replacements);
|
JANET_API JanetTable *janet_core_env(JanetTable *replacements);
|
||||||
|
JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements);
|
||||||
|
|
||||||
JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_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);
|
||||||
@@ -1628,6 +1630,7 @@ 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, int32_t cap, int32_t *index_buffer);
|
||||||
|
|
||||||
/* VM functions */
|
/* VM functions */
|
||||||
JANET_API int janet_init(void);
|
JANET_API int janet_init(void);
|
||||||
@@ -1839,7 +1842,8 @@ typedef enum {
|
|||||||
RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */
|
RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */
|
||||||
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
|
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
|
||||||
RULE_LINE, /* [tag] */
|
RULE_LINE, /* [tag] */
|
||||||
RULE_COLUMN /* [tag] */
|
RULE_COLUMN, /* [tag] */
|
||||||
|
RULE_UNREF /* [rule, tag] */
|
||||||
} JanetPegOpcod;
|
} JanetPegOpcod;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -1042,19 +1042,23 @@ int main(int argc, char **argv) {
|
|||||||
janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0]));
|
janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0]));
|
||||||
|
|
||||||
/* Run startup script */
|
/* Run startup script */
|
||||||
Janet mainfun, out;
|
Janet mainfun;
|
||||||
janet_resolve(env, janet_csymbol("cli-main"), &mainfun);
|
janet_resolve(env, janet_csymbol("cli-main"), &mainfun);
|
||||||
Janet mainargs[1] = { janet_wrap_array(args) };
|
Janet mainargs[1] = { janet_wrap_array(args) };
|
||||||
JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs);
|
JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs);
|
||||||
fiber->env = env;
|
fiber->env = env;
|
||||||
|
|
||||||
|
#ifdef JANET_EV
|
||||||
|
janet_gcroot(janet_wrap_fiber(fiber));
|
||||||
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
|
janet_loop();
|
||||||
|
status = janet_fiber_status(fiber);
|
||||||
|
#else
|
||||||
|
Janet out;
|
||||||
status = janet_continue(fiber, janet_wrap_nil(), &out);
|
status = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||||
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
||||||
janet_stacktrace(fiber, out);
|
janet_stacktrace(fiber, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JANET_EV
|
|
||||||
status = JANET_SIGNAL_OK;
|
|
||||||
janet_loop();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Deinitialize vm */
|
/* Deinitialize vm */
|
||||||
|
|||||||
@@ -294,4 +294,25 @@
|
|||||||
(sort (mapcat (fn [[x y z]] [z y x]) (partition 3 (range 99))))) "sort 5")
|
(sort (mapcat (fn [[x y z]] [z y x]) (partition 3 (range 99))))) "sort 5")
|
||||||
(assert (<= ;(sort (map (fn [x] (math/random)) (range 1000)))) "sort 6")
|
(assert (<= ;(sort (map (fn [x] (math/random)) (range 1000)))) "sort 6")
|
||||||
|
|
||||||
|
# And and or
|
||||||
|
|
||||||
|
(assert (= (and true true) true) "and true true")
|
||||||
|
(assert (= (and true false) false) "and true false")
|
||||||
|
(assert (= (and false true) false) "and false true")
|
||||||
|
(assert (= (and true true true) true) "and true true true")
|
||||||
|
(assert (= (and 0 1 2) 2) "and 0 1 2")
|
||||||
|
(assert (= (and 0 1 nil) nil) "and 0 1 nil")
|
||||||
|
(assert (= (and 1) 1) "and 1")
|
||||||
|
(assert (= (and) true) "and with no arguments")
|
||||||
|
|
||||||
|
(assert (= (or true true) true) "or true true")
|
||||||
|
(assert (= (or true false) true) "or true false")
|
||||||
|
(assert (= (or false true) true) "or false true")
|
||||||
|
(assert (= (or false false) false) "or false true")
|
||||||
|
(assert (= (or true true false) true) "or true true false")
|
||||||
|
(assert (= (or 0 1 2) 0) "or 0 1 2")
|
||||||
|
(assert (= (or nil 1 2) 1) "or nil 1 2")
|
||||||
|
(assert (= (or 1) 1) "or 1")
|
||||||
|
(assert (= (or) nil) "or with no arguments")
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
@@ -473,4 +473,24 @@
|
|||||||
|
|
||||||
(check-deep '(* (int 2) -1) "123" nil)
|
(check-deep '(* (int 2) -1) "123" nil)
|
||||||
|
|
||||||
|
# to/thru bug
|
||||||
|
(check-deep '(to -1) "aaaa" @[])
|
||||||
|
(check-deep '(thru -1) "aaaa" @[])
|
||||||
|
(check-deep ''(to -1) "aaaa" @["aaaa"])
|
||||||
|
(check-deep ''(thru -1) "aaaa" @["aaaa"])
|
||||||
|
(check-deep '(to "b") "aaaa" nil)
|
||||||
|
(check-deep '(thru "b") "aaaa" nil)
|
||||||
|
|
||||||
|
# unref
|
||||||
|
(def grammar
|
||||||
|
(peg/compile
|
||||||
|
~{:main (* :tagged -1)
|
||||||
|
:tagged (unref (replace (* :open-tag :value :close-tag) ,struct))
|
||||||
|
:open-tag (* (constant :tag) "<" (capture :w+ :tag-name) ">")
|
||||||
|
:value (* (constant :value) (group (any (+ :tagged :untagged))))
|
||||||
|
:close-tag (* "</" (backmatch :tag-name) ">")
|
||||||
|
:untagged (capture (any (if-not "<" 1)))}))
|
||||||
|
(check-deep grammar "<p><em>foobar</em></p>" @[{:tag "p" :value @[{:tag "em" :value @["foobar"]}]}])
|
||||||
|
(check-deep grammar "<p>foobar</p>" @[{:tag "p" :value @["foobar"]}])
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
@@ -320,4 +320,8 @@
|
|||||||
(array/push a x))
|
(array/push a x))
|
||||||
(assert (deep= (range 4) a) "eachk 1")
|
(assert (deep= (range 4) a) "eachk 1")
|
||||||
|
|
||||||
|
|
||||||
|
(tracev (def my-unique-var-name true))
|
||||||
|
(assert my-unique-var-name "tracev upscopes")
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
@@ -137,4 +137,28 @@
|
|||||||
(assert (deep= (string/split "qq" "1qqqqz") @["1" "" "z"]) "string/split 1")
|
(assert (deep= (string/split "qq" "1qqqqz") @["1" "" "z"]) "string/split 1")
|
||||||
(assert (deep= (string/split "aa" "aaa") @["" "a"]) "string/split 2")
|
(assert (deep= (string/split "aa" "aaa") @["" "a"]) "string/split 2")
|
||||||
|
|
||||||
|
# Comparisons
|
||||||
|
(assert (> 1e23 100) "less than immediate 1")
|
||||||
|
(assert (> 1e23 1000) "less than immediate 2")
|
||||||
|
(assert (< 100 1e23) "greater than immediate 1")
|
||||||
|
(assert (< 1000 1e23) "greater than immediate 2")
|
||||||
|
|
||||||
|
# os/execute with environment variables
|
||||||
|
(assert (= 0 (os/execute [(dyn :executable) "-e" "(+ 1 2 3)"] :pe {"HELLO" "WORLD"})) "os/execute with env")
|
||||||
|
|
||||||
|
# Regression #638
|
||||||
|
(compwhen
|
||||||
|
(dyn 'ev/go)
|
||||||
|
(assert
|
||||||
|
(= [true :caught]
|
||||||
|
(protect
|
||||||
|
(try
|
||||||
|
(do
|
||||||
|
(ev/sleep 0)
|
||||||
|
(with-dyns []
|
||||||
|
(ev/sleep 0)
|
||||||
|
(error "oops")))
|
||||||
|
([err] :caught))))
|
||||||
|
"regression #638"))
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
Reference in New Issue
Block a user