1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-28 14:17:42 +00:00

Compare commits

...

389 Commits

Author SHA1 Message Date
Calvin Rose
87f8fe14dd Prepare for 1.16.1 release. 2021-06-09 19:08:24 -05:00
Calvin Rose
2eadb21eb7 Update changelog. 2021-05-31 16:51:53 -05:00
Calvin Rose
8b97a0dbbf Merge pull request #707 from pepe/fix-shadow
Rename level const to not to shadow line in eval1
2021-05-31 16:05:41 -05:00
Calvin Rose
69afa2a7a3 Merge branch 'master' into fix-shadow 2021-05-31 16:05:29 -05:00
Calvin Rose
da5328bae5 Merge branch 'master' of git.sr.ht:~bakpakin/janet 2021-05-31 15:14:39 -05:00
Josef Pospíšil
a4325372e2 Rename level const to not to shadow line in eval1 2021-05-31 21:51:31 +02:00
Calvin Rose
4b96b73858 Add -w and -x flags to janet for linting. 2021-05-31 14:36:25 -05:00
Calvin Rose
bbae43f259 Update copyright dates. 2021-05-31 13:46:02 -05:00
bakpakin
14fedbf063 Update copyright. 2021-05-31 09:53:52 -05:00
Calvin Rose
ab974c409d Remove externeous typedarray defines in janet.h 2021-05-31 09:23:45 -05:00
Calvin Rose
2040709585 Re-add make docs.
Wasn't hurting anything.
2021-05-30 16:44:37 -05:00
Calvin Rose
60214dc659 Update for windows compiler warning. 2021-05-30 16:42:58 -05:00
Calvin Rose
b990d77f16 Prepare for 1.16.0 release. 2021-05-30 12:15:56 -05:00
Calvin Rose
d204e06e11 Use lint information in run-context. 2021-05-30 10:33:46 -05:00
Calvin Rose
f6b37dbc77 Merge branch 'master' into linting 2021-05-30 09:34:32 -05:00
Calvin Rose
ff4d49f556 Set JANET_DIST_DIR on release. 2021-05-30 09:23:52 -05:00
Calvin Rose
dfa5fa1187 Remove some stupid shell gymnastics in Makefile. 2021-05-30 09:14:34 -05:00
Calvin Rose
1f4f69a5b6 Fix windows syntax issue. 2021-05-29 20:40:26 -05:00
Calvin Rose
84f82f5465 Remove code delimtiers from defn and defmacro. 2021-05-29 20:37:30 -05:00
Calvin Rose
c911f7c47e Address #694 - Update doc-format with more features.
Also allows having doc-format print in color with
(dyn :doc-color).
2021-05-29 20:34:22 -05:00
Calvin Rose
33c000daea Expose linting array to macros.
This has a lot of possible uses, and would let users add a macro-based
type system on top of Janet that would integrate with the usual linting
and warning system.
2021-05-28 15:15:34 -05:00
Calvin Rose
7ff204ec44 Work on system for adding compiler warnings.
This is the beginning of a system for compiler warnings. This includes
linting, deprecation notices, and other compiler warnings that are best
detected by the `compile` function and don't require the partial
evalutaion of the flychecker.
2021-05-28 15:12:05 -05:00
Calvin Rose
7c757ef3bf Make jpm configurable for environments like MinGW. 2021-05-26 10:07:11 -05:00
Calvin Rose
2db7945d6f Fix peg bug when there is no default grammar set.
This could result in a segfault when we attempt to
read from a NULL pointer.
2021-05-20 21:57:22 -05:00
Calvin Rose
81186bf262 Merge branch 'master' of github.com:janet-lang/janet 2021-05-19 18:43:50 -05:00
Calvin Rose
eeef5b0896 Add as-macro and module/add-syspath 2021-05-19 18:18:00 -05:00
Calvin Rose
8189b6fc11 Merge pull request #690 from sogaiu/specials-doc
Make doc work for special forms
2021-05-09 13:54:46 -05:00
sogaiu
e5a2df93ab Make doc work for special forms 2021-05-07 08:47:33 +09:00
Calvin Rose
c3f770da27 Fix meson build. 2021-04-29 15:59:44 -05:00
Calvin Rose
49f66a936c Merge commit 'f4c9064b79d5b32fd74e5ddf25266356c22dd53b' 2021-04-29 15:58:41 -05:00
Calvin Rose
83dda98240 Update jpm to work post patch. 2021-04-29 14:28:54 -05:00
Calvin Rose
b4ddbd0097 Address #670 - Allow modifying jpm to link to extra libraries. 2021-04-29 14:04:18 -05:00
Calvin Rose
cbe92bb985 Merge branch 'master' of github.com:janet-lang/janet 2021-04-29 13:13:55 -05:00
Calvin Rose
60c6a0d334 Add :native-deps option to jpm.
Use is like:

```
(declare-native
 :name "my-nuermical-library"
 :source @["numerical_lib.c"]
 :native-deps ["tarray"])

```

Where `tarray` is a native generated by o ne of the project
dependencies. This will lets us move more C functionality out of the
core of Janet while still allowing it's use from natives.
2021-04-29 13:11:46 -05:00
Calvin Rose
1baab5eb61 Remove typed arrays from the core.
Typed arrays will instead live in an external jpm nodule.
Also, changes have been made to `jpm` to allow other natives to use the
typedarray headers.
2021-04-29 12:33:49 -05:00
Calvin Rose
8fc8974b60 Add from-pairs to core. #683
This always creates a table, use `table/to-struct` to
create a struct.
2021-04-29 12:06:24 -05:00
Calvin Rose
ecb49c2e5e Merge pull request #688 from cjones051073/use-nsgetenviron-on-apple
Use _NSGetEnviron() on Apple
2021-04-29 12:00:35 -05:00
Chris Jones
29797b9eb0 Use _NSGetEnviron() on Apple 2021-04-27 11:54:24 +01:00
Calvin Rose
e181ee586b Prepare for 1.15.5 release. 2021-04-25 14:00:16 -05:00
Calvin Rose
7b7d742bec Add declare-headers to jpm. 2021-04-25 13:38:24 -05:00
Calvin Rose
612eaff9ff Fix #682 - Don't hardcode size of sun_path. 2021-04-15 14:57:40 -05:00
Calvin Rose
d76ef187e8 Merge pull request #681 from pyrmont/patch-2
Fix link to Introduction
2021-04-09 20:04:42 -05:00
Michael Camilleri
e01ab86a89 Fix link to Introduction 2021-04-08 16:10:24 +09:00
Calvin Rose
89b59b4ffc Merge branch 'master' of github.com:janet-lang/janet 2021-04-06 23:36:11 -05:00
Calvin Rose
e367ecf806 Update cannonical link. 2021-04-06 23:35:57 -05:00
Calvin Rose
effc9e0f33 Merge pull request #677 from uvtc/patch-1
Add note about sponsorship to README
2021-04-02 15:00:21 -05:00
John Gabriele
da06e6c6e3 Update README.md
Co-authored-by: Michael Camilleri <mike@inqk.net>
2021-03-31 21:40:30 -04:00
John Gabriele
c258bee54f Add note about sponsorship to README 2021-03-31 21:27:03 -04:00
Calvin Rose
cde4a505cf Fix #673 - check typed array index bounds as well as buffer count. 2021-03-30 21:14:42 -05:00
Calvin Rose
2802e66259 Merge branch 'master' of github.com:janet-lang/janet 2021-03-26 15:45:14 -05:00
Calvin Rose
3a3003029a Merge branch 'master' of github.com:janet-lang/janet 2021-03-26 15:44:43 -05:00
Calvin Rose
08bca8fb63 Merge branch 'master' of github.com:janet-lang/janet 2021-03-26 15:36:50 -05:00
Calvin Rose
7c7ff802fa Add net/shutdown to allow better networking with streams. 2021-03-26 15:36:25 -05:00
Calvin Rose
0945acc780 Merge pull request #672 from Luewd/cc-file-ext
Allow .cc file extension in jpm declare-native
2021-03-26 15:13:12 -05:00
Lue
64ec9f9cb6 Allow .cc file extension in jpm declare-native 2021-03-25 13:19:05 -04:00
Calvin Rose
83f7de33c0 Merge pull request #671 from pyrmont/feature.metadata
Support adding arbitrary metadata to bindings
2021-03-24 16:56:25 -05:00
Michael Camilleri
ec2d7bf349 Support adding arbitrary metadata to bindings 2021-03-24 09:38:12 +09:00
Andrew Chambers
f4c9064b79 Add config support for custom allocators. 2021-03-23 23:00:48 +13:00
Calvin Rose
8ede16dc26 Merge pull request #669 from dbready/dist_layout
Create Folder Hierarchy for Linux Release
2021-03-22 11:51:21 -05:00
Damien Ready
27e400fba3 Prepare the .tar distribution with folder layout 2021-03-20 10:53:51 -05:00
Calvin Rose
37d6cb469b Merge pull request #668 from ffontaine/master
meson.build: fix build without threads
2021-03-19 15:44:25 -05:00
Calvin Rose
100a82feb2 Version bump (development version). 2021-03-19 15:41:34 -05:00
Calvin Rose
90e5828d5d Update printing when entering debugger. 2021-03-19 15:38:46 -05:00
Calvin Rose
b3e80308d4 Change inheritance rule. 2021-03-19 15:18:19 -05:00
Fabrice Fontaine
a7abe11105 meson.build: fix build without threads
Fix the following build failure with -Dsingle_threaded=true on embedded
toolchains without pthread:

FAILED: janet.p/meson-generated_.._janet.c.o
/home/buildroot/autobuild/run/instance-3/output-1/host/bin/arm-linux-gcc -Ijanet.p -I. -I.. -I../src/include -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -std=c99 -O3 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -pthread -fvisibility=hidden -MD -MQ janet.p/meson-generated_.._janet.c.o -MF janet.p/meson-generated_.._janet.c.o.d -o janet.p/meson-generated_.._janet.c.o -c janet.c
In file included from /home/buildroot/autobuild/run/instance-3/output-1/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include/stdlib.h:24,
                 from ../src/include/janet.h:300,
                 from src/core/features.h:57:
/home/buildroot/autobuild/run/instance-3/output-1/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include/features.h:218:5: warning: #warning requested reentrant code, but thread support was disabled [-Wcpp]
  218 | #   warning requested reentrant code, but thread support was disabled
      |     ^~~~~~~
