1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-29 06:37:41 +00:00

Compare commits

..

186 Commits

Author SHA1 Message Date
Calvin Rose
fda0a081f5 Fix quoting for import. 2024-06-16 10:57:14 -05:00
Calvin Rose
94b7a69741 More fixes for patch release. 2024-06-16 10:22:49 -05:00
Calvin Rose
6518257129 Merge pull request #1460 from pnelson/fix-typos
Fix typos
2024-06-16 08:21:52 -07:00
Calvin Rose
dc325188d0 Prepare for 1.35.1 2024-06-16 10:20:01 -05:00
Philip Nelson
0b51ab157d Fix typos 2024-06-16 06:59:27 -07:00
Calvin Rose
f95de25b15 Update docstrings. 2024-06-16 07:58:38 -05:00
Calvin Rose
f424f2936b Merge pull request #1459 from sogaiu/dynvar-docstring-tweaks
Tweak some docstrings
2024-06-16 05:50:43 -07:00
sogaiu
2d6c2ee7c0 Tweak some dyn var docstrings 2024-06-16 08:48:30 +09:00
Calvin Rose
7cd106a10c Prepare for 1.35.0 release. 2024-06-15 16:11:32 -05:00
Calvin Rose
0d9e999113 Prepare for 1.35.0 release. 2024-06-15 07:11:48 -05:00
Calvin Rose
75710ccabd Error on buffer/push-uint16 with non 16 bit unsigned integer. 2024-06-15 06:47:47 -05:00
Calvin Rose
0f60115f27 Merge pull request #1457 from pnelson/buffer-push-uint
Fix buffer push uint max
2024-06-15 06:31:46 -05:00
Philip Nelson
16a3c85baa Fix buffer push uint max 2024-06-14 18:15:31 -07:00
Calvin Rose
92ff1d3be4 Add only option to merge-module and import.
This allows importing only selected bindings.

For example,

    (import foo :only [bar baz])

    (foo/bar) # works
    (foo/buzz) # doesn't work, even if the foo module has a buzz
    function.
2024-06-14 17:01:27 -05:00
Calvin Rose
58441dc49f Update gitignore. 2024-06-12 19:22:08 -05:00
Calvin Rose
dbc5d688e2 Merge branch 'master' into bundle-tools 2024-06-12 18:28:23 -05:00
Calvin Rose
e2a8951f68 Address #1452 - Partial revert some changes from #1391
This doesn't seem to reintroduce the original issue. There was
definitely some interplay with #1431

Doing git bisect landed me at commit
2f0c789ea1 as the first bad commit for
issue #1452.
2024-06-07 10:32:20 -05:00
Calvin Rose
f0f03ad519 Delete dead code. 2024-06-04 21:11:08 -05:00
Calvin Rose
e37575e763 Allow passing configs to bundle reinstall. 2024-05-31 19:20:34 -05:00
Calvin Rose
f4fd481415 copyfile should copy permission bits 2024-05-29 19:37:14 -05:00
Calvin Rose
8fca6b7af4 Don't expose bundle/pack, do expose bundle/add
Bundle/pack is a strange interface that is mostly just
to implement a safe reinistall process when the original source
is lost.
2024-05-29 07:20:37 -05:00
Calvin Rose
600e822933 Change interface for bundle/install
Name argument should be inferred in most cases. Also use :name
instead of :bundle-name in most places to be terser and simpler.
2024-05-26 16:26:08 -05:00
Calvin Rose
2028ac8a20 Merge branch 'master' into bundle-tools 2024-05-26 14:34:05 -05:00
Calvin Rose
7bae7d9efd Merge changes from bundle-tools branch:
- Update file IO to explicitly use 64bit ftell/fseek
- Add env argument to eval
- Allow naming function literals with keywords.
2024-05-26 12:04:35 -05:00
Calvin Rose
cb54fb02c1 Whitespace. 2024-05-26 12:01:27 -05:00
Calvin Rose
7529abb542 Move functions in boot.janet around. 2024-05-26 11:54:21 -05:00
Calvin Rose
16ac681ed9 Remove redundant stuff from stacktrace.
Rather than try and make ascii art, focus on whether information
is present in the stack trace that peoplpe actually need, and be terse.

Tools can better handler simpler and more stable interfaces.
2024-05-26 11:39:08 -05:00
Calvin Rose
74560ff805 Turn off cluttered traces. 2024-05-26 11:30:59 -05:00
Calvin Rose
fe348187cc Be explicit about 64 bit offset on windows. 2024-05-26 11:26:12 -05:00
Calvin Rose
fd5315793c Test feature flag 2024-05-26 11:16:31 -05:00
Calvin Rose
87db463f4e Shouldn't make a difference... 2024-05-26 11:07:23 -05:00
Calvin Rose
1225cd31c8 Assert that prime-bunlde-paths is working. 2024-05-26 10:54:00 -05:00
Calvin Rose
6998865d7b Mingw is a sepate os/which target than windows. 2024-05-26 10:41:12 -05:00
Calvin Rose
b8aec50763 Something is up with code. 2024-05-26 10:35:53 -05:00
Calvin Rose
7efb39d608 Check bundle listing before reinstall. 2024-05-26 10:28:19 -05:00
Calvin Rose
f7c90bc1ff Add testing for making and removing directory. 2024-05-26 10:21:52 -05:00
Calvin Rose
aee077c1bd Is qemu-arm buggy? 2024-05-26 09:53:04 -05:00
Calvin Rose
6968275ddf Update rmrf again to be more strict and failure early 2024-05-26 09:40:18 -05:00
Calvin Rose
074ae4fc0d When directory isn't empty, print what is in it. 2024-05-26 09:31:26 -05:00
Calvin Rose
6cd35ed9c8 Try and be OS sensitive when using path separators. 2024-05-26 09:28:56 -05:00
Calvin Rose
7911e74222 Use lstat instead of stat 2024-05-26 09:11:24 -05:00
Calvin Rose
2fafe2b5d1 Make rmrf stronger. 2024-05-26 09:09:04 -05:00
Calvin Rose
de977819ce Add some tracing. 2024-05-26 09:03:01 -05:00
Calvin Rose
1844beecc3 More work on improving stacktraces slightly.
Add extra information about when we change fibers. The janet
stack is really a spaghetti stack, where each fiber represents
a group of stack frames as well as a place where we can longjmp to. It
is therefor useful information for the programmer to know where each
stack frame is.

However, an argument could be made that this clutters the stackframe
and is more of a hindrance than a help.
2024-05-26 08:45:38 -05:00
Calvin Rose
cb529bbd63 Pass on linux. 2024-05-25 16:48:27 -05:00
Calvin Rose
25990867e2 Missing ) 2024-05-25 16:46:04 -05:00
Calvin Rose
4fbc71c70d Just don't do backslashes. 2024-05-25 16:43:51 -05:00
Calvin Rose
eb21d4fff4 Allow using keywords as names for anonymous functions.
This allows for better stack traces in macros and generally
easier debugging.
2024-05-25 16:36:08 -05:00
Calvin Rose
6d5fc1d743 Even more verbose 2024-05-25 16:15:58 -05:00
Calvin Rose
e88042b2fa Pick default bundle name better. 2024-05-25 16:09:49 -05:00
Calvin Rose
750b448f75 typo doing previous CI trigger. 2024-05-25 16:02:23 -05:00
Calvin Rose
14d1dc8749 Pathing is not quite working... 2024-05-25 16:00:43 -05:00
Calvin Rose
8e0340252b Add verbose errors to ci 2024-05-25 15:50:51 -05:00
Calvin Rose
641a16c133 Add suite-bundle to meson test list. 2024-05-25 15:42:28 -05:00
Calvin Rose
533d78bffe Merge branch 'master' into bundle-tools 2024-05-25 13:24:42 -05:00
Calvin Rose
ae2c5820a1 Fix janet_strerror when _GNU_SOURCE defined. 2024-05-25 13:24:01 -05:00
Calvin Rose
8334504f4e More work on fixing bunlde tools install. 2024-05-25 13:23:11 -05:00
Calvin Rose
2260a593bd Add some test usage for the sample bundle. 2024-05-25 12:57:09 -05:00
Calvin Rose
7d8af2f99a Add some testing to the bundle/ module. 2024-05-25 12:44:49 -05:00
Calvin Rose
46bdcece4d Add some better logging when pruning bundles. 2024-05-25 10:56:40 -05:00
Calvin Rose
7387a1d91e Add bundle/prune and support for :auto-remove.
This allows dependencies to be marked such that they are not
primary dependencies installed by the users - rather, they are
dependencies of dependencies. This distinction is important when
a user installs a package that itself has dependencies.