src/core/ev.c:39:10: fatal error: pthread.h: No such file or directory

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2021-03-18 09:13:22 +01:00
Calvin Rose
3c63a48df4 (#667) Add constant inlining for tuples and structs.
Structs and tuples composed entirely out of constant values
will themselves be considered constant values during compilation.
This reduces the amount of generated code.
2021-03-16 20:52:55 -05:00
Calvin Rose
fcb88e5a98 Merge branch 'master' of github.com:janet-lang/janet 2021-03-16 20:12:47 -05:00
Calvin Rose
a467b34de4 Prepare for 1.15.4 release. 2021-03-16 20:12:33 -05:00
Calvin Rose
a24cc77ff8 Merge pull request #666 from pyrmont/patch-1
Remove instructions to add tags
2021-03-14 16:16:42 -05:00
Michael Camilleri
d6675d9909 Remove instructions to add tags 2021-03-14 15:07:33 +09:00
Calvin Rose
fa163093d2 Update CHANGELOG.md 2021-03-13 19:22:47 -06:00
Calvin Rose
e70f64e23d Sort keys initial. 2021-03-13 19:17:07 -06:00
Calvin Rose
6f605f8141 Update pretty printing default depth. 2021-03-13 17:43:19 -06:00
Calvin Rose
d9419ef994 Merge pull request #660 from ffontaine/master
meson.build: fix static build
2021-03-12 19:06:33 -06:00
Calvin Rose
7e8639a682 Merge pull request #664 from leahneukirchen/meson-pkgconfig2
Fix include path when using meson
2021-03-12 17:11:54 -06:00
Leah Neukirchen
452b303b4c Fix include path when using meson
Closes #661.
2021-03-12 18:49:50 +01:00
Fabrice Fontaine
b0f1a4967d meson.build: fix static build
Don't enforce -rdynamic when building statically to avoid the following
build failure:

/home/giuliobenetti/autobuild/run/instance-2/output-1/host/bin/arm-linux-gcc  -o janet janet.p/meson-generated_.._janet.c.o janet.p/src_mainclient_shell.c.o -Wl,--as-needed -Wl,--allow-shlib-undefined -Wl,-O1 -rdynamic -Wl,-elf2flt -static -Wl,--start-group -lm -ldl -Wl,--end-group -pthread
arm-linux-gcc.br_real: error: unrecognized command line option '-rdynamic'

Fixes:
 - http://autobuild.buildroot.org/results/a4f927f73a7b80e65408c992d7b6023609a1eacc

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2021-03-12 08:46:05 +01:00
Calvin Rose
9eb4c59c04 Require opt-in behavior per script.
This means a binscript needs to indicate that it is a Janet script, and
then the user who is installing the script can choose whether or not to
do the magic shebang replacement.
2021-03-11 18:47:53 -06:00
Calvin Rose
0d42506cde Merge branch 'master' of github.com:janet-lang/janet 2021-03-11 18:37:54 -06:00
Calvin Rose
c8a13ce475 Add --auto-shebang option to jpm. 2021-03-11 18:37:45 -06:00
Calvin Rose
05e3467d09 Merge pull request #655 from uvtc/patch-1
Update os.c
2021-03-11 18:12:54 -06:00
Calvin Rose
90639e5068 Merge pull request #658 from pyrmont/bugfix.jpm-realpath
Fix argument passing to os/realpath in jpm
2021-03-11 18:12:38 -06:00
Calvin Rose
73c7711c78 Merge pull request #657 from ffontaine/master
meson.build: defaults to c99 for "build.c_std"
2021-03-11 18:12:25 -06:00
Calvin Rose
78f6b6a507 Add auto-shebang functionality. 2021-03-11 18:10:33 -06:00
Michael Camilleri
84f0ab5356 Fix argument passing to os/realpath in jpm 2021-03-10 17:11:12 +09:00
Fabrice Fontaine
546437d799 meson.build: defaults to c99 for "build.c_std"
Since Meson 0.51, there are special build options for "native:true"
builds, prefixed with "build.".  This change breaks cross builds
because `janet-boot/src_core_asm.c` is no longer built with `-std=c99`:

FAILED: janet-boot.p/src_core_asm.c.o
/usr/bin/gcc -Ijanet-boot.p -I. -I.. -I../src/include -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O3 -pthread -DJANET_BOOTSTRAP -MD -MQ janet-boot.p/src_core_asm.c.o -MF janet-boot.p/src_core_asm.c.o.d -o janet-boot.p/src_core_asm.c.o -c ../src/core/asm.c
../src/core/asm.c: In function 'janet_disasm_bytecode':
../src/core/asm.c:866:5: error: 'for' loop initial declarations are only allowed in C99 mode
     for (int32_t i = 0; i < def->bytecode_length; i++) {
     ^

Fixes:
 - http://autobuild.buildroot.net/results/355e0992338a8d132050517f83a3884606b00529

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2021-03-10 07:57:53 +01:00
John Gabriele
0f05aec563 Update os.c
Doc typo
2021-03-09 14:39:09 -05:00
Calvin Rose
c9097623d6 Add group-by and partition-by to the core.
Semantics are mostly emulated from Clojure.
2021-03-04 19:34:36 -06:00
Calvin Rose
6392b37c47 Merge branch 'master' of github.com:janet-lang/janet 2021-02-28 13:05:05 -06:00
Calvin Rose
4fcc8075d4 Release 1.15.3 2021-02-28 13:04:24 -06:00
Calvin Rose
b2d6a55335 Merge pull request #646 from pyrmont/bugfix.run-context-match
Fix call to match in run-context
2021-02-28 10:48:43 -06:00
Michael Camilleri
1fea5f8fe7 Fix call to match in run-context 2021-02-28 14:23:17 +09:00
Calvin Rose
d3e52a2afb Fix makefile to attach build identifier. 2021-02-27 19:50:31 -06:00
Calvin Rose
d6ea1989cc Merge branch 'master' of github.com:janet-lang/janet 2021-02-26 17:29:25 -06:00
Calvin Rose
96513665d6 Address #641 - add undef combinator.
The (undef rule :tag) combinator lets a user "scope" tagged captures.
After the rule has matched, all captures with tag :tag can no longer be
refered to by their tag. However, such captures from outside
rule are kept as is. If no tag is given, all tagged captures from rule
are unreferenced. Note that this doesn't `drop` the captures, merely
removes their association with the tag. This means subsequent calls to
`backref` and `backmatch` will no longer "see" these tagged captures.
2021-02-26 17:25:09 -06:00
Calvin Rose
b795d13f61 Merge pull request #642 from pyrmont/feature.run-context-location
Allow source location in run-context to be updated
2021-02-26 16:36:03 -06:00
Calvin Rose
970f9b3981 Merge pull request #643 from uvtc/patch-1
`sort` doc
2021-02-26 16:28:27 -06:00
John Gabriele
be7dab4d17 Update boot.janet 2021-02-23 22:30:42 -05:00
John Gabriele
0e44ce5cba Update boot.janet 2021-02-23 22:26:53 -05:00
John Gabriele
1f8c2781dd sort doc
Clarify doc for `sort` and `sorted`. Also in `sort`, changed arg name.
2021-02-23 22:24:59 -05:00
Michael Camilleri
f381a9c773 Check that new source location is a string 2021-02-22 12:50:44 +09:00
Michael Camilleri
855a9a01fc Allow source location in run-context to be updated 2021-02-22 12:38:56 +09:00
Calvin Rose
a5f237993d Don't fail testing when ev disabled. 2021-02-20 10:56:54 -06:00
Calvin Rose
c68264802a Fix #638 - update fiber status in certain cases.
This fixes a regression from changes to janet_try. In some cases, we
would not update the status of a fiber when signaling, which left the
fiber's status as whatever it had previously. This could lead to strange
control flow issues.
2021-02-20 10:55:16 -06:00
Calvin Rose
742469a8bc Address #640.
Allow for a zero length match at the end of a string when using the
to or thru combinators.
2021-02-19 16:10:03 -06:00
Calvin Rose
92928d5c4f Update definition of or. 2021-02-16 17:00:27 -06:00
Calvin Rose
8320e25d64 Merge pull request #639 from leahneukirchen/or
Fix or with zero arguments
2021-02-16 16:57:21 -06:00
Leah Neukirchen
c16a9d8463 Fix or with zero arguments.
The value is nil to be consistent for and/or and all/some.
Also add some tests for and/or.
2021-02-16 19:59:03 +01:00
Calvin Rose
f1819c916a Fix build error for 1.15.2 2021-02-15 10:27:19 -06:00
Calvin Rose
dd14b24d2a 1.15.1 release. 2021-02-15 10:21:22 -06:00
Calvin Rose
050d7c12a3 Prepare for 1.15.1 release. 2021-02-15 10:19:24 -06:00
Calvin Rose
7e2c433abc Fix #636 2021-02-14 14:34:52 -06:00
Calvin Rose
6713b23a65 Change behavior of empty env table passed to os/execute on windows. 2021-02-14 11:22:20 -06:00
Calvin Rose
60078e7950 Change os/execute implementation for windows. 2021-02-14 11:04:59 -06:00
Calvin Rose
69095fbb48 Merge pull request #633 from Alligator/master
Add missing argument to errorf in jpm
2021-02-10 17:51:47 -06:00
alligator
c88a3c64e3 Add missing argument to errorf 2021-02-10 22:45:43 +00:00
Calvin Rose
771b0d0ab1 Version bump. 2021-02-09 20:32:09 -06:00
Calvin Rose
c85310578b Merge pull request #632 from sogaiu/tweak-spec-readint
Tweak spec_readint
2021-02-09 17:47:25 -06:00
sogaiu
60e2992158 Tweak spec_readint 2021-02-10 08:33:46 +09:00
Calvin Rose
2795e8a8b7 Update some sr.ht configs. 2021-02-08 18:26:04 -06:00
Calvin Rose
bdf14170a4 Get ready for 1.15.0 release. 2021-02-08 18:10:46 -06:00
Calvin Rose
10dcbc639a Immediate instuctions will now call :compare method. 2021-02-08 11:53:25 -06:00
Calvin Rose
6a9bb0f4e4 Define immediate comparison instructions for non-integers.
Previous, the instructions were defined only for values that
fit into 32 bit integers for legacy reasons.
2021-02-08 11:41:48 -06:00
Calvin Rose
c941e5a8f4 Merge pull request #628 from yumaikas/master
Switch out `by` to `before?` in sort functions.
2021-02-05 18:17:52 -06:00
Calvin Rose
be91414c7a Improve error message from janet_call.
List expected arity in error messages.
2021-02-05 18:01:52 -06:00
Calvin Rose
6839b603c8 x86 32 bit on windows. 2021-02-04 23:31:04 -06:00
Andrew Owen
926b68d62e Switch out by to before? in sort functions.
Makes docstrings easier to read, and reduces confusion with sorted-by
and sort-by.
2021-02-04 22:28:46 -07:00
Calvin Rose
d374e90033 Update sort documentation. 2021-02-04 20:11:24 -06:00
Calvin Rose
b168b0758a Fix #625 - no fancy mixing in number hasing
Just hash upper 32 bits with lower 32 bits. Trying to get too fancy
was causing slowdowns in very trivial cases. Assuming that all
combinations of 64 bits in a double are equally likely (suspect but
probably not that incorrect), the obvious method of xoring the top
32 bits with the lower 32 bits gives a uniform distribution.
2021-02-04 19:37:11 -06:00
Calvin Rose
54c66ecfc0 Merge pull request #622 from sogaiu/tweak-add-paths-docstring
Tweak module/add-paths docstring
2021-02-04 19:05:34 -06:00
sogaiu
1c158bd4ff Tweak module/add-paths docstring 2021-02-03 21:11:16 +09:00
Calvin Rose
ff24143f54 Merge pull request #620 from sogaiu/marshal-doc
Tweak marshal docstring
2021-02-02 21:29:54 -06:00
Calvin Rose
dd117e81c2 Fix parser/insert.
We need to add the tuple wrapping code there as well.
2021-02-02 18:55:24 -06:00
sogaiu
f4744a18c6 Tweak marshal docstring 2021-02-02 15:00:57 +09:00
Calvin Rose
259d5fabd9 Update Makefile and build_win for better builds.
Use build/c/janet.c in both to prevent accidental inclusion
of build/janet.h (which may be stale) instead of the source headers.
2021-01-31 09:59:53 -06:00
Calvin Rose
d122a75efd Cleanup boot.janet to be more like normal source code.
Don't use `undef`, just use private defines.
2021-01-31 09:08:39 -06:00
Calvin Rose
c9ea3ac304 Address #618 - clarify file/open docs. 2021-01-31 08:39:57 -06:00
Calvin Rose
c63fe6ef8a Make flycheck follow GNU standards for errors. 2021-01-30 12:51:38 -06:00
Calvin Rose
72ec89dfe9 Change output format for line+col. 2021-01-30 11:33:15 -06:00
Calvin Rose
04805d106e Simpler overflow check. 2021-01-29 20:11:38 -06:00
Calvin Rose
9aed578466 Address #616 Buffer extra overflow bug.
We should have a normal error instead of undefined behavior, wrap
around, or wait for realloc to fail.
2021-01-29 18:32:54 -06:00
Calvin Rose
77c5279296 Merge pull request #611 from subsetpark/doc-example-readme
Use a slightly clearer example of the `doc` fun in README
2021-01-24 17:25:37 -06:00
Calvin Rose
af75bf3b64 Update for sending streams to new threads. 2021-01-24 16:48:46 -06:00
Zach Smith
a5157e868b Use a slightly clearer example of the doc fun in README 2021-01-24 15:44:34 -05:00
Calvin Rose
01a3d8f932 Address #478 - Disable core in static binaries/
Add --no-core option to quickbin, as well as :no-core option
to declare executable. This doesn't use the autodetection when
making binaries, instead opting for manual intervention.
2021-01-23 17:47:41 -06:00
Calvin Rose
f22472a644 Begin work on allowing small binaries. 2021-01-23 17:08:11 -06:00
Calvin Rose
5cac8bcf9f Prepare for patch release. 2021-01-23 14:48:36 -06:00
Calvin Rose
a2801fbef9 Fix #610 - POLLHUP should cause us to continue reading. 2021-01-23 14:26:24 -06:00
Calvin Rose
0b14e913da Merge branch 'master' of github.com:janet-lang/janet 2021-01-23 13:54:36 -06:00
Calvin Rose
85155bb2b4 Reference #478 Update peg/compile to use dyn for default grammar. 2021-01-23 13:54:02 -06:00
Calvin Rose
dd8de1e9ac Merge pull request #609 from yumaikas/master
Change tracev to upscope instead of using let
2021-01-22 19:02:27 -06:00
Calvin Rose
c909835b0a Update CHANGELOG. 2021-01-22 12:55:38 -06:00
Calvin Rose
a18aafedfd Merge branch 'master' of github.com:janet-lang/janet 2021-01-22 12:53:28 -06:00
Calvin Rose
317ab6df6b Add ev/thread and ev/do-thread.
- Also fix setting supervisor with net/accept-loop.
2021-01-22 12:52:45 -06:00
Andrew Owen
1fcaffe6b0 Change tracev to upscope, add test 2021-01-21 23:40:28 -07:00
Calvin Rose
3ae5c410dc Merge pull request #606 from snimmagadda/master
Replace malloc + memset with calloc.
2021-01-21 12:59:21 -06:00
Sunil Nimmagadda
381128364e Replace malloc + memset with calloc.
Fixes an overflow warning from gcc with '-Wstringop-overflow' on
NetBSD-current.
2021-01-21 19:35:57 +05:30
Calvin Rose
0acf167e84 Merge pull request #602 from pyrmont/feature.module-docstrings
Display module-level docstrings with (doc)
2021-01-20 22:11:38 -06:00
Calvin Rose
f7ca6deeb0 Merge pull request #603 from pepe/evcal-doc
Fix ev/call doc
2021-01-20 20:52:23 -06:00
Josef Pospíšil
251486e4aa Fix ev/call doc 2021-01-20 20:31:41 +01:00
Michael Camilleri
c6467be60d Conform display of path with existing display of source map info 2021-01-20 10:47:55 +09:00
Michael Camilleri
4dd512ad28 Use print-module-entry function to display docstring 2021-01-20 10:16:59 +09:00
Michael Camilleri
28076b9385 Display module-level docstrings with (doc) 2021-01-20 10:01:31 +09:00
Calvin Rose
49dcc816ae Update os/shell to be non-blocking as well. 2021-01-18 16:44:22 -06:00
Calvin Rose
fa61c70103 Release 1.14.1 2021-01-18 11:51:42 -06:00
Calvin Rose
5ee6dbcdf4 Prepare for 1.14.1 release. 2021-01-18 11:43:53 -06:00
Calvin Rose
634219da2c Fix windows swallowing IOCP events in many cases.
This fixes windows hanging on "failed" IO operations.
2021-01-17 20:41:59 -06:00
Calvin Rose
fbe3849b4b Revert change to propagate op code. 2021-01-17 15:33:42 -06:00
Calvin Rose
bd2e335063 Allow 1 argument call of debug/stacktrace
Since fibers now track the last value signaled.
2021-01-17 13:55:40 -06:00
Calvin Rose
96262e7d87 Fix integer limit docs. 2021-01-17 13:44:53 -06:00
Calvin Rose
c5da87b860 Fix broken doc format.
Many assumptions in the parsing code that could cause infinite
loops, as well as assuming things were non-nil.
2021-01-17 11:36:48 -06:00
Calvin Rose
848d4a1498 Update man page. 2021-01-16 19:40:29 -06:00
Calvin Rose
70e23df6f8 Merge branch 'master' of github.com:janet-lang/janet 2021-01-16 18:29:41 -06:00
Calvin Rose
95af205681 Merge pull request #589 from yumaikas/master
Add support for a profile.janet
2021-01-16 18:29:00 -06:00
Calvin Rose
6dfb689d1f Update versions to indicate 14.1 2021-01-16 15:54:27 -06:00
Calvin Rose
462e74ef87 Add os/proc-close to close all pipes associated with a subprocess.
This will not leak handles until the GC runs in most use cases.
2021-01-16 15:11:07 -06:00
Andrew Owen
c6aa536590 Clean up env dance 2021-01-16 12:47:50 -07:00
Calvin Rose
c79480342b Remove unused defines. 2021-01-16 07:19:28 -06:00
Calvin Rose
a1cc5ca045 Fix #593.
Also add ev/give-supervisor to the core.
2021-01-16 07:18:07 -06:00
Andrew Owen
7f74ff3dd7 Restore :source property to keep import* working at REPL 2021-01-15 02:59:17 -07:00
Andrew Owen
c4a95e9a1e Update error handling, kill a bikeshed argument 2021-01-15 01:53:14 -07:00
Andrew Owen
71f9e2b1d7 Add support for a profile.janet
Add support for a profile.janet, along with a flag for disabling it's use.
2021-01-15 01:31:23 -07:00
Calvin Rose
16fe32215b Merge pull request #584 from sogaiu/tweak-file-docs
Tweak file docs
2021-01-13 21:41:33 -06:00
Calvin Rose
dd7342a6cf Merge pull request #583 from sogaiu/tweak-debug-docs
Tweak debug/stack docs
2021-01-13 21:41:26 -06:00
Calvin Rose
35c88d10cd Merge pull request #582 from sogaiu/tweak-parser-docs
Tweak parser docs
2021-01-13 21:41:09 -06:00
Calvin Rose
42532de0eb Merge pull request #585 from sogaiu/tweak-os-docs
Tweak os docs
2021-01-13 21:41:01 -06:00
sogaiu
122e2a9378 Tweak os docs 2021-01-14 08:44:56 +09:00
sogaiu
33c9395d79 Tweak file docs 2021-01-14 08:33:04 +09:00
sogaiu
fc49aa359c Tweak debug/stack docs 2021-01-14 07:47:50 +09:00
sogaiu
fcf37942a7 Tweak parser docs 2021-01-14 07:31:20 +09:00
Calvin Rose
9b42d5a5e9 Merge pull request #579 from sogaiu/tweak-type-docs
Tweak type docs
2021-01-13 12:26:30 -06:00
Calvin Rose
ba92dfcbe9 Merge pull request #580 from sogaiu/tweak-update-docs
Tweak update docs
2021-01-13 12:26:10 -06:00
Calvin Rose
fd03603adb Merge pull request #577 from sogaiu/tweak-expand-path-docs
Tweak module/expand-path docs
2021-01-13 12:25:55 -06:00
Calvin Rose
2008ddf8a8 Merge pull request #578 from sogaiu/tweak-disasm-docs
Tweak disasm docs
2021-01-13 12:25:30 -06:00
sogaiu
c56b876bfe Tweak update docs 2021-01-13 23:04:06 +09:00
sogaiu
c4957d5dfb Tweak type docs 2021-01-13 22:59:43 +09:00
sogaiu
068bd33afb Tweak disasm docs 2021-01-13 22:27:03 +09:00
sogaiu
e9bd108be9 Tweak module/expand-path docs 2021-01-13 22:16:54 +09:00
Calvin Rose
4f2d1cdc00 Go back to a single supervisor channel per fiber.
We now also use the fiber mask to figure out which flags to wait for.
2021-01-12 21:35:28 -06:00
Calvin Rose
61cca10cf6 Allow iterating through the properties of core abstract types. 2021-01-11 23:14:07 -06:00
Calvin Rose
dfbdd17dce Add doc-of function to core for reverse documentation lookup. 2021-01-11 20:32:26 -06:00
Calvin Rose
9078d3bd37 Update CHANGELOG.md 2021-01-11 18:54:50 -06:00
Calvin Rose
5e1a8c86f9 Add more network and subprocess testing with redirection. 2021-01-11 18:32:56 -06:00
Calvin Rose
bf01bf631d More work on windows networking code.
Remove use of WSARecv and WSASend since for whatever reason
they seem suspect. We may want to revisit this later.
2021-01-11 18:00:31 -06:00
Calvin Rose
80c5ba32b5 Remove wait from CI testing for networking tests.
We want to expose any existing race conditions.
2021-01-11 15:55:12 -06:00
Calvin Rose
874cc79443 Fix #571 - fiber/status and fiber/new docstrings. 2021-01-11 15:44:46 -06:00
Calvin Rose
3883460202 Remove length checks to a number of core functions.
This lets them be more generic and implemented over a wider range of
data types, such as fibers.
2021-01-11 15:01:41 -06:00
Calvin Rose
f0dbc2e404 Fix subprocess spawning on windows.
Also fix (:read stream :all)
2021-01-11 11:10:23 -06:00
Calvin Rose
4df1ac5b23 Fix some issues in os.c to diagnose improve windows subprocess code. 2021-01-11 09:06:39 -06:00
Calvin Rose
1f6d0d342b Fix #566 - bad docstring and bad arity for net/flush. 2021-01-10 12:02:28 -06:00
Calvin Rose
4625c28e6a Merge branch 'master' of github.com:janet-lang/janet 2021-01-10 11:59:41 -06:00
Calvin Rose
5536ba20a8 Move socket setup code from ev.c to net.c 2021-01-10 11:58:47 -06:00
Calvin Rose
ef398e9036 Merge pull request #567 from Nananas/patch-1
Minor typo in ev/rselect docstring
2021-01-10 11:47:37 -06:00
Thomas Dendale
0c73c3f1cd Minor typo in ev/rselect docstring
`ev/choice` is actually called `ev/select`
2021-01-10 16:42:52 +01:00
Calvin Rose
7ae7984f3c Allow yielding from root fiber to ev loop. 2021-01-09 23:35:34 -06:00
Calvin Rose
8286b33c52 Add event-chan argument to ev/go.
The event-chan is the final piece of the puzzle for fibers, and
will be pushed to when a fiber yields to the event loop.
2021-01-09 23:33:23 -06:00
Calvin Rose
475775cc9d Add a "new_channel" for root fibers.
When new fibers are scheduled on the event loop, this new_channel
receives the newly created fibers. This lets a fiber track which fibers
have been added and let's a user implement a supervisor.

Fix formatting.
2021-01-09 18:33:40 -06:00
Calvin Rose
11067d7a56 Update module and rem operator for int types. 2021-01-09 14:47:43 -06:00
Calvin Rose
5b05da65f0 Allow wrap around on u64.
This lets some math work as expected.
2021-01-09 12:43:33 -06:00
Calvin Rose
444e630783 Fix formatting. 2021-01-09 10:14:20 -06:00
Calvin Rose
8951b8de7a Inherit the supervisor channel from the root fiber if not given. 2021-01-08 16:32:23 -06:00
Calvin Rose
2abb87eb63 Add space in docstring. 2021-01-07 18:57:13 -06:00
Calvin Rose
32e8ac912d Merge branch 'master' of github.com:janet-lang/janet 2021-01-07 18:08:08 -06:00
Calvin Rose
e403fb4652 Do not try and preload imports that are relative. 2021-01-07 18:07:47 -06:00
Calvin Rose
daa37c22f5 Merge pull request #551 from pepe/remove-redundant-do
Remove redundant do
2021-01-07 10:38:21 -06:00
Josef Pospíšil
5a2a134c95 Remove redundant do 2021-01-07 14:38:58 +01:00
Calvin Rose
b9acb6dfa5 Update CHANGELOG.md 2021-01-06 23:25:00 -06:00
Calvin Rose
4e7ad3c7ce Add initial implementation for supervisor channels.
Supervisor channels are a simple concept to more efficiently
enable dynamic, structure concurrency. When a top-level fiber
completes (or errors), it will push itself to it's supervisor
channel if it has one (instead of printing a stacktrace). This
let's another fiber poll a channel and "supervise" a set of fibers.
2021-01-06 23:19:22 -06:00
Calvin Rose
ee0e1a2342 Remove jpm.bat from windows dist.
It is still present in the MSI.
2021-01-06 19:36:37 -06:00
Calvin Rose
f206b476d1 Fix #550 - add varfn to safe forms for flycheck. 2021-01-06 17:31:08 -06:00
Calvin Rose
dd2595c53f Merge branch 'master' of github.com:janet-lang/janet 2021-01-06 17:27:50 -06:00
Calvin Rose
545df28d71 Add flycheck function to core.
Also make flychecking work with stdin out of the box.
2021-01-06 17:27:17 -06:00
Calvin Rose
16f80b78cf Merge pull request #546 from pepe/doc-thread-new-loop
Update doc for thread/new and remove ws in loop's
2021-01-05 20:31:46 -06:00
Calvin Rose
147bcce01b Merge pull request #549 from pyrmont/docs.string-find-all-typo
Fix typos in string/find-all documentation
2021-01-05 20:31:12 -06:00
Calvin Rose
f5877ac6d1 Revert makefile. 2021-01-05 20:29:50 -06:00
Calvin Rose
adc41e31f4 Address #547 - don't drop references.
Keep a separate stack for tagged references. May cause pegs to
use more memory but makes the backref and backmatch features much more
powerful.

Also disables the second stack if backref and backmatch are not used in the peg.
2021-01-05 20:27:15 -06:00
Michael Camilleri
2e555a930f Fix typos in string/find-all documentation 2021-01-06 10:14:49 +09:00
Calvin Rose
bcba0c0279 Fix #548 - string/split bug.
Also update docstrings for string/find. The 'skipping'
behavior that was documented only applies to to string/replace-all.
2021-01-05 18:54:51 -06:00
Josef Pospíšil
c7f382add6 Update doc for thread/new and remove ws in loop's 2021-01-04 18:29:00 +01:00
Calvin Rose
665b1e68d5 Pluralize arity compile warning. 2021-01-03 20:15:51 -06:00
Calvin Rose
2ca9300bf7 Add sort tests. 2021-01-03 16:45:37 -06:00
Calvin Rose
81f62b246c Merge pull request #545 from felixr/master
Revert my buggy hybrid sort
2021-01-03 16:39:23 -06:00
Calvin Rose
87badc71d2 Remove :generate verb from loop.
Instead, one case use `:in` as with otehr data structures.
2021-01-03 16:38:38 -06:00
Calvin Rose
e5242c67ff Update changelog and documentation. 2021-01-03 16:30:43 -06:00
Calvin Rose
4355420994 Remove function eachy.
Instead use `each`.
2021-01-03 16:19:23 -06:00
Calvin Rose
c357af02c2 Allow iterating over fibers with each and similar. 2021-01-03 16:17:36 -06:00
Felix Riedel
19576effbe Revert "Tweak sort: use insertion sort for small arrays"
This reverts commit 0ea77cabfb.
2021-01-03 20:09:50 +00:00
Calvin Rose
ecc6eb7497 Don't fail jpm if os/realpath fails. 2021-01-03 13:09:41 -06:00
Calvin Rose
d0ac318980 Don't print to stderr in Makefile to detect version. Fix #544 2021-01-03 12:59:16 -06:00
Calvin Rose
7b030fe70d Fix some return issues. 2021-01-03 11:54:31 -06:00
Calvin Rose
115556fcf2 Merge branch 'ev_execute' 2021-01-03 11:48:00 -06:00
Calvin Rose
9760cf1f4e Fix MSVC warning. 2021-01-03 11:47:29 -06:00
Calvin Rose
47bb7fd21b Begin implementing async subproccesses for windows. 2021-01-03 11:21:44 -06:00
Calvin Rose
1c7ed8ca48 Use PostQueuedCompletionStatus for threaded calls on windows.
Ore efficient than using a self pipe.
2021-01-03 11:08:12 -06:00
Calvin Rose
6b268c5df4 find-index now takes optional default. 2021-01-03 09:33:52 -06:00
Calvin Rose
62f783f1dc Merge branch 'master' of github.com:janet-lang/janet 2021-01-03 09:26:31 -06:00
Calvin Rose
61c65f3df1 Fix valgrind warning. 2020-12-31 16:30:54 -06:00
Calvin Rose
05166b3673 Fix proc getter bug. 2020-12-31 16:23:20 -06:00
Calvin Rose
0a1c93b869 Add ev api for making threaded calls.
Easy way to make arbitrary functions in C async.
2020-12-31 16:12:42 -06:00
Calvin Rose
788f91a36f Remove unneeded book keeping for sub processes.
Since we are not using signals we no longer need some bookkeeping.
2020-12-31 11:52:12 -06:00
Calvin Rose
c831ecf5d2 Working implementation of process waiting with threads.
Does not require all sorts of signal handling code
that is not thread-safe and can "steal processes".

However, there is a much simpler way to add this functionality
by creating a new stream and thread for each subprocess when it is
waited on. This is perhaps _slightly_ less efficient but oh so much
simpler, since we can reuse all of our concepts from streams and there
is no need to implement a whole system around the selfpipe.
2020-12-31 11:22:18 -06:00
Calvin Rose
9e42ee153c Merge branch 'master' into HEAD 2020-12-30 12:19:13 -06:00
Calvin Rose
d457aa5951 Deprecate file/popen.
os/spawn is the prefered way of creating a subprocess and
communicating with it.
2020-12-30 10:22:45 -06:00
Calvin Rose
ab37ee6ebb Add :all option to ev/read.
Brings ev/read more in line with file/read.
2020-12-29 20:37:59 -06:00
Calvin Rose
8655530b19 Rename predicates in module/paths 2020-12-29 19:52:26 -06:00
Calvin Rose
27b1f59aa9 Change Ctrl-C and move old behavior to Ctrl-Q
This lets Janet be a better unix citizen and lets Ctrl-C
raise an interrupt. Trying to make Janet behave superficially
like a shell by overriding Ctrl-C is not helpful.
2020-12-29 16:20:37 -06:00
Calvin Rose
cc2cc4db43 Merge pull request #541 from sogaiu/match-doc-formatting
Tweak match docstring
2020-12-29 13:10:35 -06:00
Calvin Rose
20bcd95279 Merge commit '0ea77cabfb30afc15433581f5888171c1f65aafd' 2020-12-28 12:20:21 -06:00
Calvin Rose
d7954be5e5 Update docstring for os/open. 2020-12-28 11:00:15 -06:00
Felix Riedel
0ea77cabfb Tweak sort: use insertion sort for small arrays 2020-12-28 16:06:48 +00:00
Felix Riedel
0d46352ff4 Revert to better performing number hash. 2020-12-27 14:05:40 +00:00
sogaiu
ffa0d5fe45 Tweak match docstring 2020-12-27 13:42:22 +09:00
Calvin Rose
a2c837a99c Merge remote-tracking branch 'felixr/master' into master 2020-12-26 20:06:34 -06:00
Calvin Rose
13d8d11011 Try new number hashing with frexp.
This may be a bit slower in some cases but generally should
have much better hashing for numbers.
2020-12-26 16:54:14 -06:00
Calvin Rose
2357b6162f Update test-install target. 2020-12-26 15:42:13 -06:00
Calvin Rose
b4f242193d Improve hash function for numbers. 2020-12-26 15:38:04 -06:00
Calvin Rose
7242ee0186 Merge pull request #540 from felixr/better-quicksort
Improve quicksort to avoid worst case performance on sorted input
2020-12-26 15:23:01 -06:00
Felix Riedel
3e742ffc4c Improve quicksort to avoid worst case performance.
The current implementation will have quadratic behaviour for already
sorted arrays because it picks the last element as pivot. In an sorted
array this splits the array repeatedly into the biggest value and all
other values.

The implementation in this commit uses the *median of three* as pivot.

`janet -e "(sort (range 10000))"` to reproduce quadratic behaviour.
2020-12-26 19:18:17 +00:00
Felix Riedel
2ec12fe06f Improve hashing of numbers
Using an integer hash (https://stackoverflow.com/a/12996028/60617) on
the number casted to int32 combined with lower bits of the number.
2020-12-26 13:09:11 +00:00
Felix Riedel
c76e0ae685 Use boost's way of combining hash values for arrays and kv pairs.
`seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);`
from https://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html

The current way of combining hashes peforms poorly on hash values of
numbers. Changing the way hashes are combined canlead to a significant speed up:

```
time janet_new -e '(def tbl @{}) (loop [x :in (range 1000) y :in (range 1000)] (put tbl {0 x 1 y} true))'
3.77s user 0.08s system 99% cpu 3.843 total

time janet_orig -e '(def tbl @{}) (loop [x :in (range 1000) y :in (range 1000)] (put tbl {0 x 1 y} true))'
48.98s user 0.15s system 99% cpu 49.136 total
```
2020-12-26 13:05:03 +00:00
Calvin Rose
25ded775ad Add array/clear.
Also improve map, find-index, and find to work on data structures
which do not defined length.
2020-12-18 12:37:58 -06:00
Calvin Rose
cae4f19629 Merge pull request #532 from pyrmont/feature.parser-line-col-setting
Update (parser/where) to support optional line and column
2020-12-15 19:03:25 -06:00
Michael Camilleri
04f6c7b156 Clarify docstring of parser/where 2020-12-15 16:41:45 +09:00
Michael Camilleri
77b79e9899 Update (parser/where) to support optional line and column 2020-12-15 14:12:33 +09:00
Calvin Rose
a55354357c Make dofile error if source file errors.
This should make dofile a bit easier to use.
It also means that import properly raises errors when
things go bad.
2020-12-14 08:23:06 -06:00
Calvin Rose
392d5d51df Fix build info for 1.13.1 2020-12-13 11:59:52 -06:00
Calvin Rose
9bc996a630 Prepare for 1.13.0 initial release. 2020-12-13 11:17:10 -06:00
Calvin Rose
7b709d4c68 Prevent buffer/trim from shrinking buffer to 0 bytes as well. 2020-12-13 09:38:35 -06:00
Calvin Rose
eab5f67c5c Fix buffer with NULL data pointer issue.
Simply prevent buffers from ever having a NULL data pointer.
2020-12-13 09:33:57 -06:00
Calvin Rose
6020106000 Address #529 2020-12-11 19:21:54 -06:00
Calvin Rose
12f470ed10 Use :_name instead of :name for printing tagged tables. 2020-12-11 18:28:09 -06:00
Calvin Rose
945cbcfad6 Tail recursive match implementation.
This implementation uses multiple passes on patterns
to remove the need for a sentinel value to check if there was a match.
This also re-uses extracted subpatterns for complicated patterns.
2020-12-10 08:35:34 -06:00
Calvin Rose
d53007739e Invert read/write bits on pipe in os/execute.
It was backwards, breaking this functionality.
2020-12-09 19:04:05 -06:00
Calvin Rose
6eaf8272e1 Merge pull request #525 from uvtc/patch-1
light markup in some docs in corelib
2020-12-07 15:57:09 -06:00
Calvin Rose
6fb83dce06 Merge pull request #526 from sogaiu/tweak-comment
Tweak comment for janet_fiber_popframe
2020-12-07 15:56:25 -06:00
John Gabriele
52addc877d Use xs 2020-12-07 14:07:13 -05:00
sogaiu
53a5f3d2dc Tweak comment for janet_fiber_popframe 2020-12-07 12:23:27 +09:00
Calvin Rose
711ee5a36d Merge branch 'preload' 2020-12-06 21:06:59 -06:00
Calvin Rose
cd09b696b5 Add :preload loader. 2020-12-06 21:06:17 -06:00
John Gabriele
df1ca255a9 parts/xs --> pieces 2020-12-06 21:29:30 -05:00
Calvin Rose
811a5d93f4 Prevent some potential bad characters in test out. 2020-12-06 17:10:18 -06:00
John Gabriele
adbe361b9b light markup in some docs in corelib 2020-12-06 17:51:48 -05:00
Calvin Rose
0f16f21677 Make builds deterministic again.
Also prevent marshal from creating multiple copies of
a function - (marshal function pointer before function def pointer).
2020-12-06 16:32:23 -06:00
Calvin Rose
aa0de01e5f Fix some formatting and undefined behavior. 2020-12-06 14:33:08 -06:00
Calvin Rose
785757f2f6 Remove pthreads from shell.c and update bsd build. 2020-12-06 13:51:06 -06:00
Calvin Rose
01120dfc46 Try and fix openbsd st.ht build.
Oneline meson configs, remove extra `cd janet`.
2020-12-06 11:57:40 -06:00
Calvin Rose
a119eb4ef0 Merge branch 'master' of github.com:janet-lang/janet 2020-12-06 11:47:46 -06:00
Calvin Rose
0aa4c3d217 Consolidate sr.ht builds to 1-per-platform.
This generally makes more sense from an infrastructure
point of view and works around 4 builds per push limit of sr.ht.
2020-12-06 11:46:45 -06:00
Calvin Rose
3c0cc59d77 Rename some srht build files. 2020-12-06 11:22:35 -06:00
Calvin Rose
7e1d095996 Merge pull request #522 from pyrmont/docs.keep-docstring
Clarify description of keep
2020-12-05 14:31:58 -06:00
Calvin Rose
cfa9fb6ee4 Update changelog. 2020-12-05 10:36:27 -06:00
Calvin Rose
9d23192614 Add ev/deadline and ev/with-deadline.
This should be more useful than timeouts in real-world
use cases. The deadline system is based on fibers and is target
to much more coarse-grained (and therfor reliable) timeouts than things
like ev/sleep and timeout arguments.
2020-12-05 10:32:34 -06:00
Michael Camilleri
7c1a52ae65 Use 'different from' in preference to 'different to' 2020-12-05 16:43:44 +09:00
Michael Camilleri
9aa1b9c740 Clarify description of keep 2020-12-05 16:02:36 +09:00
Calvin Rose
c4a4916055 Address #500 - update docs and add buffer/push
This updates the documentation and adds a function buffer/push, which
is a more useful function than buffer/push-string or buffer/push-byte by
combining both.
2020-12-04 17:56:47 -06:00
Calvin Rose
b402e0671a Merge pull request #514 from uvtc/patch-2
boot.janet, fix possible typo
2020-12-04 17:40:46 -06:00
Calvin Rose
8144f83b66 Merge pull request #516 from uvtc/patch-4
doc for identity
2020-12-04 17:40:31 -06:00
Calvin Rose
cd2a55e268 Merge pull request #513 from uvtc/patch-1
boot.janet, cond doc
2020-12-04 17:38:02 -06:00
Calvin Rose
f92b5d69c8 Merge pull request #515 from uvtc/patch-3
C-style (hyphenate)
2020-12-04 17:37:24 -06:00
Calvin Rose
a8c21459c3 Merge pull request #517 from uvtc/patch-5
boot.janet, compare*, light formatting
2020-12-04 17:37:06 -06:00
Calvin Rose
4789b4c9f3 Merge pull request #520 from uvtc/patch-6
corelib.c, describe, add hyphen
2020-12-04 17:31:15 -06:00
Calvin Rose
ee1cd6f151 Merge pull request #521 from sogaiu/parser-with-a-colon
Minor tweak in changelog
2020-12-04 17:30:59 -06:00
sogaiu
dfcda296a3 Minor tweak in changelog 2020-12-02 17:52:29 +09:00
John Gabriele
4d38fcb289 corelib.c, describe, add hyphen 2020-12-01 11:56:53 -05:00
Calvin Rose
cbdea8f331 Make os/execute cooperate with ev module.
os/execute, os/proc-wait do not block (currently posix only).
This uses the self-pipe trick to turn signals into a pollable entity.
2020-11-29 15:36:21 -06:00
John Gabriele
51d6a13510 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:31:01 -05:00
John Gabriele
7b4eeecd9f Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:30:48 -05:00
John Gabriele
82eff7e082 Update src/boot/boot.janet
Agreed. That's more clear.

Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:30:26 -05:00
John Gabriele
b922e36071 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:18:19 -05:00
John Gabriele
7c75aeaad2 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:17:38 -05:00
John Gabriele
2db9323671 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:17:23 -05:00
John Gabriele
31ae93de19 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:17:12 -05:00
John Gabriele
a81e9f23f0 Update src/boot/boot.janet
Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:16:55 -05:00
John Gabriele
59f09a4386 Update src/boot/boot.janet
omit needless word

Co-authored-by: Michael Camilleri <mike@inqk.net>
2020-11-29 14:15:55 -05:00
John Gabriele
53400ecac1 boot.janet, compare*, light formatting
Since those represent code, they should get backticks.
2020-11-28 14:41:42 -05:00
John Gabriele
1b8928a8ec doc for identity
This function only takes one argument anyway, and errors if you try to pass more.
2020-11-28 14:35:17 -05:00
John Gabriele
e706494893 C-style 2020-11-28 14:29:13 -05:00
John Gabriele
894aea7ce7 boot.janet, fix possible typo
Possible typo?
2020-11-28 14:25:10 -05:00
John Gabriele
87167a21c9 boot.janet, cond doc
Arranged this way seems to make more sense.
2020-11-28 14:18:35 -05:00
Calvin Rose
7c8f5ef811 Merge branch 'master' of github.com:janet-lang/janet 2020-11-28 12:18:51 -06:00
Calvin Rose
7aa4241662 Add testing for the new reindent behavior.
This also provides a reference function to reimplement
the behavior in Janet.
2020-11-28 12:18:36 -06:00
Calvin Rose
56a915b5b1 Long strings now autoindent contents - doc-format is simpler.
No need to try and auto detect the base indentation - it is 0.
This will be taken care of by the parser.
2020-11-28 10:04:25 -06:00
Calvin Rose
90a0dfa35f Merge pull request #512 from timgates42/bugfix_typo_source
docs: fix simple typo, soucre -> source
2020-11-27 16:54:34 -06:00
Tim Gates
128d72785f docs: fix simple typo, soucre -> source
There is a small typo in src/core/features.h.

Should read `source` rather than `soucre`.
2020-11-28 09:45:46 +11:00
Calvin Rose
21a6017547 typo 2020-11-27 12:27:44 -06:00
Calvin Rose
a0964d44d5 Fix some valgrind errors.
A null pointer dereference and a memory leak with the line/col mapping.
2020-11-27 12:21:23 -06:00
Calvin Rose
fb0859dfe6 Merge remote-tracking branch 'pyrmont/feature.markdown-docstrings' into longstring-autoindent 2020-11-27 12:13:45 -06:00
Calvin Rose
dadd6037bb Merge branch 'master' into longstring-autoindent 2020-11-27 10:40:10 -06:00
Michael Camilleri
6f3eff3258 Add example docstring 2020-11-27 18:29:41 +09:00
Michael Camilleri
02224d5aa9 Fix bugs in parsing logic 2020-11-27 18:28:58 +09:00
Calvin Rose
bfd2845077 Add merge-module to core.
This is a little utility used for manually importing modules.
It is responsible for taking the output of dofile, run-context, or
require and merging into another environment as if import was called.
2020-11-27 00:16:54 -06:00
Michael Camilleri
ba2e0489e6 Add initial implementation of docstring formatter 2020-11-27 15:07:38 +09:00
Calvin Rose
ca7c5b8b10 ev/call uses current env as prototype of environment. 2020-11-26 21:13:41 -06:00
Calvin Rose
6c43489fb2 Fix #508 - nil fiber environment.
run-context did not handle a nil environment well, so that was fixed
and ev/call inherits the environment when creating the fiber.
2020-11-26 19:04:45 -06:00
Calvin Rose
d76f671d37 Update changelog and make arg to peg's error optional. 2020-11-26 18:57:24 -06:00
Calvin Rose
776ce586bc Add line and column combinators to peg.
These capture the line and column number of the current position
in the matched text. This is useful for error reporting as well
as indentation checking.

This works by lazily creating an index on first use that stores all
newline character indices in order. We can then do a binary search on
this to get both line number and column number in log(n) time.
This is good enough for most use cases and doesn't slow down the common case at all
- these will not be commonly used patterns in a hot loop so it is not worth to try and
optimize this at all. Constant time look up should be possible but at
the cost of complicating code and slowing down all matching to check for
new lines.
2020-11-26 18:32:56 -06:00
Calvin Rose
adc3066dc8 Update doc-format and boot.janet docstrings.
Make doc-format respect leading indents, increase the default format
width to better accommodate markdown formatted documentation. We still
need to support single line style doc strings, such as those used
for most c functions which can be a single line of much longer than
80 or 120 characters.

Consecutive whitespace internal to lines is not preserved, though.
2020-11-26 14:58:36 -06:00
Calvin Rose
7fd2da1096 Add code in parser to automatically indent long strings.
Leading spaces are stripped based on the column index of the first
backtick character in the first delimiter. If there are
characters that are not newline or space before that column in the
string, then the behavior is the same as the old behvaior - no
re-indentation is performed.
2020-11-26 13:20:58 -06:00
Calvin Rose
451340e4c0 Update docstrings in boot.janet (#506)
Elaborate on usage of reduce and accumulate.
2020-11-26 10:34:51 -06:00
Calvin Rose
a3e812b86d Fix #505 - bat int64 parsing.
Fixes an off-by-1 error.

Also makes windows testing hopefully a bit less flaky.
2020-11-25 09:45:46 -06:00
Calvin Rose
a3f98091c4 Fix #509
janet_fiber returns NULL if there is a bad arity, check that before
continuing.
2020-11-23 15:28:28 -06:00
Calvin Rose
6720b34868 Don't use peg for patch tool. 2020-11-18 19:37:18 -06:00
Calvin Rose
781ed0dc67 Merge branch 'master' of github.com:janet-lang/janet 2020-11-18 19:36:12 -06:00
Calvin Rose
8f00848c7b Fix build issues on windows by using a size_t instead of int. 2020-11-18 19:31:20 -06:00
Calvin Rose
53aa19a916 Several changes to move pipe creation back into ev.c 2020-11-18 10:53:36 -06:00
Calvin Rose
2dc04d2957 On install, merge janetconf.h into janet.h
This results in a cleaner amalgmated build
2020-11-17 09:53:12 -06:00
Calvin Rose
306bdee673 Merge branch 'master' of github.com:janet-lang/janet 2020-11-16 18:47:28 -06:00
Calvin Rose
cff52ded58 Add JANET_ASYNC_EVENT_CANCEL
also fix bug that could cause event loop to hang.
2020-11-16 18:46:59 -06:00
Calvin Rose
fbe658a724 Merge pull request #503 from sogaiu/boot-janet-docstring-tweaks
Tweak docstrings in boot.janet
2020-11-16 17:03:54 -06:00
Calvin Rose
f9d0eb47b7 Merge branch 'master' of github.com:janet-lang/janet 2020-11-16 16:51:29 -06:00
Calvin Rose
078f50d45a When reading from a stream, EPIPE is considered EOS.
Before, EPIPE caused an error, but in most cases it is better
to consider it an end of stream. In the future, we may want to allow
cusomtization of this behavior with flags on the stream but for now
let's keep it simpler.
2020-11-16 16:49:27 -06:00
Calvin Rose
974a45c804 When reading from a stream, EPIPE is considered EOS.
Before, EPIPE caused an error, but in most cases it is better
to consider it an end of stream. In the future, we may want to allow
cusomtization of this behavior with flags on the stream but for now
let's keep it simpler.
2020-11-16 16:42:09 -06:00
Calvin Rose
760e4e3d68 Add upscope special form.
Upscope is similar to do, but does not introduce a new lexical scope.
2020-11-16 16:41:27 -06:00
Calvin Rose
9ec5689d6b Don't use gcroot/unroot for tracking IO operations.
This could have bad effects in higher load situations, and
duplicates code. It is better to keep a dedicated list of
scheduled IO operations which can be efficiently added and
removed from. It also provides and easy way to enumerate
scheduled IO operations.
2020-11-16 09:30:04 -06:00
sogaiu
c8b72431a3 Some more 2020-11-16 16:13:28 +09:00
sogaiu
0eb913fb9a A couple more tweaks 2020-11-16 14:14:51 +09:00
sogaiu
fce27cb2e8 Tweak docstrings in boot.janet 2020-11-16 14:03:26 +09:00
Calvin Rose
1b6272db2e Fix windows ifdef. 2020-11-15 19:55:58 -06:00
Calvin Rose
b1c0ad5e42 CD into source directory in build recipe. 2020-11-15 19:50:33 -06:00
Calvin Rose
3f7cdcb6a7 Add meson test build for epoll. 2020-11-15 19:47:11 -06:00
Calvin Rose
a25b030e36 Fix EPOLL implementation. 2020-11-15 19:40:47 -06:00
Calvin Rose
717fac02d1 Update janet.h for janet_thread_current 2020-11-15 16:12:02 -06:00
Calvin Rose
dcf8ba0edb Update CHANGELOG.md 2020-11-15 15:35:50 -06:00
Calvin Rose
3ab2ae130b Address #495 Add :read and :parser to run-context. 2020-11-15 15:26:16 -06:00
Calvin Rose
6e6900fa3a os/execute and os/spawn can take streams. 2020-11-15 12:17:29 -06:00
Calvin Rose
d7af4596e1 Move math.h include out of windows ifdef 2020-11-15 10:21:37 -06:00
Calvin Rose
1759151875 Change suite 9 test a bit. 2020-11-15 10:12:10 -06:00
Calvin Rose
a7ed3dea4b Remove some flags in os/open. 2020-11-15 10:06:20 -06:00
Calvin Rose
cdcb774dc8 Add os/pipe and os/open.
ev/pipe -> os/pipe, and os/open is a wrapper
around the open system call.
2020-11-15 09:57:29 -06:00
109 changed files with 5562 additions and 3129 deletions

23
.builds/linux.yml Normal file
View File

@@ -0,0 +1,23 @@
image: archlinux
sources:
- https://git.sr.ht/~bakpakin/janet
packages:
- meson
tasks:
- with-epoll: |
cd janet
meson setup with-epoll --buildtype=release
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
ninja
ninja test
sudo ninja install
sudo jpm --verbose install circlet
sudo jpm --verbose install spork

View File

@@ -1,14 +0,0 @@
image: openbsd/latest
sources:
- https://git.sr.ht/~bakpakin/janet
packages:
- meson
tasks:
- build: |
cd janet
meson setup build --buildtype=release
cd build
ninja
ninja test
doas ninja install
doas jpm --verbose install circlet

View File

@@ -1,15 +0,0 @@
image: openbsd/latest
sources:
- https://git.sr.ht/~bakpakin/janet
packages:
- meson
tasks:
- build: |
cd janet
meson setup build --buildtype=release
cd build
meson configure -Dprf=true
ninja
ninja test
doas ninja install
doas jpm --verbose install circlet

View File

@@ -1,22 +0,0 @@
image: openbsd/latest
sources:
- https://git.sr.ht/~bakpakin/janet
packages:
- meson
tasks:
- build: |
cd janet
meson setup build --buildtype=release
cd build
meson configure -Dsingle_threaded=true
meson configure -Dnanbox=false
meson configure -Ddynamic_modules=false
meson configure -Ddocstrings=false
meson configure -Dnet=false
meson configure -Dsourcemaps=false
meson configure -Dpeg=false
meson configure -Dassembler=false
meson configure -Dint_types=false
meson configure -Dtyped_array=false
meson configure -Dreduced_os=true
ninja # will not pass tests but should build

View File

@@ -3,10 +3,31 @@ sources:
- https://git.sr.ht/~bakpakin/janet
packages:
- gmake
- meson
tasks:
- build: |
- gmake: |
cd janet
gmake
gmake test
doas gmake install
gmake test-install
- meson_min: |
cd janet
meson setup build_meson_min --buildtype=release -Dsingle_threaded=true -Dnanbox=false -Ddynamic_modules=false -Ddocstrings=false -Dnet=false -Dsourcemaps=false -Dpeg=false -Dassembler=false -Dint_types=false -Dtyped_array=false -Dreduced_os=true
cd build_meson_min
ninja
- meson_prf: |
cd janet
meson setup build_meson_prf --buildtype=release -Dprf=true
cd build_meson_prf
ninja
ninja test
- meson_default: |
cd janet
meson setup build_meson_default --buildtype=release
cd build_meson_default
ninja
ninja test
doas ninja install
doas jpm --verbose install circlet

6
.gitignore vendored
View File

@@ -32,8 +32,9 @@ lockfile.janet
# Local directory for testing
local
# Common test file I use.
# Common test files I use.
temp.janet
scratch.janet
# Emscripten
*.bc
@@ -140,3 +141,6 @@ compile_commands.json
CTestTestfile.cmake
# End of https://www.gitignore.io/api/cmake
# Astyle
*.orig

View File

@@ -4,7 +4,7 @@ script:
- make test
- sudo make install
- make test-install
- make build/janet-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.tar.gz
- JANET_DIST_DIR=janet-${TRAVIS_TAG}-${TRAVIS_OS_NAME} make build/janet-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.tar.gz
compiler:
- clang
- gcc

View File

@@ -1,14 +1,137 @@
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased - ???
## 1.16.1 - 2021-06-09
- Add `maclintf` - a utility for adding linting messages when inside macros.
- Print source code of offending line on compiler warnings and errors.
- Fix some issues with linting and re-add missing `make docs`.
- Allow controlling linting with dynamic bindings `:lint-warn`, `:lint-error`, and `:lint-levels`.
- Add `-w` and `-x` command line flags to the `janet` binary to set linting thresholds.
linting thresholds are as follows:
- :none - will never be trigger.
- :relaxed - will only trigger on `:relaxed` lints.
- :normal - will trigger on `:relaxed` and `:normal` lints.
- :strict - will trigger on `:strict`, `:normal`, and `:relaxed` lints. This will catch the most issues
but can be distracting.
## 1.16.0 - 2021-05-30
- Add color documentation to the `doc` macro - enable/disable with `(dyn :doc-color)`.
- Remove simpler HTML docs from distribution - use website or built-in documentation instead.
- Add compiler warnings and deprecation levels.
- Add `as-macro` to make using macros within quasiquote easier to do hygienically.
- Expose `JANET_OUT_OF_MEMORY` as part of the Janet API.
- Add `native-deps` option to `decalre-native` in `jpm`. This lets native libraries link to other
native libraries when building with jpm.
- Remove the `tarray` module. The functionality of typed arrays will be moved to an external module
that can be installed via `jpm`.
- Add `from-pairs` to core.
- Add `JPM_OS_WHICH` environment variable to jpm to allow changing auto-detection behavior.
- The flychecker will consider any top-level calls of functions that start with `define-` to
be safe to execute and execute them. This allows certain patterns (like spork/path) to be
better processed by the flychecker.
## 1.15.5 - 2021-04-25
- Add `declare-headers` to jpm.
- Fix error using unix pipes on BSDs.
- Support .cc and .cxx extensions in `jpm` for C++ code.
- Change networking code to not create as many HUP errors.
- Add `net/shutdown` to close sockets in one direction without hang ups.
- Update code for printing the debug repl
## 1.15.4 - 2021-03-16
- 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
- Add `doc-of` for reverse documentation lookup.
- Add `ev/give-supervsior` to send a message to the supervising channel.
- Add `ev/gather` and `chan` argument to `ev/go`. This new argument allows "supervisor channels"
for fibers to enable structured concurrency.
- Make `-k` flag work on stdin if no files are given.
- Add `flycheck` function to core.
- Make `backmatch` and `backref` more expressive in pegs.
- Fix buggy `string/split`.
- Add `fiber/last-value` to get the value that was last yielded, errored, or signaled
by a fiber.
- Remove `:generate` verb from `loop` macros. Instead, use the `:in` verb
which will now work on fibers as well as other data structures.
- Define `next`, `get`, and `in` for fibers. This lets
`each`, `map`, and similar iteration macros can now iterate over fibers.
- Remove macro `eachy`, which can be replaced by `each`.
- Add `dflt` argument to find-index.
- Deprecate `file/popen` in favor of `os/spawn`.
- Add `:all` keyword to `ev/read` and `net/read` to make them more like `file/read`. However, we
do not provide any `:line` option as that requires buffering.
- Change repl behavior to make Ctrl-C raise SIGINT on posix. The old behavior for Ctrl-C,
to clear the current line buffer, has been moved to Ctrl-Q.
- Importing modules that start with `/` is now the only way to import from project root.
Before, this would import from / on disk. Previous imports that did not start with `.` or `/`
are now unambiguously importing from the syspath, instead of checking both the syspath and
the project root. This is backwards incompatible and dependencies should be updated for this.
- Change hash function for numbers.
- Improve error handling of `dofile`.
- Bug fixes in networking and subprocess code.
- Use markdown formatting in more places for docstrings.
## 1.13.1 - 2020-12-13
- Pretty printing a table with a prototype will look for `:_name` instead of `:name`
in the prototype table to tag the output.
- `match` macro implementation changed to be tail recursive.
- Adds a :preload loader which allows one to manually put things into `module/cache`.
- Add `buffer/push` function.
- Backtick delimited strings and buffers are now reindented based on the column of the
opening delimiter. Whitespace in columns to the left of the starting column is ignored unless
there are non-space/non-newline characters in that region, in which case the old behavior is preserved.
- Argument to `(error)` combinator in PEGs is now optional.
- Add `(line)` and `(column)` combinators to PEGs to capture source line and column.
This should make error reporting a bit easier.
- Add `merge-module` to core.
- During installation and release, merge janetconf.h into janet.h for easier install.
- Add `upscope` special form.
- `os/execute` and `os/spawn` can take streams for redirecting IO.
- Add `:parser` and `:read` parameters to `run-context`.
- Add `os/open` if ev is enabled.
- Add `os/pipe` if ev is enabled.
- Add `janet_thread_current(void)` to C API
- Add integer parsing forms to pegs. This makes parsing many binary protocols easier.
- Lots of updates to networking code - now can use epoll (or poll) on linux and IOCP on windows.
- Add `ev/` module. This exposes a fiber scheduler, queues, timeouts, and other functionality to users
for single threaded cooperative scheduling and asynchornous IO.
for single threaded cooperative scheduling and asynchronous IO.
- Add `net/accept-loop` and `net/listen`. These functions break down `net/server` into it's essential parts
and are more flexible. They also allow furter improvements to these utility functions.
and are more flexible. They also allow further improvements to these utility functions.
- Various small bug fixes.
## 1.12.2 - 2020-09-20
- Add janet\_try and janet\_restore to C API.

View File

@@ -14,7 +14,6 @@ Please read this document before making contributions.
on how to reproduce it. If it is a compiler or language bug, please try to include a minimal
example. This means don't post all 200 lines of code from your project, but spend some time
distilling the problem to just the relevant code.
* Add the `bug` tag to the issue.
## Contributing Changes
@@ -30,8 +29,7 @@ may require changes before being merged.
the test folder and make sure it is run when`make test` is invoked.
* Be consistent with the style. For C this means follow the indentation and style in
other files (files have MIT license at top, 4 spaces indentation, no trailing
whitespace, cuddled brackets, etc.) Use `make format` to
automatically format your C code with
whitespace, cuddled brackets, etc.) Use `make format` to automatically format your C code with
[astyle](http://astyle.sourceforge.net/astyle.html). You will probably need
to install this, but it can be installed with most package managers.
@@ -75,4 +73,3 @@ timely manner. In short, if you want extra functionality now, then build it.
* Include a good description of the problem that is being solved
* Include descriptions of potential solutions if you have some in mind.
* Add the appropriate tags to the issue. For new features, add the `enhancement` tag.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2020 Calvin Rose and contributors
Copyright (c) 2021 Calvin Rose and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -27,7 +27,7 @@ PREFIX?=/usr/local
INCLUDEDIR?=$(PREFIX)/include
BINDIR?=$(PREFIX)/bin
LIBDIR?=$(PREFIX)/lib
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 1 || echo local)\""
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 1 2> /dev/null || echo local)\""
CLIBS=-lm -lpthread
JANET_TARGET=build/janet
JANET_LIBRARY=build/libjanet.so
@@ -35,6 +35,7 @@ JANET_STATIC_LIBRARY=build/libjanet.a
JANET_PATH?=$(LIBDIR)/janet
JANET_MANPATH?=$(PREFIX)/share/man/man1/
JANET_PKG_CONFIG_PATH?=$(LIBDIR)/pkgconfig
JANET_DIST_DIR?=janet-dist
DEBUGGER=gdb
SONAME_SETTER=-Wl,-soname,
@@ -66,8 +67,8 @@ ifeq ($(UNAME), Haiku)
LDFLAGS=-Wl,--export-dynamic
endif
$(shell mkdir -p build/core build/mainclient build/webclient build/boot)
all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY)
$(shell mkdir -p build/core build/c build/boot)
all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.h
######################
##### Name Files #####
@@ -119,7 +120,6 @@ JANET_CORE_SOURCES=src/core/abstract.c \
src/core/table.c \
src/core/thread.c \
src/core/tuple.c \
src/core/typedarray.c \
src/core/util.c \
src/core/value.c \
src/core/vector.c \
@@ -149,7 +149,7 @@ build/janet_boot: $(JANET_BOOT_OBJECTS)
$(CC) $(BOOT_CFLAGS) -o $@ $(JANET_BOOT_OBJECTS) $(CLIBS)
# 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)' > $@
cksum $@
@@ -157,22 +157,22 @@ build/janet.c: build/janet_boot src/boot/boot.janet
##### Amalgamation #####
########################
SONAME=libjanet.so.1.12
SONAME=libjanet.so.1.16
build/shell.c: src/mainclient/shell.c
build/c/shell.c: src/mainclient/shell.c
cp $< $@
build/janet.h: src/include/janet.h
cp $< $@
build/janet.h: $(JANET_TARGET) src/include/janet.h src/conf/janetconf.h
./$(JANET_TARGET) tools/patch-header.janet src/include/janet.h src/conf/janetconf.h $@
build/janetconf.h: src/conf/janetconf.h
cp $< $@
build/janet.o: build/janet.c build/janet.h build/janetconf.h
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@ -I build
build/janet.o: build/c/janet.c src/conf/janetconf.h src/include/janet.h
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@
build/shell.o: build/shell.c build/janet.h build/janetconf.h
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@ -I build
build/shell.o: build/c/shell.c src/conf/janetconf.h src/include/janet.h
$(HOSTCC) $(BUILD_CFLAGS) -c $< -o $@
$(JANET_TARGET): build/janet.o build/shell.o
$(HOSTCC) $(LDFLAGS) $(BUILD_CFLAGS) -o $@ $^ $(CLIBS)
@@ -222,13 +222,22 @@ callgrind: $(JANET_TARGET)
dist: build/janet-dist.tar.gz
build/janet-%.tar.gz: $(JANET_TARGET) \
src/include/janet.h src/conf/janetconf.h \
build/janet.h \
jpm.1 janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) \
build/doc.html README.md build/janet.c build/shell.c jpm
$(eval JANET_DIST_DIR = "janet-$(shell basename $*)")
mkdir -p build/$(JANET_DIST_DIR)
cp -r $^ build/$(JANET_DIST_DIR)/
cd build && tar -czvf ../$@ $(JANET_DIST_DIR)
README.md build/c/janet.c build/c/shell.c jpm
mkdir -p build/$(JANET_DIST_DIR)/bin
cp $(JANET_TARGET) build/$(JANET_DIST_DIR)/bin/
cp jpm build/$(JANET_DIST_DIR)/bin/
mkdir -p build/$(JANET_DIST_DIR)/include
cp build/janet.h build/$(JANET_DIST_DIR)/include/
mkdir -p build/$(JANET_DIST_DIR)/lib/
cp $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/$(JANET_DIST_DIR)/lib/
mkdir -p build/$(JANET_DIST_DIR)/man/man1/
cp janet.1 jpm.1 build/$(JANET_DIST_DIR)/man/man1/
mkdir -p build/$(JANET_DIST_DIR)/src/
cp build/c/janet.c build/c/shell.c build/$(JANET_DIST_DIR)/src/
cp CONTRIBUTING.md LICENSE README.md build/$(JANET_DIST_DIR)/
cd build && tar -czvf ../$@ ./$(JANET_DIST_DIR)
#########################
##### Documentation #####
@@ -262,11 +271,11 @@ build/janet.pc: $(JANET_TARGET)
echo 'Libs: -L$${libdir} -ljanet' >> $@
echo 'Libs.private: $(CLIBS)' >> $@
install: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.pc build/jpm
install: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.pc build/jpm build/janet.h
mkdir -p '$(DESTDIR)$(BINDIR)'
cp $(JANET_TARGET) '$(DESTDIR)$(BINDIR)/janet'
mkdir -p '$(DESTDIR)$(INCLUDEDIR)/janet'
cp -rf $(JANET_HEADERS) '$(DESTDIR)$(INCLUDEDIR)/janet'
cp -r build/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet'
mkdir -p '$(DESTDIR)$(JANET_PATH)'
mkdir -p '$(DESTDIR)$(LIBDIR)'
cp $(JANET_LIBRARY) '$(DESTDIR)$(LIBDIR)/libjanet.so.$(shell $(JANET_TARGET) -e '(print janet/version)')'

View File

@@ -4,8 +4,6 @@
[![Build Status](https://travis-ci.org/janet-lang/janet.svg?branch=master)](https://travis-ci.org/janet-lang/janet)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/commits/freebsd.yml.svg)](https://builds.sr.ht/~bakpakin/janet/commits/freebsd.yml?)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/commits/openbsd.yml.svg)](https://builds.sr.ht/~bakpakin/janet/commits/openbsd.yml?)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/commits/meson.yml.svg)](https://builds.sr.ht/~bakpakin/janet/commits/meson.yml?)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/commits/meson_min.yml.svg)](https://builds.sr.ht/~bakpakin/janet/commits/meson_min.yml?)
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">
@@ -19,6 +17,9 @@ to run script files. This client program is separate from the core runtime, so
Janet can be embedded in other programs. Try Janet in your browser at
[https://janet-lang.org](https://janet-lang.org).
If you'd like to financially support the ongoing development of Janet, consider
[sponsoring its primary author](https://github.com/sponsors/bakpakin) through GitHub.
<br>
## Use Cases
@@ -60,9 +61,9 @@ Documentation is also available locally in the REPL.
Use the `(doc symbol-name)` macro to get API
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
environment, use the `(all-bindings)` function. You
@@ -172,7 +173,7 @@ Emacs, and Atom will have syntax packages for the Janet language, though.
## Installation
See [the Introduction](https://janet-lang.org/introduction.html) for more details. If you just want
See the [Introduction](https://janet-lang.org/docs/index.html) for more details. If you just want
to try out the language, you don't need to install anything. You can also move the `janet` executable wherever you want on your system and run it.
## Usage
@@ -233,7 +234,7 @@ See the examples directory for some example janet code.
## Discussion
Feel free to ask questions and join the discussion on the [Janet Gitter Channel](https://gitter.im/janet-language/community).
Alternatively, check out [the #janet channel on Freenode](https://webchat.freenode.net/)
Gitter provides Matrix and irc bridges as well.
## FAQ
@@ -245,8 +246,35 @@ will not. If your terminal does not support ANSI escape codes, run the REPL with
the `-n` flag, which disables color output. You can also try the `-s` if further issues
ensue.
## Why Janet
### Where is (favorite feature from other language)?
It may exist, it may not. If you want to propose major language features, go ahead and open an issue, but
they will likely by closed as "will not implement". Often, such features make one usecase simpler at the expense
of 5 others by making the language more complicated.
### Where is the example code?
In the examples directory.
### Is this a Clojure port?
No. It's similar to Clojure superficially because I like Lisps and I like the asthetics.
Internally, Janet is not at all like Clojure.
### Are the immutable data structures (tuples and structs) implemented as hash tries?
No. They are immutable arrays and hash tables. Don't try and use them like Clojure's vectors
and maps, instead they work well as table keys or other identifiers.
### Why can't we add (feature from Clojure) into the core?
Usually, one of a few reasons:
- Often, it already exists in a different form and the Clojure port would be redundant.
- Clojure programs often generate a lot of garbage and rely on the JVM to clean it up.
Janet does not run on the JVM. We admittedly have a much more primitive GC.
- We want to keep the Janet core small. With Lisps, usually a feature can be added as a library
without feeling "bolted on", especially when compared to ALGOL like languages.
## Why is it called "Janet"?
Janet is named after the almost omniscient and friendly artificial being in [The Good Place](https://en.wikipedia.org/wiki/The_Good_Place).
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-the-good-place.gif" alt="Janet logo" width="115px" align="left">

View File

@@ -35,9 +35,6 @@ artifacts:
- name: janet.h
path: dist\janet.h
type: File
- name: janetconf.h
path: dist\janetconf.h
type: File
- name: shell.c
path: dist\shell.c
type: File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

View File

@@ -28,10 +28,10 @@ if not "%JANET_BUILD%" == "" (
@set JANET_COMPILE=%JANET_COMPILE% /DJANET_BUILD="\"%JANET_BUILD%\""
)
mkdir build
mkdir build\core
mkdir build\mainclient
mkdir build\boot
if not exist build mkdir build
if not exist build\core mkdir build\core
if not exist build\c mkdir build\c
if not exist build\boot mkdir build\boot
@rem Build the bootstrap interpreter
for %%f in (src\core\*.c) do (
@@ -44,10 +44,10 @@ for %%f in (src\boot\*.c) do (
)
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
@if errorlevel 1 goto :BUILDFAIL
build\janet_boot . > build\janet.c
build\janet_boot . > build\c\janet.c
@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
%JANET_COMPILE% /Fobuild\shell.obj src\mainclient\shell.c
@if errorlevel 1 goto :BUILDFAIL
@@ -102,9 +102,9 @@ exit /b 0
mkdir dist
janet.exe tools\gendoc.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 janet.exe dist\janet.exe
copy LICENSE dist\LICENSE
@@ -113,12 +113,11 @@ copy README.md dist\README.md
copy janet.lib dist\janet.lib
copy janet.exp dist\janet.exp
copy src\include\janet.h dist\janet.h
copy src\conf\janetconf.h dist\janetconf.h
janet.exe tools\patch-header.janet src\include\janet.h src\conf\janetconf.h build\janet.h
copy build\janet.h dist\janet.h
copy build\libjanet.lib dist\libjanet.lib
copy .\jpm dist\jpm
copy tools\jpm.bat dist\jpm.bat
@rem Create installer
janet.exe -e "(->> janet/version (peg/match ''(* :d+ `.` :d+ `.` :d+)) first print)" > build\version.txt

View File

@@ -0,0 +1,22 @@
(defn dowork [name n]
(print name " starting work...")
(os/execute [(dyn :executable) "-e" (string "(os/sleep " n ")")])
(print name " finished work!"))
# Will be done in parallel
(print "starting group A")
(ev/call dowork "A 2" 2)
(ev/call dowork "A 1" 1)
(ev/call dowork "A 3" 3)
(ev/sleep 4)
# Will also be done in parallel
(print "starting group B")
(ev/call dowork "B 2" 2)
(ev/call dowork "B 1" 1)
(ev/call dowork "B 3" 3)
(ev/sleep 4)
(print "all work done")

View File

@@ -0,0 +1,19 @@
(def f
(coro
(for i 0 10
(yield (string "yield " i))
(os/sleep 0))))
(print "simple yielding")
(each item f (print "got: " item ", now " (fiber/status f)))
(def f
(coro
(for i 0 10
(yield (string "yield " i))
(ev/sleep 0))))
(print "complex yielding")
(each item f (print "got: " item ", now " (fiber/status f)))
(print (fiber/status f))

View File

@@ -7,13 +7,13 @@ typedef struct {
} num_array;
static num_array *num_array_init(num_array *array, size_t size) {
array->data = (double *)calloc(size, sizeof(double));
array->data = (double *)janet_calloc(size, sizeof(double));
array->size = size;
return array;
}
static void num_array_deinit(num_array *array) {
free(array->data);
janet_free(array->data);
}
static int num_array_gc(void *p, size_t s) {

View File

@@ -1,73 +0,0 @@
# naive matrix implementation for testing typed array
(defn matrix [nrow ncol] {:nrow nrow :ncol ncol :array (tarray/new :float64 (* nrow ncol))})
(defn matrix/row [mat i]
(def {:nrow nrow :ncol ncol :array array} mat)
(tarray/new :float64 ncol 1 (* i ncol) array))
(defn matrix/column [mat j]
(def {:nrow nrow :ncol ncol :array array} mat)
(tarray/new :float64 nrow ncol j array))
(defn matrix/set [mat i j value]
(def {:nrow nrow :ncol ncol :array array} mat)
(set (array (+ (* i ncol) j)) value))
(defn matrix/get [mat i j value]
(def {:nrow nrow :ncol ncol :array array} mat)
(array (+ (* i ncol) j)))
# other variants to test rows and cols views
(defn matrix/set* [mat i j value]
(set ((matrix/row mat i) j) value))
(defn matrix/set** [mat i j value]
(set ((matrix/column mat j) i) value))
(defn matrix/get* [mat i j value]
((matrix/row mat i) j))
(defn matrix/get** [mat i j value]
((matrix/column mat j) i))
(defn tarray/print [arr]
(def size (tarray/length arr))
(prinf "[%2i]" size)
(for i 0 size
(prinf " %+6.3f " (arr i)))
(print))
(defn matrix/print [mat]
(def {:nrow nrow :ncol ncol :array tarray} mat)
(printf "matrix %iX%i %p" nrow ncol tarray)
(for i 0 nrow
(tarray/print (matrix/row mat i))))
(def nr 5)
(def nc 4)
(def A (matrix nr nc))
(loop (i :range (0 nr) j :range (0 nc))
(matrix/set A i j i))
(matrix/print A)
(loop (i :range (0 nr) j :range (0 nc))
(matrix/set* A i j i))
(matrix/print A)
(loop (i :range (0 nr) j :range (0 nc))
(matrix/set** A i j i))
(matrix/print A)
(printf "properties:\n%p" (tarray/properties (A :array)))
(for i 0 nr
(printf "row properties:[%i]\n%p" i (tarray/properties (matrix/row A i))))
(for i 0 nc
(printf "col properties:[%i]\n%p" i (tarray/properties (matrix/column A i))))

View File

@@ -1,4 +1,4 @@
(def server (net/server "127.0.0.1" "8009" nil :datagram))
(def server (net/listen "127.0.0.1" "8009" :datagram))
(while true
(def buf @"")
(def who (:recv-from server 1024 buf))

33
janet.1
View File

@@ -8,6 +8,8 @@ janet \- run the Janet language abstract machine
[\fB\-l\fR \fIMODULE\fR]
[\fB\-m\fR \fIPATH\fR]
[\fB\-c\fR \fIMODULE JIMAGE\fR]
[\fB\-w\fR \fILEVEL\fR]
[\fB\-x\fR \fILEVEL\fR]
[\fB\-\-\fR]
.BR script
.BR args ...
@@ -64,6 +66,10 @@ Move cursor to the beginning of input line.
.BR Ctrl\-B
Move cursor one character to the left.
.TP 16
.BR Ctrl\-D
If on a newline, indicate end of stream and exit the repl.
.TP 16
.BR Ctrl\-E
Move cursor to the end of input line.
@@ -100,6 +106,10 @@ Delete one word before the cursor.
.BR Ctrl\-G
Show documentation for the current symbol under the cursor.
.TP 16
.BR Ctrl\-Q
Clear the current command, including already typed lines.
.TP 16
.BR Alt\-B/Alt\-F
Move cursor backwards and forwards one word.
@@ -167,6 +177,10 @@ Disable ANSI colors in the repl. Has no effect if no repl is run.
Open a REPL (Read Eval Print Loop) after executing all sources. By default, if Janet is called with no
arguments, a REPL is opened.
.TP
.BR \-R
If using the REPL, disable loading the user profile from the JANET_PROFILE environment variable.
.TP
.BR \-p
Turn on the persistent flag. By default, when Janet is executing commands from a file and encounters an error,
@@ -198,7 +212,18 @@ resulting image. Output should usually end with the .jimage extension.
Import a Janet module before running a script or repl. Multiple files can be loaded
in this manner, and exports from each file will be made available to the script
or repl.
.TP
.BR \-w\ level
Set the warning linting level for Janet.
This linting level should be one of :relaxed, :none, :strict, :normal, or a
Janet number. Any linting message that is of a greater lint level than this setting will be displayed as
a warning, but not stop compilation or execution.
.TP
.BR \-x\ level
Set the error linting level for Janet.
This linting level should be one of :relaxed, :none, :strict, :normal, or a
Janet number. Any linting message that is of a greater lint level will cause a compilation error
and stop compilation.
.TP
.BR \-\-
Stop parsing command line arguments. All arguments after this one will be considered file names
@@ -213,6 +238,12 @@ find native and source code modules. If no JANET_PATH is set, Janet will look in
the default location set at compile time.
.RE
.B JANET_PROFILE
.RS
Path to a profile file that the interpreter will load before entering the REPL. This profile file will
not run for scripts, though. This behavior can be disabled with the -R option.
.RE
.B JANET_HASHSEED
.RS
To disable randomization of Janet's PRF on start up, one can set this variable. This can have the

276
jpm
View File

@@ -6,14 +6,21 @@
# Basic Path Settings
#
# Windows is the OS outlier
(def- is-win (= (os/which) :windows))
(def- is-mac (= (os/which) :macos))
(def- sep (if is-win "\\" "/"))
(def- objext (if is-win ".obj" ".o"))
(def- modext (if is-win ".dll" ".so"))
(def- statext (if is-win ".static.lib" ".a"))
(def- absprefix (if is-win "C:\\" "/"))
# Allow changing the behavior via an environment variable
(def- host-os (keyword (string/ascii-lower (os/getenv "JPM_OS_WHICH" (os/which)))))
(defn- define-utils
[]
(def is-win (= host-os :windows))
(defglobal 'is-win is-win)
(defglobal 'is-mac (= host-os :macos))
(def sep (if is-win "\\" "/"))
(defglobal 'sep sep)
(defglobal 'objext (if is-win ".obj" ".o"))
(defglobal 'modext (if is-win ".dll" ".so"))
(defglobal 'statext (if is-win ".static.lib" ".a"))
(defglobal 'absprefix (if is-win "C:\\" "/")))
(define-utils)
#
# Defaults
@@ -22,6 +29,19 @@
###START###
# Overriden on some installs.
# To configure this script, replace the code between
# the START and END comments and define a function
# (install-paths) that gives the the default paths
# to use. Trailing directory separator not expected.
#
# Example.
#
# (defn- install-paths []
# {:headerpath "/usr/local/include/janet"
# :libpath "/usr/local/lib/janet"
# :binpath "/usr/local/bin"
#
(def- exe-dir
"Directory containing jpm script"
(do
@@ -29,13 +49,28 @@
(def i (last (string/find-all sep exe)))
(slice exe 0 i)))
(defn- try-real [path]
"If os/realpath fails just use normal path."
(try (os/realpath path) ([_] path)))
(defn- install-paths []
{:headerpath (os/realpath (string exe-dir "/../include/janet"))
:libpath (os/realpath (string exe-dir "/../lib"))
{:headerpath (try-real (string exe-dir "/../include/janet"))
:libpath (try-real (string exe-dir "/../lib"))
:binpath exe-dir})
# If janetconf.h has been modified such that core janet functions and macros require
# linking to external libraries, modify this.
#
# Example - (def- extra-lflags ["-lmimalloc"])
###END###
# Redefine utils in case the above section is overriden on some installs.
(define-utils)
(compwhen (not (dyn 'extra-lflags))
(def- extra-lflags []))
# Default based on janet binary location
(def JANET_HEADERPATH (or (os/getenv "JANET_HEADERPATH")
(get (install-paths) :headerpath)))
@@ -152,9 +187,7 @@
[& args]
(if (dyn :verbose)
(print ;(interpose " " args)))
(def res (os/execute args :p))
(unless (zero? res)
(error (string "command exited with status " res))))
(os/execute args :px))
(defn copy
"Copy a file or directory recursively from one location to another."
@@ -347,11 +380,11 @@
# flags needed for the janet binary and compiling standalone
# executables.
(def janet-lflags
(case (os/which)
:macos ["-ldl" "-lm" ;thread-flags]
:windows [;thread-flags]
:linux ["-lm" "-ldl" "-lrt" ;thread-flags]
["-lm" ;thread-flags]))
(case host-os
:macos ["-ldl" "-lm" ;thread-flags ;extra-lflags]
:windows [;thread-flags ;extra-lflags]
:linux ["-lm" "-ldl" "-lrt" ;thread-flags ;extra-lflags]
["-lm" ;thread-flags ;extra-lflags]))
(def janet-ldflags [])
(def janet-cflags [])
@@ -437,6 +470,7 @@
[opts]
@[;(opt opts :cflags default-cflags)
(string "-I" (dyn :headerpath JANET_HEADERPATH))
(string "-I" (dyn :modpath JANET_MODPATH))
(string "-O" (opt opts :optimize 2))])
(defn- getcppflags
@@ -444,6 +478,7 @@
[opts]
@[;(opt opts :cppflags default-cppflags)
(string "-I" (dyn :headerpath JANET_HEADERPATH))
(string "-I" (dyn :modpath JANET_MODPATH))
(string "-O" (opt opts :optimize 2))])
(defn- entry-name
@@ -506,35 +541,26 @@
(string hpath `\\janet.lib`))
(defn- link-c
"Link C object files together to make a native module."
[opts target & objects]
(def linker (opt opts (if is-win :linker :compiler) default-linker))
(def cflags (getcflags opts))
"Link C or C++ object files together to make a native module."
[has-cpp opts target & objects]
(def linker
(if has-cpp
(opt opts (if is-win :cpp-linker :cpp-compiler) default-cpp-linker)
(opt opts (if is-win :linker :compiler) default-linker)))
(def cflags ((if has-cpp getcppflags getcflags) opts))
(def lflags [;(opt opts :lflags default-lflags)
;(if (opts :static) [] dynamic-lflags)])
(def ldflags [;(opt opts :ldflags [])])
(def deplibs (get opts :native-deps []))
(def dep-ldflags (seq [x :in deplibs] (string (dyn :modpath JANET_MODPATH) sep x modext)))
# Use import libs on windows - we need an import lib to link natives to other natives.
(def dep-importlibs (seq [x :in deplibs] (string (dyn :modpath JANET_MODPATH) sep x ".lib")))
(def ldflags [;(opt opts :ldflags []) ;dep-ldflags])
(rule target objects
(check-cc)
(print "linking " target "...")
(create-dirs target)
(if is-win
(shell linker ;ldflags (string "/OUT:" target) ;objects (win-import-library) ;lflags)
(shell linker ;cflags ;ldflags `-o` target ;objects ;lflags))))
(defn- link-cpp
"Link C++ object files together to make a native module."
[opts target & objects]
(def linker (opt opts (if is-win :cpp-linker :cpp-compiler) default-cpp-linker))
(def cflags (getcppflags opts))
(def lflags [;(opt opts :lflags default-lflags)
;(if (opts :static) [] dynamic-lflags)])
(def ldflags [;(opt opts :ldflags [])])
(rule target objects
(check-cc)
(print "linking " target "...")
(create-dirs target)
(if is-win
(shell linker ;ldflags (string "/OUT:" target) ;objects (win-import-library) ;lflags)
(shell linker ;ldflags (string "/OUT:" target) ;objects (win-import-library) ;dep-importlibs ;lflags)
(shell linker ;cflags ;ldflags `-o` target ;objects ;lflags))))
(defn- archive-c
@@ -585,7 +611,7 @@
(string (string/slice path 0 (- -1 (length modext))) statext))
(defn- make-bin-source
[declarations lookup-into-invocations]
[declarations lookup-into-invocations no-core]
(string
declarations
```
@@ -610,15 +636,22 @@ int main(int argc, const char **argv) {
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 */
JanetTable *env = janet_core_env(NULL);
JanetTable *lookup = janet_env_lookup(env);
JanetTable *temptab;
int handle = janet_gclock();
/* Load natives into unmarshalling dictionary */
```
```)
lookup-into-invocations
```
/* Unmarshal bytecode */
@@ -646,7 +679,6 @@ int main(int argc, const char **argv) {
}
/* Create enviornment */
temptab = janet_table(0);
temptab = env;
janet_table_put(temptab, janet_ckeywordv("args"), janet_wrap_array(args));
janet_gcroot(janet_wrap_table(temptab));
@@ -657,6 +689,14 @@ int main(int argc, const char **argv) {
/* Run everything */
JanetFiber *fiber = janet_fiber(jfunc, 64, argc, argc ? args->data : NULL);
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;
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
if (result != JANET_SIGNAL_OK && result != JANET_SIGNAL_EVENT) {
@@ -664,11 +704,9 @@ int main(int argc, const char **argv) {
janet_deinit();
return result;
}
#ifdef JANET_NET
janet_loop();
#endif
janet_deinit();
return 0;
#endif
}
```))
@@ -677,7 +715,7 @@ int main(int argc, const char **argv) {
"Links an image with libjanet.a (or .lib) to produce an
executable. Also will try to link native modules into the
final executable as well."
[opts source dest]
[opts source dest no-core]
# Create executable's janet image
(def cimage_dest (string dest ".c"))
@@ -693,7 +731,16 @@ int main(int argc, const char **argv) {
(def dep-ldflags @[])
# 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
(def prefixes @{})
(def static-libs @[])
@@ -738,7 +785,7 @@ int main(int argc, const char **argv) {
# Make image byte buffer
(create-buffer-c-impl image cimage_dest "janet_payload_image")
# 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"))
# Compile and link final exectable
(unless no-compile
@@ -932,17 +979,18 @@ int main(int argc, const char **argv) {
(var has-cpp false)
(def objects
(seq [src :in sources]
(cond
(string/has-suffix? ".cpp" src)
(let [op (out-path src ".cpp" objext)]
(compile-cpp opts src op)
(set has-cpp true)
op)
(string/has-suffix? ".c" src)
(let [op (out-path src ".c" objext)]
(compile-c opts src op)
op)
(errorf "unknown source file type: %s, expected .c or .cpp"))))
(def suffix
(cond
(string/has-suffix? ".cpp" src) ".cpp"
(string/has-suffix? ".cc" src) ".cc"
(string/has-suffix? ".c" src) ".c"
(errorf "unknown source file type: %s, expected .c, .cc, or .cpp" src)))
(def op (out-path src suffix objext))
(if (= suffix ".c")
(compile-c opts src op)
(do (compile-cpp opts src op)
(set has-cpp true)))
op))
(when-let [embedded (opts :embedded)]
(loop [src :in embedded]
@@ -951,7 +999,7 @@ int main(int argc, const char **argv) {
(array/push objects o-src)
(create-buffer-c src c-src (embed-name src))
(compile-c opts c-src o-src)))
((if has-cpp link-cpp link-c) opts lname ;objects)
(link-c has-cpp opts lname ;objects)
(add-dep "build" lname)
(install-rule lname path)
@@ -980,16 +1028,17 @@ int main(int argc, const char **argv) {
# Get static objects
(def sobjects
(seq [src :in sources]
(cond
(string/has-suffix? ".cpp" src)
(let [op (out-path src ".cpp" sobjext)]
(compile-cpp opts src op true)
op)
(string/has-suffix? ".c" src)
(let [op (out-path src ".c" sobjext)]
(compile-c opts src op true)
op)
(errorf "unknown source file type: %s, expected .c or .cpp"))))
(def suffix
(cond
(string/has-suffix? ".cpp" src) ".cpp"
(string/has-suffix? ".cc" src) ".cc"
(string/has-suffix? ".c" src) ".c"
(errorf "unknown source file type: %s, expected .c, .cc, or .cpp" src)))
(def op (out-path src suffix sobjext))
(if (= suffix ".c")
(compile-c opts src op true)
(compile-cpp opts src op true))
op))
(when-let [embedded (opts :embedded)]
(loop [src :in embedded]
@@ -1015,6 +1064,16 @@ int main(int argc, const char **argv) {
(each s sources
(install-rule s path))))
(defn declare-headers
"Declare headers for a library installation. Installed headers can be used by other native
libraries."
[&keys {:headers headers :prefix prefix}]
(def path (string (dyn :modpath JANET_MODPATH) (or prefix "")))
(if (bytes? headers)
(install-rule headers path)
(each h headers
(install-rule h path))))
(defn declare-bin
"Declare a generic file to be installed as an executable."
[&keys {:main main}]
@@ -1027,10 +1086,10 @@ int main(int argc, const char **argv) {
This executable can be installed as well to the --binpath given."
[&keys {:install install :name name :entry entry :headers headers
: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 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
(let [cdest (string dest ".c")]
(add-dep "build" cdest))
@@ -1044,12 +1103,15 @@ int main(int argc, const char **argv) {
(install-rule dest (dyn :binpath JANET_BINPATH))))))
(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
such that it will run correctly even when JANET_PATH is changed."
[&keys {:main main :hardcode-syspath hardcode}]
such that it will run correctly even when JANET_PATH is changed. if auto-shebang
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))
(if hardcode
(def auto-shebang (and is-janet (dyn :auto-shebang)))
(if (or auto-shebang hardcode)
(let [syspath (dyn :modpath JANET_MODPATH)]
(def parts (peg/match path-splitter main))
(def name (last parts))
@@ -1061,7 +1123,9 @@ int main(int argc, const char **argv) {
(def first-line (:read f :line))
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
(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)
(spit path contents)
(unless is-win (shell "chmod" "+x" path))))
@@ -1337,7 +1401,9 @@ Flags are:
(defn quickbin
[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))
(defn jpm-debug-repl
@@ -1384,26 +1450,30 @@ Flags are:
"load-lockfile" load-lockfile
"quickbin" quickbin})
(def- args (tuple/slice (dyn :args) 1))
(def- len (length args))
(var i :private 0)
(defn- main
"Script entry."
[& argv]
# Get flags
(while (< i len)
(if-let [m (peg/match argpeg (args i))]
(if (= 2 (length m))
(let [[key value] m]
(setdyn (keyword key) value))
(setdyn (keyword (m 0)) true))
(break))
(++ i))
(def- args (tuple/slice argv 1))
(def- len (length args))
(var i :private 0)
# 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)))))
# Get flags
(while (< i len)
(if-let [m (peg/match argpeg (args i))]
(if (= 2 (length m))
(let [[key value] m]
(setdyn (keyword key) value))
(setdyn (keyword (m 0)) true))
(break))
(++ 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))))))

29
jpm.1
View File

@@ -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
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
.TP
@@ -265,5 +269,30 @@ An optional path to a git executable to use to clone git dependencies. By defaul
if you have a normal install of git.
.RE
.B JPM_OS_WHICH
.RS
Use this option to override the C compiler and build system auto-detection for the host operating system. For example, set this
environment variable to "posix" to make sure that on platforms like MinGW, you will use GCC instead of MSVC. On most platforms, users will not need to
set this environment variable. Set this to one of the following
strings:
.IP
\- windows
.IP
\- macos
.IP
\- linux
.IP
\- freebsd
.IP
\- openbsd
.IP
\- netbsd
.IP
\- bsd
.IP
\- posix
.RE
.SH AUTHOR
Written by Calvin Rose <calsrose@gmail.com>

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose and contributors
# Copyright (c) 2021 Calvin Rose and contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -19,8 +19,8 @@
# IN THE SOFTWARE.
project('janet', 'c',
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.13.0')
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.16.1')
# Global settings
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')
# 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')
endif
@@ -60,9 +60,8 @@ conf.set('JANET_NO_SOURCEMAPS', not get_option('sourcemaps'))
conf.set('JANET_NO_ASSEMBLER', not get_option('assembler'))
conf.set('JANET_NO_PEG', not get_option('peg'))
conf.set('JANET_NO_NET', not get_option('net'))
conf.set('JANET_NO_EV', not get_option('ev'))
conf.set('JANET_NO_EV', not get_option('ev') or get_option('single_threaded'))
conf.set('JANET_REDUCED_OS', get_option('reduced_os'))
conf.set('JANET_NO_TYPED_ARRAY', not get_option('typed_array'))
conf.set('JANET_NO_INT_TYPES', not get_option('int_types'))
conf.set('JANET_PRF', get_option('prf'))
conf.set('JANET_RECURSION_GUARD', get_option('recursion_guard'))
@@ -73,6 +72,7 @@ conf.set('JANET_NO_UMASK', not get_option('umask'))
conf.set('JANET_NO_REALPATH', not get_option('realpath'))
conf.set('JANET_NO_PROCESSES', not get_option('processes'))
conf.set('JANET_SIMPLE_GETLINE', get_option('simple_getline'))
conf.set('JANET_EV_EPOLL', get_option('epoll'))
if get_option('os_name') != ''
conf.set('JANET_OS_NAME', get_option('os_name'))
endif
@@ -134,7 +134,6 @@ core_src = [
'src/core/table.c',
'src/core/thread.c',
'src/core/tuple.c',
'src/core/typedarray.c',
'src/core/util.c',
'src/core/value.c',
'src/core/vector.c',
@@ -172,9 +171,14 @@ janetc = custom_target('janetc',
'JANET_PATH', janet_path, 'JANET_HEADERPATH', header_path
])
janet_dependencies = [m_dep, dl_dep]
if not get_option('single_threaded')
janet_dependencies += thread_dep
endif
libjanet = library('janet', janetc,
include_directories : incdir,
dependencies : [m_dep, dl_dep, thread_dep],
dependencies : janet_dependencies,
version: meson.project_version(),
soversion: version_parts[0] + '.' + version_parts[1],
install : true)
@@ -188,7 +192,7 @@ else
endif
janet_mainclient = executable('janet', janetc, mainclient_src,
include_directories : incdir,
dependencies : [m_dep, dl_dep, thread_dep],
dependencies : janet_dependencies,
c_args : extra_cflags,
install : true)
@@ -201,7 +205,7 @@ if meson.is_cross_build()
endif
janet_nativeclient = executable('janet-native', janetc, mainclient_src,
include_directories : incdir,
dependencies : [m_dep, dl_dep, thread_dep],
dependencies : janet_dependencies,
c_args : extra_native_cflags,
native : true)
else
@@ -243,12 +247,19 @@ janet_dep = declare_dependency(include_directories : incdir,
# pkgconfig
pkg = import('pkgconfig')
pkg.generate(libjanet,
subdirs: 'janet',
description: 'Library for the Janet programming language.')
# Installation
install_man('janet.1')
install_headers(['src/include/janet.h', jconf], subdir: 'janet')
install_data(sources : ['tools/.keep'], install_dir : join_paths(get_option('libdir'), 'janet'))
patched_janet = custom_target('patched-janeth',
input : ['tools/patch-header.janet', 'src/include/janet.h', jconf],
install : true,
install_dir : join_paths(get_option('includedir'), 'janet'),
build_by_default : true,
output : ['janet.h'],
command : [janet_nativeclient, '@INPUT@', '@OUTPUT@'])
if get_option('peg') and not get_option('reduced_os') and get_option('processes')
install_man('jpm.1')
patched_jpm = custom_target('patched-jpm',

View File

@@ -8,7 +8,6 @@ option('sourcemaps', type : 'boolean', value : true)
option('reduced_os', type : 'boolean', value : false)
option('assembler', type : 'boolean', value : true)
option('peg', type : 'boolean', value : true)
option('typed_array', type : 'boolean', value : true)
option('int_types', type : 'boolean', value : true)
option('prf', type : 'boolean', value : false)
option('net', type : 'boolean', value : true)
@@ -17,6 +16,7 @@ option('processes', type : 'boolean', value : true)
option('umask', type : 'boolean', value : true)
option('realpath', type : 'boolean', value : true)
option('simple_getline', type : 'boolean', value : false)
option('epoll', type : 'boolean', value : false)
option('recursion_guard', type : 'integer', min : 10, max : 8000, value : 1024)
option('max_proto_depth', type : 'integer', min : 10, max : 8000, value : 200)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -93,7 +93,7 @@ int main(int argc, const char **argv) {
fseek(boot_file, 0, SEEK_END);
size_t boot_size = ftell(boot_file);
fseek(boot_file, 0, SEEK_SET);
unsigned char *boot_buffer = malloc(boot_size);
unsigned char *boot_buffer = janet_malloc(boot_size);
if (NULL == boot_buffer) {
fprintf(stderr, "Failed to allocate boot buffer\n");
exit(1);
@@ -105,7 +105,7 @@ int main(int argc, const char **argv) {
fclose(boot_file);
status = janet_dobytes(env, boot_buffer, (int32_t) boot_size, boot_filename, NULL);
free(boot_buffer);
janet_free(boot_buffer);
/* Deinitialize vm */
janet_deinit();

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,36 +1,13 @@
/*
* Copyright (c) 2020 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* This is an example janetconf.h file. This will be usually generated
* by the build system. */
/* This will be generated by the build system if this file is not used */
#ifndef JANETCONF_H
#define JANETCONF_H
#define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 13
#define JANET_VERSION_PATCH 0
#define JANET_VERSION_EXTRA "-dev"
#define JANET_VERSION "1.13.0-dev"
#define JANET_VERSION_MINOR 16
#define JANET_VERSION_PATCH 1
#define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.16.1"
/* #define JANET_BUILD "local" */
@@ -50,7 +27,6 @@
/* #define JANET_NO_ASSEMBLER */
/* #define JANET_NO_PEG */
/* #define JANET_NO_NET */
/* #define JANET_NO_TYPED_ARRAY */
/* #define JANET_NO_INT_TYPES */
/* #define JANET_NO_EV */
/* #define JANET_NO_REALPATH */
@@ -72,6 +48,13 @@
/* #define JANET_ARCH_NAME pdp-8 */
/* #define JANET_EV_EPOLL */
/* Custom vm allocator support */
/* #include <mimalloc.h> */
/* #define janet_malloc(X) mi_malloc((X)) */
/* #define janet_realloc(X, Y) mi_realloc((X), (Y)) */
/* #define janet_calloc(X, Y) mi_calloc((X), (Y)) */
/* #define janet_free(X) mi_free((X)) */
/* Main client settings, does not affect library code */
/* #define JANET_SIMPLE_GETLINE */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -36,7 +36,7 @@ JanetArray *janet_array(int32_t capacity) {
Janet *data = NULL;
if (capacity > 0) {
janet_vm_next_collection += capacity * sizeof(Janet);
data = (Janet *) malloc(sizeof(Janet) * (size_t) capacity);
data = (Janet *) janet_malloc(sizeof(Janet) * (size_t) capacity);
if (NULL == data) {
JANET_OUT_OF_MEMORY;
}
@@ -52,7 +52,7 @@ JanetArray *janet_array_n(const Janet *elements, int32_t n) {
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
array->capacity = n;
array->count = n;
array->data = malloc(sizeof(Janet) * (size_t) n);
array->data = janet_malloc(sizeof(Janet) * (size_t) n);
if (!array->data) {
JANET_OUT_OF_MEMORY;
}
@@ -68,7 +68,7 @@ void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth) {
int64_t new_capacity = ((int64_t) capacity) * growth;
if (new_capacity > INT32_MAX) new_capacity = INT32_MAX;
capacity = (int32_t) new_capacity;
newData = realloc(old, capacity * sizeof(Janet));
newData = janet_realloc(old, capacity * sizeof(Janet));
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
@@ -275,7 +275,7 @@ static Janet cfun_array_trim(int32_t argc, Janet *argv) {
JanetArray *array = janet_getarray(argv, 0);
if (array->count) {
if (array->count < array->capacity) {
Janet *newData = realloc(array->data, array->count * sizeof(Janet));
Janet *newData = janet_realloc(array->data, array->count * sizeof(Janet));
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
@@ -284,12 +284,19 @@ static Janet cfun_array_trim(int32_t argc, Janet *argv) {
}
} else {
array->capacity = 0;
free(array->data);
janet_free(array->data);
array->data = NULL;
}
return argv[0];
}
static Janet cfun_array_clear(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetArray *array = janet_getarray(argv, 0);
array->count = 0;
return argv[0];
}
static const JanetReg array_cfuns[] = {
{
"array/new", cfun_array_new,
@@ -370,6 +377,12 @@ static const JanetReg array_cfuns[] = {
JDOC("(array/trim arr)\n\n"
"Set the backing capacity of an array to its current length. Returns the modified array.")
},
{
"array/clear", cfun_array_clear,
JDOC("(array/clear arr)\n\n"
"Empties an array, setting it's count to 0 but does not free the backing capacity. "
"Returns the modified array.")
},
{NULL, NULL, NULL}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -224,7 +224,7 @@ static int32_t janet_asm_addenv(JanetAssembler *a, Janet envname) {
janet_table_put(&a->envs, envname, janet_wrap_number(envindex));
if (envindex >= a->environments_capacity) {
int32_t newcap = 2 * envindex;
def->environments = realloc(def->environments, newcap * sizeof(int32_t));
def->environments = janet_realloc(def->environments, newcap * sizeof(int32_t));
if (NULL == def->environments) {
JANET_OUT_OF_MEMORY;
}
@@ -582,7 +582,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
x = janet_get1(s, janet_ckeywordv("constants"));
if (janet_indexed_view(x, &arr, &count)) {
def->constants_length = count;
def->constants = malloc(sizeof(Janet) * (size_t) count);
def->constants = janet_malloc(sizeof(Janet) * (size_t) count);
if (NULL == def->constants) {
JANET_OUT_OF_MEMORY;
}
@@ -614,7 +614,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
newlen = def->defs_length + 1;
if (a.defs_capacity < newlen) {
int32_t newcap = newlen;
def->defs = realloc(def->defs, newcap * sizeof(JanetFuncDef *));
def->defs = janet_realloc(def->defs, newcap * sizeof(JanetFuncDef *));
if (NULL == def->defs) {
JANET_OUT_OF_MEMORY;
}
@@ -643,7 +643,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
}
/* Allocate bytecode array */
def->bytecode_length = blength;
def->bytecode = malloc(sizeof(uint32_t) * (size_t) blength);
def->bytecode = janet_malloc(sizeof(uint32_t) * (size_t) blength);
if (NULL == def->bytecode) {
JANET_OUT_OF_MEMORY;
}
@@ -685,7 +685,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
x = janet_get1(s, janet_ckeywordv("sourcemap"));
if (janet_indexed_view(x, &arr, &count)) {
janet_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode");
def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) count);
def->sourcemap = janet_malloc(sizeof(JanetSourceMapping) * (size_t) count);
if (NULL == def->sourcemap) {
JANET_OUT_OF_MEMORY;
}
@@ -711,7 +711,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
/* Set environments */
def->environments =
realloc(def->environments, def->environments_length * sizeof(int32_t));
janet_realloc(def->environments, def->environments_length * sizeof(int32_t));
if (NULL == def->environments) {
JANET_OUT_OF_MEMORY;
}
@@ -992,18 +992,18 @@ static const JanetReg asm_cfuns[] = {
"func must be a function, not a c function. Will throw on error on a badly\n"
"typed argument. If given a field name, will only return that part of the function assembly.\n"
"Possible fields are:\n\n"
"\t:arity - number of required and optional arguments.\n"
"\t:min-arity - minimum number of arguments function can be called with.\n"
"\t:max-arity - maximum number of arguments function can be called with.\n"
"\t:vararg - true if function can take a variable number of arguments.\n"
"\t:bytecode - array of parsed bytecode instructions. Each instruction is a tuple.\n"
"\t:source - name of source file that this function was compiled from.\n"
"\t:name - name of function.\n"
"\t:slotcount - how many virtual registers, or slots, this function uses. Corresponds to stack space used by function.\n"
"\t:constants - an array of constants referenced by this function.\n"
"\t:sourcemap - a mapping of each bytecode instruction to a line and column in the source file.\n"
"\t:environments - an internal mapping of which enclosing functions are referenced for bindings.\n"
"\t:defs - other function definitions that this function may instantiate.\n")
"* :arity - number of required and optional arguments.\n\n"
"* :min-arity - minimum number of arguments function can be called with.\n\n"
"* :max-arity - maximum number of arguments function can be called with.\n\n"
"* :vararg - true if function can take a variable number of arguments.\n\n"
"* :bytecode - array of parsed bytecode instructions. Each instruction is a tuple.\n\n"
"* :source - name of source file that this function was compiled from.\n\n"
"* :name - name of function.\n\n"
"* :slotcount - how many virtual registers, or slots, this function uses. Corresponds to stack space used by function.\n\n"
"* :constants - an array of constants referenced by this function.\n\n"
"* :sourcemap - a mapping of each bytecode instruction to a line and column in the source file.\n\n"
"* :environments - an internal mapping of which enclosing functions are referenced for bindings.\n\n"
"* :defs - other function definitions that this function may instantiate.\n")
},
{NULL, NULL, NULL}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -31,12 +31,11 @@
/* Initialize a buffer */
JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) {
uint8_t *data = NULL;
if (capacity > 0) {
janet_gcpressure(capacity);
data = malloc(sizeof(uint8_t) * (size_t) capacity);
if (NULL == data) {
JANET_OUT_OF_MEMORY;
}
if (capacity < 4) capacity = 4;
janet_gcpressure(capacity);
data = janet_malloc(sizeof(uint8_t) * (size_t) capacity);
if (NULL == data) {
JANET_OUT_OF_MEMORY;
}
buffer->count = 0;
buffer->capacity = capacity;
@@ -46,7 +45,7 @@ JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) {
/* Deinitialize a buffer (free data memory) */
void janet_buffer_deinit(JanetBuffer *buffer) {
free(buffer->data);
janet_free(buffer->data);
}
/* Initialize a buffer */
@@ -63,7 +62,7 @@ void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth)
int64_t big_capacity = ((int64_t) capacity) * growth;
capacity = big_capacity > INT32_MAX ? INT32_MAX : (int32_t) big_capacity;
janet_gcpressure(capacity - buffer->capacity);
new_data = realloc(old, (size_t) capacity * sizeof(uint8_t));
new_data = janet_realloc(old, (size_t) capacity * sizeof(uint8_t));
if (NULL == new_data) {
JANET_OUT_OF_MEMORY;
}
@@ -92,8 +91,8 @@ void janet_buffer_extra(JanetBuffer *buffer, int32_t n) {
}
int32_t new_size = buffer->count + n;
if (new_size > buffer->capacity) {
int32_t new_capacity = new_size * 2;
uint8_t *new_data = realloc(buffer->data, new_capacity * sizeof(uint8_t));
int32_t new_capacity = (new_size > (INT32_MAX / 2)) ? INT32_MAX : (new_size * 2);
uint8_t *new_data = janet_realloc(buffer->data, new_capacity * sizeof(uint8_t));
janet_gcpressure(new_capacity - buffer->capacity);
if (NULL == new_data) {
JANET_OUT_OF_MEMORY;
@@ -200,19 +199,14 @@ static Janet cfun_buffer_fill(int32_t argc, Janet *argv) {
static Janet cfun_buffer_trim(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
if (buffer->count) {
if (buffer->count < buffer->capacity) {
uint8_t *newData = realloc(buffer->data, buffer->count);
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
buffer->data = newData;
buffer->capacity = buffer->count;
if (buffer->count < buffer->capacity) {
int32_t newcap = buffer->count > 4 ? buffer->count : 4;
uint8_t *newData = janet_realloc(buffer->data, newcap);
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
} else {
buffer->capacity = 0;
free(buffer->data);
buffer->data = NULL;
buffer->data = newData;
buffer->capacity = newcap;
}
return argv[0];
}
@@ -256,6 +250,26 @@ static Janet cfun_buffer_chars(int32_t argc, Janet *argv) {
return argv[0];
}
static Janet cfun_buffer_push(int32_t argc, Janet *argv) {
int32_t i;
janet_arity(argc, 1, -1);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
for (i = 1; i < argc; i++) {
if (janet_checktype(argv[i], JANET_NUMBER)) {
janet_buffer_push_u8(buffer, (uint8_t)(janet_getinteger(argv, i) & 0xFF));
} else {
JanetByteView view = janet_getbytes(argv, i);
if (view.bytes == buffer->data) {
janet_buffer_ensure(buffer, buffer->count + view.len, 2);
view.bytes = buffer->data;
}
janet_buffer_push_bytes(buffer, view.bytes, view.len);
}
}
return argv[0];
}
static Janet cfun_buffer_clear(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
@@ -407,22 +421,32 @@ static const JanetReg buffer_cfuns[] = {
},
{
"buffer/push-byte", cfun_buffer_u8,
JDOC("(buffer/push-byte buffer x)\n\n"
"Append a byte to a buffer. Will expand the buffer as necessary. "
JDOC("(buffer/push-byte buffer & xs)\n\n"
"Append bytes to a buffer. Will expand the buffer as necessary. "
"Returns the modified buffer. Will throw an error if the buffer overflows.")
},
{
"buffer/push-word", cfun_buffer_word,
JDOC("(buffer/push-word buffer x)\n\n"
"Append a machine word to a buffer. The 4 bytes of the integer are appended "
"in twos complement, little endian order, unsigned. Returns the modified buffer. Will "
JDOC("(buffer/push-word buffer & xs)\n\n"
"Append machine words to a buffer. The 4 bytes of the integer are appended "
"in twos complement, little endian order, unsigned for all x. Returns the modified buffer. Will "
"throw an error if the buffer overflows.")
},
{
"buffer/push-string", cfun_buffer_chars,
JDOC("(buffer/push-string buffer str)\n\n"
"Push a string onto the end of a buffer. Non string values will be converted "
"to strings before being pushed. Returns the modified buffer. "
JDOC("(buffer/push-string buffer & xs)\n\n"
"Push byte sequences onto the end of a buffer. "
"Will accept any of strings, keywords, symbols, and buffers. "
"Returns the modified buffer. "
"Will throw an error if the buffer overflows.")
},
{
"buffer/push", cfun_buffer_push,
JDOC("(buffer/push buffer & xs)\n\n"
"Push both individual bytes and byte sequences to a buffer. For each x in xs, "
"push the byte if x is an integer, otherwise push the bytesequence to the buffer. "
"Thus, this function behaves like both `buffer/push-string` and `buffer/push-byte`. "
"Returns the modified buffer. "
"Will throw an error if the buffer overflows.")
},
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -53,7 +53,9 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
void janet_signalv(JanetSignal sig, Janet message) {
if (janet_vm_return_reg != NULL) {
*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)
_longjmp(*janet_vm_jmp_buf, sig);
#else
@@ -147,6 +149,23 @@ int janet_getmethod(const uint8_t *method, const JanetMethod *methods, Janet *ou
return 0;
}
Janet janet_nextmethod(const JanetMethod *methods, Janet key) {
if (!janet_checktype(key, JANET_NIL)) {
while (methods->name) {
if (janet_keyeq(key, methods->name)) {
methods++;
break;
}
methods++;
}
}
if (methods->name) {
return janet_ckeywordv(methods->name);
} else {
return janet_wrap_nil();
}
}
DEFINE_GETTER(number, NUMBER, double)
DEFINE_GETTER(array, ARRAY, JanetArray *)
DEFINE_GETTER(tuple, TUPLE, const Janet *)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -53,6 +53,36 @@ void janetc_cerror(JanetCompiler *c, const char *m) {
janetc_error(c, janet_cstring(m));
}
static const char *janet_lint_level_names[] = {
"relaxed",
"normal",
"strict"
};
/* Emit compiler linter messages */
void janetc_lintf(JanetCompiler *c, JanetCompileLintLevel level, const char *format, ...) {
if (NULL != c->lints) {
/* format message */
va_list args;
JanetBuffer buffer;
int32_t len = 0;
while (format[len]) len++;
janet_buffer_init(&buffer, len);
va_start(args, format);
janet_formatbv(&buffer, format, args);
va_end(args);
const uint8_t *str = janet_string(buffer.data, buffer.count);
janet_buffer_deinit(&buffer);
/* construct linting payload */
Janet *payload = janet_tuple_begin(4);
payload[0] = janet_ckeywordv(janet_lint_level_names[level]);
payload[1] = c->current_mapping.line == -1 ? janet_wrap_nil() : janet_wrap_integer(c->current_mapping.line);
payload[2] = c->current_mapping.column == -1 ? janet_wrap_nil() : janet_wrap_integer(c->current_mapping.column);
payload[3] = janet_wrap_string(str);
janet_array_push(c->lints, janet_wrap_tuple(janet_tuple_end(payload)));
}
}
/* Free a slot */
void janetc_freeslot(JanetCompiler *c, JanetSlot s) {
if (s.flags & (JANET_SLOT_CONSTANT | JANET_SLOT_REF | JANET_SLOT_NAMED)) return;
@@ -199,24 +229,41 @@ JanetSlot janetc_resolve(
/* Symbol not found - check for global */
{
Janet check;
JanetBindingType btype = janet_resolve(c->env, sym, &check);
switch (btype) {
JanetBinding binding = janet_resolve_ext(c->env, sym);
switch (binding.type) {
default:
case JANET_BINDING_NONE:
janetc_error(c, janet_formatc("unknown symbol %q", janet_wrap_symbol(sym)));
return janetc_cslot(janet_wrap_nil());
case JANET_BINDING_DEF:
case JANET_BINDING_MACRO: /* Macro should function like defs when not in calling pos */
return janetc_cslot(check);
ret = janetc_cslot(binding.value);
break;
case JANET_BINDING_VAR: {
JanetSlot ret = janetc_cslot(check);
/* TODO save type info */
ret = janetc_cslot(binding.value);
ret.flags |= JANET_SLOT_REF | JANET_SLOT_NAMED | JANET_SLOT_MUTABLE | JANET_SLOTTYPE_ANY;
ret.flags &= ~JANET_SLOT_CONSTANT;
return ret;
break;
}
}
JanetCompileLintLevel depLevel = JANET_C_LINT_RELAXED;
switch (binding.deprecation) {
case JANET_BINDING_DEP_NONE:
break;
case JANET_BINDING_DEP_RELAXED:
depLevel = JANET_C_LINT_RELAXED;
break;
case JANET_BINDING_DEP_NORMAL:
depLevel = JANET_C_LINT_NORMAL;
break;
case JANET_BINDING_DEP_STRICT:
depLevel = JANET_C_LINT_STRICT;
break;
}
if (binding.deprecation != JANET_BINDING_DEP_NONE) {
janetc_lintf(c, depLevel, "%q is deprecated", janet_wrap_symbol(sym));
}
return ret;
}
/* Symbol was found */
@@ -399,6 +446,7 @@ void janetc_throwaway(JanetFopts opts, Janet x) {
int32_t mapbufstart = janet_v_count(c->mapbuffer);
janetc_scope(&unusedScope, c, JANET_SCOPE_UNUSED, "unusued");
janetc_value(opts, x);
janetc_lintf(c, JANET_C_LINT_STRICT, "dead code, consider removing %.2q", x);
janetc_popscope(c);
if (c->buffer) {
janet_v__cnt(c->buffer) = bufstart;
@@ -439,22 +487,22 @@ static JanetSlot janetc_call(JanetFopts opts, JanetSlot *slots, JanetSlot fun) {
min_arity = -1 - min_arity;
if (min_arity > max && max >= 0) {
const uint8_t *es = janet_formatc(
"%v expects at most %d argument, got at least %d",
fun.constant, max, min_arity);
"%v expects at most %d argument%s, got at least %d",
fun.constant, max, max == 1 ? "" : "s", min_arity);
janetc_error(c, es);
}
} else {
/* Call has no splices */
if (min_arity > max && max >= 0) {
const uint8_t *es = janet_formatc(
"%v expects at most %d argument, got %d",
fun.constant, max, min_arity);
"%v expects at most %d argument%s, got %d",
fun.constant, max, max == 1 ? "" : "s", min_arity);
janetc_error(c, es);
}
if (min_arity < min) {
const uint8_t *es = janet_formatc(
"%v expects at least %d argument, got %d",
fun.constant, min, min_arity);
"%v expects at least %d argument%s, got %d",
fun.constant, min, min == 1 ? "" : "s", min_arity);
janetc_error(c, es);
}
}
@@ -504,10 +552,40 @@ static JanetSlot janetc_call(JanetFopts opts, JanetSlot *slots, JanetSlot fun) {
static JanetSlot janetc_maker(JanetFopts opts, JanetSlot *slots, int op) {
JanetCompiler *c = opts.compiler;
JanetSlot retslot;
janetc_pushslots(c, slots);
janetc_freeslots(c, slots);
retslot = janetc_gettarget(opts);
janetc_emit_s(c, op, retslot, 1);
/* Check if this structure is composed entirely of constants */
int can_inline = 1;
for (int32_t i = 0; i < janet_v_count(slots); i++) {
if (!(slots[i].flags & JANET_SLOT_CONSTANT) ||
(slots[i].flags & JANET_SLOT_SPLICED)) {
can_inline = 0;
break;
}
}
if (can_inline && (op == JOP_MAKE_STRUCT)) {
JanetKV *st = janet_struct_begin(janet_v_count(slots) / 2);
for (int32_t i = 0; i < janet_v_count(slots); i += 2) {
Janet k = slots[i].constant;
Janet v = slots[i + 1].constant;
janet_struct_put(st, k, v);
}
retslot = janetc_cslot(janet_wrap_struct(janet_struct_end(st)));
janetc_freeslots(c, slots);
} else if (can_inline && (op == JOP_MAKE_TUPLE)) {
Janet *tup = janet_tuple_begin(janet_v_count(slots));
for (int32_t i = 0; i < janet_v_count(slots); i++) {
tup[i] = slots[i].constant;
}
retslot = janetc_cslot(janet_wrap_tuple(janet_tuple_end(tup)));
janetc_freeslots(c, slots);
} else {
janetc_pushslots(c, slots);
janetc_freeslots(c, slots);
retslot = janetc_gettarget(opts);
janetc_emit_s(c, op, retslot, 1);
}
return retslot;
}
@@ -601,6 +679,9 @@ static int macroexpand1(
Janet tempOut;
JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &tempOut);
janet_table_put(c->env, mf_kw, janet_wrap_nil());
if (c->lints) {
janet_table_put(c->env, janet_ckeywordv("macro-lints"), janet_wrap_array(c->lints));
}
janet_gcunlock(lock);
if (status != JANET_SIGNAL_OK) {
const uint8_t *es = janet_formatc("(macro) %V", tempOut);
@@ -745,7 +826,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
def->bytecode_length = janet_v_count(c->buffer) - scope->bytecode_start;
if (def->bytecode_length) {
size_t s = sizeof(int32_t) * (size_t) def->bytecode_length;
def->bytecode = malloc(s);
def->bytecode = janet_malloc(s);
if (NULL == def->bytecode) {
JANET_OUT_OF_MEMORY;
}
@@ -753,7 +834,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
janet_v__cnt(c->buffer) = scope->bytecode_start;
if (NULL != c->mapbuffer && c->source) {
size_t s = sizeof(JanetSourceMapping) * (size_t) def->bytecode_length;
def->sourcemap = malloc(s);
def->sourcemap = janet_malloc(s);
if (NULL == def->sourcemap) {
JANET_OUT_OF_MEMORY;
}
@@ -778,7 +859,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
int32_t slotchunks = (def->slotcount + 31) >> 5;
/* numchunks is min of slotchunks and scope->ua.count */
int32_t numchunks = slotchunks > scope->ua.count ? scope->ua.count : slotchunks;
uint32_t *chunks = calloc(sizeof(uint32_t), slotchunks);
uint32_t *chunks = janet_calloc(sizeof(uint32_t), slotchunks);
if (NULL == chunks) {
JANET_OUT_OF_MEMORY;
}
@@ -795,7 +876,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
}
/* Initialize a compiler */
static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where) {
static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where, JanetArray *lints) {
c->scope = NULL;
c->buffer = NULL;
c->mapbuffer = NULL;
@@ -804,6 +885,7 @@ static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where)
c->source = where;
c->current_mapping.line = -1;
c->current_mapping.column = -1;
c->lints = lints;
/* Init result */
c->result.error = NULL;
c->result.status = JANET_COMPILE_OK;
@@ -821,12 +903,13 @@ static void janetc_deinit(JanetCompiler *c) {
}
/* Compile a form. */
JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *where) {
JanetCompileResult janet_compile_lint(Janet source,
JanetTable *env, const uint8_t *where, JanetArray *lints) {
JanetCompiler c;
JanetScope rootscope;
JanetFopts fopts;
janetc_init(&c, env, where);
janetc_init(&c, env, where, lints);
/* Push a function scope */
janetc_scope(&rootscope, &c, JANET_SCOPE_FUNCTION | JANET_SCOPE_TOP, "root");
@@ -854,26 +937,35 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w
return c.result;
}
JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *where) {
return janet_compile_lint(source, env, where, NULL);
}
/* C Function for compiling */
static Janet cfun(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 3);
janet_arity(argc, 1, 4);
JanetTable *env = argc > 1 ? janet_gettable(argv, 1) : janet_vm_fiber->env;
if (NULL == env) {
env = janet_table(0);
janet_vm_fiber->env = env;
}
const uint8_t *source = NULL;
if (argc == 3) {
if (argc >= 3) {
source = janet_getstring(argv, 2);
}
JanetCompileResult res = janet_compile(argv[0], env, source);
JanetArray *lints = (argc >= 4) ? janet_getarray(argv, 3) : NULL;
JanetCompileResult res = janet_compile_lint(argv[0], env, source, lints);
if (res.status == JANET_COMPILE_OK) {
return janet_wrap_function(janet_thunk(res.funcdef));
} else {
JanetTable *t = janet_table(4);
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));
janet_table_put(t, janet_ckeywordv("column"), janet_wrap_integer(res.error_mapping.column));
if (res.error_mapping.line > 0) {
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) {
janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber));
}
@@ -884,11 +976,13 @@ static Janet cfun(int32_t argc, Janet *argv) {
static const JanetReg compile_cfuns[] = {
{
"compile", cfun,
JDOC("(compile ast &opt env source)\n\n"
JDOC("(compile ast &opt env source lints)\n\n"
"Compiles an Abstract Syntax Tree (ast) into a function. "
"Pair the compile function with parsing functionality to implement "
"eval. Returns a new function and does not modify ast. Returns an error "
"struct with keys :line, :column, and :error if compilation fails.")
"struct with keys :line, :column, and :error if compilation fails. "
"If a `lints` array is given, linting messages will be appended to the array. "
"Each message will be a tuple of the form `(level line col message)`.")
},
{NULL, NULL, NULL}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -29,6 +29,13 @@
#include "regalloc.h"
#endif
/* Levels for compiler warnings */
typedef enum {
JANET_C_LINT_RELAXED,
JANET_C_LINT_NORMAL,
JANET_C_LINT_STRICT
} JanetCompileLintLevel;
/* Tags for some functions for the prepared inliner */
#define JANET_FUN_DEBUG 1
#define JANET_FUN_ERROR 2
@@ -78,10 +85,10 @@ typedef struct JanetSpecial JanetSpecial;
#define JANET_SLOT_MUTABLE 0x40000
#define JANET_SLOT_REF 0x80000
#define JANET_SLOT_RETURNED 0x100000
/* Needed for handling single element arrays as global vars. */
/* Used for unquote-splicing */
#define JANET_SLOT_SPLICED 0x200000
#define JANET_SLOT_DEP_NOTE 0x200000
#define JANET_SLOT_DEP_WARN 0x400000
#define JANET_SLOT_DEP_ERROR 0x800000
#define JANET_SLOT_SPLICED 0x1000000
#define JANET_SLOTTYPE_ANY 0xFFFF
@@ -164,6 +171,9 @@ struct JanetCompiler {
/* Prevent unbounded recursion */
int recursion_guard;
/* Collect linting results */
JanetArray *lints;
};
#define JANET_FOPTS_TAIL 0x10000
@@ -230,6 +240,9 @@ JanetSlot janetc_return(JanetCompiler *c, JanetSlot s);
void janetc_error(JanetCompiler *c, const uint8_t *m);
void janetc_cerror(JanetCompiler *c, const char *m);
/* Linting */
void janetc_lintf(JanetCompiler *C, JanetCompileLintLevel level, const char *format, ...);
/* Dispatch to correct form compiler */
JanetSlot janetc_value(JanetFopts opts, Janet x);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -70,7 +70,7 @@ static char *get_processed_name(const char *name) {
if (*c == '/') return (char *) name;
}
size_t l = (size_t)(c - name);
char *ret = malloc(l + 3);
char *ret = janet_malloc(l + 3);
if (NULL == ret) {
JANET_OUT_OF_MEMORY;
}
@@ -85,7 +85,7 @@ JanetModule janet_native(const char *name, const uint8_t **error) {
Clib lib = load_clib(processed_name);
JanetModule init;
JanetModconf getter;
if (name != processed_name) free(processed_name);
if (name != processed_name) janet_free(processed_name);
if (!lib) {
*error = janet_cstring(error_clib());
return NULL;
@@ -548,35 +548,35 @@ static const JanetReg corelib_cfuns[] = {
{
"describe", janet_core_describe,
JDOC("(describe x)\n\n"
"Returns a string that is a human readable description of a value x.")
"Returns a string that is a human-readable description of a value x.")
},
{
"string", janet_core_string,
JDOC("(string & parts)\n\n"
"Creates a string by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. "
JDOC("(string & xs)\n\n"
"Creates a string by concatenating the elements of `xs` together. If an "
"element is not a byte sequence, it is converted to bytes via `describe`. "
"Returns the new string.")
},
{
"symbol", janet_core_symbol,
JDOC("(symbol & xs)\n\n"
"Creates a symbol by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns "
"the new symbol.")
"Creates a symbol by concatenating the elements of `xs` together. If an "
"element is not a byte sequence, it is converted to bytes via `describe`. "
"Returns the new symbol.")
},
{
"keyword", janet_core_keyword,
JDOC("(keyword & xs)\n\n"
"Creates a keyword by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns "
"the new keyword.")
"Creates a keyword by concatenating the elements of `xs` together. If an "
"element is not a byte sequence, it is converted to bytes via `describe`. "
"Returns the new keyword.")
},
{
"buffer", janet_core_buffer,
JDOC("(buffer & xs)\n\n"
"Creates a new buffer by concatenating values together. Values are "
"converted to bytes via describe if they are not byte sequences. Returns "
"the new buffer.")
"Creates a buffer by concatenating the elements of `xs` together. If an "
"element is not a byte sequence, it is converted to bytes via `describe`. "
"Returns the new buffer.")
},
{
"abstract?", janet_core_is_abstract,
@@ -645,20 +645,21 @@ static const JanetReg corelib_cfuns[] = {
{
"type", janet_core_type,
JDOC("(type x)\n\n"
"Returns the type of x as a keyword. x is one of\n"
"\t:nil\n"
"\t:boolean\n"
"\t:number\n"
"\t:array\n"
"\t:tuple\n"
"\t:table\n"
"\t:struct\n"
"\t:string\n"
"\t:buffer\n"
"\t:symbol\n"
"\t:keyword\n"
"\t:function\n"
"\t:cfunction\n\n"
"Returns the type of `x` as a keyword. `x` is one of:\n\n"
"* :nil\n\n"
"* :boolean\n\n"
"* :number\n\n"
"* :array\n\n"
"* :tuple\n\n"
"* :table\n\n"
"* :struct\n\n"
"* :string\n\n"
"* :buffer\n\n"
"* :symbol\n\n"
"* :keyword\n\n"
"* :function\n\n"
"* :cfunction\n\n"
"* :fiber\n\n"
"or another keyword for an abstract type.")
},
{
@@ -699,16 +700,16 @@ static const JanetReg corelib_cfuns[] = {
{
"module/expand-path", janet_core_expand_path,
JDOC("(module/expand-path path template)\n\n"
"Expands a path template as found in module/paths for module/find. "
"This takes in a path (the argument to require) and a template string, template, "
"Expands a path template as found in `module/paths` for `module/find`. "
"This takes in a path (the argument to require) and a template string, "
"to expand the path to a path that can be "
"used for importing files. The replacements are as follows:\n\n"
"\t:all:\tthe value of path verbatim\n"
"\t:cur:\tthe current file, or (dyn :current-file)\n"
"\t:dir:\tthe directory containing the current file\n"
"\t:name:\tthe name component of path, with extension if given\n"
"\t:native:\tthe extension used to load natives, .so or .dll\n"
"\t:sys:\tthe system path, or (dyn :syspath)")
"* :all: -- the value of path verbatim\n\n"
"* :cur: -- the current file, or (dyn :current-file)\n\n"
"* :dir: -- the directory containing the current file\n\n"
"* :name: -- the name component of path, with extension if given\n\n"
"* :native: -- the extension used to load natives, .so or .dll\n\n"
"* :sys: -- the system path, or (dyn :syspath)")
},
{
"int?", janet_core_check_int,
@@ -753,7 +754,7 @@ static void janet_quick_asm(
def->max_arity = max_arity;
def->flags = flags;
def->slotcount = slots;
def->bytecode = malloc(bytecode_size);
def->bytecode = janet_malloc(bytecode_size);
def->bytecode_length = (int32_t)(bytecode_size / sizeof(uint32_t));
def->name = janet_cstring(name);
if (!def->bytecode) {
@@ -1025,9 +1026,6 @@ static void janet_load_libs(JanetTable *env) {
#ifdef JANET_ASSEMBLER
janet_lib_asm(env);
#endif
#ifdef JANET_TYPED_ARRAY
janet_lib_typed_array(env);
#endif
#ifdef JANET_INT_TYPES
janet_lib_inttypes(env);
#endif
@@ -1205,7 +1203,8 @@ JanetTable *janet_core_env(JanetTable *replacements) {
"if native modules are compatible with the host program."));
/* 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_gcroot(janet_wrap_table(env));
@@ -1220,7 +1219,42 @@ JanetTable *janet_core_env(JanetTable *replacements) {
return janet_vm_core_env;
}
/* Load core cfunctions (and some built in janet assembly functions) */
JanetTable *dict = janet_core_lookup_table(replacements);
/* Unmarshal bytecode */
Janet marsh_out = janet_unmarshal(
janet_core_image,
janet_core_image_size,
0,
dict,
NULL);
/* Memoize */
janet_gcroot(marsh_out);
JanetTable *env = janet_unwrap_table(marsh_out);
janet_vm_core_env = env;
/* Invert image dict manually here. We can't do this in boot.janet as it
* breaks deterministic builds */
Janet lidv, midv;
lidv = midv = janet_wrap_nil();
janet_resolve(env, janet_csymbol("load-image-dict"), &lidv);
janet_resolve(env, janet_csymbol("make-image-dict"), &midv);
JanetTable *lid = janet_unwrap_table(lidv);
JanetTable *mid = janet_unwrap_table(midv);
for (int32_t i = 0; i < lid->capacity; i++) {
const JanetKV *kv = lid->data + i;
if (!janet_checktype(kv->key, JANET_NIL)) {
janet_table_put(mid, kv->value, kv->key);
}
}
return env;
}
#endif
JanetTable *janet_core_lookup_table(JanetTable *replacements) {
JanetTable *dict = janet_table(512);
janet_load_libs(dict);
@@ -1237,20 +1271,5 @@ JanetTable *janet_core_env(JanetTable *replacements) {
}
}
/* Unmarshal bytecode */
Janet marsh_out = janet_unmarshal(
janet_core_image,
janet_core_image_size,
0,
dict,
NULL);
/* Memoize */
janet_gcroot(marsh_out);
JanetTable *env = janet_unwrap_table(marsh_out);
janet_vm_core_env = env;
return env;
return dict;
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -102,7 +102,9 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) {
int32_t fi;
const char *errstr = (const char *)janet_to_string(err);
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"));
if (print_color) janet_eprintf("\x1b[31m");
@@ -299,9 +301,10 @@ static Janet cfun_debug_stack(int32_t argc, Janet *argv) {
}
static Janet cfun_debug_stacktrace(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
janet_arity(argc, 1, 2);
JanetFiber *fiber = janet_getfiber(argv, 0);
janet_stacktrace(fiber, argv[1]);
Janet x = argc == 1 ? janet_wrap_nil() : argv[1];
janet_stacktrace(fiber, x);
return argv[0];
}
@@ -325,12 +328,12 @@ static Janet cfun_debug_step(int32_t argc, Janet *argv) {
static const JanetReg debug_cfuns[] = {
{
"debug/break", cfun_debug_break,
JDOC("(debug/break source byte-offset)\n\n"
"Sets a breakpoint with source a key at a given line and column. "
JDOC("(debug/break source line col)\n\n"
"Sets a breakpoint in `source` at a given line and column. "
"Will throw an error if the breakpoint location "
"cannot be found. For example\n\n"
"\t(debug/break \"core.janet\" 1000)\n\n"
"wil set a breakpoint at the 1000th byte of the file core.janet.")
"\t(debug/break \"core.janet\" 10 4)\n\n"
"wil set a breakpoint at line 10, 4th column of the file core.janet.")
},
{
"debug/unbreak", cfun_debug_unbreak,
@@ -362,25 +365,25 @@ static const JanetReg debug_cfuns[] = {
"debug/stack", cfun_debug_stack,
JDOC("(debug/stack fib)\n\n"
"Gets information about the stack as an array of tables. Each table "
"in the array contains information about a stack frame. The top most, current "
"stack frame is the first table in the array, and the bottom most stack frame "
"in the array contains information about a stack frame. The top-most, current "
"stack frame is the first table in the array, and the bottom-most stack frame "
"is the last value. Each stack frame contains some of the following attributes:\n\n"
"\t:c - true if the stack frame is a c function invocation\n"
"\t:column - the current source column of the stack frame\n"
"\t:function - the function that the stack frame represents\n"
"\t:line - the current source line of the stack frame\n"
"\t:name - the human friendly name of the function\n"
"\t:pc - integer indicating the location of the program counter\n"
"\t:source - string with the file path or other identifier for the source code\n"
"\t:slots - array of all values in each slot\n"
"\t:tail - boolean indicating a tail call")
"* :c - true if the stack frame is a c function invocation\n\n"
"* :column - the current source column of the stack frame\n\n"
"* :function - the function that the stack frame represents\n\n"
"* :line - the current source line of the stack frame\n\n"
"* :name - the human-friendly name of the function\n\n"
"* :pc - integer indicating the location of the program counter\n\n"
"* :source - string with the file path or other identifier for the source code\n\n"
"* :slots - array of all values in each slot\n\n"
"* :tail - boolean indicating a tail call")
},
{
"debug/stacktrace", cfun_debug_stacktrace,
JDOC("(debug/stacktrace fiber err)\n\n"
"Prints a nice looking stacktrace for a fiber. The error message "
"err must be passed to the function as fiber's do not keep track of "
"the last error they have thrown. Returns the fiber.")
JDOC("(debug/stacktrace fiber &opt err)\n\n"
"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 "
"provided, will skipp the error line. Returns the fiber.")
},
{
"debug/lineage", cfun_debug_lineage,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -27,7 +27,7 @@
#if defined(__NetBSD__) || defined(__APPLE__) || defined(__OpenBSD__) \
|| defined(__bsdi__) || defined(__DragonFly__)
/* Use BSD soucre on any BSD systems, include OSX */
/* Use BSD source on any BSD systems, include OSX */
# define _BSD_SOURCE
#else
/* Use POSIX feature flags */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -37,9 +37,11 @@ static void fiber_reset(JanetFiber *fiber) {
fiber->child = NULL;
fiber->flags = JANET_FIBER_MASK_YIELD | JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
fiber->env = NULL;
fiber->last_value = janet_wrap_nil();
#ifdef JANET_EV
fiber->waiting = NULL;
fiber->sched_id = 0;
fiber->supervisor_channel = NULL;
#endif
janet_fiber_set_status(fiber, JANET_STATUS_NEW);
}
@@ -51,7 +53,7 @@ static JanetFiber *fiber_alloc(int32_t capacity) {
capacity = 32;
}
fiber->capacity = capacity;
data = malloc(sizeof(Janet) * (size_t) capacity);
data = janet_malloc(sizeof(Janet) * (size_t) capacity);
if (NULL == data) {
JANET_OUT_OF_MEMORY;
}
@@ -81,7 +83,10 @@ JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t
}
if (janet_fiber_funcframe(fiber, callee)) return NULL;
janet_fiber_frame(fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
#ifdef JANET_EV
fiber->waiting = NULL;
fiber->supervisor_channel = NULL;
#endif
return fiber;
}
@@ -95,12 +100,12 @@ JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity, int32_t argc, c
static void janet_fiber_refresh_memory(JanetFiber *fiber) {
int32_t n = fiber->capacity;
if (n) {
Janet *newData = malloc(sizeof(Janet) * n);
Janet *newData = janet_malloc(sizeof(Janet) * n);
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
memcpy(newData, fiber->data, fiber->capacity * sizeof(Janet));
free(fiber->data);
janet_free(fiber->data);
fiber->data = newData;
}
}
@@ -110,7 +115,7 @@ static void janet_fiber_refresh_memory(JanetFiber *fiber) {
void janet_fiber_setcapacity(JanetFiber *fiber, int32_t n) {
int32_t old_size = fiber->capacity;
int32_t diff = n - old_size;
Janet *newData = realloc(fiber->data, sizeof(Janet) * n);
Janet *newData = janet_realloc(fiber->data, sizeof(Janet) * n);
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
@@ -249,7 +254,7 @@ static void janet_env_detach(JanetFuncEnv *env) {
janet_env_valid(env);
int32_t len = env->length;
size_t s = sizeof(Janet) * (size_t) len;
Janet *vmem = malloc(s);
Janet *vmem = janet_malloc(s);
janet_vm_next_collection += (uint32_t) s;
if (NULL == vmem) {
JANET_OUT_OF_MEMORY;
@@ -418,8 +423,7 @@ void janet_fiber_cframe(JanetFiber *fiber, JanetCFunction cfun) {
newframe->flags = 0;
}
/* Pop a stack frame from the fiber. Returns the new stack frame, or
* NULL if there are no more frames */
/* Pop a stack frame from the fiber. */
void janet_fiber_popframe(JanetFiber *fiber) {
JanetStackFrame *frame = janet_fiber_frame(fiber);
if (fiber->frame == 0) return;
@@ -585,6 +589,12 @@ static Janet cfun_fiber_can_resume(int32_t argc, Janet *argv) {
return janet_wrap_boolean(!isFinished);
}
static Janet cfun_fiber_last_value(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetFiber *fiber = janet_getfiber(argv, 0);
return fiber->last_value;
}
static const JanetReg fiber_cfuns[] = {
{
"fiber/new", cfun_fiber_new,
@@ -592,34 +602,37 @@ static const JanetReg fiber_cfuns[] = {
"Create a new fiber with function body func. Can optionally "
"take a set of signals to block from the current parent fiber "
"when called. The mask is specified as a keyword where each character "
"is used to indicate a signal to block. The default sigmask is :y. "
"For example, \n\n"
"\t(fiber/new myfun :e123)\n\n"
"is used to indicate a signal to block. If the ev module is enabled, and "
"this fiber is used as an argument to `ev/go`, these \"blocked\" signals "
"will result in messages being sent to the supervisor channel. "
"The default sigmask is :y. "
"For example,\n\n"
" (fiber/new myfun :e123)\n\n"
"blocks error signals and user signals 1, 2 and 3. The signals are "
"as follows: \n\n"
"\ta - block all signals\n"
"\td - block debug signals\n"
"\te - block error signals\n"
"\tt - block termination signals: error + user[0-4]\n"
"\tu - block user signals\n"
"\ty - block yield signals\n"
"\t0-9 - block a specific user signal\n\n"
"as follows:\n\n"
"* :a - block all signals\n"
"* :d - block debug signals\n"
"* :e - block error signals\n"
"* :t - block termination signals: error + user[0-4]\n"
"* :u - block user signals\n"
"* :y - block yield signals\n"
"* :0-9 - block a specific user signal\n\n"
"The sigmask argument also can take environment flags. If any mutually "
"exclusive flags are present, the last flag takes precedence.\n\n"
"\ti - inherit the environment from the current fiber\n"
"\tp - the environment table's prototype is the current environment table")
"* :i - inherit the environment from the current fiber\n"
"* :p - the environment table's prototype is the current environment table")
},
{
"fiber/status", cfun_fiber_status,
JDOC("(fiber/status fib)\n\n"
"Get the status of a fiber. The status will be one of:\n\n"
"\t:dead - the fiber has finished\n"
"\t:error - the fiber has errored out\n"
"\t:debug - the fiber is suspended in debug mode\n"
"\t:pending - the fiber has been yielded\n"
"\t:user(0-9) - the fiber is suspended by a user signal\n"
"\t:alive - the fiber is currently running and cannot be resumed\n"
"\t:new - the fiber has just been created and not yet run")
"* :dead - the fiber has finished\n"
"* :error - the fiber has errored out\n"
"* :debug - the fiber is suspended in debug mode\n"
"* :pending - the fiber has been yielded\n"
"* :user(0-9) - the fiber is suspended by a user signal\n"
"* :alive - the fiber is currently running and cannot be resumed\n"
"* :new - the fiber has just been created and not yet run")
},
{
"fiber/root", cfun_fiber_root,
@@ -662,6 +675,11 @@ static const JanetReg fiber_cfuns[] = {
JDOC("(fiber/can-resume? fiber)\n\n"
"Check if a fiber is finished and cannot be resumed.")
},
{
"fiber/last-value", cfun_fiber_last_value,
JDOC("(fiber/last-value\n\n"
"Get the last value returned or signaled from the fiber.")
},
{NULL, NULL, NULL}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -226,11 +226,14 @@ static void janet_mark_function(JanetFunction *func) {
if (janet_gc_reachable(func))
return;
janet_gc_mark(func);
numenvs = func->def->environments_length;
for (i = 0; i < numenvs; ++i) {
janet_mark_funcenv(func->envs[i]);
if (NULL != func->def) {
/* this should always be true, except if function is only partially constructed */
numenvs = func->def->environments_length;
for (i = 0; i < numenvs; ++i) {
janet_mark_funcenv(func->envs[i]);
}
janet_mark_funcdef(func->def);
}
janet_mark_funcdef(func->def);
}
static void janet_mark_fiber(JanetFiber *fiber) {
@@ -241,6 +244,8 @@ recur:
return;
janet_gc_mark(fiber);
janet_mark(fiber->last_value);
/* Mark values on the argument stack */
janet_mark_many(fiber->data + fiber->stackstart,
fiber->stacktop - fiber->stackstart);
@@ -262,6 +267,12 @@ recur:
if (fiber->env)
janet_mark_table(fiber->env);
#ifdef JANET_EV
if (fiber->supervisor_channel) {
janet_mark_abstract(fiber->supervisor_channel);
}
#endif
/* Explicit tail recursion */
if (fiber->child) {
fiber = fiber->child;
@@ -279,13 +290,13 @@ static void janet_deinit_block(JanetGCObject *mem) {
janet_symbol_deinit(((JanetStringHead *) mem)->data);
break;
case JANET_MEMORY_ARRAY:
free(((JanetArray *) mem)->data);
janet_free(((JanetArray *) mem)->data);
break;
case JANET_MEMORY_TABLE:
free(((JanetTable *) mem)->data);
janet_free(((JanetTable *) mem)->data);
break;
case JANET_MEMORY_FIBER:
free(((JanetFiber *)mem)->data);
janet_free(((JanetFiber *)mem)->data);
break;
case JANET_MEMORY_BUFFER:
janet_buffer_deinit((JanetBuffer *) mem);
@@ -300,18 +311,18 @@ static void janet_deinit_block(JanetGCObject *mem) {
case JANET_MEMORY_FUNCENV: {
JanetFuncEnv *env = (JanetFuncEnv *)mem;
if (0 == env->offset)
free(env->as.values);
janet_free(env->as.values);
}
break;
case JANET_MEMORY_FUNCDEF: {
JanetFuncDef *def = (JanetFuncDef *)mem;
/* TODO - get this all with one alloc and one free */
free(def->defs);
free(def->environments);
free(def->constants);
free(def->bytecode);
free(def->sourcemap);
free(def->closure_bitset);
janet_free(def->defs);
janet_free(def->environments);
janet_free(def->constants);
janet_free(def->bytecode);
janet_free(def->sourcemap);
janet_free(def->closure_bitset);
}
break;
}
@@ -336,7 +347,7 @@ void janet_sweep() {
} else {
janet_vm_blocks = next;
}
free(current);
janet_free(current);
}
current = next;
}
@@ -348,7 +359,7 @@ void *janet_gcalloc(enum JanetMemoryType type, size_t size) {
/* Make sure everything is inited */
janet_assert(NULL != janet_vm_cache, "please initialize janet before use");
mem = malloc(size);
mem = janet_malloc(size);
/* Check for bad malloc */
if (NULL == mem) {
@@ -371,7 +382,7 @@ static void free_one_scratch(JanetScratch *s) {
if (NULL != s->finalize) {
s->finalize((char *) s->mem);
}
free(s);
janet_free(s);
}
/* Free all allocated scratch memory */
@@ -423,7 +434,7 @@ void janet_gcroot(Janet root) {
size_t newcount = janet_vm_root_count + 1;
if (newcount > janet_vm_root_capacity) {
size_t newcap = 2 * newcount;
janet_vm_roots = realloc(janet_vm_roots, sizeof(Janet) * newcap);
janet_vm_roots = janet_realloc(janet_vm_roots, sizeof(Janet) * newcap);
if (NULL == janet_vm_roots) {
JANET_OUT_OF_MEMORY;
}
@@ -483,12 +494,12 @@ void janet_clear_memory(void) {
while (NULL != current) {
janet_deinit_block(current);
JanetGCObject *next = current->next;
free(current);
janet_free(current);
current = next;
}
janet_vm_blocks = NULL;
janet_free_all_scratch();
free(janet_scratch_mem);
janet_free(janet_scratch_mem);
}
/* Primitives for suspending GC. */
@@ -502,14 +513,14 @@ void janet_gcunlock(int handle) {
/* Scratch memory API */
void *janet_smalloc(size_t size) {
JanetScratch *s = malloc(sizeof(JanetScratch) + size);
JanetScratch *s = janet_malloc(sizeof(JanetScratch) + size);
if (NULL == s) {
JANET_OUT_OF_MEMORY;
}
s->finalize = NULL;
if (janet_scratch_len == janet_scratch_cap) {
size_t newcap = 2 * janet_scratch_cap + 2;
JanetScratch **newmem = (JanetScratch **) realloc(janet_scratch_mem, newcap * sizeof(JanetScratch));
JanetScratch **newmem = (JanetScratch **) janet_realloc(janet_scratch_mem, newcap * sizeof(JanetScratch));
if (NULL == newmem) {
JANET_OUT_OF_MEMORY;
}
@@ -536,7 +547,7 @@ void *janet_srealloc(void *mem, size_t size) {
if (janet_scratch_len) {
for (size_t i = janet_scratch_len - 1; ; i--) {
if (janet_scratch_mem[i] == s) {
JanetScratch *news = realloc(s, size + sizeof(JanetScratch));
JanetScratch *news = janet_realloc(s, size + sizeof(JanetScratch));
if (NULL == news) {
JANET_OUT_OF_MEMORY;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose & contributors
* Copyright (c) 2021 Calvin Rose & contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -39,6 +39,8 @@
static int it_s64_get(void *p, Janet key, Janet *out);
static int it_u64_get(void *p, Janet key, Janet *out);
static Janet janet_int64_next(void *p, Janet key);
static Janet janet_uint64_next(void *p, Janet key);
static int32_t janet_int64_hash(void *p1, size_t size) {
(void) size;
@@ -92,7 +94,8 @@ const JanetAbstractType janet_s64_type = {
it_s64_tostring,
janet_int64_compare,
janet_int64_hash,
JANET_ATEND_HASH
janet_int64_next,
JANET_ATEND_NEXT
};
const JanetAbstractType janet_u64_type = {
@@ -106,7 +109,8 @@ const JanetAbstractType janet_u64_type = {
it_u64_tostring,
janet_uint64_compare,
janet_int64_hash,
JANET_ATEND_HASH
janet_uint64_next,
JANET_ATEND_NEXT
};
int64_t janet_unwrap_s64(Janet x) {
@@ -134,7 +138,7 @@ int64_t janet_unwrap_s64(Janet x) {
break;
}
}
janet_panic("bad s64 initializer");
janet_panicf("bad s64 initializer: %t", x);
return 0;
}
@@ -144,7 +148,9 @@ uint64_t janet_unwrap_u64(Janet x) {
break;
case JANET_NUMBER : {
double dbl = janet_unwrap_number(x);
if ((dbl >= 0) && (dbl <= MAX_INT_IN_DBL))
/* Allow negative values to be cast to "wrap around".
* This let's addition and subtraction work as expected. */
if (fabs(dbl) <= MAX_INT_IN_DBL)
return (uint64_t)dbl;
break;
}
@@ -163,7 +169,7 @@ uint64_t janet_unwrap_u64(Janet x) {
break;
}
}
janet_panic("bad u64 initializer");
janet_panicf("bad u64 initializer: %t", x);
return 0;
}
@@ -197,15 +203,14 @@ static Janet cfun_it_u64_new(int32_t argc, Janet *argv) {
return janet_wrap_u64(janet_unwrap_u64(argv[0]));
}
// Code to support polymorphic comparison.
//
// int/u64 and int/s64 support a "compare" method that allows
// comparison to each other, and to Janet numbers, using the
// "compare" "compare<" ... functions.
//
// In the following code explicit casts are sometimes used to help
// make it clear when int/float conversions are happening.
//
/*
* Code to support polymorphic comparison.
* int/u64 and int/s64 support a "compare" method that allows
* comparison to each other, and to Janet numbers, using the
* "compare" "compare<" ... functions.
* In the following code explicit casts are sometimes used to help
* make it clear when int/float conversions are happening.
*/
static int compare_double_double(double x, double y) {
return (x < y) ? -1 : ((x > y) ? 1 : 0);
}
@@ -242,7 +247,6 @@ static int compare_uint64_double(uint64_t x, double y) {
}
}
static Janet cfun_it_s64_compare(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
if (janet_is_int(argv[0]) != JANET_INT_S64)
@@ -383,31 +387,14 @@ static Janet cfun_it_##type##_##name(int32_t argc, Janet *argv) { \
} \
static Janet cfun_it_s64_mod(int32_t argc, Janet *argv) {
janet_arity(argc, 2, -1);
int64_t *box = janet_abstract(&janet_s64_type, sizeof(int64_t));
*box = janet_unwrap_s64(argv[0]);
for (int32_t i = 1; i < argc; i++) {
int64_t value = janet_unwrap_s64(argv[i]);
if (value == 0) janet_panic("division by zero");
int64_t x = *box % value;
if (x < 0) {
x = (*box < 0) ? x - *box : x + *box;
}
*box = x;
}
return janet_wrap_abstract(box);
}
static Janet cfun_it_s64_modi(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
int64_t *box = janet_abstract(&janet_s64_type, sizeof(int64_t));
int64_t op1 = janet_unwrap_s64(argv[0]);
int64_t op2 = janet_unwrap_s64(argv[1]);
int64_t x = op1 % op2;
if (x < 0) {
x = (op1 < 0) ? x - op1 : x + op1;
}
*box = x;
*box = (op1 > 0)
? ((op2 > 0) ? x : (0 == x ? x : x + op2))
: ((op2 > 0) ? (0 == x ? x : x + op2) : x);
return janet_wrap_abstract(box);
}
@@ -418,7 +405,6 @@ OPMETHOD(int64_t, s64, mul, *)
DIVMETHOD_SIGNED(int64_t, s64, div, /)
DIVMETHOD_SIGNED(int64_t, s64, rem, %)
DIVMETHODINVERT_SIGNED(int64_t, s64, divi, /)
DIVMETHODINVERT_SIGNED(int64_t, s64, remi, %)
OPMETHOD(int64_t, s64, and, &)
OPMETHOD(int64_t, s64, or, |)
OPMETHOD(int64_t, s64, xor, ^)
@@ -431,7 +417,6 @@ OPMETHOD(uint64_t, u64, mul, *)
DIVMETHOD(uint64_t, u64, div, /)
DIVMETHOD(uint64_t, u64, mod, %)
DIVMETHODINVERT(uint64_t, u64, divi, /)
DIVMETHODINVERT(uint64_t, u64, modi, %)
OPMETHOD(uint64_t, u64, and, &)
OPMETHOD(uint64_t, u64, or, |)
OPMETHOD(uint64_t, u64, xor, ^)
@@ -454,9 +439,9 @@ static JanetMethod it_s64_methods[] = {
{"/", cfun_it_s64_div},
{"r/", cfun_it_s64_divi},
{"mod", cfun_it_s64_mod},
{"rmod", cfun_it_s64_modi},
{"rmod", cfun_it_s64_mod},
{"%", cfun_it_s64_rem},
{"r%", cfun_it_s64_remi},
{"r%", cfun_it_s64_rem},
{"&", cfun_it_s64_and},
{"r&", cfun_it_s64_and},
{"|", cfun_it_s64_or},
@@ -480,9 +465,9 @@ static JanetMethod it_u64_methods[] = {
{"/", cfun_it_u64_div},
{"r/", cfun_it_u64_divi},
{"mod", cfun_it_u64_mod},
{"rmod", cfun_it_u64_modi},
{"rmod", cfun_it_u64_mod},
{"%", cfun_it_u64_mod},
{"r%", cfun_it_u64_modi},
{"r%", cfun_it_u64_mod},
{"&", cfun_it_u64_and},
{"r&", cfun_it_u64_and},
{"|", cfun_it_u64_or},
@@ -496,6 +481,16 @@ static JanetMethod it_u64_methods[] = {
{NULL, NULL}
};
static Janet janet_int64_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(it_s64_methods, key);
}
static Janet janet_uint64_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(it_u64_methods, key);
}
static int it_s64_get(void *p, Janet key, Janet *out) {
(void) p;
if (!janet_checktype(key, JANET_KEYWORD))

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -39,6 +39,7 @@ static int cfun_io_gc(void *p, size_t len);
static int io_file_get(void *p, Janet key, Janet *out);
static void io_file_marshal(void *p, JanetMarshalContext *ctx);
static void *io_file_unmarshal(JanetMarshalContext *ctx);
static Janet io_file_next(void *p, Janet key);
const JanetAbstractType janet_file_type = {
"core/file",
@@ -48,7 +49,11 @@ const JanetAbstractType janet_file_type = {
NULL,
io_file_marshal,
io_file_unmarshal,
JANET_ATEND_UNMARSHAL
NULL, /* tostring */
NULL, /* compare */
NULL, /* hash */
io_file_next,
JANET_ATEND_NEXT
};
/* Check arguments to fopen */
@@ -259,20 +264,29 @@ static Janet cfun_io_fflush(int32_t argc, Janet *argv) {
#define WEXITSTATUS(x) x
#endif
/* For closing files from C API */
int janet_file_close(JanetFile *file) {
int ret = 0;
if (!(file->flags & (JANET_FILE_NOT_CLOSEABLE | JANET_FILE_CLOSED))) {
#ifndef JANET_NO_PROCESSES
if (file->flags & JANET_FILE_PIPED) {
ret = pclose(file->file);
} else
#endif
{
ret = fclose(file->file);
}
file->flags |= JANET_FILE_CLOSED;
return ret;
}
return 0;
}
/* Cleanup a file */
static int cfun_io_gc(void *p, size_t len) {
(void) len;
JanetFile *iof = (JanetFile *)p;
if (!(iof->flags & (JANET_FILE_NOT_CLOSEABLE | JANET_FILE_CLOSED))) {
/* We can't panic inside a gc, so just ignore bad statuses here */
if (iof->flags & JANET_FILE_PIPED) {
#ifndef JANET_NO_PROCESSES
pclose(iof->file);
#endif
} else {
fclose(iof->file);
}
}
janet_file_close(iof);
return 0;
}
@@ -346,6 +360,11 @@ static int io_file_get(void *p, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), io_file_methods, out);
}
static Janet io_file_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(io_file_methods, key);
}
static void io_file_marshal(void *p, JanetMarshalContext *ctx) {
JanetFile *iof = (JanetFile *)p;
if (ctx->flags & JANET_MARSHAL_UNSAFE) {
@@ -525,7 +544,7 @@ static Janet cfun_io_printf_impl_x(int32_t argc, Janet *argv, int newline,
/* Clear buffer to make things easier for GC */
buf->count = 0;
buf->capacity = 0;
free(buf->data);
janet_free(buf->data);
buf->data = NULL;
return janet_wrap_nil();
}
@@ -713,23 +732,24 @@ static const JanetReg io_cfuns[] = {
{
"file/temp", cfun_io_temp,
JDOC("(file/temp)\n\n"
"Open an anonymous temporary file that is removed on close."
"Open an anonymous temporary file that is removed on close. "
"Raises an error on failure.")
},
{
"file/open", cfun_io_fopen,
JDOC("(file/open path &opt mode)\n\n"
"Open a file. path is an absolute or relative path, and "
"mode is a set of flags indicating the mode to open the file in. "
"mode is a keyword where each character represents a flag. If the file "
"Open a file. `path` is an absolute or relative path, and "
"`mode` is a set of flags indicating the mode to open the file in. "
"`mode` is a keyword where each character represents a flag. If the file "
"cannot be opened, returns nil, otherwise returns the new file handle. "
"Mode flags:\n\n"
"\tr - allow reading from the file\n"
"\tw - allow writing to the file\n"
"\ta - append to the file\n"
"\tb - open the file in binary mode (rather than text mode)\n"
"\t+ - append to the file instead of overwriting it\n"
"\tn - error if the file cannot be opened instead of returning nil")
"* r - allow reading from the file\n\n"
"* w - allow writing 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"
"* + - append to the file instead of overwriting it\n\n"
"* n - error if the file cannot be opened instead of returning nil")
},
{
"file/close", cfun_io_fclose,
@@ -742,14 +762,14 @@ static const JanetReg io_cfuns[] = {
{
"file/read", cfun_io_fread,
JDOC("(file/read f what &opt buf)\n\n"
"Read a number of bytes from a file into a buffer. A buffer can "
"be provided as an optional fourth argument, otherwise a new buffer "
"is created. 'what' can either be an integer or a keyword. Returns the "
"Read a number of bytes from a file `f` into a buffer. A buffer `buf` can "
"be provided as an optional third argument, otherwise a new buffer "
"is created. `what` can either be an integer or a keyword. Returns the "
"buffer with file contents. "
"Values for 'what':\n\n"
"\t:all - read the whole file\n"
"\t:line - read up to and including the next newline character\n"
"\tn (integer) - read up to n bytes from the file")
"Values for `what`:\n\n"
"* :all - read the whole file\n\n"
"* :line - read up to and including the next newline character\n\n"
"* n (integer) - read up to n bytes from the file")
},
{
"file/write", cfun_io_fwrite,
@@ -766,18 +786,18 @@ static const JanetReg io_cfuns[] = {
{
"file/seek", cfun_io_fseek,
JDOC("(file/seek f &opt whence n)\n\n"
"Jump to a relative location in the file. 'whence' must be one of\n\n"
"\t:cur - jump relative to the current file location\n"
"\t:set - jump relative to the beginning of the file\n"
"\t:end - jump relative to the end of the file\n\n"
"By default, 'whence' is :cur. Optionally a value n may be passed "
"for the relative number of bytes to seek in the file. n may be a real "
"number to handle large files of more the 4GB. Returns the file handle.")
"Jump to a relative location in the file `f`. `whence` must be one of:\n\n"
"* :cur - jump relative to the current file location\n\n"
"* :set - jump relative to the beginning of the file\n\n"
"* :end - jump relative to the end of the file\n\n"
"By default, `whence` is :cur. Optionally a value `n` may be passed "
"for the relative number of bytes to seek in the file. `n` may be a real "
"number to handle large files of more than 4GB. Returns the file handle.")
},
#ifndef JANET_NO_PROCESSES
{
"file/popen", cfun_io_popen,
JDOC("(file/popen command &opt mode)\n\n"
JDOC("(file/popen command &opt mode) (DEPRECATED for os/spawn)\n\n"
"Open a file that is backed by a process. The file must be opened in either "
"the :r (read) or the :w (write) mode. In :r mode, the stdout of the "
"process can be read from the file. In :w mode, the stdin of the process "

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -286,7 +286,7 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
#define JANET_FIBER_FLAG_HASCHILD (1 << 29)
#define JANET_FIBER_FLAG_HASENV (1 << 30)
#define JANET_STACKFRAME_HASENV (1 << 31)
#define JANET_STACKFRAME_HASENV (INT32_MIN)
/* Marshal a fiber */
static void marshal_one_fiber(MarshalState *st, JanetFiber *fiber, int flags) {
@@ -542,9 +542,10 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
case JANET_FUNCTION: {
pushbyte(st, LB_FUNCTION);
JanetFunction *func = janet_unwrap_function(x);
marshal_one_def(st, func->def, flags);
/* Mark seen after reading def, but before envs */
/* Mark seen before reading def */
MARK_SEEN();
pushint(st, func->def->environments_length);
marshal_one_def(st, func->def, flags);
for (int32_t i = 0; i < func->def->environments_length; i++)
marshal_one_env(st, func->envs[i], flags + 1);
return;
@@ -737,7 +738,7 @@ static const uint8_t *unmarshal_one_env(
if (length == 0) {
janet_panic("invalid funcenv length");
}
env->as.values = malloc(sizeof(Janet) * (size_t) length);
env->as.values = janet_malloc(sizeof(Janet) * (size_t) length);
if (!env->as.values) {
JANET_OUT_OF_MEMORY;
}
@@ -833,7 +834,7 @@ static const uint8_t *unmarshal_one_def(
/* Unmarshal constants */
if (constants_length) {
def->constants = malloc(sizeof(Janet) * constants_length);
def->constants = janet_malloc(sizeof(Janet) * constants_length);
if (!def->constants) {
JANET_OUT_OF_MEMORY;
}
@@ -845,7 +846,7 @@ static const uint8_t *unmarshal_one_def(
def->constants_length = constants_length;
/* Unmarshal bytecode */
def->bytecode = malloc(sizeof(uint32_t) * bytecode_length);
def->bytecode = janet_malloc(sizeof(uint32_t) * bytecode_length);
if (!def->bytecode) {
JANET_OUT_OF_MEMORY;
}
@@ -854,7 +855,7 @@ static const uint8_t *unmarshal_one_def(
/* Unmarshal environments */
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS) {
def->environments = calloc(1, sizeof(int32_t) * (size_t) environments_length);
def->environments = janet_calloc(1, sizeof(int32_t) * (size_t) environments_length);
if (!def->environments) {
JANET_OUT_OF_MEMORY;
}
@@ -868,7 +869,7 @@ static const uint8_t *unmarshal_one_def(
/* Unmarshal sub funcdefs */
if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) {
def->defs = calloc(1, sizeof(JanetFuncDef *) * (size_t) defs_length);
def->defs = janet_calloc(1, sizeof(JanetFuncDef *) * (size_t) defs_length);
if (!def->defs) {
JANET_OUT_OF_MEMORY;
}
@@ -883,7 +884,7 @@ static const uint8_t *unmarshal_one_def(
/* Unmarshal source maps if needed */
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
int32_t current = 0;
def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) bytecode_length);
def->sourcemap = janet_malloc(sizeof(JanetSourceMapping) * (size_t) bytecode_length);
if (!def->sourcemap) {
JANET_OUT_OF_MEMORY;
}
@@ -899,7 +900,7 @@ static const uint8_t *unmarshal_one_def(
/* Unmarshal closure bitset if needed */
if (def->flags & JANET_FUNCDEF_FLAG_HASCLOBITSET) {
int32_t n = (def->slotcount + 31) >> 5;
def->closure_bitset = malloc(sizeof(uint32_t) * (size_t) n);
def->closure_bitset = janet_malloc(sizeof(uint32_t) * (size_t) n);
if (NULL == def->closure_bitset) {
JANET_OUT_OF_MEMORY;
}
@@ -937,6 +938,7 @@ static const uint8_t *unmarshal_one_fiber(
#ifdef JANET_EV
fiber->waiting = NULL;
fiber->sched_id = 0;
fiber->supervisor_channel = NULL;
#endif
/* Push fiber to seen stack */
@@ -959,7 +961,7 @@ static const uint8_t *unmarshal_one_fiber(
/* Allocate stack memory */
fiber->capacity = fiber_stacktop + 10;
fiber->data = malloc(sizeof(Janet) * fiber->capacity);
fiber->data = janet_malloc(sizeof(Janet) * fiber->capacity);
if (!fiber->data) {
JANET_OUT_OF_MEMORY;
}
@@ -1228,12 +1230,20 @@ static const uint8_t *unmarshal_one(
case LB_FUNCTION: {
JanetFunction *func;
JanetFuncDef *def;
data = unmarshal_one_def(st, data + 1, &def, flags + 1);
data++;
int32_t len = readnat(st, &data);
if (len > 255) {
janet_panicf("invalid function");
}
func = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) +
def->environments_length * sizeof(JanetFuncEnv));
func->def = def;
len * sizeof(JanetFuncEnv));
*out = janet_wrap_function(func);
janet_v_push(st->lookup, *out);
data = unmarshal_one_def(st, data, &def, flags + 1);
if (def->environments_length != len) {
janet_panicf("invalid function");
}
func->def = def;
for (int32_t i = 0; i < def->environments_length; i++) {
data = unmarshal_one_env(st, data, &(func->envs[i]), flags + 1);
}
@@ -1418,9 +1428,9 @@ static const JanetReg marsh_cfuns[] = {
"marshal", cfun_marshal,
JDOC("(marshal x &opt reverse-lookup buffer)\n\n"
"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 "
"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 "
"unmarshalling.")
},

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -31,6 +31,7 @@
static JANET_THREAD_LOCAL JanetRNG janet_vm_rng = {0, 0, 0, 0, 0};
static int janet_rng_get(void *p, Janet key, Janet *out);
static Janet janet_rng_next(void *p, Janet key);
static void janet_rng_marshal(void *p, JanetMarshalContext *ctx) {
JanetRNG *rng = (JanetRNG *)p;
@@ -60,7 +61,11 @@ const JanetAbstractType janet_rng_type = {
NULL,
janet_rng_marshal,
janet_rng_unmarshal,
JANET_ATEND_UNMARSHAL
NULL, /* tostring */
NULL, /* compare */
NULL, /* hash */
janet_rng_next,
JANET_ATEND_NEXT
};
JanetRNG *janet_default_rng(void) {
@@ -203,6 +208,11 @@ static int janet_rng_get(void *p, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), rng_methods, out);
}
static Janet janet_rng_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(rng_methods, key);
}
/* Get a random number */
static Janet janet_rand(int32_t argc, Janet *argv) {
(void) argv;
@@ -500,13 +510,13 @@ void janet_lib_math(JanetTable *env) {
janet_def(env, "math/-inf", janet_wrap_number(-INFINITY),
JDOC("The number representing negative infinity"));
janet_def(env, "math/int32-min", janet_wrap_number(INT32_MIN),
JDOC("The maximum contiguous integer representable by a 32 bit signed integer"));
JDOC("The minimum contiguous integer representable by a 32 bit signed integer"));
janet_def(env, "math/int32-max", janet_wrap_number(INT32_MAX),
JDOC("The minimum contiguous integer represtenable by a 32 bit signed integer"));
JDOC("The maximum contiguous integer represtenable by a 32 bit signed integer"));
janet_def(env, "math/int-min", janet_wrap_number(JANET_INTMIN_DOUBLE),
JDOC("The maximum contiguous integer representable by a double (2^53)"));
JDOC("The minimum contiguous integer representable by a double (2^53)"));
janet_def(env, "math/int-max", janet_wrap_number(JANET_INTMAX_DOUBLE),
JDOC("The minimum contiguous integer represtenable by a double (-(2^53))"));
JDOC("The maximum contiguous integer represtenable by a double (-(2^53))"));
#ifdef NAN
janet_def(env, "math/nan", janet_wrap_number(NAN),
#else

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose and contributors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -80,15 +80,22 @@ static JanetStream *make_stream(JSock handle, uint32_t flags);
#define MSG_NOSIGNAL 0
#endif
static void nosigpipe(JSock s) {
/* Make sure a socket doesn't block */
static void janet_net_socknoblock(JSock s) {
#ifdef JANET_WINDOWS
unsigned long arg = 1;
ioctlsocket(s, FIONBIO, &arg);
#else
#if !defined(SOCK_CLOEXEC) && defined(O_CLOEXEC)
int extra = O_CLOEXEC;
#else
int extra = 0;
#endif
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK | extra);
#ifdef SO_NOSIGPIPE
int enable = 1;
if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) < 0) {
JSOCKCLOSE(s);
janet_panic("setsockopt(SO_NOSIGPIPE) failed");
}
#else
(void) s;
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int));
#endif
#endif
}
@@ -139,6 +146,7 @@ JanetAsyncStatus net_machine_accept(JanetListenerState *s, JanetAsyncEvent event
if (state->function) {
/* Schedule worker */
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
fiber->supervisor_channel = s->fiber->supervisor_channel;
janet_schedule(fiber, janet_wrap_nil());
/* Now listen again for next connection */
Janet err;
@@ -210,11 +218,12 @@ JanetAsyncStatus net_machine_accept(JanetListenerState *s, JanetAsyncEvent event
case JANET_ASYNC_EVENT_READ: {
JSock connfd = accept(s->stream->handle, NULL, NULL);
if (JSOCKVALID(connfd)) {
nosigpipe(connfd);
janet_net_socknoblock(connfd);
JanetStream *stream = make_stream(connfd, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
Janet streamv = janet_wrap_abstract(stream);
if (state->function) {
JanetFiber *fiber = janet_fiber(state->function, 64, 1, &streamv);
fiber->supervisor_channel = s->fiber->supervisor_channel;
janet_schedule(fiber, janet_wrap_nil());
} else {
janet_schedule(s->fiber, streamv);
@@ -256,20 +265,20 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
#ifndef JANET_WINDOWS
if (janet_keyeq(argv[offset], "unix")) {
const char *path = janet_getcstring(argv, offset + 1);
struct sockaddr_un *saddr = malloc(sizeof(struct sockaddr_un));
struct sockaddr_un *saddr = janet_calloc(1, sizeof(struct sockaddr_un));
if (saddr == NULL) {
JANET_OUT_OF_MEMORY;
}
saddr->sun_family = AF_UNIX;
memset(&saddr->sun_path, 0, 108);
size_t path_size = sizeof(saddr->sun_path);
#ifdef JANET_LINUX
if (path[0] == '@') {
saddr->sun_path[0] = '\0';
snprintf(saddr->sun_path + 1, 107, "%s", path + 1);
snprintf(saddr->sun_path + 1, path_size - 1, "%s", path + 1);
} else
#endif
{
snprintf(saddr->sun_path, 108, "%s", path);
snprintf(saddr->sun_path, path_size, "%s", path);
}
*is_unix = 1;
return (struct addrinfo *) saddr;
@@ -351,12 +360,12 @@ static Janet cfun_net_connect(int32_t argc, Janet *argv) {
/* Create socket */
JSock sock = JSOCKDEFAULT;
void *addr = NULL;
socklen_t addrlen;
socklen_t addrlen = 0;
#ifndef JANET_WINDOWS
if (is_unix) {
sock = socket(AF_UNIX, socktype | JSOCKFLAGS, 0);
if (!JSOCKVALID(sock)) {
janet_panic("could not create socket");
janet_panicf("could not create socket: %V", janet_ev_lasterr());
}
addr = (void *) ai;
addrlen = sizeof(struct sockaddr_un);
@@ -378,24 +387,30 @@ static Janet cfun_net_connect(int32_t argc, Janet *argv) {
}
if (NULL == addr) {
freeaddrinfo(ai);
janet_panic("could not create socket");
janet_panicf("could not create socket: %V", janet_ev_lasterr());
}
}
/* Connect to socket */
#ifdef JANET_WINDOWS
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
freeaddrinfo(ai);
#else
int status = connect(sock, addr, addrlen);
if (is_unix) {
free(ai);
janet_free(ai);
} else {
freeaddrinfo(ai);
}
#endif
if (status == -1) {
JSOCKCLOSE(sock);
janet_panic("could not connect to socket");
janet_panicf("could not connect to socket: %V", janet_ev_lasterr());
}
nosigpipe(sock);
/* Set up the socket for non-blocking IO after connect - TODO - non-blocking connect? */
janet_net_socknoblock(sock);
/* Wrap socket in abstract type JanetStream */
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
@@ -413,9 +428,51 @@ static const char *serverify_socket(JSock sfd) {
return "setsockopt(SO_REUSEPORT) failed";
}
#endif
janet_net_socknoblock(sfd);
return NULL;
}
#ifdef JANET_WINDOWS
#define JANET_SHUTDOWN_RW SD_BOTH
#define JANET_SHUTDOWN_R SD_RECEIVE
#define JANET_SHUTDOWN_W SD_SEND
#else
#define JANET_SHUTDOWN_RW SHUT_RDWR
#define JANET_SHUTDOWN_R SHUT_RD
#define JANET_SHUTDOWN_W SHUT_WR
#endif
static Janet cfun_net_shutdown(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 2);
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
janet_stream_flags(stream, JANET_STREAM_SOCKET);
int shutdown_type = JANET_SHUTDOWN_RW;
if (argc == 2) {
const uint8_t *kw = janet_getkeyword(argv, 1);
if (0 == janet_cstrcmp(kw, "rw")) {
shutdown_type = JANET_SHUTDOWN_RW;
} else if (0 == janet_cstrcmp(kw, "r")) {
shutdown_type = JANET_SHUTDOWN_R;
} else if (0 == janet_cstrcmp(kw, "w")) {
shutdown_type = JANET_SHUTDOWN_W;
} else {
janet_panicf("unexpected keyword %v", argv[1]);
}
}
int status;
#ifdef JANET_WINDOWS
status = shutdown((SOCKET) stream->handle, shutdown_type);
#else
do {
status = shutdown(stream->handle, shutdown_type);
} while (status == -1 && errno == EINTR);
#endif
if (status) {
janet_panicf("could not shutdown socket: %V", janet_ev_lasterr());
}
return argv[0];
}
static Janet cfun_net_listen(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 3);
@@ -429,16 +486,20 @@ static Janet cfun_net_listen(int32_t argc, Janet *argv) {
if (is_unix) {
sfd = socket(AF_UNIX, socktype | JSOCKFLAGS, 0);
if (!JSOCKVALID(sfd)) {
free(ai);
janet_panic("could not create socket");
janet_free(ai);
janet_panicf("could not create socket: %V", janet_ev_lasterr());
}
const char *err = serverify_socket(sfd);
if (NULL != err || bind(sfd, (struct sockaddr *)ai, sizeof(struct sockaddr_un))) {
JSOCKCLOSE(sfd);
free(ai);
janet_panic(err ? err : "could not bind socket");
janet_free(ai);
if (err) {
janet_panic(err);
} else {
janet_panicf("could not bind socket: %V", janet_ev_lasterr());
}
}
free(ai);
janet_free(ai);
} else
#endif
{
@@ -466,8 +527,6 @@ static Janet cfun_net_listen(int32_t argc, Janet *argv) {
}
}
nosigpipe(sfd);
if (socktype == SOCK_DGRAM) {
/* Datagram server (UDP) */
JanetStream *stream = make_stream(sfd, JANET_STREAM_UDPSERVER | JANET_STREAM_READABLE);
@@ -479,7 +538,7 @@ static Janet cfun_net_listen(int32_t argc, Janet *argv) {
int status = listen(sfd, 1024);
if (status) {
JSOCKCLOSE(sfd);
janet_panic("could not listen on file descriptor");
janet_panicf("could not listen on file descriptor: %V", janet_ev_lasterr());
}
/* Put sfd on our loop */
@@ -488,18 +547,6 @@ static Janet cfun_net_listen(int32_t argc, Janet *argv) {
}
}
void janet_stream_flags(JanetStream *stream, uint32_t flags) {
if ((stream->flags & flags) != flags || (stream->flags & JANET_STREAM_CLOSED)) {
const char *rmsg = "", *wmsg = "", *amsg = "", *dmsg = "", *smsg = "stream";
if (flags & JANET_STREAM_READABLE) rmsg = "readable ";
if (flags & JANET_STREAM_WRITABLE) wmsg = "writable ";
if (flags & JANET_STREAM_ACCEPTABLE) amsg = "server ";
if (flags & JANET_STREAM_UDPSERVER) dmsg = "datagram ";
if (flags & JANET_STREAM_SOCKET) smsg = "socket";
janet_panicf("bad stream, expected %s%s%s%s%s", rmsg, wmsg, amsg, dmsg, smsg);
}
}
static Janet cfun_stream_accept_loop(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
@@ -521,11 +568,16 @@ static Janet cfun_stream_read(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 4);
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
janet_stream_flags(stream, JANET_STREAM_READABLE | JANET_STREAM_SOCKET);
int32_t n = janet_getnat(argv, 1);
JanetBuffer *buffer = janet_optbuffer(argv, argc, 2, 10);
double to = janet_optnumber(argv, argc, 3, INFINITY);
if (to != INFINITY) janet_addtimeout(to);
janet_ev_recv(stream, buffer, n, MSG_NOSIGNAL);
if (janet_keyeq(argv[1], "all")) {
if (to != INFINITY) janet_addtimeout(to);
janet_ev_recvchunk(stream, buffer, INT32_MAX, MSG_NOSIGNAL);
} else {
int32_t n = janet_getnat(argv, 1);
if (to != INFINITY) janet_addtimeout(to);
janet_ev_recv(stream, buffer, n, MSG_NOSIGNAL);
}
janet_await();
}
@@ -587,7 +639,7 @@ static Janet cfun_stream_send_to(int32_t argc, Janet *argv) {
}
static Janet cfun_stream_flush(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
janet_fixarity(argc, 1);
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
janet_stream_flags(stream, JANET_STREAM_WRITABLE | JANET_STREAM_SOCKET);
/* Toggle no delay flag */
@@ -612,6 +664,7 @@ static const JanetMethod net_stream_methods[] = {
{"evread", janet_cfun_stream_read},
{"evchunk", janet_cfun_stream_chunk},
{"evwrite", janet_cfun_stream_write},
{"shutdown", cfun_net_shutdown},
{NULL, NULL}
};
@@ -633,7 +686,7 @@ static const JanetReg net_cfuns[] = {
"net/listen", cfun_net_listen,
JDOC("(net/listen host port &opt type)\n\n"
"Creates a server. Returns a new stream that is neither readable nor "
"writeable. Use net/accept or net/accept-loop be to handle connections and start the server."
"writeable. Use net/accept or net/accept-loop be to handle connections and start the server. "
"The type parameter specifies the type of network connection, either "
"a :stream (usually tcp), or :datagram (usually udp). If not specified, the default is "
":stream. The host and port arguments are the same as in net/address.")
@@ -648,13 +701,14 @@ static const JanetReg net_cfuns[] = {
{
"net/accept-loop", cfun_stream_accept_loop,
JDOC("(net/accept-loop stream handler)\n\n"
"Shorthand for running a server stream that will continuously accept new connections."
"Shorthand for running a server stream that will continuously accept new connections. "
"Blocks the current fiber until the stream is closed, and will return the stream.")
},
{
"net/read", cfun_stream_read,
JDOC("(net/read stream nbytes &opt buf timeout)\n\n"
"Read up to n bytes from a stream, suspending the current fiber until the bytes are available. "
"`n` can also be the keyword `:all` to read into the buffer until end of stream. "
"If less than n bytes are available (and more than 0), will push those bytes and return early. "
"Takes an optional timeout in seconds, after which will return nil. "
"Returns a buffer with up to n more bytes in it, or raises an error if the read failed.")
@@ -693,11 +747,21 @@ static const JanetReg net_cfuns[] = {
},
{
"net/connect", cfun_net_connect,
JDOC("(net/connect host porti &opt type)\n\n"
JDOC("(net/connect host port &opt type)\n\n"
"Open a connection to communicate with a server. Returns a duplex stream "
"that can be used to communicate with the server. Type is an optional keyword "
"to specify a connection type, either :stream or :datagram. The default is :stream. ")
},
{
"net/shutdown", cfun_net_shutdown,
JDOC("(net/shutdown stream &opt mode)\n\n"
"Stop communication on this socket in a graceful manner, either in both directions or just "
"reading/writing from the stream. The `mode` parameter controls which communication to stop on the socket. "
"\n\n* `:wr` is the default and prevents both reading new data from the socket and writing new data to the socket.\n"
"* `:r` disables reading new data from the socket.\n"
"* `:w` disable writing data to the socket.\n\n"
"Returns the original socket.")
},
{NULL, NULL, NULL}
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -123,7 +123,7 @@ static void NAME(JanetParser *p, T x) { \
if (newcount > p->STACKCAP) { \
T *next; \
size_t newcap = 2 * newcount; \
next = realloc(p->STACK, sizeof(T) * newcap); \
next = janet_realloc(p->STACK, sizeof(T) * newcap); \
if (NULL == next) { \
JANET_OUT_OF_MEMORY; \
} \
@@ -175,7 +175,14 @@ static void popstate(JanetParser *p, Janet val) {
if (newtop->flags & PFLAG_CONTAINER) {
newtop->argn++;
/* 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);
return;
} else if (newtop->flags & PFLAG_READERMAC) {
@@ -313,11 +320,48 @@ static int stringend(JanetParser *p, JanetParseState *state) {
uint8_t *bufstart = p->buf;
int32_t buflen = (int32_t) p->bufcount;
if (state->flags & PFLAG_LONGSTRING) {
/* Check for leading newline character so we can remove it */
if (bufstart[0] == '\n') {
bufstart++;
buflen--;
/* Post process to remove leading whitespace */
JanetParseState top = p->states[p->statecount - 1];
int32_t indent_col = (int32_t) top.column - 1;
uint8_t *r = bufstart, *end = r + buflen;
/* Check if there are any characters before the start column -
* if so, do not reindent. */
int reindent = 1;
while (reindent && (r < end)) {
if (*r++ == '\n') {
for (int32_t j = 0; (r < end) && (*r != '\n') && (j < indent_col); j++, r++) {
if (*r != ' ') {
reindent = 0;
break;
}
}
}
}
/* Now reindent if able to, otherwise just drop leading newline. */
if (!reindent) {
if (buflen > 0 && bufstart[0] == '\n') {
buflen--;
bufstart++;
}
} else {
uint8_t *w = bufstart;
r = bufstart;
while (r < end) {
if (*r == '\n') {
if (r == bufstart) {
/* Skip leading newline */
r++;
} else {
*w++ = *r++;
}
for (int32_t j = 0; (r < end) && (*r != '\n') && (j < indent_col); j++, r++);
} else {
*w++ = *r++;
}
}
buflen = (int32_t)(w - bufstart);
}
/* Check for trailing newline character so we can remove it */
if (buflen > 0 && bufstart[buflen - 1] == '\n') {
buflen--;
}
@@ -693,6 +737,19 @@ const char *janet_parser_error(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;
size_t i;
if (parser->pending == 0) return janet_wrap_nil();
@@ -726,9 +783,9 @@ void janet_parser_init(JanetParser *parser) {
}
void janet_parser_deinit(JanetParser *parser) {
free(parser->args);
free(parser->buf);
free(parser->states);
janet_free(parser->args);
janet_free(parser->buf);
janet_free(parser->states);
}
void janet_parser_clone(const JanetParser *src, JanetParser *dest) {
@@ -755,17 +812,17 @@ void janet_parser_clone(const JanetParser *src, JanetParser *dest) {
dest->states = NULL;
dest->buf = NULL;
if (dest->bufcap) {
dest->buf = malloc(dest->bufcap);
dest->buf = janet_malloc(dest->bufcap);
if (!dest->buf) goto nomem;
memcpy(dest->buf, src->buf, dest->bufcap);
}
if (dest->argcap) {
dest->args = malloc(sizeof(Janet) * dest->argcap);
dest->args = janet_malloc(sizeof(Janet) * dest->argcap);
if (!dest->args) goto nomem;
memcpy(dest->args, src->args, dest->argcap * sizeof(Janet));
}
if (dest->statecap) {
dest->states = malloc(sizeof(JanetParseState) * dest->statecap);
dest->states = janet_malloc(sizeof(JanetParseState) * dest->statecap);
if (!dest->states) goto nomem;
memcpy(dest->states, src->states, dest->statecap * sizeof(JanetParseState));
}
@@ -803,13 +860,21 @@ static int parsergc(void *p, size_t size) {
}
static int parserget(void *p, Janet key, Janet *out);
static Janet parsernext(void *p, Janet key);
const JanetAbstractType janet_parser_type = {
"core/parser",
parsergc,
parsermark,
parserget,
JANET_ATEND_GET
NULL, /* put */
NULL, /* marshal */
NULL, /* unmarshal */
NULL, /* tostring */
NULL, /* compare */
NULL, /* hash */
parsernext,
JANET_ATEND_NEXT
};
/* C Function parser */
@@ -865,15 +930,20 @@ static Janet cfun_parse_insert(int32_t argc, Janet *argv) {
if (s->flags & PFLAG_COMMENT) s--;
if (s->flags & PFLAG_CONTAINER) {
s->argn++;
if (p->statecount == 1) p->pending++;
push_arg(p, argv[1]);
if (p->statecount == 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)) {
const uint8_t *str = janet_to_string(argv[1]);
int32_t slen = janet_string_length(str);
size_t newcount = p->bufcount + slen;
if (p->bufcap < newcount) {
size_t newcap = 2 * newcount;
p->buf = realloc(p->buf, newcap);
p->buf = janet_realloc(p->buf, newcap);
if (p->buf == NULL) {
JANET_OUT_OF_MEMORY;
}
@@ -935,9 +1005,13 @@ static Janet cfun_parse_error(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);
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) {
@@ -948,8 +1022,20 @@ static Janet cfun_parse_flush(int32_t argc, Janet *argv) {
}
static Janet cfun_parse_where(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
janet_arity(argc, 1, 3);
JanetParser *p = janet_getabstract(argv, 0, &janet_parser_type);
if (argc > 1) {
int32_t line = janet_getinteger(argv, 1);
if (line < 1)
janet_panicf("invalid line number %d", line);
p->line = (size_t) line;
}
if (argc > 2) {
int32_t column = janet_getinteger(argv, 2);
if (column < 0)
janet_panicf("invalid column number %d", column);
p->column = (size_t) column;
}
Janet *tup = janet_tuple_begin(2);
tup[0] = janet_wrap_integer(p->line);
tup[1] = janet_wrap_integer(p->column);
@@ -1134,6 +1220,11 @@ static int parserget(void *p, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), parser_methods, out);
}
static Janet parsernext(void *p, Janet key) {
(void) p;
return janet_nextmethod(parser_methods, key);
}
static const JanetReg parse_cfuns[] = {
{
"parser/new", cfun_parse_parser,
@@ -1155,10 +1246,12 @@ static const JanetReg parse_cfuns[] = {
},
{
"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 "
"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,
@@ -1185,9 +1278,9 @@ static const JanetReg parse_cfuns[] = {
JDOC("(parser/status parser)\n\n"
"Gets the current status of the parser state machine. The status will "
"be one of:\n\n"
"\t:pending - a value is being parsed.\n"
"\t:error - a parsing error was encountered.\n"
"\t:root - the parser can either read more values or safely terminate.")
"* :pending - a value is being parsed.\n\n"
"* :error - a parsing error was encountered.\n\n"
"* :root - the parser can either read more values or safely terminate.")
},
{
"parser/flush", cfun_parse_flush,
@@ -1201,17 +1294,19 @@ static const JanetReg parse_cfuns[] = {
JDOC("(parser/state parser &opt key)\n\n"
"Returns a representation of the internal state of the parser. If a key is passed, "
"only that information about the state is returned. Allowed keys are:\n\n"
"\t:delimiters - Each byte in the string represents a nested data structure. For example, "
"* :delimiters - Each byte in the string represents a nested data structure. For example, "
"if the parser state is '([\"', then the parser is in the middle of parsing a "
"string inside of square brackets inside parentheses. Can be used to augment a REPL prompt."
"\t:frames - Each table in the array represents a 'frame' in the parser state. Frames "
"string inside of square brackets inside parentheses. Can be used to augment a REPL prompt.\n\n"
"* :frames - Each table in the array represents a 'frame' in the parser state. Frames "
"contain information about the start of the expression being parsed as well as the "
"type of that expression and some type-specific information.")
},
{
"parser/where", cfun_parse_where,
JDOC("(parser/where parser)\n\n"
"Returns the current line number and column of the parser's internal state.")
JDOC("(parser/where parser &opt line col)\n\n"
"Returns the current line number and column of the parser's internal state. If line is "
"provided, the current line number of the parser is first set to that value. If column is "
"also provided, the current column number of the parser is also first set to that value.")
},
{
"parser/eof", cfun_parse_eof,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -44,9 +44,13 @@ typedef struct {
JanetArray *captures;
JanetBuffer *scratch;
JanetBuffer *tags;
JanetArray *tagged_captures;
const Janet *extrav;
int32_t *linemap;
int32_t extrac;
int32_t depth;
int32_t linemaplen;
int32_t has_backref;
enum {
PEG_MODE_NORMAL,
PEG_MODE_ACCUMULATE
@@ -58,6 +62,7 @@ typedef struct {
* if one branch fails and try a new branch. */
typedef struct {
int32_t cap;
int32_t tcap;
int32_t scratch;
} CapState;
@@ -66,6 +71,7 @@ static CapState cap_save(PegState *s) {
CapState cs;
cs.scratch = s->scratch->count;
cs.cap = s->captures->count;
cs.tcap = s->tagged_captures->count;
return cs;
}
@@ -73,7 +79,15 @@ static CapState cap_save(PegState *s) {
static void cap_load(PegState *s, CapState cs) {
s->scratch->count = cs.scratch;
s->captures->count = cs.cap;
s->tags->count = cs.cap;
s->tags->count = cs.tcap;
s->tagged_captures->count = cs.tcap;
}
/* Load a saved capture state in the case of success. Keeps
* tagged captures around for backref. */
static void cap_load_keept(PegState *s, CapState cs) {
s->scratch->count = cs.scratch;
s->captures->count = cs.cap;
}
/* Add a capture */
@@ -81,12 +95,66 @@ static void pushcap(PegState *s, Janet capture, uint32_t tag) {
if (s->mode == PEG_MODE_ACCUMULATE) {
janet_to_string_b(s->scratch, capture);
}
if (tag || s->mode == PEG_MODE_NORMAL) {
if (s->mode == PEG_MODE_NORMAL) {
janet_array_push(s->captures, capture);
}
if (s->has_backref) {
janet_array_push(s->tagged_captures, capture);
janet_buffer_push_u8(s->tags, tag);
}
}
/* Lazily generate line map to get line and column information for PegState.
* line and column are 1-indexed. */
typedef struct {
int32_t line;
int32_t col;
} LineCol;
static LineCol get_linecol_from_position(PegState *s, int32_t position) {
/* Generate if not made yet */
if (s->linemaplen < 0) {
int32_t newline_count = 0;
for (const uint8_t *c = s->text_start; c < s->text_end; c++) {
if (*c == '\n') newline_count++;
}
int32_t *mem = janet_smalloc(sizeof(int32_t) * newline_count);
size_t index = 0;
for (const uint8_t *c = s->text_start; c < s->text_end; c++) {
if (*c == '\n') mem[index++] = (int32_t)(c - s->text_start);
}
s->linemaplen = newline_count;
s->linemap = mem;
}
/* Do binary search for line. Slightly modified from classic binary search:
* - if we find that our current character is a line break, just return immediately.
* a newline character is consider to be on the same line as the character before
* (\n is line terminator, not line separator).
* - in the not-found case, we still want to find the greatest-indexed newline that
* is before position. we use that to calcuate the line and column.
* - in the case that lo = 0 and s->linemap[0] is still greater than position, we
* are on the first line and our column is position + 1. */
int32_t hi = s->linemaplen; /* hi is greater than the actual line */
int32_t lo = 0; /* lo is less than or equal to the actual line */
LineCol ret;
while (lo + 1 < hi) {
int32_t mid = lo + (hi - lo) / 2;
if (s->linemap[mid] >= position) {
hi = mid;
} else {
lo = mid;
}
}
/* first line case */
if (s->linemaplen == 0 || (lo == 0 && s->linemap[0] >= position)) {
ret.line = 1;
ret.col = position + 1;
} else {
ret.line = lo + 2;
ret.col = position - s->linemap[lo];
}
return ret;
}
/* Convert a uint64_t to a int64_t by wrapping to a maximum number of bytes */
static int64_t peg_convert_u64_s64(uint64_t from, int width) {
int shift = 8 * (8 - width);
@@ -218,7 +286,7 @@ tail:
const uint8_t *next_text;
CapState cs = cap_save(s);
down1(s);
while (text < s->text_end) {
while (text <= s->text_end) {
CapState cs2 = cap_save(s);
next_text = peg_rule(s, rule_a, text);
if (next_text) {
@@ -228,7 +296,7 @@ tail:
text++;
}
up1(s);
if (text >= s->text_end) {
if (text > s->text_end) {
cap_load(s, cs);
return NULL;
}
@@ -268,7 +336,7 @@ tail:
uint32_t tag = rule[2];
for (int32_t i = s->tags->count - 1; i >= 0; i--) {
if (s->tags->data[i] == search) {
pushcap(s, s->captures->data[i], tag);
pushcap(s, s->tagged_captures->data[i], tag);
return text;
}
}
@@ -280,6 +348,18 @@ tail:
return text;
}
case RULE_LINE: {
LineCol lc = get_linecol_from_position(s, (int32_t)(text - s->text_start));
pushcap(s, janet_wrap_number((double)(lc.line)), rule[1]);
return text;
}
case RULE_COLUMN: {
LineCol lc = get_linecol_from_position(s, (int32_t)(text - s->text_start));
pushcap(s, janet_wrap_number((double)(lc.col)), rule[1]);
return text;
}
case RULE_ARGUMENT: {
int32_t index = ((int32_t *)rule)[1];
Janet capture = (index >= s->extrac) ? janet_wrap_nil() : s->extrav[index];
@@ -293,15 +373,15 @@ tail:
}
case RULE_CAPTURE: {
uint32_t tag = rule[2];
down1(s);
const uint8_t *result = peg_rule(s, s->bytecode + rule[1], text);
up1(s);
if (!result) return NULL;
/* Specialized pushcap - avoid intermediate string creation */
if (!tag && s->mode == PEG_MODE_ACCUMULATE) {
if (!s->has_backref && s->mode == PEG_MODE_ACCUMULATE) {
janet_buffer_push_bytes(s->scratch, text, (int32_t)(result - text));
} else {
uint32_t tag = rule[2];
pushcap(s, janet_stringv(text, (int32_t)(result - text)), tag);
}
return result;
@@ -323,7 +403,7 @@ tail:
if (!result) return NULL;
Janet cap = janet_stringv(s->scratch->data + cs.scratch,
s->scratch->count - cs.scratch);
cap_load(s, cs);
cap_load_keept(s, cs);
pushcap(s, cap, tag);
return result;
}
@@ -354,7 +434,7 @@ tail:
s->captures->data + cs.cap,
sizeof(Janet) * num_sub_captures);
sub_captures->count = num_sub_captures;
cap_load(s, cs);
cap_load_keept(s, cs);
pushcap(s, janet_wrap_array(sub_captures), tag);
return result;
}
@@ -399,7 +479,7 @@ tail:
s->captures->data + cs.cap);
break;
}
cap_load(s, cs);
cap_load_keept(s, cs);
if (rule[0] == RULE_MATCHTIME && !janet_truthy(cap)) return NULL;
pushcap(s, cap, tag);
return result;
@@ -420,8 +500,8 @@ tail:
} else {
/* Throw generic error */
int32_t start = (int32_t)(text - s->text_start);
int32_t end = (int32_t)(result - s->text_start);
janet_panicf("match error in range (%d:%d)", start, end);
LineCol lc = get_linecol_from_position(s, start);
janet_panicf("match error at line %d, column %d", lc.line, lc.col);
}
return NULL;
}
@@ -430,7 +510,7 @@ tail:
uint32_t search = rule[1];
for (int32_t i = s->tags->count - 1; i >= 0; i--) {
if (s->tags->data[i] == search) {
Janet capture = s->captures->data[i];
Janet capture = s->tagged_captures->data[i];
if (!janet_checktype(capture, JANET_STRING))
return NULL;
const uint8_t *bytes = janet_unwrap_string(capture);
@@ -516,6 +596,30 @@ tail:
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;
}
}
}
@@ -532,6 +636,7 @@ typedef struct {
Janet form;
int depth;
uint32_t nexttag;
int has_backref;
} Builder;
/* Forward declaration to allow recursion */
@@ -830,10 +935,13 @@ static void spec_not(Builder *b, int32_t argc, const Janet *argv) {
spec_onerule(b, argc, argv, RULE_NOT);
}
static void spec_error(Builder *b, int32_t argc, const Janet *argv) {
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);
if (argc == 0) {
Reserve r = reserve(b, 2);
uint32_t rule = peg_compile1(b, janet_wrap_number(0));
emit_1(r, RULE_ERROR, rule);
} else {
spec_onerule(b, argc, argv, RULE_ERROR);
}
}
static void spec_to(Builder *b, int32_t argc, const Janet *argv) {
spec_onerule(b, argc, argv, RULE_TO);
@@ -841,6 +949,9 @@ static void spec_to(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);
}
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] */
static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
@@ -860,12 +971,16 @@ static void spec_accumulate(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);
}
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) {
peg_arity(b, argc, 1, 2);
Reserve r = reserve(b, 3);
uint32_t search = emit_tag(b, argv[0]);
uint32_t tag = (argc == 2) ? emit_tag(b, argv[1]) : 0;
b->has_backref = 1;
emit_2(r, RULE_GETTAG, search, tag);
}
@@ -880,8 +995,15 @@ static void spec_tag1(Builder *b, int32_t argc, const Janet *argv, uint32_t op)
static void spec_position(Builder *b, int32_t argc, const Janet *argv) {
spec_tag1(b, argc, argv, RULE_POSITION);
}
static void spec_line(Builder *b, int32_t argc, const Janet *argv) {
spec_tag1(b, argc, argv, RULE_LINE);
}
static void spec_column(Builder *b, int32_t argc, const Janet *argv) {
spec_tag1(b, argc, argv, RULE_COLUMN);
}
static void spec_backmatch(Builder *b, int32_t argc, const Janet *argv) {
b->has_backref = 1;
spec_tag1(b, argc, argv, RULE_BACKMATCH);
}
@@ -932,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) {
peg_arity(b, argc, 1, 2);
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]);
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);
@@ -983,6 +1105,7 @@ static const SpecialPair peg_specials[] = {
{"capture", spec_capture},
{"choice", spec_choice},
{"cmt", spec_matchtime},
{"column", spec_column},
{"constant", spec_constant},
{"drop", spec_drop},
{"error", spec_error},
@@ -992,6 +1115,7 @@ static const SpecialPair peg_specials[] = {
{"int", spec_int_le},
{"int-be", spec_int_be},
{"lenprefix", spec_lenprefix},
{"line", spec_line},
{"look", spec_look},
{"not", spec_not},
{"opt", spec_opt},
@@ -1007,6 +1131,7 @@ static const SpecialPair peg_specials[] = {
{"to", spec_to},
{"uint", spec_uint_le},
{"uint-be", spec_uint_be},
{"unref", spec_unref},
};
/* Compile a janet value into a rule and return the rule index. */
@@ -1023,7 +1148,9 @@ static uint32_t peg_compile1(Builder *b, Janet peg) {
for (; i > 0 && janet_checktype(peg, JANET_KEYWORD); --i) {
Janet nextPeg = janet_table_get_ex(grammar, peg, &grammar);
if (!grammar || janet_checktype(nextPeg, JANET_NIL)) {
nextPeg = janet_table_get(b->default_grammar, peg);
nextPeg = (b->default_grammar == NULL)
? janet_wrap_nil()
: janet_table_get(b->default_grammar, peg);
if (janet_checktype(nextPeg, JANET_NIL)) {
peg_panic(b, "unknown rule");
}
@@ -1210,12 +1337,13 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
* bytecode. */
uint32_t blen = (int32_t) peg->bytecode_len;
uint32_t clen = peg->num_constants;
uint8_t *op_flags = calloc(1, blen);
uint8_t *op_flags = janet_calloc(1, blen);
if (NULL == op_flags) {
JANET_OUT_OF_MEMORY;
}
/* verify peg bytecode */
int32_t has_backref = 0;
uint32_t i = 0;
while (i < blen) {
uint32_t instr = bytecode[i];
@@ -1229,9 +1357,15 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
case RULE_NOTNCHAR:
case RULE_RANGE:
case RULE_POSITION:
case RULE_LINE:
case RULE_COLUMN:
/* [1 word] */
i += 2;
break;
case RULE_BACKMATCH:
/* [1 word] */
i += 2;
has_backref = 1;
break;
case RULE_SET:
/* [8 words] */
@@ -1272,9 +1406,13 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
i += 4;
break;
case RULE_ARGUMENT:
/* [searchtag, tag] */
i += 3;
break;
case RULE_GETTAG:
/* [searchtag, tag] */
i += 3;
has_backref = 1;
break;
case RULE_CONSTANT:
/* [constant, tag] */
@@ -1284,6 +1422,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
case RULE_ACCUMULATE:
case RULE_GROUP:
case RULE_CAPTURE:
case RULE_UNREF:
/* [rule, tag] */
if (rule[1] >= blen) goto bad;
op_flags[rule[1]] |= 0x01;
@@ -1328,25 +1467,31 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
/* Good return */
peg->bytecode = bytecode;
peg->constants = constants;
free(op_flags);
peg->has_backref = has_backref;
janet_free(op_flags);
return peg;
bad:
free(op_flags);
janet_free(op_flags);
janet_panic("invalid peg bytecode");
}
static int cfun_peg_getter(JanetAbstract a, Janet key, Janet *out);
static Janet peg_next(void *p, Janet key);
const JanetAbstractType janet_peg_type = {
"core/peg",
NULL,
peg_mark,
cfun_peg_getter,
NULL,
NULL, /* put */
peg_marshal,
peg_unmarshal,
JANET_ATEND_UNMARSHAL
NULL, /* tostring */
NULL, /* compare */
NULL, /* hash */
peg_next,
JANET_ATEND_NEXT
};
/* Convert Builder to JanetPeg (Janet Abstract Value) */
@@ -1364,6 +1509,7 @@ static JanetPeg *make_peg(Builder *b) {
safe_memcpy(peg->bytecode, b->bytecode, bytecode_size);
safe_memcpy(peg->constants, b->constants, constants_size);
peg->bytecode_len = janet_v_count(b->bytecode);
peg->has_backref = b->has_backref;
return peg;
}
@@ -1371,13 +1517,20 @@ static JanetPeg *make_peg(Builder *b) {
static JanetPeg *compile_peg(Janet x) {
Builder builder;
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.constants = NULL;
builder.bytecode = NULL;
builder.nexttag = 1;
builder.form = x;
builder.depth = JANET_RECURSION_GUARD;
builder.has_backref = 0;
peg_compile1(&builder, x);
JanetPeg *peg = make_peg(&builder);
builder_cleanup(&builder);
@@ -1434,10 +1587,14 @@ static PegCall peg_cfun_init(int32_t argc, Janet *argv, int get_replace) {
ret.s.text_end = ret.bytes.bytes + ret.bytes.len;
ret.s.depth = JANET_RECURSION_GUARD;
ret.s.captures = janet_array(0);
ret.s.tagged_captures = janet_array(0);
ret.s.scratch = janet_buffer(10);
ret.s.tags = janet_buffer(10);
ret.s.constants = ret.peg->constants;
ret.s.bytecode = ret.peg->bytecode;
ret.s.linemap = NULL;
ret.s.linemaplen = -1;
ret.s.has_backref = ret.peg->has_backref;
return ret;
}
@@ -1526,12 +1683,18 @@ static int cfun_peg_getter(JanetAbstract a, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), peg_methods, out);
}
static Janet peg_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(peg_methods, key);
}
static const JanetReg peg_cfuns[] = {
{
"peg/compile", cfun_peg_compile,
JDOC("(peg/compile peg)\n\n"
"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,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -42,7 +42,14 @@ static void number_to_string_b(JanetBuffer *buffer, double x) {
const char *fmt = (x == floor(x) &&
x <= JANET_INTMAX_DOUBLE &&
x >= JANET_INTMIN_DOUBLE) ? "%.0f" : "%g";
int count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, fmt, x);
int count;
if (x == 0.0) {
/* Prevent printing of '-0' */
count = 1;
buffer->data[buffer->count] = '0';
} else {
count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, fmt, x);
}
buffer->count += count;
}
@@ -344,6 +351,9 @@ struct pretty {
int indent;
int flags;
int32_t bufstartlen;
int32_t *keysort_buffer;
int32_t keysort_capacity;
int32_t keysort_start;
JanetTable seen;
};
@@ -565,7 +575,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
JanetTable *t = janet_unwrap_table(x);
JanetTable *proto = t->proto;
if (NULL != proto) {
Janet name = janet_table_get(proto, janet_ckeywordv("name"));
Janet name = janet_table_get(proto, janet_ckeywordv("_name"));
const uint8_t *n;
int32_t len;
if (janet_bytes_view(name, &n, &len)) {
@@ -587,31 +597,55 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
janet_buffer_push_cstring(S->buffer, "...");
} else {
int32_t i = 0, len = 0, cap = 0;
int first_kv_pair = 1;
const JanetKV *kvs = NULL;
int counter = 0;
janet_dictionary_view(x, &kvs, &len, &cap);
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
janet_buffer_push_u8(S->buffer, ' ');
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
for (i = 0; i < cap; i++) {
if (!janet_checktype(kvs[i].key, JANET_NIL)) {
if (counter == JANET_PRETTY_DICT_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
print_newline(S, 0);
janet_buffer_push_cstring(S->buffer, "...");
break;
}
if (first_kv_pair) {
first_kv_pair = 0;
} else {
print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
}
janet_pretty_one(S, kvs[i].key, 0);
janet_buffer_push_u8(S->buffer, ' ');
janet_pretty_one(S, kvs[i].value, 1);
counter++;
int32_t ks_start = S->keysort_start;
/* Ensure buffer is large enough to sort keys. */
int truncated = 0;
int64_t mincap = (int64_t) len + (int64_t) ks_start;
if (mincap > INT32_MAX) {
truncated = 1;
len = 0;
mincap = ks_start;
}
if (S->keysort_capacity < mincap) {
if (mincap >= INT32_MAX / 2) {
S->keysort_capacity = INT32_MAX;
} else {
S->keysort_capacity = (int32_t)(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->depth++;
@@ -634,6 +668,9 @@ static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Jan
S.indent = 0;
S.flags = flags;
S.bufstartlen = startlen;
S.keysort_capacity = 0;
S.keysort_buffer = NULL;
S.keysort_start = 0;
janet_table_init(&S.seen, 10);
janet_pretty_one(&S, x, 0);
janet_table_deinit(&S.seen);
@@ -656,6 +693,9 @@ static JanetBuffer *janet_jdn_(JanetBuffer *buffer, int depth, Janet x, int32_t
S.indent = 0;
S.flags = 0;
S.bufstartlen = startlen;
S.keysort_capacity = 0;
S.keysort_buffer = NULL;
S.keysort_start = 0;
janet_table_init(&S.seen, 10);
int res = print_jdn_one(&S, x, depth);
janet_table_deinit(&S.seen);
@@ -815,7 +855,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
case 'P':
case 'p': { /* janet pretty , precision = depth */
int depth = atoi(precision);
if (depth < 1) depth = 4;
if (depth < 1) depth = JANET_RECURSION_GUARD;
char d = c[-1];
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
@@ -967,7 +1007,7 @@ void janet_buffer_format(
case 'P':
case 'p': { /* janet pretty , precision = depth */
int depth = atoi(precision);
if (depth < 1) depth = 4;
if (depth < 1) depth = JANET_RECURSION_GUARD;
char d = strfrmt[-1];
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -36,7 +36,7 @@ void janetc_regalloc_init(JanetcRegisterAllocator *ra) {
}
void janetc_regalloc_deinit(JanetcRegisterAllocator *ra) {
free(ra->chunks);
janet_free(ra->chunks);
}
/* Fallbacks for when ctz not available */
@@ -70,7 +70,7 @@ void janetc_regalloc_clone(JanetcRegisterAllocator *dest, JanetcRegisterAllocato
size = sizeof(uint32_t) * (size_t) dest->capacity;
dest->regtemps = 0;
if (size) {
dest->chunks = malloc(size);
dest->chunks = janet_malloc(size);
if (!dest->chunks) {
JANET_OUT_OF_MEMORY;
}
@@ -87,7 +87,7 @@ static void pushchunk(JanetcRegisterAllocator *ra) {
int32_t newcount = ra->count + 1;
if (newcount > ra->capacity) {
int32_t newcapacity = newcount * 2;
ra->chunks = realloc(ra->chunks, (size_t) newcapacity * sizeof(uint32_t));
ra->chunks = janet_realloc(ra->chunks, (size_t) newcapacity * sizeof(uint32_t));
if (!ra->chunks) {
JANET_OUT_OF_MEMORY;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -251,6 +251,9 @@ static JanetTable *handleattr(JanetCompiler *c, int32_t argn, const Janet *argv)
case JANET_STRING:
janet_table_put(tab, janet_ckeywordv("doc"), attr);
break;
case JANET_STRUCT:
janet_table_merge_struct(tab, janet_unwrap_struct(attr));
break;
}
}
return tab;
@@ -336,10 +339,8 @@ static int defleaf(
/* Put value in table when evaulated */
janetc_emit_sss(c, JOP_PUT, tabslot, valsym, s, 0);
return 1;
} else {
return namelocal(c, sym, 0, s);
}
return namelocal(c, sym, 0, s);
}
static JanetSlot janetc_def(JanetFopts opts, int32_t argn, const Janet *argv) {
@@ -409,7 +410,9 @@ static JanetSlot janetc_if(JanetFopts opts, int32_t argn, const Janet *argv) {
right = janetc_value(bodyopts, truebody);
if (!drop && !tail) janetc_copy(c, target, right);
janetc_popscope(c);
janetc_throwaway(bodyopts, falsebody);
if (!janet_checktype(falsebody, JANET_NIL)) {
janetc_throwaway(bodyopts, falsebody);
}
janetc_popscope(c);
return target;
}
@@ -470,6 +473,28 @@ static JanetSlot janetc_do(JanetFopts opts, int32_t argn, const Janet *argv) {
return ret;
}
/* Compile an upscope form. Upscope forms execute their body sequentially and
* evaluate to the last expression in the body, but without lexical scope. */
static JanetSlot janetc_upscope(JanetFopts opts, int32_t argn, const Janet *argv) {
int32_t i;
JanetSlot ret = janetc_cslot(janet_wrap_nil());
JanetCompiler *c = opts.compiler;
JanetFopts subopts = janetc_fopts_default(c);
for (i = 0; i < argn; i++) {
if (i != argn - 1) {
subopts.flags = JANET_FOPTS_DROP;
} else {
subopts = opts;
}
ret = janetc_value(subopts, argv[i]);
if (i != argn - 1) {
janetc_freeslot(c, ret);
}
}
return ret;
}
/* Add a funcdef to the top most function scope */
static int32_t janetc_addfuncdef(JanetCompiler *c, JanetFuncDef *def) {
JanetScope *scope = c->scope;
@@ -854,6 +879,7 @@ static const JanetSpecial janetc_specials[] = {
{"set", janetc_varset},
{"splice", janetc_splice},
{"unquote", janetc_unquote},
{"upscope", janetc_upscope},
{"var", janetc_var},
{"while", janetc_while}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -108,7 +108,7 @@ static void kmp_init(
if (patlen == 0) {
janet_panic("expected non-empty pattern");
}
int32_t *lookup = calloc(patlen, sizeof(int32_t));
int32_t *lookup = janet_calloc(patlen, sizeof(int32_t));
if (!lookup) {
JANET_OUT_OF_MEMORY;
}
@@ -131,7 +131,7 @@ static void kmp_init(
}
static void kmp_deinit(struct kmp_state *state) {
free(state->lookup);
janet_free(state->lookup);
}
static void kmp_seti(struct kmp_state *state, int32_t i) {
@@ -398,6 +398,7 @@ static Janet cfun_string_split(int32_t argc, Janet *argv) {
const uint8_t *slice = janet_string(state.text + lastindex, result - lastindex);
janet_array_push(array, janet_wrap_string(slice));
lastindex = result + state.patlen;
kmp_seti(&state, lastindex);
}
const uint8_t *slice = janet_string(state.text + lastindex, state.textlen - lastindex);
janet_array_push(array, janet_wrap_string(slice));
@@ -588,19 +589,18 @@ static const JanetReg string_cfuns[] = {
},
{
"string/find", cfun_string_find,
JDOC("(string/find patt str)\n\n"
JDOC("(string/find patt str &opt start-index)\n\n"
"Searches for the first instance of pattern patt in string "
"str. Returns the index of the first character in patt if found, "
"otherwise returns nil.")
},
{
"string/find-all", cfun_string_findall,
JDOC("(string/find-all patt str)\n\n"
JDOC("(string/find-all patt str &opt start-index)\n\n"
"Searches for all instances of pattern patt in string "
"str. Returns an array of all indices of found patterns. Overlapping "
"instances of the pattern are not counted, meaning a byte in string "
"will only contribute to finding at most on occurrence of pattern. If no "
"occurrences are found, will return an empty array.")
"instances of the pattern are counted individually, meaning a byte in str "
"may contribute to multiple found patterns.")
},
{
"string/has-prefix?", cfun_string_hasprefix,
@@ -621,7 +621,8 @@ static const JanetReg string_cfuns[] = {
{
"string/replace-all", cfun_string_replaceall,
JDOC("(string/replace-all patt subst str)\n\n"
"Replace all instances of patt with subst in the string str. "
"Replace all instances of patt with subst in the string str. Overlapping "
"matches will not be counted, only the first match in such a span will be replaced. "
"Will return the new string if patt is found, otherwise returns str.")
},
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -87,7 +87,7 @@ static uint32_t *bignat_extra(struct BigNat *mant, int32_t n) {
int32_t newn = oldn + n;
if (mant->cap < newn) {
int32_t newcap = 2 * newn;
uint32_t *mem = realloc(mant->digits, (size_t) newcap * sizeof(uint32_t));
uint32_t *mem = janet_realloc(mant->digits, (size_t) newcap * sizeof(uint32_t));
if (NULL == mem) {
JANET_OUT_OF_MEMORY;
}
@@ -368,11 +368,11 @@ int janet_scan_number(
goto error;
*out = convert(neg, &mant, base, ex);
free(mant.digits);
janet_free(mant.digits);
return 0;
error:
free(mant.digits);
janet_free(mant.digits);
return 1;
}
@@ -447,7 +447,7 @@ int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out) {
int neg;
uint64_t bi;
if (scan_uint64(str, len, &bi, &neg)) {
if (neg && bi <= (UINT64_MAX / 2)) {
if (neg && bi <= ((UINT64_MAX / 2) + 1)) {
if (bi > INT64_MAX) {
*out = INT64_MIN;
} else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -45,7 +45,7 @@ JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted = 0;
/* Initialize the cache (allocate cache memory) */
void janet_symcache_init() {
janet_vm_cache_capacity = 1024;
janet_vm_cache = calloc(1, (size_t) janet_vm_cache_capacity * sizeof(const uint8_t *));
janet_vm_cache = janet_calloc(1, (size_t) janet_vm_cache_capacity * sizeof(const uint8_t *));
if (NULL == janet_vm_cache) {
JANET_OUT_OF_MEMORY;
}
@@ -55,7 +55,7 @@ void janet_symcache_init() {
/* Deinitialize the cache (free the cache memory) */
void janet_symcache_deinit() {
free((void *)janet_vm_cache);
janet_free((void *)janet_vm_cache);
janet_vm_cache = NULL;
janet_vm_cache_capacity = 0;
janet_vm_cache_count = 0;
@@ -122,7 +122,7 @@ notfound:
static void janet_cache_resize(uint32_t newCapacity) {
uint32_t i, oldCapacity;
const uint8_t **oldCache = janet_vm_cache;
const uint8_t **newCache = calloc(1, (size_t) newCapacity * sizeof(const uint8_t *));
const uint8_t **newCache = janet_calloc(1, (size_t) newCapacity * sizeof(const uint8_t *));
if (newCache == NULL) {
JANET_OUT_OF_MEMORY;
}
@@ -145,7 +145,7 @@ static void janet_cache_resize(uint32_t newCapacity) {
}
}
/* Free the old cache */
free((void *)oldCache);
janet_free((void *)oldCache);
}
/* Add an item to the cache */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -117,7 +117,7 @@ static void janet_table_rehash(JanetTable *t, int32_t size) {
if (islocal) {
janet_sfree(olddata);
} else {
free(olddata);
janet_free(olddata);
}
}
@@ -237,7 +237,7 @@ JanetTable *janet_table_clone(JanetTable *table) {
newTable->capacity = table->capacity;
newTable->deleted = table->deleted;
newTable->proto = table->proto;
newTable->data = malloc(newTable->capacity * sizeof(JanetKV));
newTable->data = janet_malloc(newTable->capacity * sizeof(JanetKV));
if (NULL == newTable->data) {
JANET_OUT_OF_MEMORY;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -84,13 +84,16 @@ static JANET_THREAD_LOCAL JanetTable *janet_vm_thread_decode = NULL;
static JanetTable *janet_thread_get_decode(void) {
if (janet_vm_thread_decode == NULL) {
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));
}
return janet_vm_thread_decode;
}
static JanetMailbox *janet_mailbox_create(int refCount, uint16_t capacity) {
JanetMailbox *mailbox = malloc(sizeof(JanetMailbox) + sizeof(JanetBuffer) * (size_t) capacity);
JanetMailbox *mailbox = janet_malloc(sizeof(JanetMailbox) + sizeof(JanetBuffer) * (size_t) capacity);
if (NULL == mailbox) {
JANET_OUT_OF_MEMORY;
}
@@ -123,7 +126,7 @@ static void janet_mailbox_destroy(JanetMailbox *mailbox) {
for (uint16_t i = 0; i < mailbox->messageCapacity; i++) {
janet_buffer_deinit(mailbox->messages + i);
}
free(mailbox);
janet_free(mailbox);
}
static void janet_mailbox_lock(JanetMailbox *mailbox) {
@@ -182,7 +185,7 @@ static int thread_mark(void *p, size_t size) {
}
static JanetMailboxPair *make_mailbox_pair(JanetMailbox *original, uint64_t flags) {
JanetMailboxPair *pair = malloc(sizeof(JanetMailboxPair));
JanetMailboxPair *pair = janet_malloc(sizeof(JanetMailboxPair));
if (NULL == pair) {
JANET_OUT_OF_MEMORY;
}
@@ -196,7 +199,7 @@ static JanetMailboxPair *make_mailbox_pair(JanetMailbox *original, uint64_t flag
static void destroy_mailbox_pair(JanetMailboxPair *pair) {
janet_mailbox_ref(pair->original, -1);
janet_mailbox_ref(pair->newbox, -1);
free(pair);
janet_free(pair);
}
/* Abstract waiting for timeout across windows/posix */
@@ -418,13 +421,21 @@ int janet_thread_receive(Janet *msg_out, double timeout) {
}
static int janet_thread_getter(void *p, Janet key, Janet *out);
static Janet janet_thread_next(void *p, Janet key);
const JanetAbstractType janet_thread_type = {
"core/thread",
thread_gc,
thread_mark,
janet_thread_getter,
JANET_ATEND_GET
NULL, /* put */
NULL, /* marshal */
NULL, /* unmarshal */
NULL, /* tostring */
NULL, /* compare */
NULL, /* hash */
janet_thread_next,
JANET_ATEND_NEXT
};
static JanetThread *janet_make_thread(JanetMailbox *mailbox, JanetTable *encode) {
@@ -512,7 +523,7 @@ static int thread_worker(JanetMailboxPair *pair) {
janet_stacktrace(fiber, out);
}
#ifdef JANET_NET
#ifdef JANET_EV
janet_loop();
#endif
@@ -708,6 +719,11 @@ static int janet_thread_getter(void *p, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), janet_thread_methods, out);
}
static Janet janet_thread_next(void *p, Janet key) {
(void) p;
return janet_nextmethod(janet_thread_methods, key);
}
static const JanetReg threadlib_cfuns[] = {
{
"thread/current", cfun_thread_current,
@@ -720,10 +736,10 @@ static const JanetReg threadlib_cfuns[] = {
"Start a new thread that will start immediately. "
"If capacity is provided, that is how many messages can be stored in the thread's mailbox before blocking senders. "
"The capacity must be between 1 and 65535 inclusive, and defaults to 10. "
"Can optionally provide flags to the new thread - supported flags are:\n"
"\t:h - Start a heavyweight thread. This loads the core environment by default, so may use more memory initially. Messages may compress better, though.\n"
"\t:a - Allow sending over registered abstract types to the new thread\n"
"\t:c - Send over cfunction information to the new thread.\n"
"Can optionally provide flags to the new thread - supported flags are:\n\n"
"* :h - Start a heavyweight thread. This loads the core environment by default, so may use more memory initially. Messages may compress better, though.\n\n"
"* :a - Allow sending over registered abstract types to the new thread\n\n"
"* :c - Send over cfunction information to the new thread.\n\n"
"Returns a handle to the new thread.")
},
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,614 +0,0 @@
/*
* Copyright (c) 2020 Calvin Rose & contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef JANET_AMALG
#include "features.h"
#include <janet.h>
#include "util.h"
#endif
#ifdef JANET_TYPED_ARRAY
static char *ta_type_names[] = {
"uint8",
"int8",
"uint16",
"int16",
"uint32",
"int32",
"uint64",
"int64",
"float32",
"float64",
"?"
};
static size_t ta_type_sizes[] = {
sizeof(uint8_t),
sizeof(int8_t),
sizeof(uint16_t),
sizeof(int16_t),
sizeof(uint32_t),
sizeof(int32_t),
sizeof(uint64_t),
sizeof(int64_t),
sizeof(float),
sizeof(double),
0
};
#define TA_COUNT_TYPES (JANET_TARRAY_TYPE_F64 + 1)
#define TA_ATOM_MAXSIZE 8
#define TA_FLAG_BIG_ENDIAN 1
static JanetTArrayType get_ta_type_by_name(const uint8_t *name) {
for (int i = 0; i < TA_COUNT_TYPES; i++) {
if (!janet_cstrcmp(name, ta_type_names[i]))
return i;
}
janet_panicf("invalid typed array type %S", name);
return 0;
}
static JanetTArrayBuffer *ta_buffer_init(JanetTArrayBuffer *buf, size_t size) {
buf->data = NULL;
if (size > 0) {
buf->data = (uint8_t *)calloc(size, sizeof(uint8_t));
if (buf->data == NULL) {
JANET_OUT_OF_MEMORY;
}
}
buf->size = size;
#ifdef JANET_BIG_ENDIAN
buf->flags = TA_FLAG_BIG_ENDIAN;
#else
buf->flags = 0;
#endif
return buf;
}
static int ta_buffer_gc(void *p, size_t s) {
(void) s;
JanetTArrayBuffer *buf = (JanetTArrayBuffer *)p;
free(buf->data);
return 0;
}
static void ta_buffer_marshal(void *p, JanetMarshalContext *ctx) {
JanetTArrayBuffer *buf = (JanetTArrayBuffer *)p;
janet_marshal_abstract(ctx, p);
janet_marshal_size(ctx, buf->size);
janet_marshal_int(ctx, buf->flags);
janet_marshal_bytes(ctx, buf->data, buf->size);
}
static void *ta_buffer_unmarshal(JanetMarshalContext *ctx) {
JanetTArrayBuffer *buf = janet_unmarshal_abstract(ctx, sizeof(JanetTArrayBuffer));
size_t size = janet_unmarshal_size(ctx);
int32_t flags = janet_unmarshal_int(ctx);
ta_buffer_init(buf, size);
buf->flags = flags;
janet_unmarshal_bytes(ctx, buf->data, size);
return buf;
}
const JanetAbstractType janet_ta_buffer_type = {
"ta/buffer",
ta_buffer_gc,
NULL,
NULL,
NULL,
ta_buffer_marshal,
ta_buffer_unmarshal,
JANET_ATEND_UNMARSHAL
};
static int ta_mark(void *p, size_t s) {
(void) s;
JanetTArrayView *view = (JanetTArrayView *)p;
janet_mark(janet_wrap_abstract(view->buffer));
return 0;
}
static void ta_view_marshal(void *p, JanetMarshalContext *ctx) {
JanetTArrayView *view = (JanetTArrayView *)p;
size_t offset = (view->buffer->data - view->as.u8);
janet_marshal_abstract(ctx, p);
janet_marshal_size(ctx, view->size);
janet_marshal_size(ctx, view->stride);
janet_marshal_int(ctx, view->type);
janet_marshal_size(ctx, offset);
janet_marshal_janet(ctx, janet_wrap_abstract(view->buffer));
}
static void *ta_view_unmarshal(JanetMarshalContext *ctx) {
size_t offset;
int32_t atype;
Janet buffer;
JanetTArrayView *view = janet_unmarshal_abstract(ctx, sizeof(JanetTArrayView));
view->size = janet_unmarshal_size(ctx);
view->stride = janet_unmarshal_size(ctx);
atype = janet_unmarshal_int(ctx);
if (atype < 0 || atype >= TA_COUNT_TYPES)
janet_panic("bad typed array type");
view->type = atype;
offset = janet_unmarshal_size(ctx);
buffer = janet_unmarshal_janet(ctx);
if (!janet_checktype(buffer, JANET_ABSTRACT) ||
(janet_abstract_type(janet_unwrap_abstract(buffer)) != &janet_ta_buffer_type)) {
janet_panicf("expected typed array buffer");
}
view->buffer = (JanetTArrayBuffer *)janet_unwrap_abstract(buffer);
size_t buf_need_size = offset + (ta_type_sizes[view->type]) * ((view->size - 1) * view->stride + 1);
if (view->buffer->size < buf_need_size)
janet_panic("bad typed array offset in marshalled data");
view->as.u8 = view->buffer->data + offset;
return view;
}
static JanetMethod tarray_view_methods[6];
static int ta_getter(void *p, Janet key, Janet *out) {
size_t index, i;
JanetTArrayView *array = p;
if (janet_checktype(key, JANET_KEYWORD)) {
return janet_getmethod(janet_unwrap_keyword(key), tarray_view_methods, out);
}
if (!janet_checksize(key)) janet_panic("expected size as key");
index = (size_t) janet_unwrap_number(key);
i = index * array->stride;
if (index >= array->size) {
return 0;
} else {
switch (array->type) {
case JANET_TARRAY_TYPE_U8:
*out = janet_wrap_number(array->as.u8[i]);
break;
case JANET_TARRAY_TYPE_S8:
*out = janet_wrap_number(array->as.s8[i]);
break;
case JANET_TARRAY_TYPE_U16:
*out = janet_wrap_number(array->as.u16[i]);
break;
case JANET_TARRAY_TYPE_S16:
*out = janet_wrap_number(array->as.s16[i]);
break;
case JANET_TARRAY_TYPE_U32:
*out = janet_wrap_number(array->as.u32[i]);
break;
case JANET_TARRAY_TYPE_S32:
*out = janet_wrap_number(array->as.s32[i]);
break;
#ifdef JANET_INT_TYPES
case JANET_TARRAY_TYPE_U64:
*out = janet_wrap_u64(array->as.u64[i]);
break;
case JANET_TARRAY_TYPE_S64:
*out = janet_wrap_s64(array->as.s64[i]);
break;
#endif
case JANET_TARRAY_TYPE_F32:
*out = janet_wrap_number_safe(array->as.f32[i]);
break;
case JANET_TARRAY_TYPE_F64:
*out = janet_wrap_number_safe(array->as.f64[i]);
break;
default:
janet_panicf("cannot get from typed array of type %s",
ta_type_names[array->type]);
break;
}
}
return 1;
}
static void ta_setter(void *p, Janet key, Janet value) {
size_t index, i;
if (!janet_checksize(key)) janet_panic("expected size as key");
index = (size_t) janet_unwrap_number(key);
JanetTArrayView *array = p;
i = index * array->stride;
if (index >= array->size) {
janet_panic("index out of bounds");
}
if (!janet_checktype(value, JANET_NUMBER) &&
array->type != JANET_TARRAY_TYPE_U64 &&
array->type != JANET_TARRAY_TYPE_S64) {
janet_panic("expected number value");
}
switch (array->type) {
case JANET_TARRAY_TYPE_U8:
array->as.u8[i] = (uint8_t) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_S8:
array->as.s8[i] = (int8_t) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_U16:
array->as.u16[i] = (uint16_t) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_S16:
array->as.s16[i] = (int16_t) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_U32:
array->as.u32[i] = (uint32_t) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_S32:
array->as.s32[i] = (int32_t) janet_unwrap_number(value);
break;
#ifdef JANET_INT_TYPES
case JANET_TARRAY_TYPE_U64:
array->as.u64[i] = janet_unwrap_u64(value);
break;
case JANET_TARRAY_TYPE_S64:
array->as.s64[i] = janet_unwrap_s64(value);
break;
#endif
case JANET_TARRAY_TYPE_F32:
array->as.f32[i] = (float) janet_unwrap_number(value);
break;
case JANET_TARRAY_TYPE_F64:
array->as.f64[i] = janet_unwrap_number(value);
break;
default:
janet_panicf("cannot set typed array of type %s",
ta_type_names[array->type]);
break;
}
}
static Janet ta_view_next(void *p, Janet key) {
JanetTArrayView *view = p;
if (janet_checktype(key, JANET_NIL)) {
if (view->size > 0) {
return janet_wrap_number(0);
} else {
return janet_wrap_nil();
}
}
if (!janet_checksize(key)) janet_panic("expected size as key");
size_t index = (size_t) janet_unwrap_number(key);
index++;
if (index < view->size) {
return janet_wrap_number((double) index);
}
return janet_wrap_nil();
}
const JanetAbstractType janet_ta_view_type = {
"ta/view",
NULL,
ta_mark,
ta_getter,
ta_setter,
ta_view_marshal,
ta_view_unmarshal,
NULL,
NULL,
NULL,
ta_view_next,
JANET_ATEND_NEXT
};
JanetTArrayBuffer *janet_tarray_buffer(size_t size) {
JanetTArrayBuffer *buf = janet_abstract(&janet_ta_buffer_type, sizeof(JanetTArrayBuffer));
ta_buffer_init(buf, size);
return buf;
}
JanetTArrayView *janet_tarray_view(
JanetTArrayType type,
size_t size,
size_t stride,
size_t offset,
JanetTArrayBuffer *buffer) {
JanetTArrayView *view = janet_abstract(&janet_ta_view_type, sizeof(JanetTArrayView));
if ((stride < 1) || (size < 1)) janet_panic("stride and size should be > 0");
size_t buf_size = offset + ta_type_sizes[type] * ((size - 1) * stride + 1);
if (NULL == buffer) {
buffer = janet_abstract(&janet_ta_buffer_type, sizeof(JanetTArrayBuffer));
ta_buffer_init(buffer, buf_size);
}
if (buffer->size < buf_size) {
janet_panicf("bad buffer size, %i bytes allocated < %i required",
buffer->size,
buf_size);
}
view->buffer = buffer;
view->stride = stride;
view->size = size;
view->as.u8 = buffer->data + offset;
view->type = type;
return view;
}
JanetTArrayBuffer *janet_gettarray_buffer(const Janet *argv, int32_t n) {
return janet_getabstract(argv, n, &janet_ta_buffer_type);
}
JanetTArrayView *janet_gettarray_any(const Janet *argv, int32_t n) {
return janet_getabstract(argv, n, &janet_ta_view_type);
}
JanetTArrayView *janet_gettarray_view(const Janet *argv, int32_t n, JanetTArrayType type) {
JanetTArrayView *view = janet_getabstract(argv, n, &janet_ta_view_type);
if (view->type != type) {
janet_panicf("bad slot #%d, expected typed array of type %s, got %v",
n, ta_type_names[type], argv[n]);
}
return view;
}
static Janet cfun_typed_array_new(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 5);
size_t offset = 0;
size_t stride = 1;
JanetTArrayBuffer *buffer = NULL;
const uint8_t *keyw = janet_getkeyword(argv, 0);
JanetTArrayType type = get_ta_type_by_name(keyw);
size_t size = janet_getsize(argv, 1);
if (argc > 2)
stride = janet_getsize(argv, 2);
if (argc > 3)
offset = janet_getsize(argv, 3);
if (argc > 4) {
int32_t blen;
const uint8_t *bytes;
if (janet_bytes_view(argv[4], &bytes, &blen)) {
buffer = janet_abstract(&janet_ta_buffer_type, sizeof(JanetTArrayBuffer));
ta_buffer_init(buffer, (size_t) blen);
memcpy(buffer->data, bytes, blen);
} else {
if (!janet_checktype(argv[4], JANET_ABSTRACT)) {
janet_panicf("bad slot #%d, expected ta/view|ta/buffer, got %v",
4, argv[4]);
}
void *p = janet_unwrap_abstract(argv[4]);
if (janet_abstract_type(p) == &janet_ta_view_type) {
JanetTArrayView *view = (JanetTArrayView *)p;
offset = (view->buffer->data - view->as.u8) + offset * ta_type_sizes[view->type];
stride *= view->stride;
buffer = view->buffer;
} else if (janet_abstract_type(p) == &janet_ta_buffer_type) {
buffer = p;
} else {
janet_panicf("bad slot #%d, expected ta/view|ta/buffer, got %v",
4, argv[4]);
}
}
}
JanetTArrayView *view = janet_tarray_view(type, size, stride, offset, buffer);
return janet_wrap_abstract(view);
}
static JanetTArrayView *ta_is_view(Janet x) {
if (!janet_checktype(x, JANET_ABSTRACT)) return NULL;
void *abst = janet_unwrap_abstract(x);
if (janet_abstract_type(abst) != &janet_ta_view_type) return NULL;
return (JanetTArrayView *)abst;
}
static Janet cfun_typed_array_buffer(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetTArrayView *view;
if ((view = ta_is_view(argv[0]))) {
return janet_wrap_abstract(view->buffer);
}
size_t size = janet_getsize(argv, 0);
JanetTArrayBuffer *buf = janet_tarray_buffer(size);
return janet_wrap_abstract(buf);
}
static Janet cfun_typed_array_size(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetTArrayView *view;
if ((view = ta_is_view(argv[0]))) {
return janet_wrap_number((double) view->size);
}
JanetTArrayBuffer *buf = (JanetTArrayBuffer *)janet_getabstract(argv, 0, &janet_ta_buffer_type);
return janet_wrap_number((double) buf->size);
}
static Janet cfun_typed_array_properties(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
JanetTArrayView *view;
if ((view = ta_is_view(argv[0]))) {
JanetTArrayView *view = janet_unwrap_abstract(argv[0]);
JanetKV *props = janet_struct_begin(6);
ptrdiff_t boffset = view->as.u8 - view->buffer->data;
janet_struct_put(props, janet_ckeywordv("size"),
janet_wrap_number((double) view->size));
janet_struct_put(props, janet_ckeywordv("byte-offset"),
janet_wrap_number((double) boffset));
janet_struct_put(props, janet_ckeywordv("stride"),
janet_wrap_number((double) view->stride));
janet_struct_put(props, janet_ckeywordv("type"),
janet_ckeywordv(ta_type_names[view->type]));
janet_struct_put(props, janet_ckeywordv("type-size"),
janet_wrap_number((double) ta_type_sizes[view->type]));
janet_struct_put(props, janet_ckeywordv("buffer"),
janet_wrap_abstract(view->buffer));
return janet_wrap_struct(janet_struct_end(props));
} else {
JanetTArrayBuffer *buffer = janet_gettarray_buffer(argv, 0);
JanetKV *props = janet_struct_begin(2);
janet_struct_put(props, janet_ckeywordv("size"),
janet_wrap_number((double) buffer->size));
janet_struct_put(props, janet_ckeywordv("big-endian"),
janet_wrap_boolean(buffer->flags & TA_FLAG_BIG_ENDIAN));
return janet_wrap_struct(janet_struct_end(props));
}
}
static Janet cfun_typed_array_slice(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 3);
JanetTArrayView *src = janet_getabstract(argv, 0, &janet_ta_view_type);
JanetRange range;
int32_t length = (int32_t)src->size;
if (argc == 1) {
range.start = 0;
range.end = length;
} else if (argc == 2) {
range.start = janet_gethalfrange(argv, 1, length, "start");
range.end = length;
} else {
range.start = janet_gethalfrange(argv, 1, length, "start");
range.end = janet_gethalfrange(argv, 2, length, "end");
if (range.end < range.start)
range.end = range.start;
}
JanetArray *array = janet_array(range.end - range.start);
if (array->data) {
for (int32_t i = range.start; i < range.end; i++) {
if (!ta_getter(src, janet_wrap_number(i), &array->data[i - range.start]))
array->data[i - range.start] = janet_wrap_nil();
}
}
array->count = range.end - range.start;
return janet_wrap_array(array);
}
static Janet cfun_typed_array_copy_bytes(int32_t argc, Janet *argv) {
janet_arity(argc, 4, 5);
JanetTArrayView *src = janet_getabstract(argv, 0, &janet_ta_view_type);
size_t index_src = janet_getsize(argv, 1);
JanetTArrayView *dst = janet_getabstract(argv, 2, &janet_ta_view_type);
size_t index_dst = janet_getsize(argv, 3);
size_t count = (argc == 5) ? janet_getsize(argv, 4) : 1;
size_t src_atom_size = ta_type_sizes[src->type];
size_t dst_atom_size = ta_type_sizes[dst->type];
size_t step_src = src->stride * src_atom_size;
size_t step_dst = dst->stride * dst_atom_size;
size_t pos_src = (src->as.u8 - src->buffer->data) + (index_src * step_src);
size_t pos_dst = (dst->as.u8 - dst->buffer->data) + (index_dst * step_dst);
uint8_t *ps = src->buffer->data + pos_src, * pd = dst->buffer->data + pos_dst;
if ((pos_dst + (count - 1)*step_dst + src_atom_size <= dst->buffer->size) &&
(pos_src + (count - 1)*step_src + src_atom_size <= src->buffer->size)) {
for (size_t i = 0; i < count; i++) {
memmove(pd, ps, src_atom_size);
pd += step_dst;
ps += step_src;
}
} else {
janet_panic("typed array copy out of bounds");
}
return janet_wrap_nil();
}
static Janet cfun_typed_array_swap_bytes(int32_t argc, Janet *argv) {
janet_arity(argc, 4, 5);
JanetTArrayView *src = janet_getabstract(argv, 0, &janet_ta_view_type);
size_t index_src = janet_getsize(argv, 1);
JanetTArrayView *dst = janet_getabstract(argv, 2, &janet_ta_view_type);
size_t index_dst = janet_getsize(argv, 3);
size_t count = (argc == 5) ? janet_getsize(argv, 4) : 1;
size_t src_atom_size = ta_type_sizes[src->type];
size_t dst_atom_size = ta_type_sizes[dst->type];
size_t step_src = src->stride * src_atom_size;
size_t step_dst = dst->stride * dst_atom_size;
size_t pos_src = (src->as.u8 - src->buffer->data) + (index_src * step_src);
size_t pos_dst = (dst->as.u8 - dst->buffer->data) + (index_dst * step_dst);
uint8_t *ps = src->buffer->data + pos_src, * pd = dst->buffer->data + pos_dst;
uint8_t temp[TA_ATOM_MAXSIZE];
if ((pos_dst + (count - 1)*step_dst + src_atom_size <= dst->buffer->size) &&
(pos_src + (count - 1)*step_src + src_atom_size <= src->buffer->size)) {
for (size_t i = 0; i < count; i++) {
memcpy(temp, ps, src_atom_size);
memcpy(ps, pd, src_atom_size);
memcpy(pd, temp, src_atom_size);
pd += step_dst;
ps += step_src;
}
} else {
janet_panic("typed array swap out of bounds");
}
return janet_wrap_nil();
}
static const JanetReg ta_cfuns[] = {
{
"tarray/new", cfun_typed_array_new,
JDOC("(tarray/new type size &opt stride offset tarray|buffer)\n\n"
"Create new typed array.")
},
{
"tarray/buffer", cfun_typed_array_buffer,
JDOC("(tarray/buffer array|size)\n\n"
"Return typed array buffer or create a new buffer.")
},
{
"tarray/length", cfun_typed_array_size,
JDOC("(tarray/length array|buffer)\n\n"
"Return typed array or buffer size.")
},
{
"tarray/properties", cfun_typed_array_properties,
JDOC("(tarray/properties array)\n\n"
"Return typed array properties as a struct.")
},
{
"tarray/copy-bytes", cfun_typed_array_copy_bytes,
JDOC("(tarray/copy-bytes src sindex dst dindex &opt count)\n\n"
"Copy count elements (default 1) of src array from index sindex "
"to dst array at position dindex "
"memory can overlap.")
},
{
"tarray/swap-bytes", cfun_typed_array_swap_bytes,
JDOC("(tarray/swap-bytes src sindex dst dindex &opt count)\n\n"
"Swap count elements (default 1) between src array from index sindex "
"and dst array at position dindex "
"memory can overlap.")
},
{
"tarray/slice", cfun_typed_array_slice,
JDOC("(tarray/slice tarr &opt start end)\n\n"
"Takes a slice of a typed array from start to end. The range is half "
"open, [start, end). Indexes can also be negative, indicating indexing "
"from the end of the end of the typed array. By default, start is 0 and end is "
"the size of the typed array. Returns a new janet array.")
},
{NULL, NULL, NULL}
};
static JanetMethod tarray_view_methods[] = {
{"length", cfun_typed_array_size},
{"properties", cfun_typed_array_properties},
{"copy-bytes", cfun_typed_array_copy_bytes},
{"swap-bytes", cfun_typed_array_swap_bytes},
{"slice", cfun_typed_array_slice},
{NULL, NULL}
};
/* Module entry point */
void janet_lib_typed_array(JanetTable *env) {
janet_core_cfuns(env, NULL, ta_cfuns);
janet_register_abstract_type(&janet_ta_buffer_type);
janet_register_abstract_type(&janet_ta_view_type);
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -227,19 +227,21 @@ int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
/* Computes hash of an array of values */
int32_t janet_array_calchash(const Janet *array, int32_t len) {
const Janet *end = array + len;
uint32_t hash = 5381;
while (array < end)
hash = (hash << 5) + hash + janet_hash(*array++);
uint32_t hash = 0;
while (array < end) {
uint32_t elem = janet_hash(*array++);
hash ^= elem + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return (int32_t) hash;
}
/* Computes hash of an array of values */
int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len) {
const JanetKV *end = kvs + len;
uint32_t hash = 5381;
uint32_t hash = 0;
while (kvs < end) {
hash = (hash << 5) + hash + janet_hash(kvs->key);
hash = (hash << 5) + hash + janet_hash(kvs->value);
hash ^= janet_hash(kvs->key) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= janet_hash(kvs->value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
kvs++;
}
return (int32_t) hash;
@@ -395,7 +397,7 @@ static void _janet_cfuns_prefix(JanetTable *env, const char *regprefix, const Ja
if (NULL != regprefix) {
prefixlen = strlen(regprefix);
bufsize = prefixlen + 256;
longname_buffer = malloc(bufsize);
longname_buffer = janet_malloc(bufsize);
if (NULL == longname_buffer) {
JANET_OUT_OF_MEMORY;
}
@@ -411,7 +413,7 @@ static void _janet_cfuns_prefix(JanetTable *env, const char *regprefix, const Ja
int32_t totallen = (int32_t) prefixlen + nmlen;
if ((size_t) totallen > bufsize) {
bufsize = (size_t)(totallen) + 128;
longname_buffer = realloc(longname_buffer, bufsize);
longname_buffer = janet_realloc(longname_buffer, bufsize);
if (NULL == longname_buffer) {
JANET_OUT_OF_MEMORY;
}
@@ -434,7 +436,7 @@ static void _janet_cfuns_prefix(JanetTable *env, const char *regprefix, const Ja
janet_table_put(janet_vm_registry, fun, name);
cfuns++;
}
free(longname_buffer);
(janet_free)(longname_buffer);
}
void janet_cfuns_prefix(JanetTable *env, const char *regprefix, const JanetReg *cfuns) {
@@ -485,27 +487,60 @@ void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cf
}
#endif
/* Resolve a symbol in the environment */
JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out) {
JanetBinding janet_resolve_ext(JanetTable *env, const uint8_t *sym) {
Janet ref;
JanetTable *entry_table;
Janet entry = janet_table_get(env, janet_wrap_symbol(sym));
JanetBinding binding = {
JANET_BINDING_NONE,
janet_wrap_nil(),
JANET_BINDING_DEP_NONE
};
/* Check environment for entry */
if (!janet_checktype(entry, JANET_TABLE))
return JANET_BINDING_NONE;
return binding;
entry_table = janet_unwrap_table(entry);
/* deprecation check */
Janet deprecate = janet_table_get(entry_table, janet_ckeywordv("deprecated"));
if (janet_checktype(deprecate, JANET_KEYWORD)) {
JanetKeyword depkw = janet_unwrap_keyword(deprecate);
if (!janet_cstrcmp(depkw, "relaxed")) {
binding.deprecation = JANET_BINDING_DEP_RELAXED;
} else if (!janet_cstrcmp(depkw, "normal")) {
binding.deprecation = JANET_BINDING_DEP_NORMAL;
} else if (!janet_cstrcmp(depkw, "strict")) {
binding.deprecation = JANET_BINDING_DEP_STRICT;
}
} else if (!janet_checktype(deprecate, JANET_NIL)) {
binding.deprecation = JANET_BINDING_DEP_NORMAL;
}
if (!janet_checktype(
janet_table_get(entry_table, janet_ckeywordv("macro")),
JANET_NIL)) {
*out = janet_table_get(entry_table, janet_ckeywordv("value"));
return JANET_BINDING_MACRO;
binding.value = janet_table_get(entry_table, janet_ckeywordv("value"));
binding.type = JANET_BINDING_MACRO;
return binding;
}
ref = janet_table_get(entry_table, janet_ckeywordv("ref"));
if (janet_checktype(ref, JANET_ARRAY)) {
*out = ref;
return JANET_BINDING_VAR;
binding.value = ref;
binding.type = JANET_BINDING_VAR;
return binding;
}
*out = janet_table_get(entry_table, janet_ckeywordv("value"));
return JANET_BINDING_DEF;
binding.value = janet_table_get(entry_table, janet_ckeywordv("value"));
binding.type = JANET_BINDING_DEF;
return binding;
}
JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out) {
JanetBinding binding = janet_resolve_ext(env, sym);
*out = binding.value;
return binding.type;
}
/* Resolve a symbol in the core environment. */
@@ -600,6 +635,38 @@ JanetTable *janet_get_core_table(const char *name) {
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 */
#ifdef JANET_GETTIME
/* For macos */
@@ -686,3 +753,21 @@ int janet_cryptorand(uint8_t *out, size_t n) {
return -1;
#endif
}
/* Alloc function macro fills */
void *(janet_malloc)(size_t size) {
return janet_malloc(size);
}
void (janet_free)(void *ptr) {
janet_free(ptr);
}
void *(janet_calloc)(size_t nmemb, size_t size) {
return janet_calloc(nmemb, size);
}
void *(janet_realloc)(void *ptr, size_t size) {
return janet_realloc(ptr, size);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -52,12 +52,6 @@
if (!(c)) JANET_EXIT((m)); \
} while (0)
/* What to do when out of memory */
#ifndef JANET_OUT_OF_MEMORY
#include <stdio.h>
#define JANET_OUT_OF_MEMORY do { fprintf(stderr, "janet out of memory\n"); exit(1); } while (0)
#endif
/* Omit docstrings in some builds */
#ifndef JANET_BOOTSTRAP
#define JDOC(x) NULL
@@ -91,6 +85,7 @@ void janet_buffer_format(
int32_t argstart,
int32_t argc,
Janet *argv);
Janet janet_next_impl(Janet ds, Janet key, int is_interpreter);
/* Inside the janet core, defining globals is different
* at bootstrap time and normal runtime */
@@ -107,6 +102,11 @@ void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cf
int janet_gettime(struct timespec *spec);
#endif
/* strdup */
#ifdef JANET_WINDOWS
#define strdup(x) _strdup(x)
#endif
#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR)
/* Initialize builtin libraries */
@@ -145,6 +145,7 @@ extern const JanetAbstractType janet_address_type;
#ifdef JANET_EV
void janet_lib_ev(JanetTable *env);
void janet_ev_mark(void);
int janet_make_pipe(JanetHandle handles[2], int mode);
#endif
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -25,9 +25,12 @@
#include "util.h"
#include "state.h"
#include "gc.h"
#include "fiber.h"
#include <janet.h>
#endif
#include <math.h>
JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal = NULL;
JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_top = NULL;
JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_base = NULL;
@@ -44,7 +47,7 @@ static void push_traversal_node(void *lhs, void *rhs, int32_t index2) {
if (newsize < 128) {
newsize = 128;
}
JanetTraversalNode *tn = realloc(janet_vm_traversal_base, newsize * sizeof(JanetTraversalNode));
JanetTraversalNode *tn = janet_realloc(janet_vm_traversal_base, newsize * sizeof(JanetTraversalNode));
if (tn == NULL) {
JANET_OUT_OF_MEMORY;
}
@@ -113,6 +116,10 @@ static int traversal_next(Janet *x, Janet *y) {
*/
Janet janet_next(Janet ds, Janet key) {
return janet_next_impl(ds, key, 0);
}
Janet janet_next_impl(Janet ds, Janet key, int is_interpreter) {
JanetType t = janet_type(ds);
switch (t) {
default:
@@ -175,6 +182,44 @@ Janet janet_next(Janet ds, Janet key) {
if (NULL == at->next) break;
return at->next(abst, key);
}
case JANET_FIBER: {
JanetFiber *child = janet_unwrap_fiber(ds);
Janet retreg;
JanetFiberStatus status = janet_fiber_status(child);
if (status == JANET_STATUS_ALIVE ||
status == JANET_STATUS_DEAD ||
status == JANET_STATUS_ERROR ||
status == JANET_STATUS_USER0 ||
status == JANET_STATUS_USER1 ||
status == JANET_STATUS_USER2 ||
status == JANET_STATUS_USER3 ||
status == JANET_STATUS_USER4) {
return janet_wrap_nil();
}
janet_vm_fiber->child = child;
JanetSignal sig = janet_continue(child, janet_wrap_nil(), &retreg);
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
if (is_interpreter) {
janet_signalv(sig, retreg);
} else {
janet_vm_fiber->child = NULL;
janet_panicv(retreg);
}
}
janet_vm_fiber->child = NULL;
if (sig == JANET_SIGNAL_OK ||
sig == JANET_SIGNAL_ERROR ||
sig == JANET_SIGNAL_USER0 ||
sig == JANET_SIGNAL_USER1 ||
sig == JANET_SIGNAL_USER2 ||
sig == JANET_SIGNAL_USER3 ||
sig == JANET_SIGNAL_USER4) {
/* Fiber cannot be resumed, so discard last value. */
return janet_wrap_nil();
} else {
return janet_wrap_integer(0);
}
}
}
return janet_wrap_nil();
}
@@ -261,6 +306,17 @@ int32_t janet_hash(Janet x) {
case JANET_STRUCT:
hash = janet_struct_hash(janet_unwrap_struct(x));
break;
case JANET_NUMBER: {
union {
double d;
uint64_t u;
} as;
as.d = janet_unwrap_number(x);
uint32_t lo = (uint32_t)(as.u & 0xFFFFFFFF);
uint32_t hi = (uint32_t)(as.u >> 32);
hash = (int32_t)(hi ^ (lo >> 3));
break;
}
case JANET_ABSTRACT: {
JanetAbstract xx = janet_unwrap_abstract(x);
const JanetAbstractType *at = janet_abstract_type(xx);
@@ -417,6 +473,14 @@ Janet janet_in(Janet ds, Janet key) {
}
break;
}
case JANET_FIBER: {
/* Bit of a hack to allow iterating over fibers. */
if (janet_equals(key, janet_wrap_integer(0))) {
return janet_unwrap_fiber(ds)->last_value;
} else {
janet_panicf("expected key 0, got %v", key);
}
}
}
return value;
}
@@ -472,6 +536,14 @@ Janet janet_get(Janet ds, Janet key) {
const JanetKV *st = janet_unwrap_struct(ds);
return janet_struct_get(st, key);
}
case JANET_FIBER: {
/* Bit of a hack to allow iterating over fibers. */
if (janet_equals(key, janet_wrap_integer(0))) {
return janet_unwrap_fiber(ds)->last_value;
} else {
return janet_wrap_nil();
}
}
}
}
@@ -528,6 +600,14 @@ Janet janet_getindex(Janet ds, int32_t index) {
}
break;
}
case JANET_FIBER: {
if (index == 0) {
value = janet_unwrap_fiber(ds)->last_value;
} else {
value = janet_wrap_nil();
}
break;
}
}
return value;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -43,7 +43,7 @@ void *janet_v_flattenmem(void *v, int32_t itemsize) {
int32_t *p;
if (NULL == v) return NULL;
size_t size = (size_t) itemsize * janet_v__cnt(v);
p = malloc(size);
p = janet_malloc(size);
if (NULL != p) {
safe_memcpy(p, v, size);
return p;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -202,6 +202,20 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
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 */
static void vm_do_trace(JanetFunction *func, int32_t argc, const Janet *argv) {
@@ -261,11 +275,16 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
return janet_method_invoke(callee, argc, fiber->data + fiber->stacktop);
}
/* Method lookup could potentially handle tables specially... */
static Janet method_to_fun(Janet method, Janet obj) {
return janet_get(obj, method);
}
/* Get a callable from a keyword method name and ensure that it is valid. */
static Janet resolve_method(Janet name, JanetFiber *fiber) {
int32_t argc = fiber->stacktop - fiber->stackstart;
if (argc < 1) janet_panicf("method call (%v) takes at least 1 argument, got 0", name);
Janet callee = janet_get(fiber->data[fiber->stackstart], name);
Janet callee = method_to_fun(name, fiber->data[fiber->stackstart]);
if (janet_checktype(callee, JANET_NIL))
janet_panicf("unknown method %v invoked on %v", name, fiber->data[fiber->stackstart]);
return callee;
@@ -273,8 +292,7 @@ static Janet resolve_method(Janet name, JanetFiber *fiber) {
/* Lookup method on value x */
static Janet janet_method_lookup(Janet x, const char *name) {
Janet kname = janet_ckeywordv(name);
return janet_get(x, kname);
return method_to_fun(janet_ckeywordv(name), x);
}
/* Call a method first on the righthand side, and then on the left hand side with a prefix */
@@ -780,8 +798,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_compop( <=);
VM_OP(JOP_LESS_THAN_IMMEDIATE)
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) < CS);
vm_pcnext();
vm_compop_imm( <);
VM_OP(JOP_GREATER_THAN)
vm_compop( >);
@@ -790,15 +807,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_compop( >=);
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) > CS);
vm_pcnext();
vm_compop_imm( >);
VM_OP(JOP_EQUALS)
stack[A] = janet_wrap_boolean(janet_equals(stack[B], stack[C]));
vm_pcnext();
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_OP(JOP_NOT_EQUALS)
@@ -806,7 +822,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_pcnext();
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_OP(JOP_COMPARE)
@@ -815,7 +831,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
VM_OP(JOP_NEXT)
vm_commit();
stack[A] = janet_next(stack[B], stack[C]);
{
Janet temp = janet_next_impl(stack[B], stack[C], 1);
vm_restore();
stack[A] = temp;
}
vm_pcnext();
VM_OP(JOP_LOAD_NIL)
@@ -1272,7 +1292,14 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
/* Push frame */
janet_fiber_pushn(janet_vm_fiber, argv, argc);
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;
@@ -1341,18 +1368,42 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
janet_fiber_did_resume(fiber);
#endif
/* Clear last value */
fiber->last_value = janet_wrap_nil();
/* Continue child fiber if it exists */
if (fiber->child) {
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
JanetFiber *child = fiber->child;
uint32_t instr = (janet_stack_frame(fiber->data + fiber->frame)->pc)[0];
janet_vm_stackn++;
JanetSignal sig = janet_continue(child, in, &in);
janet_vm_stackn--;
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
*out = in;
janet_fiber_set_status(fiber, sig);
return sig;
}
/* Check if we need any special handling for certain opcodes */
switch (instr & 0x7F) {
default:
break;
case JOP_NEXT: {
if (sig == JANET_SIGNAL_OK ||
sig == JANET_SIGNAL_ERROR ||
sig == JANET_SIGNAL_USER0 ||
sig == JANET_SIGNAL_USER1 ||
sig == JANET_SIGNAL_USER2 ||
sig == JANET_SIGNAL_USER3 ||
sig == JANET_SIGNAL_USER4) {
in = janet_wrap_nil();
} else {
in = janet_wrap_integer(0);
}
break;
}
}
fiber->child = NULL;
}
@@ -1371,22 +1422,23 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
/* Save global state */
JanetTryState tstate;
JanetSignal signal = janet_try(&tstate);
if (!signal) {
JanetSignal sig = janet_try(&tstate);
if (!sig) {
/* Normal setup */
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
janet_vm_fiber = fiber;
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
signal = run_vm(fiber, in);
sig = run_vm(fiber, in);
}
/* Restore */
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);
fiber->last_value = tstate.payload;
*out = tstate.payload;
return signal;
return sig;
}
/* Enter the main vm loop */
@@ -1478,7 +1530,6 @@ int janet_init(void) {
janet_vm_fiber = NULL;
janet_vm_root_fiber = NULL;
janet_vm_stackn = 0;
/* Threads */
#ifdef JANET_THREADS
janet_threads_init();
#endif
@@ -1495,7 +1546,7 @@ int janet_init(void) {
void janet_deinit(void) {
janet_clear_memory();
janet_symcache_deinit();
free(janet_vm_roots);
janet_free(janet_vm_roots);
janet_vm_roots = NULL;
janet_vm_root_count = 0;
janet_vm_root_capacity = 0;
@@ -1503,7 +1554,7 @@ void janet_deinit(void) {
janet_vm_abstract_registry = NULL;
janet_vm_core_env = NULL;
janet_vm_top_dyns = NULL;
free(janet_vm_traversal_base);
janet_free(janet_vm_traversal_base);
janet_vm_fiber = NULL;
janet_vm_root_fiber = NULL;
#ifdef JANET_THREADS

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -162,7 +162,7 @@ Janet(janet_wrap_number)(double x) {
void *janet_memalloc_empty(int32_t count) {
int32_t i;
void *mem = malloc((size_t) count * sizeof(JanetKV));
void *mem = janet_malloc((size_t) count * sizeof(JanetKV));
janet_vm_next_collection += (size_t) count * sizeof(JanetKV);
if (NULL == mem) {
JANET_OUT_OF_MEMORY;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -20,6 +20,8 @@
* IN THE SOFTWARE.
*/
#include "janetconf.h"
#ifndef JANET_H_defined
#define JANET_H_defined
@@ -35,8 +37,6 @@ extern "C" {
/***** START SECTION CONFIG *****/
#include "janetconf.h"
#ifndef JANET_VERSION
#define JANET_VERSION "latest"
#endif
@@ -172,11 +172,6 @@ extern "C" {
#define JANET_PEG
#endif
/* Enable or disable the typedarray module */
#ifndef JANET_NO_TYPED_ARRAY
#define JANET_TYPED_ARRAY
#endif
/* Enable or disable event loop */
#if !defined(JANET_NO_EV) && !defined(__EMSCRIPTEN__)
#define JANET_EV
@@ -288,15 +283,21 @@ typedef struct {
JANET_CURRENT_CONFIG_BITS })
#endif
/* What to do when out of memory */
#ifndef JANET_OUT_OF_MEMORY
#include <stdio.h>
#define JANET_OUT_OF_MEMORY do { fprintf(stderr, "janet out of memory\n"); exit(1); } while (0)
#endif
/***** END SECTION CONFIG *****/
/***** START SECTION TYPES *****/
#ifdef JANET_WINDOWS
// Must be defined before including stdlib.h
/* Must be defined before including stdlib.h */
#define _CRT_RAND_S
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@@ -517,7 +518,7 @@ typedef enum {
JANET_ASYNC_EVENT_HUP,
JANET_ASYNC_EVENT_READ,
JANET_ASYNC_EVENT_WRITE,
JANET_ASYNC_EVENT_TIMEOUT,
JANET_ASYNC_EVENT_CANCEL,
JANET_ASYNC_EVENT_COMPLETE, /* Used on windows for IOCP */
JANET_ASYNC_EVENT_USER
} JanetAsyncEvent;
@@ -560,7 +561,7 @@ struct JanetListenerState {
int bytes; /* Used to track how many bytes were transfered. */
#endif
/* internal */
int _index; /* not used in all implementations */
size_t _index;
int _mask;
JanetListenerState *_next;
};
@@ -838,9 +839,15 @@ struct JanetFiber {
JanetTable *env; /* Dynamic bindings table (usually current environment). */
Janet *data; /* Dynamically resized stack memory */
JanetFiber *child; /* Keep linked list of fibers for restarting pending fibers */
Janet last_value; /* Last returned value from a fiber */
#ifdef JANET_EV
/* These fields are only relevant for fibers that are used as "root fibers" -
* that is, fibers that are scheduled on the event loop and behave much like threads
* in a multi-tasking system. It would be possible to move these fields to a new
* type, say "JanetTask", that as separate from fibers to save a bit of space. */
JanetListenerState *waiting;
uint32_t sched_id; /* Increment everytime fiber is scheduled by event loop */
void *supervisor_channel; /* Channel to push self to when complete */
#endif
};
@@ -1279,14 +1286,60 @@ JANET_API JanetListenerState *janet_listen(JanetStream *stream, JanetListener be
/* Shorthand for yielding to event loop in C */
JANET_NO_RETURN JANET_API void janet_await(void);
JANET_NO_RETURN JANET_API void janet_sleep_await(double sec);
/* For use inside listeners - adds a timeout to the current fiber, such that
* it will be resumed after sec seconds if no other event schedules the current fiber. */
JANET_API void janet_addtimeout(double sec);
JANET_API void janet_ev_inc_refcount(void);
JANET_API void janet_ev_dec_refcount(void);
/* Get last error from a an IO operation */
JANET_API Janet janet_ev_lasterr(void);
/* Async service for calling a function or syscall in a background thread. This is not
* as efficient in the slightest as using Streams but can be used for arbitrary blocking
* functions and syscalls. */
/* Used to pass data between the main thread and worker threads for simple tasks.
* We could just use a pointer but this prevents malloc/free in the common case
* of only a handful of arguments. */
typedef struct {
int tag;
int argi;
void *argp;
JanetFiber *fiber;
} JanetEVGenericMessage;
/* How to resume or cancel after a threaded call. Not exhaustive of the possible
* ways one might want to resume after returning from a threaded call, but should
* cover most of the common cases. For something more complicated, such as resuming
* with an abstract type or a struct, one should use janet_ev_threaded_call instead
* of janet_ev_threaded_await with a custom callback. */
#define JANET_EV_TCTAG_NIL 0 /* resume with nil */
#define JANET_EV_TCTAG_INTEGER 1 /* resume with janet_wrap_integer(argi) */
#define JANET_EV_TCTAG_STRING 2 /* resume with janet_cstringv((const char *) argp) */
#define JANET_EV_TCTAG_STRINGF 3 /* resume with janet_cstringv((const char *) argp), then call free on argp. */
#define JANET_EV_TCTAG_KEYWORD 4 /* resume with janet_ckeywordv((const char *) argp) */
#define JANET_EV_TCTAG_ERR_STRING 5 /* cancel with janet_cstringv((const char *) argp) */
#define JANET_EV_TCTAG_ERR_STRINGF 6 /* cancel with janet_cstringv((const char *) argp), then call free on argp. */
#define JANET_EV_TCTAG_ERR_KEYWORD 7 /* cancel with janet_ckeywordv((const char *) argp) */
#define JANET_EV_TCTAG_BOOLEAN 8 /* resume with janet_wrap_boolean(argi) */
/* Function pointer that is run in the thread pool */
typedef JanetEVGenericMessage(*JanetThreadedSubroutine)(JanetEVGenericMessage arguments);
/* Handler that is run in the main thread with the result of the JanetAsyncSubroutine */
typedef void (*JanetThreadedCallback)(JanetEVGenericMessage return_value);
/* API calls for quickly offloading some work in C to a new thread or thread pool. */
JANET_API void janet_ev_threaded_call(JanetThreadedSubroutine fp, JanetEVGenericMessage arguments, JanetThreadedCallback cb);
JANET_NO_RETURN JANET_API void janet_ev_threaded_await(JanetThreadedSubroutine fp, int tag, int argi, void *argp);
/* Callback used by janet_ev_threaded_await */
JANET_API void janet_ev_default_threaded_callback(JanetEVGenericMessage return_value);
/* Read async from a stream */
JANET_API void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
JANET_API void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
@@ -1315,6 +1368,7 @@ JANET_API void janet_parser_deinit(JanetParser *parser);
JANET_API void janet_parser_consume(JanetParser *parser, uint8_t c);
JANET_API enum JanetParserStatus janet_parser_status(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 void janet_parser_flush(JanetParser *parser);
JANET_API void janet_parser_eof(JanetParser *parser);
@@ -1351,9 +1405,15 @@ struct JanetCompileResult {
enum JanetCompileStatus status;
};
JANET_API JanetCompileResult janet_compile(Janet source, JanetTable *env, JanetString where);
JANET_API JanetCompileResult janet_compile_lint(
Janet source,
JanetTable *env,
JanetString where,
JanetArray *lints);
/* Get the default environment for janet */
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_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out);
@@ -1576,6 +1636,7 @@ JANET_API Janet janet_wrap_number_safe(double x);
JANET_API int janet_keyeq(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 int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer);
/* VM functions */
JANET_API int janet_init(void);
@@ -1604,11 +1665,24 @@ typedef enum {
JANET_BINDING_VAR,
JANET_BINDING_MACRO
} JanetBindingType;
typedef struct {
JanetBindingType type;
Janet value;
enum {
JANET_BINDING_DEP_NONE,
JANET_BINDING_DEP_RELAXED,
JANET_BINDING_DEP_NORMAL,
JANET_BINDING_DEP_STRICT,
} deprecation;
} JanetBinding;
JANET_API void janet_def(JanetTable *env, const char *name, Janet val, const char *documentation);
JANET_API void janet_var(JanetTable *env, const char *name, Janet val, const char *documentation);
JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns);
JANET_API void janet_cfuns_prefix(JanetTable *env, const char *regprefix, const JanetReg *cfuns);
JANET_API JanetBindingType janet_resolve(JanetTable *env, JanetSymbol sym, Janet *out);
JANET_API JanetBinding janet_resolve_ext(JanetTable *env, JanetSymbol sym);
JANET_API void janet_register(const char *name, JanetCFunction cfun);
/* Get values from the core environment. */
@@ -1649,6 +1723,7 @@ JANET_API void janet_arity(int32_t arity, int32_t min, int32_t max);
JANET_API void janet_fixarity(int32_t arity, int32_t fix);
JANET_API int janet_getmethod(JanetKeyword method, const JanetMethod *methods, Janet *out);
JANET_API Janet janet_nextmethod(const JanetMethod *methods, Janet key);
JANET_API double janet_getnumber(const Janet *argv, int32_t n);
JANET_API JanetArray *janet_getarray(const Janet *argv, int32_t n);
@@ -1726,6 +1801,7 @@ JANET_API FILE *janet_dynfile(const char *name, FILE *def);
JANET_API JanetFile *janet_getjfile(const Janet *argv, int32_t n);
JANET_API JanetAbstract janet_checkfile(Janet j);
JANET_API FILE *janet_unwrapfile(Janet j, int32_t *flags);
JANET_API int janet_file_close(JanetFile *file);
JANET_API int janet_cryptorand(uint8_t *out, size_t n);
@@ -1784,70 +1860,21 @@ typedef enum {
RULE_THRU, /* [rule] */
RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
} JanetPegOpcode;
RULE_LINE, /* [tag] */
RULE_COLUMN, /* [tag] */
RULE_UNREF /* [rule, tag] */
} JanetPegOpcod;
typedef struct {
uint32_t *bytecode;
Janet *constants;
size_t bytecode_len;
uint32_t num_constants;
int has_backref;
} JanetPeg;
#endif
#ifdef JANET_TYPED_ARRAY
extern JANET_API const JanetAbstractType janet_ta_view_type;
extern JANET_API const JanetAbstractType janet_ta_buffer_type;
typedef enum {
JANET_TARRAY_TYPE_U8,
JANET_TARRAY_TYPE_S8,
JANET_TARRAY_TYPE_U16,
JANET_TARRAY_TYPE_S16,
JANET_TARRAY_TYPE_U32,
JANET_TARRAY_TYPE_S32,
JANET_TARRAY_TYPE_U64,
JANET_TARRAY_TYPE_S64,
JANET_TARRAY_TYPE_F32,
JANET_TARRAY_TYPE_F64
} JanetTArrayType;
typedef struct {
uint8_t *data;
size_t size;
int32_t flags;
} JanetTArrayBuffer;
typedef struct {
union {
void *pointer;
uint8_t *u8;
int8_t *s8;
uint16_t *u16;
int16_t *s16;
uint32_t *u32;
int32_t *s32;
uint64_t *u64;
int64_t *s64;
float *f32;
double *f64;
} as;
JanetTArrayBuffer *buffer;
size_t size;
size_t stride;
JanetTArrayType type;
} JanetTArrayView;
JANET_API JanetTArrayBuffer *janet_tarray_buffer(size_t size);
JANET_API JanetTArrayView *janet_tarray_view(JanetTArrayType type, size_t size, size_t stride, size_t offset, JanetTArrayBuffer *buffer);
JANET_API int janet_is_tarray_view(Janet x, JanetTArrayType type);
JANET_API JanetTArrayBuffer *janet_gettarray_buffer(const Janet *argv, int32_t n);
JANET_API JanetTArrayView *janet_gettarray_view(const Janet *argv, int32_t n, JanetTArrayType type);
JanetTArrayView *janet_gettarray_any(const Janet *argv, int32_t n);
#endif
#ifdef JANET_INT_TYPES
extern JANET_API const JanetAbstractType janet_s64_type;
@@ -1875,9 +1902,28 @@ extern JANET_API const JanetAbstractType janet_thread_type;
JANET_API int janet_thread_receive(Janet *msg_out, double timeout);
JANET_API int janet_thread_send(JanetThread *thread, Janet msg, double timeout);
JANET_API JanetThread *janet_thread_current(void);
#endif
/* Custom allocator support */
JANET_API void *(janet_malloc)(size_t);
JANET_API void *(janet_realloc)(void *, size_t);
JANET_API void *(janet_calloc)(size_t, size_t);
JANET_API void (janet_free)(void *);
#ifndef janet_malloc
#define janet_malloc(X) malloc((X))
#endif
#ifndef janet_realloc
#define janet_realloc(X, Y) realloc((X), (Y))
#endif
#ifndef janet_calloc
#define janet_calloc(X, Y) calloc((X), (Y))
#endif
#ifndef janet_free
#define janet_free(X) free((X))
#endif
/***** END SECTION MAIN *****/
/* Re-enable popped variable length array warnings */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -126,28 +126,21 @@ https://github.com/antirez/linenoise/blob/master/linenoise.c
#define JANET_LINE_MAX 1024
#define JANET_MATCH_MAX 256
#define JANET_HISTORY_MAX 100
static int gbl_israwmode = 0;
static const char *gbl_prompt = "> ";
static int gbl_plen = 2;
static char gbl_buf[JANET_LINE_MAX];
static int gbl_len = 0;
static int gbl_pos = 0;
static int gbl_cols = 80;
static char *gbl_history[JANET_HISTORY_MAX];
static int gbl_history_count = 0;
static int gbl_historyi = 0;
static int gbl_sigint_flag = 0;
static struct termios gbl_termios_start;
static JanetByteView gbl_matches[JANET_MATCH_MAX];
static int gbl_match_count = 0;
static int gbl_lines_below = 0;
/* Put a lock around this global state so we don't screw up
* the terminal in a multithreaded situation */
#ifndef JANET_SINGLE_THREADED
#include <pthread.h>
static pthread_mutex_t gbl_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static JANET_THREAD_LOCAL int gbl_israwmode = 0;
static JANET_THREAD_LOCAL const char *gbl_prompt = "> ";
static JANET_THREAD_LOCAL int gbl_plen = 2;
static JANET_THREAD_LOCAL char gbl_buf[JANET_LINE_MAX];
static JANET_THREAD_LOCAL int gbl_len = 0;
static JANET_THREAD_LOCAL int gbl_pos = 0;
static JANET_THREAD_LOCAL int gbl_cols = 80;
static JANET_THREAD_LOCAL char *gbl_history[JANET_HISTORY_MAX];
static JANET_THREAD_LOCAL int gbl_history_count = 0;
static JANET_THREAD_LOCAL int gbl_historyi = 0;
static JANET_THREAD_LOCAL int gbl_sigint_flag = 0;
static JANET_THREAD_LOCAL struct termios gbl_termios_start;
static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX];
static JANET_THREAD_LOCAL int gbl_match_count = 0;
static JANET_THREAD_LOCAL int gbl_lines_below = 0;
/* Unsupported terminal list from linenoise */
static const char *badterms[] = {
@@ -159,7 +152,7 @@ static const char *badterms[] = {
static char *sdup(const char *s) {
size_t len = strlen(s) + 1;
char *mem = malloc(len);
char *mem = janet_malloc(len);
if (!mem) {
return NULL;
}
@@ -169,9 +162,6 @@ static char *sdup(const char *s) {
/* Ansi terminal raw mode */
static int rawmode(void) {
struct termios t;
#ifndef JANET_SINGLE_THREADED
pthread_mutex_lock(&gbl_lock);
#endif
if (!isatty(STDIN_FILENO)) goto fatal;
if (tcgetattr(STDIN_FILENO, &gbl_termios_start) == -1) goto fatal;
t = gbl_termios_start;
@@ -185,9 +175,6 @@ static int rawmode(void) {
return 0;
fatal:
errno = ENOTTY;
#ifndef JANET_SINGLE_THREADED
pthread_mutex_unlock(&gbl_lock);
#endif
return -1;
}
@@ -195,9 +182,6 @@ fatal:
static void norawmode(void) {
if (gbl_israwmode && tcsetattr(STDIN_FILENO, TCSADRAIN, &gbl_termios_start) != -1)
gbl_israwmode = 0;
#ifndef JANET_SINGLE_THREADED
pthread_mutex_unlock(&gbl_lock);
#endif
}
static int curpos(void) {
@@ -316,7 +300,7 @@ static int insert(char c, int draw) {
static void historymove(int delta) {
if (gbl_history_count > 1) {
free(gbl_history[gbl_historyi]);
janet_free(gbl_history[gbl_historyi]);
gbl_history[gbl_historyi] = sdup(gbl_buf);
gbl_historyi += delta;
@@ -342,7 +326,7 @@ static void addhistory(void) {
gbl_history[gbl_history_count++] = newline;
len++;
} else {
free(gbl_history[JANET_HISTORY_MAX - 1]);
janet_free(gbl_history[JANET_HISTORY_MAX - 1]);
}
for (i = len - 1; i > 0; i--) {
gbl_history[i] = gbl_history[i - 1];
@@ -354,7 +338,7 @@ static void replacehistory(void) {
/* History count is always > 0 here */
if (gbl_len == 0 || (gbl_history_count > 1 && !strcmp(gbl_buf, gbl_history[1]))) {
/* Delete history */
free(gbl_history[0]);
janet_free(gbl_history[0]);
for (int i = 1; i < gbl_history_count; i++) {
gbl_history[i - 1] = gbl_history[i];
}
@@ -362,7 +346,7 @@ static void replacehistory(void) {
} else {
char *newline = sdup(gbl_buf);
if (!newline) return;
free(gbl_history[0]);
janet_free(gbl_history[0]);
gbl_history[0] = newline;
}
}
@@ -774,6 +758,10 @@ static int line() {
kleft();
break;
case 3: /* ctrl-c */
clearlines();
gbl_sigint_flag = 1;
return -1;
case 17: /* ctrl-q */
gbl_cancel_current_repl_form = 1;
clearlines();
return -1;
@@ -946,7 +934,7 @@ void janet_line_deinit() {
int i;
norawmode();
for (i = 0; i < gbl_history_count; i++)
free(gbl_history[i]);
janet_free(gbl_history[i]);
gbl_historyi = 0;
}
@@ -1054,19 +1042,23 @@ int main(int argc, char **argv) {
janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0]));
/* Run startup script */
Janet mainfun, out;
Janet mainfun;
janet_resolve(env, janet_csymbol("cli-main"), &mainfun);
Janet mainargs[1] = { janet_wrap_array(args) };
JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs);
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);
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
janet_stacktrace(fiber, out);
}
#ifdef JANET_EV
status = JANET_SIGNAL_OK;
janet_loop();
#endif
/* Deinitialize vm */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose
* Copyright (c) 2021 Calvin Rose
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -13,7 +13,7 @@
(when x (++ num-tests-passed))
(def str (string e))
(def truncated
(if (> (length e) 40) (string (string/slice e 0 35) "...") (string e)))
(if (> (length e) 40) (string (string/slice e 0 35) "...") (describe e)))
(if x
(eprintf "\e[32m✔\e[0m %s: %v" truncated x)
(eprintf "\n\e[31m✘\e[0m %s: %v" truncated x))

View File

@@ -2,20 +2,24 @@
:name "testmod")
(declare-native
:name "testmod"
:source @["testmod.c"])
:name "testmod"
:source @["testmod.c"])
(declare-native
:name "testmod2"
:source @["testmod2.c"])
:name "testmod2"
:source @["testmod2.c"])
(declare-native
:name "testmod3"
:source @["testmod3.cpp"])
:name "testmod3"
:source @["testmod3.cpp"])
(declare-native
:name "test-mod-4"
:source @["testmod4.c"])
:name "test-mod-4"
:source @["testmod4.c"])
(declare-native
:name "testmod5"
:source @["testmod5.cc"])
(declare-executable
:name "testexec"

View File

@@ -1,3 +1,3 @@
(import build/testmod :as testmod)
(import /build/testmod :as testmod)
(if (not= 5 (testmod/get5)) (error "testmod/get5 failed"))

View File

@@ -1,8 +1,9 @@
(use build/testmod)
(use build/testmod2)
(use build/testmod3)
(use build/test-mod-4)
(use /build/testmod)
(use /build/testmod2)
(use /build/testmod3)
(use /build/test-mod-4)
(use /build/testmod5)
(defn main [&]
(print "Hello from executable!")
(print (+ (get5) (get6) (get7) (get8))))
(print (+ (get5) (get6) (get7) (get8) (get9))))

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose and contributors
* Copyright (c) 2021 Calvin Rose and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose and contributors
* Copyright (c) 2021 Calvin Rose and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose and contributors
* Copyright (c) 2021 Calvin Rose and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Calvin Rose and contributors
* Copyright (c) 2021 Calvin Rose and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

42
test/install/testmod5.cc Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 Calvin Rose and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* A very simple native module */
#include <janet.h>
#include <iostream>
static Janet cfun_get_nine(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 0);
std::cout << "Hello!" << std::endl;
return janet_wrap_number(9.0);
}
static const JanetReg array_cfuns[] = {
{"get9", cfun_get_nine, NULL},
{NULL, NULL, NULL}
};
JANET_MODULE_ENTRY(JanetTable *env) {
janet_cfuns(env, NULL, array_cfuns);
}

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -281,4 +281,38 @@
(assert (not (even? -10.1)) "even? 8")
(assert (not (even? -10.6)) "even? 9")
# Map arities
(assert (deep= (map inc [1 2 3]) @[2 3 4]))
(assert (deep= (map + [1 2 3] [10 20 30]) @[11 22 33]))
(assert (deep= (map + [1 2 3] [10 20 30] [100 200 300]) @[111 222 333]))
(assert (deep= (map + [1 2 3] [10 20 30] [100 200 300] [1000 2000 3000]) @[1111 2222 3333]))
(assert (deep= (map + [1 2 3] [10 20 30] [100 200 300] [1000 2000 3000] [10000 20000 30000]) @[11111 22222 33333]))
# Sort function
(assert (deep=
(range 99)
(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")
# 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)

View File

@@ -1,4 +1,4 @@
#' Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -49,7 +49,7 @@
# Generators
(def gen (generate [x :range [0 100] :when (pos? (% x 4))] x))
(var gencount 0)
(loop [x :generate gen]
(loop [x :in gen]
(++ gencount)
(assert (pos? (% x 4)) "generate in loop"))
(assert (= gencount 75) "generate loop count")

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -360,6 +360,14 @@
(check-match janet-longstring "``` `` ```" true)
(check-match janet-longstring "`` ```" false)
# Line and column capture
(def line-col (peg/compile '(any (* (line) (column) 1))))
(check-deep line-col "abcd" @[1 1 1 2 1 3 1 4])
(check-deep line-col "" @[])
(check-deep line-col "abcd\n" @[1 1 1 2 1 3 1 4 1 5])
(check-deep line-col "abcd\nz" @[1 1 1 2 1 3 1 4 1 5 2 1])
# Backmatch
(def backmatcher-1 '(* (capture (any "x") :1) "y" (backmatch :1) -1))
@@ -465,4 +473,24 @@
(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)

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose
# Copyright (c) 2021 Calvin Rose
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -70,5 +70,17 @@
(assert (= ~(,defn 1 2 3) [defn 1 2 3]) "bracket tuples are never macros")
(assert (= ~(,+ 1 2 3) [+ 1 2 3]) "bracket tuples are never function calls")
# Metadata
(def foo-with-tags :a-tag :bar)
(assert (get (dyn 'foo-with-tags) :a-tag) "extra keywords in def are metadata tags")
(def foo-with-meta {:baz :quux} :bar)
(assert (= :quux (get (dyn 'foo-with-meta) :baz)) "extra struct in def is metadata")
(defn foo-fn-with-meta {:baz :quux} "This is a function" [x] (identity x))
(assert (= :quux (get (dyn 'foo-fn-with-meta) :baz)) "extra struct in defn is metadata")
(assert (= "(foo-fn-with-meta x)\n\nThis is a function" (get (dyn 'foo-fn-with-meta) :doc)) "extra string in defn is docstring")
(end-suite)

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Calvin Rose & contributors
# Copyright (c) 2021 Calvin Rose & contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -21,54 +21,6 @@
(import ./helper :prefix "" :exit true)
(start-suite 5)
# some tests typed array
(defn inspect-tarray
[x]
(def a @[])
(for i 0 (tarray/length x) (array/push a (x i)))
(pp a))
(assert-no-error
"create some typed arrays"
(do
(def a (tarray/new :float64 10))
(def b (tarray/new :float64 5 2 0 a))
(def c (tarray/new :uint32 20))))
(assert-no-error
"create some typed arrays from a buffer"
(do
(def buf (tarray/buffer (+ 64 (* (+ 1 (* (- 10 1) 2)) 8))))
(def b (tarray/new :float64 10 2 64 buf))))
(def a (tarray/new :float64 10))
(def b (tarray/new :float64 5 2 0 a))
(assert-no-error
"fill tarray"
(for i 0 (tarray/length a)
(set (a i) i)))
(assert (= (tarray/buffer a) (tarray/buffer b)) "tarray views pointing same buffer")
(assert (= (a 2) (b 1) ) "tarray views pointing same buffer")
(assert (= ((tarray/slice b) 3) (b 3) (a 6) 6) "tarray slice")
(assert (= ((tarray/slice b 1) 2) (b 3) (a 6) 6) "tarray slice")
(assert (= (:length a) (length a)) "length method and function")
(assert (= ((unmarshal (marshal b)) 3) (b 3)) "marshal")
# Issue 408
(assert-error :invalid-type (tarray/new :int32 10 1 0 (int/u64 7)) "tarray/new should only allow tarray or buffer for last argument")
(def ta (tarray/new :int32 10))
(assert (= (next a nil) 0) "tarray next 1")
(assert (= (next a 0) 1) "tarray next 2")
(assert (= (next a 8) 9) "tarray next 3")
(assert (nil? (next a 9)) "tarray next 4")
(put ta 3 7)
(put ta 9 7)
(assert (= 2 (count |(= $ 7) ta)) "tarray count")
# Array remove
(assert (deep= (array/remove @[1 2 3 4 5] 2) @[1 2 4 5]) "array/remove 1")

Some files were not shown because too many files have changed in this diff Show More