This also interacts with new features to prevent a user from breaking
their installation by installing needed packages or
installing/uninstalling bundles out of order.
2024-05-25 10:48:26 -05:00
Calvin Rose
ae4b8078df Merge branch 'master' into bundle-tools 2024-05-25 09:26:25 -05:00
Calvin Rose
60e0c8ea92 Ignore gcov 2024-05-25 09:25:27 -05:00
Calvin Rose
7d3acc0ed6 Get rid of "extended locale" support.
While useful on some platforms, behavior seems to be different across
the board, making use difficult.
2024-05-19 18:01:20 -05:00
Calvin Rose
2637b33957 Include locale.h and xlocale.h on some platforms. 2024-05-19 17:40:39 -05:00
Calvin Rose
58ccb66659 Move janet_buffer_dtostr 2024-05-19 17:14:21 -05:00
Calvin Rose
634429cf61 Merge branch 'locales' 2024-05-19 17:05:49 -05:00
Calvin Rose
6ac65e603d Merge branch 'master' into bundle-tools 2024-05-19 15:52:25 -05:00
Calvin Rose
03166a745a Disallow nan and inf in jdn. 2024-05-19 13:25:25 -05:00
Calvin Rose
4d61ba20ce Fix -Werror=calloc-transposed-args 2024-05-19 09:55:39 -05:00
Calvin Rose
751ff677fe Merge branch 'master' into bundle-tools 2024-05-19 09:53:14 -05:00
Calvin Rose
ace60e1898 Add ev/with-*lock macros. 2024-05-18 17:55:47 -05:00
Calvin Rose
876b7f106f OpenBSD does not work with LC_*_MASK stuff. 2024-05-18 17:22:10 -05:00
Calvin Rose
809b6589a1 Put limits.h back. 2024-05-18 15:31:23 -05:00
Calvin Rose
02f53ca014 Formatting. 2024-05-18 15:21:37 -05:00
Calvin Rose
0b03ddb21b More work on setting locale for extended locale support. 2024-05-18 15:20:22 -05:00
Calvin Rose
ea5d4fd3af JANET_BSD not defined on apple. 2024-05-18 14:24:51 -05:00
Calvin Rose
e6b73f8cd1 BSD, use xlocale for thread safe functionality 2024-05-18 14:11:05 -05:00
Calvin Rose
af232ef729 windows needs a distinct implementation from posix for thread safety.
I must say, the windows solution is a lot simpler.
2024-05-18 14:02:20 -05:00
Calvin Rose
2e2f8abfc0 Work on add locales.
Need to be careful not to mess with %j formatter, or
in some other places.
2024-05-18 13:23:33 -05:00
Calvin Rose
91a583db27 Merge pull request #1448 from znley/master
Add LoongArch64 support
2024-05-18 06:33:07 -05:00
Calvin Rose
dc5cc630ff Keep track of hooks and simple dependency tracking.
Refuse to install bundle unless dependencies are present.
Dependencies can be found for a bundle pre-install
by looking in ./bundle/info.jdn
2024-05-18 06:24:39 -05:00
znley
c1647a74c5 Add LoongArch64 support 2024-05-18 07:18:59 +00:00
Calvin Rose
721f280966 Add with-env. 2024-05-16 21:52:49 -05:00
Calvin Rose
258ebb9145 Merge branch 'master' into bundle-tools 2024-05-16 21:39:41 -05:00
Calvin Rose
e914eaf055 Update CHANGELOG.md 2024-05-16 21:37:08 -05:00
Calvin Rose
fe54013679 Update naming *module-make-env* for #1447 2024-05-16 19:11:25 -05:00
Calvin Rose
fdaf2e1594 Add *module/make-env* 2024-05-16 19:10:30 -05:00
Calvin Rose
f0092ef69b Add module/*make-env* 2024-05-16 19:06:07 -05:00
Calvin Rose
a88ae7e1d9 Merge branch 'master' into bundle-tools 2024-05-15 20:41:58 -05:00
Calvin Rose
9946f3bdf4 Add buffer/format-at
Move changes over from bundle-tools branch and add testing.
2024-05-15 20:16:42 -05:00
Calvin Rose
c747e8d16c Address some compiler linter messages on openbsd 2024-05-15 18:20:20 -05:00
Calvin Rose
3e402d397e Use older openbsd build for CI. 2024-05-15 18:16:19 -05:00
Calvin Rose
0350834cd3 By default, require and import extend current env. 2024-05-15 07:40:21 -05:00
Calvin Rose
980981c9ee Print message if no hook found, but looked for 2024-05-15 07:30:29 -05:00
Calvin Rose
3c8346f24e Install to bundle/ instead of _bundles/ 2024-05-14 20:51:29 -05:00
Calvin Rose
42bd27c24b Use a single janet file for hooks.. 2024-05-14 16:45:27 -05:00
Calvin Rose
4a0f67f3bd Update copyright. 2024-05-13 21:35:55 -05:00
Calvin Rose
09b6fc4670 Change storage locations for bundles.
Organize metadata a bit more cleanly under .bundles/<bundle-name>/
2024-05-13 20:59:06 -05:00
Calvin Rose
4d9bcd6bcc Add is-backup option to bundle/pack.
We don't always to keep the old manifest and hooks.
2024-05-13 19:42:44 -05:00
Calvin Rose
cd34b89977 Rename bundle/backup to bundle/pack. 2024-05-13 19:38:14 -05:00
Calvin Rose
3151fa3988 Don't expose bundle/do-hook.
This is really an internal detail - rather than users writing
custom hooks, custom functionality should just be normal janet scripts.
2024-05-13 18:45:43 -05:00
Calvin Rose
5e58110e19 Add copyfile for copying large files. 2024-05-13 18:39:45 -05:00
Calvin Rose
e1cdd0f8cc Update CHANGELOG.md 2024-05-13 12:47:46 -05:00
Calvin Rose
1f39a0f180 Add bundle/backup and buffer/format-at
bundle/backup is needed to make failed reinstalls able to rollback. It
also allows python wheel like functionality, where bundles can be build
on one machine, packaged, and then distributed and installed on other
compatible machines without compilers.

buffer/format-at is to buffer/format as buffer/push-at is to
buffer/push. It allows us to format in the middle of an existing
buffer. Prior, to do this operation and extra buffer creating was
required.
2024-05-13 12:06:17 -05:00
Calvin Rose
367c4b14f5 Sync manifest on error so that we uninstall the correct files.
If we cannot create files during install, we want to be able
to do a correct rollback.
2024-05-12 15:08:27 -05:00
Calvin Rose
9c437796d3 Add first versions of bundle/* module
The bundle module contains tools for modifying the contents of
(dyn *syspath*) and providing a common interface for installing
packages (called "bundles").

The functions are:

* bundle/install
* bundle/uninstall
* bundle/manifest
* bundle/do-hook
* bundle/list
* bundle/add-file
* bundle/add-directory

A bundle is a directory that contains any number of source files and
other extra files, as well as a directory "hooks/", which contains a
flat listing of janet scripts. This version of the bundle module is not
responsible for building C source modules or for downloading files over
the network.
2024-05-12 14:42:05 -05:00
Calvin Rose
60e22d9703 Merge pull request #1445 from wishdev/defbind-alias
Add ffi/defbind-alias
2024-05-11 14:25:03 -05:00
John W Higgins
ee7362e847 Add ffi/defbind-alias 2024-05-09 21:31:22 -07:00
Calvin Rose
369f96b80e Update README to prefer Zulip. 2024-05-03 07:51:35 -05:00
Calvin Rose
7c5ed04ab1 A few minor improvements.
- Add long-form CLI options
- Update changelog.
- Use snprintf instead of sprintf for linters.
2024-05-02 09:13:29 -05:00
Calvin Rose
4779a445e0 Fix BSD/Macos issue for #1431 2024-04-26 19:32:47 -05:00
Calvin Rose
f0f1b7ce9e Address #1431 - level-trigger mode for net/accept-loop
In the edge-trigger mode before this change, if a socket
receives 2 connections before one can be handled, then only a single
connection is handle and 1 connection will never be handled in some
cases. Reverting to level-trigger mode makes this impossible.
2024-04-26 19:28:20 -05:00
Calvin Rose
7c9157a0ed Remove unneeded string functions. 2024-04-26 18:11:10 -05:00
Calvin Rose
522a6cb435 Merge pull request #1440 from ahgamut/cosmo-build
Build janet with Cosmopolitan Libc
2024-04-21 08:06:51 -05:00
Gautham
d0d551d739 remove superconfigure recipe 2024-04-21 01:16:54 -05:00
Gautham
71a123fef7 apelink 2024-04-21 01:14:58 -05:00
Gautham
3f40c8d7fb fix typo 2024-04-21 01:12:59 -05:00
Gautham
983c2e5499 simplify build to use only cosmocc 2024-04-21 01:10:06 -05:00
Gautham
eebb4c3ade remove logging 2024-04-20 22:35:04 -05:00
Gautham
50425eac72 typo 2024-04-20 22:23:29 -05:00
Gautham
382ff77bbe typo 2024-04-20 22:16:23 -05:00
Gautham
bf680fb5d3 simplify janet APE build 2024-04-20 22:09:10 -05:00
Gautham
4ed7db4f91 simplify naming 2024-04-19 10:56:46 -05:00
Calvin Rose
bf19920d65 Improve casting. 2024-04-18 03:29:45 -05:00
Gautham
174b5f6686 missing folder 2024-04-16 22:24:31 -05:00
Gautham
4173645b81 missing folder 2024-04-16 22:23:12 -05:00
Gautham
af511f1f55 patch folder location 2024-04-16 22:15:54 -05:00
Gautham
83c6080380 yml config for building with Cosmopolitan Libc 2024-04-16 22:02:31 -05:00
Calvin Rose
2f0c789ea1 More work to address #1391
Properly set read_fiber and write_fiber to NULL when unused.
This was causing extra listening in the poll implemenation leading to
busy loops where a read was accidentally listening for POLLOUT.
2024-04-15 21:32:17 -05:00
Calvin Rose
a9b8f8e8a9 Address #1391 - set fd to negative value if not used.
See https://groups.google.com/g/comp.unix.programmer/c/bNNadBIEpTo/m/G5gs1mqNhbIJ?pli=1 for a conversation and workaround.
2024-04-15 18:12:42 -05:00
Calvin Rose
f92f3eb6fa Address #1434 - add dynamic bindings for module state. 2024-04-15 16:20:13 -05:00
Calvin Rose
89e74dca3e Update freebsd build 2024-04-15 16:02:34 -05:00
Calvin Rose
f2e86d2f8d Merge pull request #1432 from wishdev/os/clock
Add additional format options for os/clock
2024-04-15 07:34:02 -05:00
John W Higgins
623da131e5 os/clock docstring typos 2024-03-27 22:32:27 -07:00
John W Higgins
e89ec31ae5 Add additional format options for os/clock 2024-03-27 22:32:27 -07:00
Calvin Rose
68a6ed208e Merge pull request #1430 from pepe/fix-win-clean
Add exists test for dist directory on build command clean
2024-03-24 10:49:34 -07:00
Calvin Rose
c01b32c4f3 Merge pull request #1429 from pepe/prepare-134 2024-03-22 06:52:40 -07:00
Josef Pospíšil
ee11ff9da9 Move date and sort people 2024-03-22 07:54:23 +01:00
Josef Pospíšil
ed56d5d6ff Add @llmII to docs 2024-03-20 10:40:30 +01:00
Josef Pospíšil
b317ab755c One more commit 2024-03-20 10:34:30 +01:00
Josef Pospíšil
9819994999 Correct changelog 2024-03-20 10:32:13 +01:00
Josef Pospíšil
e9dbaa81d2 Add exists test on clean 2024-03-20 10:18:42 +01:00
Josef Pospíšil
9f9146ffae Prepare for 1.34.0 release 2024-03-20 10:11:08 +01:00
Josef Pospíšil
9d9732af97 Update changelog for 1.34.0 2024-03-20 09:57:57 +01:00
Calvin Rose
ebb8fa9787 Merge pull request #1410 from sogaiu/ev-deadline-and-friends-doc-tweaks
Doc tweaks for ev/deadline and ev/with-deadline
2024-03-12 06:18:40 -07:00
Calvin Rose
9e6abbf4d4 Fix asm roundtrip issue. 2024-03-10 09:07:11 -05:00
Calvin Rose
6032a6d658 Merge pull request #1414 from MaxGyver83/master
Fix documentation of peg/replace
2024-02-24 11:06:16 -08:00
Max Schillinger
c29ab22e6d Fix documentation of peg/replace 2024-02-23 12:46:45 +01:00
sogaiu
592ac4904c Doc tweaks for ev/deadline and ev/with-deadline 2024-02-23 10:59:43 +09:00
Calvin Rose
03ae2ec153 Merge pull request #1394 from amano-kenji/master
Improve documentation on subprocess API
2024-02-19 11:25:17 -08:00
Calvin Rose
3bc42d0d37 Only re-register when using poll. 2024-02-19 13:19:23 -06:00
Calvin Rose
12630d3e54 Register stream on unmarshal 2024-02-19 13:16:45 -06:00
Calvin Rose
c9897f99c3 Address #1405 - don't try and resume fibers that can't be resumed.
FOr fibers that _can_ be resumed and then get cancelled, the sched_id
will be incremented later prevent the spurious wake ups.
2024-02-19 08:37:49 -06:00
Calvin Rose
e66dc14b3a Formatting. 2024-02-17 13:35:07 -06:00
Calvin Rose
7a2868c147 Fix macex1 to keep syntax location for all tuples - Address #1404 2024-02-17 13:34:23 -06:00
Calvin Rose
9e0daaee09 Address #1401 - restore if-let tail calls.
Changes to avoid multiple macro expansions of the "false" branch caused
a regression in this functionality.
2024-02-15 06:30:26 -06:00
Calvin Rose
c293c7de93 Merge pull request #1402 from sogaiu/each-body-before-set
Swap set / body order for each (#1400)
2024-02-15 04:05:15 -08:00
Calvin Rose
49eb5f8563 Merge pull request #1403 from llmII/fix-os-proc-wait
Fix: make `proc_get_status` compliant to OS documentation.
2024-02-15 04:01:09 -08:00
amano.kenji
674b375b2c Improve documentation on subprocess API 2024-02-13 05:34:52 +00:00
llmII
7e94c091eb Fix: os/proc-wait
As discused over gitter, `WIFSIGNALED` macro must be checked before one
uses the WTERMSIG macro. This change reflects that necessity and adds a
final else clause which will panic if no status code could be
determined.
2024-02-12 23:06:08 -06:00
sogaiu
5885ccba61 Swap set / body order for each (#1400) 2024-02-13 11:12:18 +09:00
Calvin Rose
431ecd3d1a Abort on assert failure instead of exit 2024-02-03 14:12:10 -06:00
Calvin Rose
f6df8ff935 Expose _exit to skip certain cleanup with os/exit 2024-02-03 14:12:10 -06:00
Calvin Rose
3fd70f0951 Update debug meson options. 2024-02-03 14:12:10 -06:00
Calvin Rose
bebb635d4f Merge pull request #1392 from sogaiu/propagate-docstring-additions
Add to propagate docstring (#1365)
2024-02-03 10:52:27 -08:00
sogaiu
354896bc4b Add to propagate docstring (#1365) 2024-02-03 15:48:19 +09:00
Calvin Rose
5ddefff27e Merge pull request #1389 from sogaiu/fiber-last-value-doc-tweak 2024-02-02 08:42:48 -08:00
sogaiu
91827eef4f Tweak fiber/last-value docstring 2024-02-02 19:06:56 +09:00
Calvin Rose
9c14c09962 Add explicit stdatomic config setting for #1374
There was some hacky workaround code for development versions of TCC
that interfered with other compilers and technically was not legal
c99.
2024-01-28 15:53:41 -06:00
Calvin Rose
e85a84171f Revert local change that removes stdatomic.h 2024-01-28 07:58:22 -06:00
Calvin Rose
3a4f86c3d7 Make host and port configurable for suite-ev.janet 2024-01-28 07:56:59 -06:00
Calvin Rose
5e75963312 Merge pull request #1367 from sogaiu/debug-stacktrace-doc-tweak
Tweak debug/stacktrace docstring (#1365)
2024-01-28 05:33:11 -08:00
Calvin Rose
184d9289b5 Merge pull request #1371 from pepe/destructuring-typo
Fix typo in destructuring
2024-01-28 05:33:05 -08:00
Calvin Rose
b7ff9577c0 Merge pull request #1373 from sogaiu/module-expand-path-doc-suggestion
Address #1370
2024-01-28 05:32:50 -08:00
sogaiu
942a1aaac6 Address #1370 2024-01-27 21:20:27 +09:00
Josef Pospíšil
69f0fe004d Fix typo in destructuring 2024-01-26 14:36:56 +01:00
sogaiu
2a04347a42 Tweak debug/stacktrace docstring (#1365) 2024-01-24 16:52:37 +09:00
Calvin Rose
1394f1a5c0 Merge pull request #1364 from sogaiu/module-expand-path-doc-tweak
Cosmetically tweak module/expand-path docstring
2024-01-23 16:01:49 -08:00
sogaiu
cf4d19a8ea Cosmetically tweak module/expand-path docstring 2024-01-22 22:16:14 +09:00
Calvin Rose
23b0fe9f8e Merge pull request #1360 from pepe/patch-1 2024-01-17 11:51:59 -08:00
Josef Pospíšil
1ba718b15e Update CHANGELOG.md 2024-01-17 13:58:00 +01:00
Calvin Rose
df5f79ff35 Merge pull request #1359 from pnelson/binary
Add buffer/push-* sized int and float
2024-01-15 08:56:57 -08:00
Calvin Rose
6d7e8528ea Merge pull request #1346 from ianthehenry/peg-split
add a new (split) PEG special
2024-01-15 08:16:06 -08:00
Philip Nelson
197bb73a62 Add buffer/push-* sized int and float 2024-01-14 15:32:13 -08:00
Ian Henry
61f38fab37 add a new (split) PEG special
This works similarly to string/split, but the separator is a PEG.
2024-01-05 22:02:52 -08:00
62 changed files with 1725 additions and 358 deletions

View File

@@ -1,4 +1,4 @@
image: freebsd/12.x
image: freebsd/14.x
sources:
- https://git.sr.ht/~bakpakin/janet
packages:

View File

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

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

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

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

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

View File

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

View File

@@ -73,7 +73,7 @@ jobs:
- name: Compile the project
run: make clean && make CC=x86_64-w64-mingw32-gcc LD=x86_64-w64-mingw32-gcc UNAME=MINGW RUN=wine
- name: Test the project
run: make test UNAME=MINGW RUN=wine
run: make test UNAME=MINGW RUN=wine VERBOSE=1
test-arm-linux:
name: Build and test ARM32 cross compilation
@@ -88,4 +88,4 @@ jobs:
- name: Compile the project
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-gcc
- name: Test the project
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" SUBRUN="qemu-arm -L /usr/arm-linux-gnueabi/" test
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" SUBRUN="qemu-arm -L /usr/arm-linux-gnueabi/" test VERBOSE=1

8
.gitignore vendored
View File

@@ -48,6 +48,8 @@ janet.wasm
# Generated files
*.gen.h
*.gen.c
*.tmp
temp.*
# Generate test files
*.out
@@ -126,6 +128,9 @@ vgcore.*
*.idb
*.pdb
# GGov
*.gcov
# Kernel Module Compile Results
*.mod*
*.cmd
@@ -134,6 +139,9 @@ Module.symvers
Mkfile.old
dkms.conf
# Coverage files
*.cov
# End of https://www.gitignore.io/api/c
# Created by https://www.gitignore.io/api/cmake

View File

@@ -1,7 +1,39 @@
# Changelog
All notable changes to this project will be documented in this file.
## 1.33.0 - 2023-01-07
## 1.35.2 - 2024-06-16
- Fix some documentation typos.
- Allow using `:only` in import without quoting.
## 1.35.0 - 2024-06-15
- Add `:only` argument to `import` to allow for easier control over imported bindings.
- Add extra optional `env` argument to `eval` and `eval-string`.
- Allow naming function literals with a keyword. This allows better stacktraces for macros without
accidentally adding new bindings.
- Add `bundle/` module for managing packages within Janet. This should replace the jpm packaging
format eventually and is much simpler and amenable to more complicated builds.
- Add macros `ev/with-lock`, `ev/with-rlock`, and `ev/with-wlock` for using mutexes and rwlocks.
- Add `with-env`
- Add *module-make-env* dynamic binding
- Add buffer/format-at
- Add long form command line options for readable CLI usage
- Fix bug with `net/accept-loop` that would sometimes miss connections.
## 1.34.0 - 2024-03-22
- Add a new (split) PEG special by @ianthehenry
- Add buffer/push-* sized int and float by @pnelson
- Documentation improvements: @amano-kenji, @llmII, @MaxGyver83, @pepe, @sogaiu.
- Expose _exit to skip certain cleanup with os/exit.
- Swap set / body order for each by @sogaiu.
- Abort on assert failure instead of exit.
- Fix: os/proc-wait by @llmII.
- Fix macex1 to keep syntax location for all tuples.
- Restore if-let tail calls.
- Don't try and resume fibers that can't be resumed.
- Register stream on unmarshal.
- Fix asm roundtrip issue.
## 1.33.0 - 2024-01-07
- Add more + and * keywords to default-peg-grammar by @sogaiu.
- Use libc strlen in janet_buffer_push_cstring by @williewillus.
- Be a bit safer with reference counting.
@@ -86,7 +118,7 @@ All notable changes to this project will be documented in this file.
See http://no-color.org/
- Disallow using `(splice x)` in contexts where it doesn't make sense rather than silently coercing to `x`.
Instead, raise a compiler error.
- Change the names of `:user8` and `:user9` sigals to `:interrupt` and `:await`
- Change the names of `:user8` and `:user9` signals to `:interrupt` and `:await`
- Change the names of `:user8` and `:user9` fiber statuses to `:interrupted` and `:suspended`.
- Add `ev/all-tasks` to see all currently suspended fibers.
- Add `keep-syntax` and `keep-syntax!` functions to make writing macros easier.
@@ -257,7 +289,7 @@ All notable changes to this project will be documented in this file.
- Add the ability to close channels with `ev/chan-close` (or `:close`).
- Add threaded channels with `ev/thread-chan`.
- Add `JANET_FN` and `JANET_REG` macros to more easily define C functions that export their source mapping information.
- Add `janet_interpreter_interupt` and `janet_loop1_interrupt` to interrupt the interpreter while running.
- Add `janet_interpreter_interrupt` and `janet_loop1_interrupt` to interrupt the interpreter while running.
- Add `table/clear`
- Add build option to disable the threading library without disabling all threads.
- Remove JPM from the main Janet distribution. Instead, JPM must be installed
@@ -311,7 +343,7 @@ saving and restoring the entire VM state.
- Sort keys in pretty printing output.
## 1.15.3 - 2021-02-28
- Fix a fiber bug that occured in deeply nested fibers
- Fix a fiber bug that occurred in deeply nested fibers
- Add `unref` combinator to pegs.
- Small docstring changes.
@@ -461,13 +493,13 @@ saving and restoring the entire VM state.
- Add `symbol/slice`
- Add `keyword/slice`
- Allow cross compilation with Makefile.
- Change `compare-primitve` to `cmp` and make it more efficient.
- Change `compare-primitive` to `cmp` and make it more efficient.
- Add `reverse!` for reversing an array or buffer in place.
- `janet_dobytes` and `janet_dostring` return parse errors in \*out
- Add `repeat` macro for iterating something n times.
- Add `eachy` (each yield) macro for iterating a fiber.
- Fix `:generate` verb in loop macro to accept non symbols as bindings.
- Add `:h`, `:h+`, and `:h*` in `default-peg-grammar` for hexidecimal digits.
- Add `:h`, `:h+`, and `:h*` in `default-peg-grammar` for hexadecimal digits.
- Fix `%j` formatter to print numbers precisely (using the `%.17g` format string to printf).
## 1.10.1 - 2020-06-18

View File

@@ -204,9 +204,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile
########################
ifeq ($(UNAME), Darwin)
SONAME=libjanet.1.33.dylib
SONAME=libjanet.1.35.dylib
else
SONAME=libjanet.so.1.33
SONAME=libjanet.so.1.35
endif
build/c/shell.c: src/mainclient/shell.c

View File

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

View File

@@ -91,7 +91,9 @@ exit /b 0
:CLEAN
del *.exe *.lib *.exp
rd /s /q build
rd /s /q dist
if exist dist (
rd /s /q dist
)
exit /b 0
@rem Run tests

View File

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

View File

@@ -0,0 +1,4 @@
@{
:name "sample-bundle"
:dependencies ["sample-dep1" "sample-dep2"]
}

View File

@@ -0,0 +1,3 @@
(defn install
[manifest &]
(bundle/add-file manifest "mymod.janet"))

View File

@@ -0,0 +1,7 @@
(import dep1)
(import dep2)
(defn myfn
[x]
(def y (dep2/function x))
(dep1/function y))

View File

@@ -0,0 +1,4 @@
@{
:name "sample-dep1"
:dependencies ["sample-dep2"]
}

View File

@@ -0,0 +1,3 @@
(defn install
[manifest &]
(bundle/add-file manifest "dep1.janet"))

View File

@@ -0,0 +1,3 @@
(defn function
[x]
(+ x x))

View File

@@ -0,0 +1,3 @@
@{
:name "sample-dep2"
}

View File

@@ -0,0 +1,3 @@
(defn install
[manifest &]
(bundle/add-file manifest "dep2.janet"))

View File

@@ -0,0 +1,3 @@
(defn function
[x]
(* x x))

View File

@@ -20,7 +20,7 @@
project('janet', 'c',
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.33.0')
version : '1.35.2')
# Global settings
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
@@ -249,6 +249,7 @@ test_files = [
'test/suite-asm.janet',
'test/suite-boot.janet',
'test/suite-buffer.janet',
'test/suite-bundle.janet',
'test/suite-capi.janet',
'test/suite-cfuns.janet',
'test/suite-compile.janet',

View File

@@ -17,8 +17,8 @@ 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('kqueue', type : 'boolean', value : false)
option('epoll', type : 'boolean', value : true)
option('kqueue', type : 'boolean', value : true)
option('interpreter_interrupt', type : 'boolean', value : true)
option('ffi', type : 'boolean', value : true)
option('ffi_jit', type : 'boolean', value : true)

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,10 @@
#define JANETCONF_H
#define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 33
#define JANET_VERSION_PATCH 0
#define JANET_VERSION_MINOR 35
#define JANET_VERSION_PATCH 2
#define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.33.0"
#define JANET_VERSION "1.35.2"
/* #define JANET_BUILD "local" */
@@ -54,6 +54,7 @@
/* #define JANET_NO_INTERPRETER_INTERRUPT */
/* #define JANET_NO_IPV6 */
/* #define JANET_NO_CRYPTORAND */
/* #define JANET_USE_STDATOMIC */
/* Custom vm allocator support */
/* #include <mimalloc.h> */

View File

@@ -31,8 +31,6 @@
#ifdef JANET_EV
#ifdef JANET_WINDOWS
#include <windows.h>
#else
#include <stdatomic.h>
#endif
#endif

View File

@@ -560,6 +560,9 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
x = janet_get1(s, janet_ckeywordv("vararg"));
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
/* Initialize slotcount */
def->slotcount = !!(def->flags & JANET_FUNCDEF_FLAG_VARARG) + def->arity;
/* Check structarg */
x = janet_get1(s, janet_ckeywordv("structarg"));
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_STRUCTARG;
@@ -784,8 +787,9 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
}
/* Verify the func def */
if (janet_verify(def)) {
janet_asm_error(&a, "invalid assembly");
int verify_status = janet_verify(def);
if (verify_status) {
janet_asm_errorv(&a, janet_formatc("invalid assembly (%d)", verify_status));
}
/* Add final flags */

View File

@@ -320,6 +320,143 @@ JANET_CORE_FN(cfun_buffer_chars,
return argv[0];
}
static int should_reverse_bytes(const Janet *argv, int32_t argc) {
JanetKeyword order_kw = janet_getkeyword(argv, argc);
if (!janet_cstrcmp(order_kw, "le")) {
#if JANET_BIG_ENDIAN
return 1;
#endif
} else if (!janet_cstrcmp(order_kw, "be")) {
#if JANET_LITTLE_ENDIAN
return 1;
#endif
} else if (!janet_cstrcmp(order_kw, "native")) {
return 0;
} else {
janet_panicf("expected endianness :le, :be or :native, got %v", argv[1]);
}
return 0;
}
static void reverse_u32(uint8_t bytes[4]) {
uint8_t temp;
temp = bytes[3];
bytes[3] = bytes[0];
bytes[0] = temp;
temp = bytes[2];
bytes[2] = bytes[1];
bytes[1] = temp;
}
static void reverse_u64(uint8_t bytes[8]) {
uint8_t temp;
temp = bytes[7];
bytes[7] = bytes[0];
bytes[0] = temp;
temp = bytes[6];
bytes[6] = bytes[1];
bytes[1] = temp;
temp = bytes[5];
bytes[5] = bytes[2];
bytes[2] = temp;
temp = bytes[4];
bytes[4] = bytes[3];
bytes[3] = temp;
}
JANET_CORE_FN(cfun_buffer_push_uint16,
"(buffer/push-uint16 buffer order data)",
"Push a 16 bit unsigned integer data onto the end of the buffer. "
"Returns the modified buffer.") {
janet_fixarity(argc, 3);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int reverse = should_reverse_bytes(argv, 1);
union {
uint16_t data;
uint8_t bytes[2];
} u;
u.data = janet_getuinteger16(argv, 2);
if (reverse) {
uint8_t temp = u.bytes[1];
u.bytes[1] = u.bytes[0];
u.bytes[0] = temp;
}
janet_buffer_push_u16(buffer, *(uint16_t *) u.bytes);
return argv[0];
}
JANET_CORE_FN(cfun_buffer_push_uint32,
"(buffer/push-uint32 buffer order data)",
"Push a 32 bit unsigned integer data onto the end of the buffer. "
"Returns the modified buffer.") {
janet_fixarity(argc, 3);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int reverse = should_reverse_bytes(argv, 1);
union {
uint32_t data;
uint8_t bytes[4];
} u;
u.data = janet_getuinteger(argv, 2);
if (reverse)
reverse_u32(u.bytes);
janet_buffer_push_u32(buffer, *(uint32_t *) u.bytes);
return argv[0];
}
JANET_CORE_FN(cfun_buffer_push_uint64,
"(buffer/push-uint64 buffer order data)",
"Push a 64 bit unsigned integer data onto the end of the buffer. "
"Returns the modified buffer.") {
janet_fixarity(argc, 3);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int reverse = should_reverse_bytes(argv, 1);
union {
uint64_t data;
uint8_t bytes[8];
} u;
u.data = janet_getuinteger64(argv, 2);
if (reverse)
reverse_u64(u.bytes);
janet_buffer_push_u64(buffer, *(uint64_t *) u.bytes);
return argv[0];
}
JANET_CORE_FN(cfun_buffer_push_float32,
"(buffer/push-float32 buffer order data)",
"Push the underlying bytes of a 32 bit float data onto the end of the buffer. "
"Returns the modified buffer.") {
janet_fixarity(argc, 3);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int reverse = should_reverse_bytes(argv, 1);
union {
float data;
uint8_t bytes[4];
} u;
u.data = (float) janet_getnumber(argv, 2);
if (reverse)
reverse_u32(u.bytes);
janet_buffer_push_u32(buffer, *(uint32_t *) u.bytes);
return argv[0];
}
JANET_CORE_FN(cfun_buffer_push_float64,
"(buffer/push-float64 buffer order data)",
"Push the underlying bytes of a 64 bit float data onto the end of the buffer. "
"Returns the modified buffer.") {
janet_fixarity(argc, 3);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int reverse = should_reverse_bytes(argv, 1);
union {
double data;
uint8_t bytes[8];
} u;
u.data = janet_getnumber(argv, 2);
if (reverse)
reverse_u64(u.bytes);
janet_buffer_push_u64(buffer, *(uint64_t *) u.bytes);
return argv[0];
}
static void buffer_push_impl(JanetBuffer *buffer, Janet *argv, int32_t argc_offset, int32_t argc) {
for (int32_t i = argc_offset; i < argc; i++) {
if (janet_checktype(argv[i], JANET_NUMBER)) {
@@ -518,6 +655,27 @@ JANET_CORE_FN(cfun_buffer_format,
return argv[0];
}
JANET_CORE_FN(cfun_buffer_format_at,
"(buffer/format-at buffer at format & args)",
"Snprintf like functionality for printing values into a buffer. Returns "
"the modified buffer.") {
janet_arity(argc, 2, -1);
JanetBuffer *buffer = janet_getbuffer(argv, 0);
int32_t at = janet_getinteger(argv, 1);
if (at < 0) {
at += buffer->count + 1;
}
if (at > buffer->count || at < 0) janet_panicf("expected index at to be in range [0, %d), got %d", buffer->count, at);
int32_t oldcount = buffer->count;
buffer->count = at;
const char *strfrmt = (const char *) janet_getstring(argv, 2);
janet_buffer_format(buffer, strfrmt, 2, argc, argv);
if (buffer->count < oldcount) {
buffer->count = oldcount;
}
return argv[0];
}
void janet_lib_buffer(JanetTable *env) {
JanetRegExt buffer_cfuns[] = {
JANET_CORE_REG("buffer/new", cfun_buffer_new),
@@ -528,6 +686,11 @@ void janet_lib_buffer(JanetTable *env) {
JANET_CORE_REG("buffer/push-byte", cfun_buffer_u8),
JANET_CORE_REG("buffer/push-word", cfun_buffer_word),
JANET_CORE_REG("buffer/push-string", cfun_buffer_chars),
JANET_CORE_REG("buffer/push-uint16", cfun_buffer_push_uint16),
JANET_CORE_REG("buffer/push-uint32", cfun_buffer_push_uint32),
JANET_CORE_REG("buffer/push-uint64", cfun_buffer_push_uint64),
JANET_CORE_REG("buffer/push-float32", cfun_buffer_push_float32),
JANET_CORE_REG("buffer/push-float64", cfun_buffer_push_float64),
JANET_CORE_REG("buffer/push", cfun_buffer_push),
JANET_CORE_REG("buffer/push-at", cfun_buffer_push_at),
JANET_CORE_REG("buffer/popn", cfun_buffer_popn),
@@ -539,6 +702,7 @@ void janet_lib_buffer(JanetTable *env) {
JANET_CORE_REG("buffer/bit-toggle", cfun_buffer_bittoggle),
JANET_CORE_REG("buffer/blit", cfun_buffer_blit),
JANET_CORE_REG("buffer/format", cfun_buffer_format),
JANET_CORE_REG("buffer/format-at", cfun_buffer_format_at),
JANET_REG_END
};
janet_core_cfuns_ext(env, NULL, buffer_cfuns);

View File

@@ -35,6 +35,13 @@
#endif
#endif
#ifdef JANET_USE_STDATOMIC
#include <stdatomic.h>
/* We don't need stdatomic on most compilers since we use compiler builtins for atomic operations.
* Some (TCC), explicitly require using stdatomic.h and don't have any exposed builtins (that I know of).
* For TCC and similar compilers, one would need -std=c11 or similar then to get access. */
#endif
JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
#ifdef JANET_TOP_LEVEL_SIGNAL
JANET_TOP_LEVEL_SIGNAL(msg);
@@ -296,11 +303,28 @@ int32_t janet_getinteger(const Janet *argv, int32_t n) {
uint32_t janet_getuinteger(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (!janet_checkuint(x)) {
janet_panicf("bad slot #%d, expected 32 bit signed integer, got %v", n, x);
janet_panicf("bad slot #%d, expected 32 bit unsigned integer, got %v", n, x);
}
return janet_unwrap_integer(x);
return (uint32_t) janet_unwrap_number(x);
}
int16_t janet_getinteger16(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (!janet_checkint16(x)) {
janet_panicf("bad slot #%d, expected 16 bit signed integer, got %v", n, x);
}
return (int16_t) janet_unwrap_number(x);
}
uint16_t janet_getuinteger16(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (!janet_checkuint16(x)) {
janet_panicf("bad slot #%d, expected 16 bit unsigned integer, got %v", n, x);
}
return (uint16_t) janet_unwrap_number(x);
}
int64_t janet_getinteger64(const Janet *argv, int32_t n) {
#ifdef JANET_INT_TYPES
return janet_unwrap_s64(argv[n]);
@@ -496,6 +520,8 @@ void *janet_optabstract(const Janet *argv, int32_t argc, int32_t n, const JanetA
JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x) {
#ifdef JANET_WINDOWS
return InterlockedIncrement(x);
#elif defined(JANET_USE_STDATOMIC)
return atomic_fetch_add_explicit(x, 1, memory_order_relaxed) + 1;
#else
return __atomic_add_fetch(x, 1, __ATOMIC_RELAXED);
#endif
@@ -504,6 +530,8 @@ JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x) {
JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) {
#ifdef JANET_WINDOWS
return InterlockedDecrement(x);
#elif defined(JANET_USE_STDATOMIC)
return atomic_fetch_add_explicit(x, -1, memory_order_acq_rel) - 1;
#else
return __atomic_add_fetch(x, -1, __ATOMIC_ACQ_REL);
#endif
@@ -512,6 +540,8 @@ JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) {
JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) {
#ifdef JANET_WINDOWS
return InterlockedOr(x, 0);
#elif defined(JANET_USE_STDATOMIC)
return atomic_load_explicit(x, memory_order_acquire);
#else
return __atomic_load_n(x, __ATOMIC_ACQUIRE);
#endif

View File

@@ -934,7 +934,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 = janet_calloc(sizeof(uint32_t), slotchunks);
uint32_t *chunks = janet_calloc(slotchunks, sizeof(uint32_t));
if (NULL == chunks) {
JANET_OUT_OF_MEMORY;
}
@@ -1056,7 +1056,7 @@ JanetCompileResult janet_compile_lint(Janet source,
if (c.result.status == JANET_COMPILE_OK) {
JanetFuncDef *def = janetc_pop_funcdef(&c);
def->name = janet_cstring("_thunk");
def->name = janet_cstring("thunk");
janet_def_addflags(def);
c.result.funcdef = def;
} else {

View File

@@ -262,7 +262,7 @@ void janetc_popscope(JanetCompiler *c);
void janetc_popscope_keepslot(JanetCompiler *c, JanetSlot retslot);
JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c);
/* Create a destory slots */
/* Create a destroy slot */
JanetSlot janetc_cslot(Janet x);
/* Search for a symbol */

View File

@@ -69,15 +69,15 @@ JanetModule janet_native(const char *name, const uint8_t **error) {
host.minor < modconf.minor ||
host.bits != modconf.bits) {
char errbuf[128];
sprintf(errbuf, "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
host.major,
host.minor,
host.patch,
host.bits,
modconf.major,
modconf.minor,
modconf.patch,
modconf.bits);
snprintf(errbuf, sizeof(errbuf), "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
host.major,
host.minor,
host.patch,
host.bits,
modconf.major,
modconf.minor,
modconf.patch,
modconf.bits);
*error = janet_cstring(errbuf);
return NULL;
}
@@ -110,14 +110,14 @@ JANET_CORE_FN(janet_core_expand_path,
"(module/expand-path path 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"
"to expand the path to a path that can be used for importing files. "
"The replacements are as follows:\n\n"
"* :all: -- the value of path verbatim.\n\n"
"* :@all: -- Same as :all:, but if `path` starts with the @ character,\n"
" the first path segment is replaced with a dynamic binding\n"
" `(dyn <first path segment as keyword>)`.\n\n"
"* :cur: -- the current file, or (dyn :current-file)\n\n"
"* :dir: -- the directory containing the current file\n\n"
"* :@all: -- Same as :all:, but if `path` starts with the @ character, "
"the first path segment is replaced with a dynamic binding "
"`(dyn <first path segment as keyword>)`.\n\n"
"* :cur: -- the directory portion, if any, of (dyn :current-file)\n\n"
"* :dir: -- the directory portion, if any, of the path argument\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)") {
@@ -976,7 +976,7 @@ static void make_apply(JanetTable *env) {
/* Push the array */
S(JOP_PUSH_ARRAY, 5),
/* Call the funciton */
/* Call the function */
S(JOP_TAILCALL, 0)
};
janet_quick_asm(env, JANET_FUN_APPLY | JANET_FUNCDEF_FLAG_VARARG,
@@ -1150,11 +1150,14 @@ JanetTable *janet_core_env(JanetTable *replacements) {
janet_quick_asm(env, JANET_FUN_PROP,
"propagate", 2, 2, 2, 2, propagate_asm, sizeof(propagate_asm),
JDOC("(propagate x fiber)\n\n"
"Propagate a signal from a fiber to the current fiber. The resulting "
"stack trace from the current fiber will include frames from fiber. If "
"fiber is in a state that can be resumed, resuming the current fiber will "
"first resume fiber. This function can be used to re-raise an error without "
"losing the original stack trace."));
"Propagate a signal from a fiber to the current fiber and "
"set the last value of the current fiber to `x`. The signal "
"value is then available as the status of the current fiber. "
"The resulting stack trace from the current fiber will include "
"frames from fiber. If fiber is in a state that can be resumed, "
"resuming the current fiber will first resume `fiber`. "
"This function can be used to re-raise an error without losing "
"the original stack trace."));
janet_quick_asm(env, JANET_FUN_DEBUG,
"debug", 1, 0, 1, 1, debug_asm, sizeof(debug_asm),
JDOC("(debug &opt x)\n\n"

View File

@@ -102,7 +102,7 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) {
}
/* Error reporting. This can be emulated from within Janet, but for
* consitency with the top level code it is defined once. */
* consistency with the top level code it is defined once. */
void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix) {
int32_t fi;
@@ -164,7 +164,7 @@ void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix) {
}
}
if (frame->flags & JANET_STACKFRAME_TAILCALL)
janet_eprintf(" (tailcall)");
janet_eprintf(" (tail call)");
if (frame->func && frame->pc) {
int32_t off = (int32_t)(frame->pc - def->bytecode);
if (def->sourcemap) {
@@ -180,6 +180,11 @@ void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix) {
}
}
janet_eprintf("\n");
/* Print fiber points optionally. Clutters traces but provides info
if (i <= 0 && fi > 0) {
janet_eprintf(" in parent fiber\n");
}
*/
}
}
@@ -388,8 +393,8 @@ JANET_CORE_FN(cfun_debug_stack,
JANET_CORE_FN(cfun_debug_stacktrace,
"(debug/stacktrace fiber &opt err prefix)",
"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, and no prefix is given, will skip the error line. Returns the fiber.") {
"an error value to print the stack trace with. If `prefix` is nil or not "
"provided, will skip the error line. Returns the fiber.") {
janet_arity(argc, 1, 3);
JanetFiber *fiber = janet_getfiber(argv, 0);
Janet x = argc == 1 ? janet_wrap_nil() : argv[1];

View File

@@ -279,8 +279,12 @@ void janet_async_in_flight(JanetFiber *fiber) {
void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state) {
JanetFiber *fiber = janet_vm.root_fiber;
janet_assert(!fiber->ev_callback, "double async on fiber");
if (mode & JANET_ASYNC_LISTEN_READ) stream->read_fiber = fiber;
if (mode & JANET_ASYNC_LISTEN_WRITE) stream->write_fiber = fiber;
if (mode & JANET_ASYNC_LISTEN_READ) {
stream->read_fiber = fiber;
}
if (mode & JANET_ASYNC_LISTEN_WRITE) {
stream->write_fiber = fiber;
}
fiber->ev_callback = callback;
fiber->ev_stream = stream;
janet_ev_inc_refcount();
@@ -429,7 +433,7 @@ static void janet_stream_marshal(void *p, JanetMarshalContext *ctx) {
}
janet_marshal_int64(ctx, (int64_t)(duph));
#else
/* Marshal after dup becuse it is easier than maintaining our own ref counting. */
/* Marshal after dup because it is easier than maintaining our own ref counting. */
int duph = dup(s->handle);
if (duph < 0) janet_panicf("failed to duplicate stream handle: %V", janet_ev_lasterr());
janet_marshal_int(ctx, (int32_t)(duph));
@@ -450,6 +454,9 @@ static void *janet_stream_unmarshal(JanetMarshalContext *ctx) {
p->handle = (JanetHandle) janet_unmarshal_int64(ctx);
#else
p->handle = (JanetHandle) janet_unmarshal_int(ctx);
#endif
#ifdef JANET_EV_POLL
janet_register_stream(p);
#endif
return p;
}
@@ -459,6 +466,12 @@ static Janet janet_stream_next(void *p, Janet key) {
return janet_nextmethod(stream->methods, key);
}
static void janet_stream_tostring(void *p, JanetBuffer *buffer) {
JanetStream *stream = p;
/* Let user print the file descriptor for debugging */
janet_formatb(buffer, "<core/stream handle=%d>", stream->handle);
}
const JanetAbstractType janet_stream_type = {
"core/stream",
janet_stream_gc,
@@ -467,7 +480,7 @@ const JanetAbstractType janet_stream_type = {
NULL,
janet_stream_marshal,
janet_stream_unmarshal,
NULL,
janet_stream_tostring,
NULL,
NULL,
janet_stream_next,
@@ -582,7 +595,7 @@ void janet_ev_deinit_common(void) {
/* Shorthand to yield to event loop */
void janet_await(void) {
/* Store the fiber in a gobal table */
/* Store the fiber in a global table */
janet_signalv(JANET_SIGNAL_EVENT, janet_wrap_nil());
}
@@ -1166,10 +1179,12 @@ JANET_CORE_FN(cfun_channel_close,
msg.argj = janet_wrap_nil();
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
} else {
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
janet_schedule(writer.fiber, make_close_result(channel));
} else {
janet_schedule(writer.fiber, janet_wrap_nil());
if (janet_fiber_can_resume(writer.fiber)) {
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
janet_schedule(writer.fiber, make_close_result(channel));
} else {
janet_schedule(writer.fiber, janet_wrap_nil());
}
}
}
}
@@ -1185,10 +1200,12 @@ JANET_CORE_FN(cfun_channel_close,
msg.argj = janet_wrap_nil();
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
} else {
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
janet_schedule(reader.fiber, make_close_result(channel));
} else {
janet_schedule(reader.fiber, janet_wrap_nil());
if (janet_fiber_can_resume(reader.fiber)) {
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
janet_schedule(reader.fiber, make_close_result(channel));
} else {
janet_schedule(reader.fiber, janet_wrap_nil());
}
}
}
}
@@ -1452,7 +1469,7 @@ void janet_ev_deinit(void) {
CloseHandle(janet_vm.iocp);
}
void janet_register_stream(JanetStream *stream) {
static void janet_register_stream(JanetStream *stream) {
if (NULL == CreateIoCompletionPort(stream->handle, janet_vm.iocp, (ULONG_PTR) stream, 0)) {
janet_panicf("failed to listen for events: %V", janet_ev_lasterr());
}
@@ -1460,7 +1477,7 @@ void janet_register_stream(JanetStream *stream) {
void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
ULONG_PTR completionKey = 0;
DWORD num_bytes_transfered = 0;
DWORD num_bytes_transferred = 0;
LPOVERLAPPED overlapped = NULL;
/* Calculate how long to wait before timeout */
@@ -1475,7 +1492,7 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
} else {
waittime = INFINITE;
}
BOOL result = GetQueuedCompletionStatus(janet_vm.iocp, &num_bytes_transfered, &completionKey, &overlapped, (DWORD) waittime);
BOOL result = GetQueuedCompletionStatus(janet_vm.iocp, &num_bytes_transferred, &completionKey, &overlapped, (DWORD) waittime);
if (result || overlapped) {
if (0 == completionKey) {
@@ -1498,7 +1515,7 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
if (fiber != NULL) {
fiber->flags &= ~JANET_FIBER_EV_FLAG_IN_FLIGHT;
/* System is done with this, we can reused this data */
overlapped->InternalHigh = (ULONG_PTR) num_bytes_transfered;
overlapped->InternalHigh = (ULONG_PTR) num_bytes_transferred;
fiber->ev_callback(fiber, result ? JANET_ASYNC_EVENT_COMPLETE : JANET_ASYNC_EVENT_FAILED);
} else {
janet_free((void *) overlapped);
@@ -1509,6 +1526,14 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
}
}
void janet_stream_edge_triggered(JanetStream *stream) {
(void) stream;
}
void janet_stream_level_triggered(JanetStream *stream) {
(void) stream;
}
#elif defined(JANET_EV_EPOLL)
static JanetTimestamp ts_now(void) {
@@ -1520,15 +1545,15 @@ static JanetTimestamp ts_now(void) {
}
/* Wait for the next event */
static void janet_register_stream(JanetStream *stream) {
static void janet_register_stream_impl(JanetStream *stream, int mod, int edge_trigger) {
struct epoll_event ev;
ev.events = EPOLLET;
ev.events = edge_trigger ? EPOLLET : 0;
if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) ev.events |= EPOLLIN;
if (stream->flags & JANET_STREAM_WRITABLE) ev.events |= EPOLLOUT;
ev.data.ptr = stream;
int status;
do {
status = epoll_ctl(janet_vm.epoll, EPOLL_CTL_ADD, stream->handle, &ev);
status = epoll_ctl(janet_vm.epoll, mod ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, stream->handle, &ev);
} while (status == -1 && errno == EINTR);
if (status == -1) {
if (errno == EPERM) {
@@ -1542,6 +1567,18 @@ static void janet_register_stream(JanetStream *stream) {
}
}
static void janet_register_stream(JanetStream *stream) {
janet_register_stream_impl(stream, 0, 1);
}
void janet_stream_edge_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1, 1);
}
void janet_stream_level_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1, 0);
}
#define JANET_EPOLL_MAX_EVENTS 64
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
struct itimerspec its;
@@ -1671,14 +1708,15 @@ static void timestamp2timespec(struct timespec *t, JanetTimestamp ts) {
t->tv_nsec = ts == 0 ? 0 : (ts % 1000) * 1000000;
}
void janet_register_stream(JanetStream *stream) {
void janet_register_stream_impl(JanetStream *stream, int edge_trigger) {
struct kevent kevs[2];
int length = 0;
int clear = edge_trigger ? EV_CLEAR : 0;
if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) {
EV_SETx(&kevs[length++], stream->handle, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, stream);
EV_SETx(&kevs[length++], stream->handle, EVFILT_READ, EV_ADD | EV_ENABLE | clear, 0, 0, stream);
}
if (stream->flags & JANET_STREAM_WRITABLE) {
EV_SETx(&kevs[length++], stream->handle, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, stream);
EV_SETx(&kevs[length++], stream->handle, EVFILT_WRITE, EV_ADD | EV_ENABLE | clear, 0, 0, stream);
}
int status;
do {
@@ -1689,6 +1727,18 @@ void janet_register_stream(JanetStream *stream) {
}
}
void janet_register_stream(JanetStream *stream) {
janet_register_stream_impl(stream, 1);
}
void janet_stream_edge_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 1);
}
void janet_stream_level_triggered(JanetStream *stream) {
janet_register_stream_impl(stream, 0);
}
#define JANET_KQUEUE_MAX_EVENTS 64
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
@@ -1811,15 +1861,30 @@ void janet_register_stream(JanetStream *stream) {
janet_vm.stream_count = new_count;
}
void janet_stream_edge_triggered(JanetStream *stream) {
(void) stream;
}
void janet_stream_level_triggered(JanetStream *stream) {
(void) stream;
}
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
/* set event flags */
for (size_t i = 0; i < janet_vm.stream_count; i++) {
JanetStream *stream = janet_vm.streams[i];
janet_vm.fds[i + 1].events = 0;
janet_vm.fds[i + 1].revents = 0;
if (stream->read_fiber && stream->read_fiber->ev_callback) janet_vm.fds[i + 1].events |= POLLIN;
if (stream->write_fiber && stream->write_fiber->ev_callback) janet_vm.fds[i + 1].events |= POLLOUT;
struct pollfd *pfd = janet_vm.fds + i + 1;
pfd->events = 0;
pfd->revents = 0;
JanetFiber *rf = stream->read_fiber;
JanetFiber *wf = stream->write_fiber;
if (rf && rf->ev_callback) pfd->events |= POLLIN;
if (wf && wf->ev_callback) pfd->events |= POLLOUT;
/* Hack to ignore a file descriptor - make file descriptor negative if we want to ignore */
if (!pfd->events) {
pfd->fd = -pfd->fd;
}
}
/* Poll for events */
@@ -1836,6 +1901,14 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
JANET_EXIT("failed to poll events");
}
/* Undo negative hack */
for (size_t i = 0; i < janet_vm.stream_count; i++) {
struct pollfd *pfd = janet_vm.fds + i + 1;
if (pfd->fd < 0) {
pfd->fd = -pfd->fd;
}
}
/* Check selfpipe */
if (janet_vm.fds[0].revents & POLLIN) {
janet_vm.fds[0].revents = 0;
@@ -2018,7 +2091,7 @@ void janet_ev_threaded_call(JanetThreadedSubroutine fp, JanetEVGenericMessage ar
int err = pthread_create(&waiter_thread, &janet_vm.new_thread_attr, janet_thread_body, init);
if (err) {
janet_free(init);
janet_panicf("%s", strerror(err));
janet_panicf("%s", janet_strerror(err));
}
#endif
@@ -2127,7 +2200,7 @@ Janet janet_ev_lasterr(void) {
}
#else
Janet janet_ev_lasterr(void) {
return janet_cstringv(strerror(errno));
return janet_cstringv(janet_strerror(errno));
}
#endif
@@ -2759,7 +2832,7 @@ static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) {
janet_gcroot(janet_wrap_table(janet_vm.abstract_registry));
}
/* Get supervsior */
/* Get supervisor */
if (flags & JANET_THREAD_SUPERVISOR_FLAG) {
Janet sup =
janet_unmarshal(nextbytes, endbytes - nextbytes,
@@ -2945,10 +3018,15 @@ JANET_CORE_FN(cfun_ev_sleep,
JANET_CORE_FN(cfun_ev_deadline,
"(ev/deadline sec &opt tocancel tocheck)",
"Set a deadline for a fiber `tocheck`. If `tocheck` is not finished after `sec` seconds, "
"`tocancel` will be canceled as with `ev/cancel`. "
"If `tocancel` and `tocheck` are not given, they default to `(fiber/root)` and "
"`(fiber/current)` respectively. Returns `tocancel`.") {
"Schedules the event loop to try to cancel the `tocancel` "
"task as with `ev/cancel`. After `sec` seconds, the event "
"loop will attempt cancellation of `tocancel` if the "
"`tocheck` fiber is resumable. `sec` is a number that can "
"have a fractional part. `tocancel` defaults to "
"`(fiber/root)`, but if specified, must be a task (root "
"fiber). `tocheck` defaults to `(fiber/current)`, but if "
"specified, should be a fiber. Returns `tocancel` "
"immediately.") {
janet_arity(argc, 1, 3);
double sec = janet_getnumber(argv, 0);
JanetFiber *tocancel = janet_optfiber(argv, argc, 1, janet_vm.root_fiber);

View File

@@ -76,4 +76,6 @@
#define __BSD_VISIBLE 1
#endif
#define _FILE_OFFSET_BITS 64
#endif

View File

@@ -475,7 +475,7 @@ JANET_CORE_FN(cfun_ffi_align,
static void *janet_ffi_getpointer(const Janet *argv, int32_t n) {
switch (janet_type(argv[n])) {
default:
janet_panicf("bad slot #%d, expected ffi pointer convertable type, got %v", n, argv[n]);
janet_panicf("bad slot #%d, expected ffi pointer convertible type, got %v", n, argv[n]);
case JANET_POINTER:
case JANET_STRING:
case JANET_KEYWORD:

View File

@@ -662,7 +662,7 @@ JANET_CORE_FN(cfun_fiber_can_resume,
}
JANET_CORE_FN(cfun_fiber_last_value,
"(fiber/last-value)",
"(fiber/last-value fiber)",
"Get the last value returned or signaled from the fiber.") {
janet_fixarity(argc, 1);
JanetFiber *fiber = janet_getfiber(argv, 0);

View File

@@ -64,7 +64,7 @@ enum JanetMemoryType {
};
/* To allocate collectable memory, one must call janet_alloc, initialize the memory,
* and then call when janet_enablegc when it is initailize and reachable by the gc (on the JANET stack) */
* and then call when janet_enablegc when it is initialized and reachable by the gc (on the JANET stack) */
void *janet_gcalloc(enum JanetMemoryType type, size_t size);
#endif

View File

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

View File

@@ -41,6 +41,11 @@ 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);
#ifdef JANET_WINDOWS
#define ftell _ftelli64
#define fseek _fseeki64
#endif
const JanetAbstractType janet_file_type = {
"core/file",
cfun_io_gc,
@@ -126,7 +131,7 @@ JANET_CORE_FN(cfun_io_temp,
// XXX use mkostemp when we can to avoid CLOEXEC race.
FILE *tmp = tmpfile();
if (!tmp)
janet_panicf("unable to create temporary file - %s", strerror(errno));
janet_panicf("unable to create temporary file - %s", janet_strerror(errno));
return janet_makefile(tmp, JANET_FILE_WRITE | JANET_FILE_READ | JANET_FILE_BINARY);
}
@@ -168,7 +173,7 @@ JANET_CORE_FN(cfun_io_fopen,
}
}
return f ? janet_makefile(f, flags)
: (flags & JANET_FILE_NONIL) ? (janet_panicf("failed to open file %s: %s", fname, strerror(errno)), janet_wrap_nil())
: (flags & JANET_FILE_NONIL) ? (janet_panicf("failed to open file %s: %s", fname, janet_strerror(errno)), janet_wrap_nil())
: janet_wrap_nil();
}
@@ -289,7 +294,7 @@ int janet_file_close(JanetFile *file) {
if (!(file->flags & (JANET_FILE_NOT_CLOSEABLE | JANET_FILE_CLOSED))) {
ret = fclose(file->file);
file->flags |= JANET_FILE_CLOSED;
file->file = NULL; /* NULL derefence is easier to debug then other problems */
file->file = NULL; /* NULL dereference is easier to debug then other problems */
return ret;
}
return 0;
@@ -337,7 +342,7 @@ JANET_CORE_FN(cfun_io_fseek,
JanetFile *iof = janet_getabstract(argv, 0, &janet_file_type);
if (iof->flags & JANET_FILE_CLOSED)
janet_panic("file is closed");
long int offset = 0;
int64_t offset = 0;
int whence = SEEK_CUR;
if (argc >= 2) {
const uint8_t *whence_sym = janet_getkeyword(argv, 1);
@@ -351,7 +356,7 @@ JANET_CORE_FN(cfun_io_fseek,
janet_panicf("expected one of :cur, :set, :end, got %v", argv[1]);
}
if (argc == 3) {
offset = (long) janet_getinteger64(argv, 2);
offset = (int64_t) janet_getinteger64(argv, 2);
}
}
if (fseek(iof->file, offset, whence)) janet_panic("error seeking file");
@@ -365,7 +370,7 @@ JANET_CORE_FN(cfun_io_ftell,
JanetFile *iof = janet_getabstract(argv, 0, &janet_file_type);
if (iof->flags & JANET_FILE_CLOSED)
janet_panic("file is closed");
long pos = ftell(iof->file);
int64_t pos = ftell(iof->file);
if (pos == -1) janet_panic("error getting position in file");
return janet_wrap_number((double)pos);
}

View File

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

View File

@@ -152,7 +152,7 @@ void net_callback_connect(JanetFiber *fiber, JanetAsyncEvent event) {
if (res == 0) {
janet_schedule(fiber, janet_wrap_abstract(stream));
} else {
janet_cancel(fiber, janet_cstringv(strerror(res)));
janet_cancel(fiber, janet_cstringv(janet_strerror(res)));
stream->flags |= JANET_STREAM_TOCLOSE;
}
} else {
@@ -319,12 +319,13 @@ JANET_NO_RETURN static void janet_sched_accept(JanetStream *stream, JanetFunctio
NetStateAccept *state = janet_malloc(sizeof(NetStateAccept));
memset(state, 0, sizeof(NetStateAccept));
state->function = fun;
if (fun) janet_stream_level_triggered(stream);
janet_async_start(stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, state);
}
#endif
/* Adress info */
/* Address info */
static int janet_get_sockettype(Janet *argv, int32_t argc, int32_t n) {
JanetKeyword stype = janet_optkeyword(argv, argc, n, NULL);
@@ -1034,7 +1035,7 @@ JANET_CORE_FN(cfun_net_setsockopt,
int r = setsockopt((JSock) stream->handle, st->level, st->optname, optval, optlen);
if (r == -1) {
janet_panicf("setsockopt(%q): %s", argv[1], strerror(errno));
janet_panicf("setsockopt(%q): %s", argv[1], janet_strerror(errno));
}
return janet_wrap_nil();

View File

@@ -38,6 +38,7 @@
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <locale.h>
#ifdef JANET_BSD
#include <sys/sysctl.h>
@@ -229,10 +230,11 @@ JANET_CORE_FN(os_compiler,
#undef janet_stringify
JANET_CORE_FN(os_exit,
"(os/exit &opt x)",
"(os/exit &opt x force)",
"Exit from janet with an exit code equal to x. If x is not an integer, "
"the exit with status equal the hash of x.") {
janet_arity(argc, 0, 1);
"the exit with status equal the hash of x. If `force` is truthy will exit immediately and "
"skip cleanup code.") {
janet_arity(argc, 0, 2);
int status;
if (argc == 0) {
status = EXIT_SUCCESS;
@@ -242,7 +244,11 @@ JANET_CORE_FN(os_exit,
status = EXIT_FAILURE;
}
janet_deinit();
exit(status);
if (argc >= 2 && janet_truthy(argv[1])) {
_exit(status);
} else {
exit(status);
}
return janet_wrap_nil();
}
@@ -500,8 +506,11 @@ static int proc_get_status(JanetProc *proc) {
status = WEXITSTATUS(status);
} else if (WIFSTOPPED(status)) {
status = WSTOPSIG(status) + 128;
} else {
} else if (WIFSIGNALED(status)) {
status = WTERMSIG(status) + 128;
} else {
/* Could possibly return -1 but for now, just panic */
janet_panicf("Undefined status code for process termination, %d.", status);
}
return status;
}
@@ -613,7 +622,11 @@ os_proc_wait_impl(JanetProc *proc) {
JANET_CORE_FN(os_proc_wait,
"(os/proc-wait proc)",
"Block until the subprocess completes. Returns the subprocess return code.") {
"Suspend the current fiber until the subprocess completes. Returns the subprocess return code. "
"os/proc-wait cannot be called twice on the same process. If `ev/with-deadline` cancels `os/proc-wait` "
"with an error or os/proc-wait is cancelled with any error caused by anything else, os/proc-wait still "
"finishes in the background. Only after os/proc-wait finishes, a process is cleaned up by the operating "
"system. Thus, a process becomes a zombie process if os/proc-wait is not called.") {
janet_fixarity(argc, 1);
JanetProc *proc = janet_getabstract(argv, 0, &ProcAT);
#ifdef JANET_EV
@@ -724,10 +737,11 @@ static int get_signal_kw(const Janet *argv, int32_t n) {
JANET_CORE_FN(os_proc_kill,
"(os/proc-kill proc &opt wait signal)",
"Kill a subprocess by sending SIGKILL to it on posix systems, or by closing the process "
"handle on windows. If `wait` is truthy, will wait for the process to finish and "
"returns the exit code. Otherwise, returns `proc`. If signal is specified send it instead."
"Signal keywords are named after their C counterparts but in lowercase with the leading "
"`SIG` stripped. Signals are ignored on windows.") {
"handle on windows. If os/proc-wait already finished for proc, os/proc-kill raises an error. After "
"sending signal to proc, if `wait` is truthy, will wait for the process to finish and return the exit "
"code by calling os/proc-wait. Otherwise, returns `proc`. If signal is specified, send it instead. "
"Signal keywords are named after their C counterparts but in lowercase with the leading `SIG` stripped. "
"Signals are ignored on windows.") {
janet_arity(argc, 1, 3);
JanetProc *proc = janet_getabstract(argv, 0, &ProcAT);
if (proc->flags & JANET_PROC_WAITED) {
@@ -748,7 +762,7 @@ JANET_CORE_FN(os_proc_kill,
}
int status = kill(proc->pid, signal == -1 ? SIGKILL : signal);
if (status) {
janet_panic(strerror(errno));
janet_panic(janet_strerror(errno));
}
#endif
/* After killing process we wait on it. */
@@ -766,8 +780,9 @@ JANET_CORE_FN(os_proc_kill,
JANET_CORE_FN(os_proc_close,
"(os/proc-close proc)",
"Wait on a process if it has not been waited on, and close pipes created by `os/spawn` "
"if they have not been closed. Returns nil.") {
"Close pipes created by `os/spawn` if they have not been closed. Then, if os/proc-wait was not already "
"called on proc, os/proc-wait is called on it, and it returns the exit code returned by os/proc-wait. "
"Otherwise, returns nil.") {
janet_fixarity(argc, 1);
JanetProc *proc = janet_getabstract(argv, 0, &ProcAT);
#ifdef JANET_EV
@@ -877,8 +892,9 @@ JANET_CORE_FN(os_sigaction,
}
struct sigaction action;
sigset_t mask;
sigfillset(&mask);
sigaddset(&mask, sig);
memset(&action, 0, sizeof(action));
action.sa_flags |= SA_RESTART;
if (can_interrupt) {
#ifdef JANET_NO_INTERPRETER_INTERRUPT
janet_panic("interpreter interrupt not enabled");
@@ -1259,7 +1275,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
status = execv(cargv[0], cargv);
}
} while (status == -1 && errno == EINTR);
janet_panicf("%p: %s", cargv[0], strerror(errno ? errno : ENOENT));
janet_panicf("%p: %s", cargv[0], janet_strerror(errno ? errno : ENOENT));
#endif
}
@@ -1316,7 +1332,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
os_execute_cleanup(envp, child_argv);
if (status) {
/* correct for macos bug where errno is not set */
janet_panicf("%p: %s", argv[0], strerror(errno ? errno : ENOENT));
janet_panicf("%p: %s", argv[0], janet_strerror(errno ? errno : ENOENT));
}
#endif
@@ -1371,28 +1387,33 @@ JANET_CORE_FN(os_execute,
"* :d - Don't try and terminate the process on garbage collection (allow spawning zombies).\n"
"`env` is a table or struct mapping environment variables to values. It can also "
"contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. "
"These arguments should be core/file values. "
"Returns the exit status of the program.") {
":in, :out, and :err should be core/file values or core/stream values. core/file values and core/stream "
"values passed to :in, :out, and :err should be closed manually because os/execute doesn't close them. "
"Returns the exit code of the program.") {
return os_execute_impl(argc, argv, JANET_EXECUTE_EXECUTE);
}
JANET_CORE_FN(os_spawn,
"(os/spawn args &opt flags env)",
"Execute a program on the system and return a handle to the process. Otherwise, takes the "
"same arguments as `os/execute`. Does not wait for the process. "
"For each of the :in, :out, and :err keys to the `env` argument, one "
"can also pass in the keyword `:pipe` "
"to get streams for standard IO of the subprocess that can be read from and written to. "
"The returned value `proc` has the fields :in, :out, :err, :return-code, and "
"the additional field :pid on unix-like platforms. Use `(os/proc-wait proc)` to rejoin the "
"subprocess or `(os/proc-kill proc)`.") {
"same arguments as `os/execute`. Does not wait for the process. For each of the :in, :out, and :err keys "
"of the `env` argument, one can also pass in the keyword `:pipe` to get streams for standard IO of the "
"subprocess that can be read from and written to. The returned value `proc` has the fields :in, :out, "
":err, and the additional field :pid on unix-like platforms. `(os/proc-wait proc)` must be called to "
"rejoin the subprocess. After `(os/proc-wait proc)` finishes, proc gains a new field, :return-code. "
"If :x flag is passed to os/spawn, non-zero exit code will cause os/proc-wait to raise an error. "
"If pipe streams created with :pipe keyword are not closed in time, janet can run out of file "
"descriptors. They can be closed individually, or `os/proc-close` can close all pipe streams on proc. "
"If pipe streams aren't read before `os/proc-wait` finishes, then pipe buffers become full, and the "
"process cannot finish because the process cannot print more on pipe buffers which are already full. "
"If the process cannot finish, os/proc-wait cannot finish, either.") {
return os_execute_impl(argc, argv, JANET_EXECUTE_SPAWN);
}
JANET_CORE_FN(os_posix_exec,
"(os/posix-exec args &opt flags env)",
"Use the execvpe or execve system calls to replace the current process with an interface similar to os/execute. "
"Hoever, instead of creating a subprocess, the current process is replaced. Is not supported on windows, and "
"However, instead of creating a subprocess, the current process is replaced. Is not supported on windows, and "
"does not allow redirection of stdio.") {
return os_execute_impl(argc, argv, JANET_EXECUTE_EXEC);
}
@@ -1412,7 +1433,7 @@ JANET_CORE_FN(os_posix_fork,
result = fork();
} while (result == -1 && errno == EINTR);
if (result == -1) {
janet_panic(strerror(errno));
janet_panic(janet_strerror(errno));
}
if (result) {
JanetProc *proc = janet_abstract(&ProcAT, sizeof(JanetProc));
@@ -1544,34 +1565,51 @@ JANET_CORE_FN(os_time,
}
JANET_CORE_FN(os_clock,
"(os/clock &opt source)",
"Return the number of whole + fractional seconds of the requested clock source.\n\n"
"(os/clock &opt source format)",
"Return the current time of the requested clock source.\n\n"
"The `source` argument selects the clock source to use, when not specified the default "
"is `:realtime`:\n"
"- :realtime: Return the real (i.e., wall-clock) time. This clock is affected by discontinuous "
" jumps in the system time\n"
"- :monotonic: Return the number of whole + fractional seconds since some fixed point in "
" time. The clock is guaranteed to be non-decreasing in real time.\n"
"- :cputime: Return the CPU time consumed by this process (i.e. all threads in the process)\n") {
"- :cputime: Return the CPU time consumed by this process (i.e. all threads in the process)\n"
"The `format` argument selects the type of output, when not specified the default is `:double`:\n"
"- :double: Return the number of seconds + fractional seconds as a double\n"
"- :int: Return the number of seconds as an integer\n"
"- :tuple: Return a 2 integer tuple [seconds, nanoseconds]\n") {
enum JanetTimeSource source;
janet_sandbox_assert(JANET_SANDBOX_HRTIME);
janet_arity(argc, 0, 1);
enum JanetTimeSource source = JANET_TIME_REALTIME;
if (argc == 1) {
JanetKeyword sourcestr = janet_getkeyword(argv, 0);
if (janet_cstrcmp(sourcestr, "realtime") == 0) {
source = JANET_TIME_REALTIME;
} else if (janet_cstrcmp(sourcestr, "monotonic") == 0) {
source = JANET_TIME_MONOTONIC;
} else if (janet_cstrcmp(sourcestr, "cputime") == 0) {
source = JANET_TIME_CPUTIME;
} else {
janet_panicf("expected :realtime, :monotonic, or :cputime, got %v", argv[0]);
}
janet_arity(argc, 0, 2);
JanetKeyword sourcestr = janet_optkeyword(argv, argc, 0, (const uint8_t *) "realtime");
if (janet_cstrcmp(sourcestr, "realtime") == 0) {
source = JANET_TIME_REALTIME;
} else if (janet_cstrcmp(sourcestr, "monotonic") == 0) {
source = JANET_TIME_MONOTONIC;
} else if (janet_cstrcmp(sourcestr, "cputime") == 0) {
source = JANET_TIME_CPUTIME;
} else {
janet_panicf("expected :realtime, :monotonic, or :cputime, got %v", argv[0]);
}
struct timespec tv;
if (janet_gettime(&tv, source)) janet_panic("could not get time");
double dtime = tv.tv_sec + (tv.tv_nsec / 1E9);
return janet_wrap_number(dtime);
JanetKeyword formatstr = janet_optkeyword(argv, argc, 1, (const uint8_t *) "double");
if (janet_cstrcmp(formatstr, "double") == 0) {
double dtime = (double)(tv.tv_sec + (tv.tv_nsec / 1E9));
return janet_wrap_number(dtime);
} else if (janet_cstrcmp(formatstr, "int") == 0) {
return janet_wrap_number((double)(tv.tv_sec));
} else if (janet_cstrcmp(formatstr, "tuple") == 0) {
Janet tup[2] = {janet_wrap_number((double)tv.tv_sec),
janet_wrap_number((double)tv.tv_nsec)
};
return janet_wrap_tuple(janet_tuple_n(tup, 2));
} else {
janet_panicf("expected :double, :int, or :tuple, got %v", argv[1]);
}
}
JANET_CORE_FN(os_sleep,
@@ -1607,7 +1645,7 @@ JANET_CORE_FN(os_isatty,
return janet_wrap_boolean(_isatty(fd));
#else
int fd = fileno(f);
if (fd == -1) janet_panic(strerror(errno));
if (fd == -1) janet_panic(janet_strerror(errno));
return janet_wrap_boolean(isatty(fd));
#endif
}
@@ -1842,7 +1880,7 @@ JANET_CORE_FN(os_mktime,
}
if (t == (time_t) -1) {
janet_panicf("%s", strerror(errno));
janet_panicf("%s", janet_strerror(errno));
}
return janet_wrap_number((double)t);
@@ -1854,6 +1892,43 @@ JANET_CORE_FN(os_mktime,
#define j_symlink symlink
#endif
JANET_CORE_FN(os_setlocale,
"(os/setlocale &opt locale category)",
"Set the system locale, which affects how dates and numbers are formatted. "
"Passing nil to locale will return the current locale. Category can be one of:\n\n"
" * :all (default)\n"
" * :collate\n"
" * :ctype\n"
" * :monetary\n"
" * :numeric\n"
" * :time\n\n"
"Returns the new locale if set successfully, otherwise nil. Note that this will affect "
"other functions such as `os/strftime` and even `printf`.") {
janet_arity(argc, 0, 2);
const char *locale_name = janet_optcstring(argv, argc, 0, NULL);
int category_int = LC_ALL;
if (argc > 1 && !janet_checktype(argv[1], JANET_NIL)) {
if (janet_keyeq(argv[1], "all")) {
category_int = LC_ALL;
} else if (janet_keyeq(argv[1], "collate")) {
category_int = LC_COLLATE;
} else if (janet_keyeq(argv[1], "ctype")) {
category_int = LC_CTYPE;
} else if (janet_keyeq(argv[1], "monetary")) {
category_int = LC_MONETARY;
} else if (janet_keyeq(argv[1], "numeric")) {
category_int = LC_NUMERIC;
} else if (janet_keyeq(argv[1], "time")) {
category_int = LC_TIME;
} else {
janet_panicf("expected one of :all, :collate, :ctype, :monetary, :numeric, or :time, got %v", argv[1]);
}
}
const char *old = setlocale(category_int, locale_name);
if (old == NULL) return janet_wrap_nil();
return janet_cstringv(old);
}
JANET_CORE_FN(os_link,
"(os/link oldpath newpath &opt symlink)",
"Create a link at newpath that points to oldpath and returns nil. "
@@ -1871,7 +1946,7 @@ JANET_CORE_FN(os_link,
const char *oldpath = janet_getcstring(argv, 0);
const char *newpath = janet_getcstring(argv, 1);
int res = ((argc == 3 && janet_truthy(argv[2])) ? j_symlink : link)(oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", janet_strerror(errno), oldpath, newpath);
return janet_wrap_nil();
#endif
}
@@ -1890,7 +1965,7 @@ JANET_CORE_FN(os_symlink,
const char *oldpath = janet_getcstring(argv, 0);
const char *newpath = janet_getcstring(argv, 1);
int res = j_symlink(oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", janet_strerror(errno), oldpath, newpath);
return janet_wrap_nil();
#endif
}
@@ -1912,7 +1987,7 @@ JANET_CORE_FN(os_mkdir,
#endif
if (res == 0) return janet_wrap_true();
if (errno == EEXIST) return janet_wrap_false();
janet_panicf("%s: %s", strerror(errno), path);
janet_panicf("%s: %s", janet_strerror(errno), path);
}
JANET_CORE_FN(os_rmdir,
@@ -1926,7 +2001,7 @@ JANET_CORE_FN(os_rmdir,
#else
int res = rmdir(path);
#endif
if (-1 == res) janet_panicf("%s: %s", strerror(errno), path);
if (-1 == res) janet_panicf("%s: %s", janet_strerror(errno), path);
return janet_wrap_nil();
}
@@ -1941,7 +2016,7 @@ JANET_CORE_FN(os_cd,
#else
int res = chdir(path);
#endif
if (-1 == res) janet_panicf("%s: %s", strerror(errno), path);
if (-1 == res) janet_panicf("%s: %s", janet_strerror(errno), path);
return janet_wrap_nil();
}
@@ -1965,7 +2040,7 @@ JANET_CORE_FN(os_touch,
bufp = NULL;
}
int res = utime(path, bufp);
if (-1 == res) janet_panic(strerror(errno));
if (-1 == res) janet_panic(janet_strerror(errno));
return janet_wrap_nil();
}
@@ -1975,7 +2050,7 @@ JANET_CORE_FN(os_remove,
janet_fixarity(argc, 1);
const char *path = janet_getcstring(argv, 0);
int status = remove(path);
if (-1 == status) janet_panicf("%s: %s", strerror(errno), path);
if (-1 == status) janet_panicf("%s: %s", janet_strerror(errno), path);
return janet_wrap_nil();
}
@@ -1994,7 +2069,7 @@ JANET_CORE_FN(os_readlink,
const char *path = janet_getcstring(argv, 0);
ssize_t len = readlink(path, buffer, sizeof buffer);
if (len < 0 || (size_t)len >= sizeof buffer)
janet_panicf("%s: %s", strerror(errno), path);
janet_panicf("%s: %s", janet_strerror(errno), path);
return janet_stringv((const uint8_t *)buffer, len);
#endif
}
@@ -2289,7 +2364,7 @@ JANET_CORE_FN(os_chmod,
#else
int res = chmod(path, os_getmode(argv, 1));
#endif
if (-1 == res) janet_panicf("%s: %s", strerror(errno), path);
if (-1 == res) janet_panicf("%s: %s", janet_strerror(errno), path);
return janet_wrap_nil();
}
@@ -2325,7 +2400,7 @@ JANET_CORE_FN(os_dir,
janet_panicf("path too long: %s", dir);
sprintf(pattern, "%s/*", dir);
intptr_t res = _findfirst(pattern, &afile);
if (-1 == res) janet_panicv(janet_cstringv(strerror(errno)));
if (-1 == res) janet_panicv(janet_cstringv(janet_strerror(errno)));
do {
if (strcmp(".", afile.name) && strcmp("..", afile.name)) {
janet_array_push(paths, janet_cstringv(afile.name));
@@ -2336,8 +2411,18 @@ JANET_CORE_FN(os_dir,
/* Read directory items with opendir / readdir / closedir */
struct dirent *dp;
DIR *dfd = opendir(dir);
if (dfd == NULL) janet_panicf("cannot open directory %s", dir);
while ((dp = readdir(dfd)) != NULL) {
if (dfd == NULL) janet_panicf("cannot open directory %s: %s", dir, janet_strerror(errno));
for (;;) {
errno = 0;
dp = readdir(dfd);
if (dp == NULL) {
if (errno) {
int olderr = errno;
closedir(dfd);
janet_panicf("failed to read directory %s: %s", dir, janet_strerror(olderr));
}
break;
}
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
continue;
}
@@ -2357,7 +2442,7 @@ JANET_CORE_FN(os_rename,
const char *dest = janet_getcstring(argv, 1);
int status = rename(src, dest);
if (status) {
janet_panic(strerror(errno));
janet_panic(janet_strerror(errno));
}
return janet_wrap_nil();
}
@@ -2377,7 +2462,7 @@ JANET_CORE_FN(os_realpath,
#else
char *dest = realpath(src, NULL);
#endif
if (NULL == dest) janet_panicf("%s: %s", strerror(errno), src);
if (NULL == dest) janet_panicf("%s: %s", janet_strerror(errno), src);
Janet ret = janet_cstringv(dest);
janet_free(dest);
return ret;
@@ -2651,6 +2736,7 @@ void janet_lib_os(JanetTable *env) {
JANET_CORE_REG("os/strftime", os_strftime),
JANET_CORE_REG("os/sleep", os_sleep),
JANET_CORE_REG("os/isatty", os_isatty),
JANET_CORE_REG("os/setlocale", os_setlocale),
/* env functions */
JANET_CORE_REG("os/environ", os_environ),

View File

@@ -39,7 +39,7 @@
typedef struct {
const uint8_t *text_start;
const uint8_t *text_end;
/* text_end will be restricted in a (sub) rule, but
/* text_end can be restricted by some rules, but
outer_text_end will always contain the real end of
input, which we need to generate a line mapping */
const uint8_t *outer_text_end;
@@ -134,7 +134,7 @@ static LineCol get_linecol_from_position(PegState *s, int32_t position) {
* 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.
* is before position. we use that to calculate 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 */
@@ -510,6 +510,44 @@ tail:
return window_end;
}
case RULE_SPLIT: {
const uint8_t *saved_end = s->text_end;
const uint32_t *rule_separator = s->bytecode + rule[1];
const uint32_t *rule_subpattern = s->bytecode + rule[2];
const uint8_t *separator_end = NULL;
do {
const uint8_t *text_start = text;
CapState cs = cap_save(s);
down1(s);
while (text <= s->text_end) {
separator_end = peg_rule(s, rule_separator, text);
cap_load(s, cs);
if (separator_end) {
break;
}
text++;
}
up1(s);
if (separator_end) {
s->text_end = text;
text = separator_end;
}
down1(s);
const uint8_t *subpattern_end = peg_rule(s, rule_subpattern, text_start);
up1(s);
s->text_end = saved_end;
if (!subpattern_end) {
return NULL;
}
} while (separator_end);
return s->text_end;
}
case RULE_REPLACE:
case RULE_MATCHTIME: {
uint32_t tag = rule[3];
@@ -629,11 +667,11 @@ tail:
case RULE_READINT: {
uint32_t tag = rule[2];
uint32_t signedness = rule[1] & 0x10;
uint32_t endianess = rule[1] & 0x20;
uint32_t endianness = rule[1] & 0x20;
int width = (int)(rule[1] & 0xF);
if (text + width > s->text_end) return NULL;
uint64_t accum = 0;
if (endianess) {
if (endianness) {
/* BE */
for (int i = 0; i < width; i++) accum = (accum << 8) | text[i];
} else {
@@ -1143,6 +1181,14 @@ static void spec_sub(Builder *b, int32_t argc, const Janet *argv) {
emit_2(r, RULE_SUB, subrule1, subrule2);
}
static void spec_split(Builder *b, int32_t argc, const Janet *argv) {
peg_fixarity(b, argc, 2);
Reserve r = reserve(b, 3);
uint32_t subrule1 = peg_compile1(b, argv[0]);
uint32_t subrule2 = peg_compile1(b, argv[1]);
emit_2(r, RULE_SPLIT, subrule1, subrule2);
}
#ifdef JANET_INT_TYPES
#define JANET_MAX_READINT_WIDTH 8
#else
@@ -1226,6 +1272,7 @@ static const SpecialPair peg_specials[] = {
{"sequence", spec_sequence},
{"set", spec_set},
{"some", spec_some},
{"split", spec_split},
{"sub", spec_sub},
{"thru", spec_thru},
{"to", spec_to},
@@ -1562,6 +1609,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
i += 4;
break;
case RULE_SUB:
case RULE_SPLIT:
/* [rule, rule] */
if (rule[1] >= blen) goto bad;
if (rule[2] >= blen) goto bad;
@@ -1580,7 +1628,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
i += 2;
break;
case RULE_READINT:
/* [ width | (endianess << 5) | (signedness << 6), tag ] */
/* [ width | (endianness << 5) | (signedness << 6), tag ] */
if (rule[1] > JANET_MAX_READINT_WIDTH) goto bad;
i += 3;
break;
@@ -1677,7 +1725,7 @@ static JanetPeg *compile_peg(Janet x) {
JANET_CORE_FN(cfun_peg_compile,
"(peg/compile peg)",
"Compiles a peg source data structure into a <core/peg>. This will speed up matching "
"if the same peg will be used multiple times. Will also use `(dyn :peg-grammar)` to suppliment "
"if the same peg will be used multiple times. Will also use `(dyn :peg-grammar)` to supplement "
"the grammar of the peg for otherwise undefined peg keywords.") {
janet_fixarity(argc, 1);
JanetPeg *peg = compile_peg(argv[0]);
@@ -1817,7 +1865,7 @@ JANET_CORE_FN(cfun_peg_replace_all,
}
JANET_CORE_FN(cfun_peg_replace,
"(peg/replace peg repl text &opt start & args)",
"(peg/replace peg subst text &opt start & args)",
"Replace first match of `peg` in `text` with `subst`, returning a new buffer. "
"The peg does not need to make captures to do replacement. "
"If `subst` is a function, it will be called with the "

View File

@@ -379,8 +379,10 @@ static int print_jdn_one(struct pretty *S, Janet x, int depth) {
break;
case JANET_NUMBER:
janet_buffer_ensure(S->buffer, S->buffer->count + BUFSIZE, 2);
int count = snprintf((char *) S->buffer->data + S->buffer->count, BUFSIZE, "%.17g", janet_unwrap_number(x));
S->buffer->count += count;
double num = janet_unwrap_number(x);
if (isnan(num)) return 1;
if (isinf(num)) return 1;
janet_buffer_dtostr(S->buffer, num);
break;
case JANET_SYMBOL:
case JANET_KEYWORD:
@@ -830,7 +832,7 @@ static const char *scanformat(
if (loc != NULL && *loc != '\0') {
const char *mapping = get_fmt_mapping(*p2++);
size_t len = strlen(mapping);
strcpy(form, mapping);
memcpy(form, mapping, len);
form += len;
} else {
*(form++) = *(p2++);

View File

@@ -149,7 +149,7 @@ static int destructure(JanetCompiler *c,
JanetTable *attr) {
switch (janet_type(left)) {
default:
janetc_error(c, janet_formatc("unexpected type in destruction, got %v", left));
janetc_error(c, janet_formatc("unexpected type in destructuring, got %v", left));
return 1;
case JANET_SYMBOL:
/* Leaf, assign right to left */
@@ -925,6 +925,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
int structarg = 0;
int allow_extra = 0;
int selfref = 0;
int hasname = 0;
int seenamp = 0;
int seenopt = 0;
int namedargs = 0;
@@ -943,6 +944,10 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
head = argv[0];
if (janet_checktype(head, JANET_SYMBOL)) {
selfref = 1;
hasname = 1;
parami = 1;
} else if (janet_checktype(head, JANET_KEYWORD)) {
hasname = 1;
parami = 1;
}
if (parami >= argn || !janet_checktype(argv[parami], JANET_TUPLE)) {
@@ -1103,7 +1108,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
if (structarg) def->flags |= JANET_FUNCDEF_FLAG_STRUCTARG;
if (selfref) def->name = janet_unwrap_symbol(head);
if (hasname) def->name = janet_unwrap_symbol(head); /* Also correctly unwraps keyword */
janet_def_addflags(def);
defindex = janetc_addfuncdef(c, def);

View File

@@ -58,7 +58,7 @@ void janet_vm_load(JanetVM *from) {
}
/* Trigger suspension of the Janet vm by trying to
* exit the interpeter loop when convenient. You can optionally
* exit the interpreter loop when convenient. You can optionally
* use NULL to interrupt the current VM when convenient */
void janet_interpreter_interrupt(JanetVM *vm) {
vm = vm ? vm : &janet_vm;

View File

@@ -149,6 +149,11 @@ struct JanetVM {
JanetTraversalNode *traversal_top;
JanetTraversalNode *traversal_base;
/* Thread safe strerror error buffer - for janet_strerror */
#ifndef JANET_WINDOWS
char strerror_buf[256];
#endif
/* Event loop and scheduler globals */
#ifdef JANET_EV
size_t tq_count;

View File

@@ -34,9 +34,9 @@
* because E is a valid digit in bases 15 or greater. For bases greater than
* 10, the letters are used as digits. A through Z correspond to the digits 10
* through 35, and the lowercase letters have the same values. The radix number
* is always in base 10. For example, a hexidecimal number could be written
* is always in base 10. For example, a hexadecimal number could be written
* '16rdeadbeef'. janet_scan_number also supports some c style syntax for
* hexidecimal literals. The previous number could also be written
* hexadecimal literals. The previous number could also be written
* '0xdeadbeef'.
*/
@@ -490,3 +490,18 @@ int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out) {
}
#endif
void janet_buffer_dtostr(JanetBuffer *buffer, double x) {
#define BUFSIZE 32
janet_buffer_extra(buffer, BUFSIZE);
int count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, "%.17g", x);
#undef BUFSIZE
/* fix locale issues with commas */
for (int i = 0; i < count; i++) {
char c = buffer->data[buffer->count + i];
if (c == ',') {
buffer->data[buffer->count + i] = '.';
}
}
buffer->count += count;
}

View File

@@ -67,7 +67,7 @@ static JanetTable *janet_table_init_impl(JanetTable *table, int32_t capacity, in
return table;
}
/* Initialize a table (for use withs scratch memory) */
/* Initialize a table (for use with scratch memory) */
JanetTable *janet_table_init(JanetTable *table, int32_t capacity) {
return janet_table_init_impl(table, capacity, 1);
}
@@ -319,13 +319,6 @@ JANET_CORE_FN(cfun_table_new,
int32_t cap = janet_getnat(argv, 0);
return janet_wrap_table(janet_table(cap));
}
/*
uint32_t flags = janet_getflags(argv, 1, "kv");
if (flags == 0) return janet_wrap_table(janet_table(cap));
if (flags == 1) return janet_wrap_table(janet_table_weakk(cap));
if (flags == 2) return janet_wrap_table(janet_table_weakv(cap));
return janet_wrap_table(janet_table_weakkv(cap));
*/
JANET_CORE_FN(cfun_table_weak,
"(table/weak capacity)",

View File

@@ -826,6 +826,20 @@ int janet_checkuint64(Janet x) {
return janet_checkuint64range(dval);
}
int janet_checkint16(Janet x) {
if (!janet_checktype(x, JANET_NUMBER))
return 0;
double dval = janet_unwrap_number(x);
return janet_checkint16range(dval);
}
int janet_checkuint16(Janet x) {
if (!janet_checktype(x, JANET_NUMBER))
return 0;
double dval = janet_unwrap_number(x);
return janet_checkuint16range(dval);
}
int janet_checksize(Janet x) {
if (!janet_checktype(x, JANET_NUMBER))
return 0;
@@ -953,6 +967,20 @@ int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
#endif
#endif
/* Better strerror (thread-safe if available) */
const char *janet_strerror(int e) {
#ifdef JANET_WINDOWS
/* Microsoft strerror seems sane here and is thread safe by default */
return strerror(e);
#elif defined(_GNU_SOURCE)
/* See https://linux.die.net/man/3/strerror_r */
return strerror_r(e, janet_vm.strerror_buf, sizeof(janet_vm.strerror_buf));
#else
strerror_r(e, janet_vm.strerror_buf, sizeof(janet_vm.strerror_buf));
return janet_vm.strerror_buf;
#endif
}
/* Setting C99 standard makes this not available, but it should
* work/link properly if we detect a BSD */
#if defined(JANET_BSD) || defined(MAC_OS_X_VERSION_10_7)

View File

@@ -49,11 +49,11 @@
#ifndef JANET_EXIT
#include <stdio.h>
#define JANET_EXIT(m) do { \
fprintf(stderr, "janet interpreter runtime error at line %d in file %s: %s\n",\
fprintf(stderr, "janet internal error at line %d in file %s: %s\n",\
__LINE__,\
__FILE__,\
(m));\
exit(1);\
abort();\
} while (0)
#endif
@@ -80,6 +80,8 @@ void janet_memempty(JanetKV *mem, int32_t count);
void *janet_memalloc_empty(int32_t count);
JanetTable *janet_get_core_table(const char *name);
void janet_def_addflags(JanetFuncDef *def);
void janet_buffer_dtostr(JanetBuffer *buffer, double x);
const char *janet_strerror(int e);
const void *janet_strbinsearch(
const void *tab,
size_t tabcount,
@@ -139,7 +141,7 @@ int janet_gettime(struct timespec *spec, enum JanetTimeSource source);
#define strdup(x) _strdup(x)
#endif
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libraries
* with native code. */
#if defined(JANET_NO_DYNAMIC_MODULES)
typedef int Clib;

View File

@@ -318,7 +318,7 @@ static Janet janet_binop_call(const char *lmethod, const char *rmethod, Janet lh
Janet lr = janet_method_lookup(rhs, rmethod);
Janet argv[2] = { rhs, lhs };
if (janet_checktype(lr, JANET_NIL)) {
janet_panicf("could not find method :%s for %v, or :%s for %v",
janet_panicf("could not find method :%s for %v or :%s for %v",
lmethod, lhs,
rmethod, rhs);
}
@@ -1268,7 +1268,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
/*
* Execute a single instruction in the fiber. Does this by inspecting
* the fiber, setting a breakpoint at the next instruction, executing, and
* reseting breakpoints to how they were prior. Yes, it's a bit hacky.
* resetting breakpoints to how they were prior. Yes, it's a bit hacky.
*/
JanetSignal janet_step(JanetFiber *fiber, Janet in, Janet *out) {
/* No finished or currently alive fibers. */
@@ -1613,7 +1613,7 @@ int janet_init(void) {
janet_vm.registry_count = 0;
janet_vm.registry_dirty = 0;
/* Intialize abstract registry */
/* Initialize abstract registry */
janet_vm.abstract_registry = janet_table(0);
janet_gcroot(janet_wrap_table(janet_vm.abstract_registry));

View File

@@ -46,7 +46,7 @@ extern "C" {
#endif
/*
* Detect OS and endianess.
* Detect OS and endianness.
* From webkit source. There is likely some extreneous
* detection for unsupported platforms
*/
@@ -112,7 +112,8 @@ extern "C" {
|| defined(__s390x__) /* S390 64-bit (BE) */ \
|| (defined(__ppc64__) || defined(__PPC64__)) \
|| defined(__aarch64__) /* ARM 64-bit */ \
|| (defined(__riscv) && (__riscv_xlen == 64)) /* RISC-V 64-bit */
|| (defined(__riscv) && (__riscv_xlen == 64)) /* RISC-V 64-bit */ \
|| defined(__loongarch64) /* LoongArch64 64-bit */
#define JANET_64 1
#else
#define JANET_32 1
@@ -261,7 +262,7 @@ extern "C" {
#endif
#endif
/* Tell complier some functions don't return */
/* Tell compiler some functions don't return */
#ifndef JANET_NO_RETURN
#ifdef JANET_WINDOWS
#define JANET_NO_RETURN __declspec(noreturn)
@@ -271,7 +272,7 @@ extern "C" {
#endif
/* Prevent some recursive functions from recursing too deeply
* ands crashing (the parser). Instead, error out. */
* and crashing (the parser). Instead, error out. */
#define JANET_RECURSION_GUARD 1024
/* Maximum depth to follow table prototypes before giving up and returning nil. */
@@ -636,6 +637,12 @@ JANET_API void janet_async_end(JanetFiber *fiber);
/* Needed for windows to mark a fiber as waiting for an IOCP completion event. Noop on other platforms. */
JANET_API void janet_async_in_flight(JanetFiber *fiber);
/* On some platforms, it is important to be able to control if a stream is edge-trigger or level triggered.
* For example, a server that is accepting connections might want to be level triggered or edge-triggered
* depending on expected service. */
JANET_API void janet_stream_edge_triggered(JanetStream *stream);
JANET_API void janet_stream_level_triggered(JanetStream *stream);
#endif
/* Janet uses atomic integers in several places for synchronization between threads and
@@ -890,12 +897,16 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer);
/* End of tagged union implementation */
#endif
JANET_API int janet_checkint16(Janet x);
JANET_API int janet_checkuint16(Janet x);
JANET_API int janet_checkint(Janet x);
JANET_API int janet_checkuint(Janet x);
JANET_API int janet_checkint64(Janet x);
JANET_API int janet_checkuint64(Janet x);
JANET_API int janet_checksize(Janet x);
JANET_API JanetAbstract janet_checkabstract(Janet x, const JanetAbstractType *at);
#define janet_checkint16range(x) ((x) >= INT16_MIN && (x) <= INT16_MAX && (x) == (int16_t)(x))
#define janet_checkuint16range(x) ((x) >= 0 && (x) <= UINT16_MAX && (x) == (uint16_t)(x))
#define janet_checkintrange(x) ((x) >= INT32_MIN && (x) <= INT32_MAX && (x) == (int32_t)(x))
#define janet_checkuintrange(x) ((x) >= 0 && (x) <= UINT32_MAX && (x) == (uint32_t)(x))
#define janet_checkint64range(x) ((x) >= JANET_INTMIN_DOUBLE && (x) <= JANET_INTMAX_DOUBLE && (x) == (int64_t)(x))
@@ -2013,7 +2024,10 @@ JANET_API void *janet_getpointer(const Janet *argv, int32_t n);
JANET_API int32_t janet_getnat(const Janet *argv, int32_t n);
JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n);
JANET_API int16_t janet_getinteger16(const Janet *argv, int32_t n);
JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n);
JANET_API uint32_t janet_getuinteger(const Janet *argv, int32_t n);
JANET_API uint16_t janet_getuinteger16(const Janet *argv, int32_t n);
JANET_API uint64_t janet_getuinteger64(const Janet *argv, int32_t n);
JANET_API size_t janet_getsize(const Janet *argv, int32_t n);
JANET_API JanetView janet_getindexed(const Janet *argv, int32_t n);
@@ -2136,12 +2150,13 @@ typedef enum {
RULE_TO, /* [rule] */
RULE_THRU, /* [rule] */
RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
RULE_READINT, /* [(signedness << 4) | (endianness << 5) | bytewidth, tag] */
RULE_LINE, /* [tag] */
RULE_COLUMN, /* [tag] */
RULE_UNREF, /* [rule, tag] */
RULE_CAPTURE_NUM, /* [rule, tag] */
RULE_SUB /* [rule, rule] */
RULE_SUB, /* [rule, rule] */
RULE_SPLIT /* [rule, rule] */
} JanetPegOpcod;
typedef struct {

View File

@@ -51,5 +51,13 @@
(def f (asm (disasm (fn [x] (fn [y] (+ x y))))))
(assert (= ((f 10) 37) 47) "asm environment tables")
# issue #1424
(assert-no-error "arity > used slots (issue #1424)"
(asm
(disasm
(fn []
(def foo (fn [one two] one))
(foo 100 200)))))
(end-suite)

View File

@@ -364,7 +364,7 @@
"sort 5")
(assert (<= ;(sort (map (fn [x] (math/random)) (range 1000)))) "sort 6")
# #1283
# #1283
(assert (deep=
(partition 2 (generate [ i :in [:a :b :c :d :e]] i))
'@[(:a :b) (:c :d) (:e)]))
@@ -754,7 +754,7 @@
(default name (string "has-key? " (++ test-has-key-auto)))
(assert (= expected (has-key? col key)) name)
(if
# guarenteed by `has-key?` to never fail
# guaranteed by `has-key?` to never fail
expected (in col key)
# if `has-key?` is false, then `in` should fail (for indexed types)
#
@@ -955,6 +955,10 @@
(defn case-4 [&]
(def x (break (break (break)))))
(bytecode-roundtrip case-4)
(defn case-5 []
(def foo (fn [one two] one))
(foo 100 200))
(bytecode-roundtrip case-5)
# Debug bytecode of these functions
# (pp (disasm case-1))
@@ -972,4 +976,7 @@
(assert (= () '() (macex '())) "macex ()")
(assert (= '[] (macex '[])) "macex []")
(assert (= :a (with-env @{:b :a} (dyn :b))) "with-env dyn")
(assert-error "unknown symbol +" (with-env @{} (eval '(+ 1 2))))
(end-suite)

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2023 Calvin Rose
# Copyright (c) 2024 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
@@ -77,6 +77,48 @@
(buffer/push-string b5 "456" @"789")
(assert (= "123456789" (string b5)) "buffer/push-buffer 2")
(def buffer-uint16-be @"")
(buffer/push-uint16 buffer-uint16-be :be 0x0102)
(assert (= "\x01\x02" (string buffer-uint16-be)) "buffer/push-uint16 big endian")
(def buffer-uint16-le @"")
(buffer/push-uint16 buffer-uint16-le :le 0x0102)
(assert (= "\x02\x01" (string buffer-uint16-le)) "buffer/push-uint16 little endian")
(def buffer-uint16-max @"")
(buffer/push-uint16 buffer-uint16-max :be 0xFFFF)
(assert (= "\xff\xff" (string buffer-uint16-max)) "buffer/push-uint16 max")
(assert-error "too large" (buffer/push-uint16 @"" 0x1FFFF))
(assert-error "too small" (buffer/push-uint16 @"" -0x1))
(def buffer-uint32-be @"")
(buffer/push-uint32 buffer-uint32-be :be 0x01020304)
(assert (= "\x01\x02\x03\x04" (string buffer-uint32-be)) "buffer/push-uint32 big endian")
(def buffer-uint32-le @"")
(buffer/push-uint32 buffer-uint32-le :le 0x01020304)
(assert (= "\x04\x03\x02\x01" (string buffer-uint32-le)) "buffer/push-uint32 little endian")
(def buffer-uint32-max @"")
(buffer/push-uint32 buffer-uint32-max :be 0xFFFFFFFF)
(assert (= "\xff\xff\xff\xff" (string buffer-uint32-max)) "buffer/push-uint32 max")
(def buffer-float32-be @"")
(buffer/push-float32 buffer-float32-be :be 1.234)
(assert (= "\x3f\x9d\xf3\xb6" (string buffer-float32-be)) "buffer/push-float32 big endian")
(def buffer-float32-le @"")
(buffer/push-float32 buffer-float32-le :le 1.234)
(assert (= "\xb6\xf3\x9d\x3f" (string buffer-float32-le)) "buffer/push-float32 little endian")
(def buffer-float64-be @"")
(buffer/push-float64 buffer-float64-be :be 1.234)
(assert (= "\x3f\xf3\xbe\x76\xc8\xb4\x39\x58" (string buffer-float64-be)) "buffer/push-float64 big endian")
(def buffer-float64-le @"")
(buffer/push-float64 buffer-float64-le :le 1.234)
(assert (= "\x58\x39\xb4\xc8\x76\xbe\xf3\x3f" (string buffer-float64-le)) "buffer/push-float64 little endian")
# Buffer from bytes
(assert (deep= @"" (buffer/from-bytes)) "buffer/from-bytes 1")
(assert (deep= @"ABC" (buffer/from-bytes 65 66 67)) "buffer/from-bytes 2")
@@ -122,5 +164,20 @@
(assert (deep= @"abc423" (buffer/push-at @"abc123" 3 "4"))
"buffer/push-at 3")
# buffer/format-at
(def start-buf (buffer/new-filled 100 (chr "x")))
(buffer/format-at start-buf 50 "aa%dbb" 32)
(assert (= (string start-buf) (string (string/repeat "x" 50) "aa32bb" (string/repeat "x" 44)))
"buffer/format-at 1")
(assert
(deep=
(buffer/format @"" "%j" [1 2 3 :a :b :c])
(buffer/format-at @"" 0 "%j" [1 2 3 :a :b :c]))
"buffer/format-at empty buffer")
(def buf @"xxxyyy")
(buffer/format-at buf -4 "xxx")
(assert (= (string buf) "xxxxxx") "buffer/format-at negative index")
(assert-error "expected index at to be in range [0, 0), got 1" (buffer/format-at @"" 1 "abc"))
(end-suite)

125
test/suite-bundle.janet Normal file
View File

@@ -0,0 +1,125 @@
# Copyright (c) 2024 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.
(import ./helper :prefix "" :exit true)
(start-suite)
(assert true) # smoke test
# Copy since not exposed in boot.janet
(defn- bundle-rpath
[path]
(string/replace-all "\\" "/" (os/realpath path)))
(defn- rmrf
"rm -rf in janet"
[x]
(case (os/lstat x :mode)
nil nil
:directory (do
(each y (os/dir x)
(rmrf (string x "/" y)))
(os/rmdir x))
(os/rm x))
nil)
# Test mkdir -> rmdir
(assert (os/mkdir "tempdir123"))
(rmrf "tempdir123")
# Setup a temporary syspath for manipultation
(math/seedrandom (os/cryptorand 16))
(def syspath (string (math/random) "_jpm_tree.tmp"))
(rmrf syspath)
(assert (os/mkdir syspath))
(put root-env *syspath* (bundle-rpath syspath))
(unless (os/getenv "VERBOSE")
(setdyn *out* @""))
(assert (empty? (bundle/list)) "initial bundle/list")
(assert (empty? (bundle/topolist)) "initial bundle/topolist")
# Try (and fail) to install sample-bundle (missing deps)
(assert-error "missing dependencies sample-dep1, sample-dep2"
(bundle/install "./examples/sample-bundle"))
(assert (empty? (bundle/list)))
# Install deps (dep1 as :auto-remove)
(assert-no-error "sample-dep2"
(bundle/install "./examples/sample-dep2"))
(assert (= 1 (length (bundle/list))))
(assert-no-error "sample-dep1" (bundle/install "./examples/sample-dep1"))
(assert (= 2 (length (bundle/list))))
(assert-no-error "sample-dep2 reinstall" (bundle/reinstall "sample-dep2"))
(assert-no-error "sample-dep1 reinstall" (bundle/reinstall "sample-dep1" :auto-remove true))
(assert (= 2 (length (bundle/list))) "bundles are listed correctly 1")
(assert (= 2 (length (bundle/topolist))) "bundles are listed correctly 2")
# Now install sample-bundle
(assert-no-error "sample-bundle install" (bundle/install "./examples/sample-bundle"))
(assert-error "" (bundle/install "./examples/sample-dep11111"))
(assert (= 3 (length (bundle/list))) "bundles are listed correctly 3")
(assert (= 3 (length (bundle/topolist))) "bundles are listed correctly 4")
# Check topolist has not bad order
(def tlist (bundle/topolist))
(assert (> (index-of "sample-bundle" tlist) (index-of "sample-dep2" tlist)) "topolist 1")
(assert (> (index-of "sample-bundle" tlist) (index-of "sample-dep1" tlist)) "topolist 2")
(assert (> (index-of "sample-dep1" tlist) (index-of "sample-dep2" tlist)) "topolist 3")
# Prune should do nothing
(assert-no-error "first prune" (bundle/prune))
(assert (= 3 (length (bundle/list))) "bundles are listed correctly 3")
(assert (= 3 (length (bundle/topolist))) "bundles are listed correctly 4")
# Check that we can import the main dependency
(import mymod)
(assert (= 288 (mymod/myfn 12)) "using sample-bundle")
# Manual uninstall of dep1 and dep2 shouldn't work either since that would break dependencies
(assert-error "cannot uninstall sample-dep1, breaks dependent bundles @[\"sample-bundle\"]"
(bundle/uninstall "sample-dep1"))
# Now re-install sample-bundle as auto-remove
(assert-no-error "sample-bundle install" (bundle/reinstall "sample-bundle" :auto-remove true))
# Reinstallation should also work without being concerned about breaking dependencies
(assert-no-error "reinstall dep" (bundle/reinstall "sample-dep2"))
# Now prune should get rid of everything except sample-dep2
(assert-no-error "second prune" (bundle/prune))
# Now check that we exactly one package left, which is dep2
(assert (= 1 (length (bundle/list))) "bundles are listed correctly 5")
(assert (= 1 (length (bundle/topolist))) "bundles are listed correctly 6")
# Which we can uninstall manually
(assert-no-error "uninstall dep2" (bundle/uninstall "sample-dep2"))
# Now check bundle listing is again empty
(assert (= 0 (length (bundle/list))) "bundles are listed correctly 7")
(assert (= 0 (length (bundle/topolist))) "bundles are listed correctly 8")
(rmrf syspath)
(end-suite)

View File

@@ -21,6 +21,9 @@
(import ./helper :prefix "" :exit true)
(start-suite)
(def test-port (os/getenv "JANET_TEST_PORT" "8761"))
(def test-host (os/getenv "JANET_TEST_HOST" "127.0.0.1"))
# Subprocess
# 5e1a8c86f
(def janet (dyn *executable*))
@@ -192,11 +195,11 @@
(net/write stream b)
(buffer/clear b)))
(def s (net/server "127.0.0.1" "8000" handler))
(def s (net/server test-host test-port handler))
(assert s "made server 1")
(defn test-echo [msg]
(with [conn (net/connect "127.0.0.1" "8000")]
(with [conn (net/connect test-host test-port)]
(net/write conn msg)
(def res (net/read conn 1024))
(assert (= (string res) msg) (string "echo " msg))))
@@ -216,18 +219,18 @@
# prevent immediate close
(ev/read stream 1)
(def [host port] (net/localname stream))
(assert (= host "127.0.0.1") "localname host server")
(assert (= port 8000) "localname port server")))
(assert (= host test-host) "localname host server")
(assert (= port (scan-number test-port)) "localname port server")))
# Test localname and peername
# 077bf5eba
(repeat 10
(with [s (net/server "127.0.0.1" "8000" names-handler)]
(with [s (net/server test-host test-port names-handler)]
(repeat 10
(with [conn (net/connect "127.0.0.1" "8000")]
(with [conn (net/connect test-host test-port)]
(def [host port] (net/peername conn))
(assert (= host "127.0.0.1") "peername host client ")
(assert (= port 8000) "peername port client")
(assert (= host test-host) "peername host client ")
(assert (= port (scan-number test-port)) "peername port client")
# let server close
(ev/write conn " "))))
(gccollect))

View File

@@ -96,11 +96,23 @@
(assert (= (in buf 0) 0) "cryptorand doesn't overwrite buffer")
(assert (= (length buf) 2) "cryptorand appends to buffer"))
(assert-no-error "realtime clock" (os/clock))
(assert-no-error "realtime clock" (os/clock nil))
(assert-no-error "realtime clock" (os/clock nil nil))
# 80db68210
(assert-no-error "realtime clock" (os/clock :realtime))
(assert-no-error "cputime clock" (os/clock :cputime))
(assert-no-error "monotonic clock" (os/clock :monotonic))
(assert-no-error "realtime clock double output" (os/clock nil :double))
(assert-no-error "realtime clock int output" (os/clock nil :int))
(assert-no-error "realtime clock tuple output" (os/clock nil :tuple))
(assert-error "invalid clock" (os/clock :a))
(assert-error "invalid output" (os/clock :realtime :b))
(assert-error "invalid clock and output" (os/clock :a :b))
(def before (os/clock :monotonic))
(def after (os/clock :monotonic))
(assert (>= after before) "monotonic clock is monotonic")
@@ -148,4 +160,3 @@
{:out dn :err dn})))
(end-suite)

View File

@@ -265,6 +265,7 @@
(marshpeg '(group "abc"))
(marshpeg '(sub "abcdf" "abc"))
(marshpeg '(* (sub 1 1)))
(marshpeg '(split "," (+ "a" "b" "c")))
# Peg swallowing errors
# 159651117
@@ -491,7 +492,7 @@
# header, followed by body, and drop the :header-len capture
:packet (/ (* :packet-header :packet-body) ,|$1)
# any exact seqence of packets (no extra characters)
# any exact sequence of packets (no extra characters)
:main (* (any :packet) -1)}))
(assert (deep= @["a" "bb" "ccc"] (peg/match peg2 "1:a2:bb3:ccc"))
@@ -710,5 +711,50 @@
"abcdef"
@[])
(test "split: basic functionality"
~(split "," '1)
"a,b,c"
@["a" "b" "c"])
(test "split: drops captures from separator pattern"
~(split '"," '1)
"a,b,c"
@["a" "b" "c"])
(test "split: can match empty subpatterns"
~(split "," ':w*)
",a,,bar,,,c,,"
@["" "a" "" "bar" "" "" "c" "" ""])
(test "split: subpattern is limited to only text before the separator"
~(split "," '(to -1))
"a,,bar,c"
@["a" "" "bar" "c"])
(test "split: fails if any subpattern fails"
~(split "," '"a")
"a,a,b"
nil)
(test "split: separator does not have to match anything"
~(split "x" '(to -1))
"a,a,b"
@["a,a,b"])
(test "split: always consumes entire input"
~(split 1 '"")
"abc"
@["" "" "" ""])
(test "split: separator can be an arbitrary PEG"
~(split :s+ '(to -1))
"a b c"
@["a" "b" "c"])
(test "split: does not advance past the end of the input"
~(* (split "," ':w+) 0)
"a,b,c"
@["a" "b" "c"])
(end-suite)

View File

@@ -42,7 +42,7 @@
(defn buffer-factory
[]
@"im am a buffer")
@"i am a buffer")
(assert (not= (buffer-factory) (buffer-factory)) "buffer instantiation")