Compare commits

...

1664 commits

Author SHA1 Message Date
Alex Shinn
af1bc5806d
Merge pull request #1022 from MikeSS8/typo
fix typo
2025-04-01 13:08:07 +09:00
Mike S. Stevenson
3c228ac0aa fix typo 2025-03-31 22:03:00 -06:00
Alex Shinn
6891ba1a33 add failing non-greedy test example
Issue #1020.
2025-04-01 10:36:06 +09:00
Alex Shinn
f8600d444f Don't consume the delimiter in read-float-tail.
Closes #1019.
2025-03-23 05:21:28 +09:00
Alex Shinn
ed37af2dfd Remove double read-char in scribble parser.
Closes #1018.
2025-03-22 11:20:04 +09:00
Alex Shinn
72ec53ca26 More thorough checks for SEXP_MIN_FIXNUM/-1.
Closes #1006.
2025-01-30 11:44:23 +09:00
Alex Shinn
558e1a895f Bind stack result to local var before casting.
Issue #1006.
2025-01-29 13:12:00 +09:00
Alex Shinn
a844854536 Don't allow mixing rational and floating point syntax.
Closes #1014.
2025-01-03 23:07:18 +09:00
Alex Shinn
1368a748a5 Patch from Vasil Sarafov clarifying DragonFlyBSD support. 2024-12-24 21:47:05 +09:00
Vasil Sarafov
68383d6359 doc: chibi runs flawlessly on OpenBSD
The README.md already includes information that chibi runs without any
issues on OpenBSD. However, the manual does not.

Furthermore, chibi builds & runs fine on OpenBSD, and is even packaged
in the ports.

Signed-off-by: Vasil Sarafov <contact@sarafov.net>
2024-12-24 21:42:08 +09:00
Alex Shinn
c437ede235 Guard against ill-formed responses in snow remote-command. 2024-12-02 11:43:36 +09:00
Alex Shinn
3716d99a02 fast-path vector-map on two vectors 2024-11-13 17:42:36 +09:00
Alex Shinn
49072ebbf4 Need to apply eof-object. 2024-11-13 15:57:26 +09:00
Alex Shinn
28676fcba9 fix csv-num-rows when last row doesn't end in nl 2024-11-08 17:00:16 +09:00
Alex Shinn
bf7187f324 add csv-num-rows 2024-11-08 16:25:13 +09:00
Alex Shinn
f28168a2a6 Adding csv-writer support. 2024-11-02 23:10:49 +09:00
Alex Shinn
8e67defd71 Add quote-doubling-escapes? and quote-non-numeric?. 2024-11-02 18:15:05 +09:00
Alex Shinn
679875d850
Merge pull request #1008 from dpk/srfi-35
Add SRFI 35 support
2024-11-02 09:36:25 +09:00
Daphne Preston-Kendal
2781739291 Move REPL condition printing into the SRFI 35 implementation 2024-11-02 01:03:27 +01:00
Daphne Preston-Kendal
76f35bc733 Define define-condition-type/constructor with syntax-rules 2024-11-02 00:49:31 +01:00
Daphne Preston-Kendal
3777c1b935 Add SRFI 35 support 2024-11-02 00:49:31 +01:00
Alex Shinn
416da21528 Add repl-print-exception. 2024-10-29 21:45:00 +09:00
Alex Shinn
f4e3c0fd0b Defining and using a repl-print generic to allow customizing REPL output. 2024-10-28 09:16:30 +09:00
Alex Shinn
4f3a98b2b3 Improving csv docs. 2024-10-25 18:44:30 +09:00
Alex Shinn
0976d04b21 Adding initial CSV library. 2024-10-23 23:17:03 +09:00
Alex Shinn
be31278685 Clarify there is no special meaning to else in match.
Closes #1005.
2024-10-09 07:16:41 +09:00
Alex Shinn
25a5534584
Merge pull request #1004 from ekaitz-zarraga/doc-formattinga
Fix typo in doc
2024-10-08 09:19:07 +09:00
Ekaitz Zarraga
c288520ca5 Fix typo in doc 2024-10-07 23:17:21 +02:00
Alex Shinn
702e881289 Add error advise when forgetting to import a language.
Closes #1001.
2024-09-20 09:13:16 +09:00
Alex Shinn
d677a135f1 Add current-test-value-formatter. 2024-09-17 18:37:40 +09:00
Alex Shinn
dce487fa3a c64/128 default values should be complex 2024-09-11 22:40:46 +09:00
Alex Shinn
2acef43da7 array-freeze! also makes the underlying storage immutable 2024-09-11 10:14:37 +09:00
Alex Shinn
0516e62b0b f*-storage-class defaults should be inexact 2024-09-11 10:14:37 +09:00
Alex Shinn
491cf324ec
Merge pull request #998 from dpk/test-error-predicate
(chibi test): add a type test for exceptions in test-error
2024-08-28 10:30:30 +09:00
Daphne Preston-Kendal
5bc498b32a (chibi test): add a type test for exceptions in test-error 2024-08-25 21:28:28 +01:00
Alex Shinn
24b5837562 Fix help output for nested command-specific options.
Closes #997.
2024-08-19 22:24:03 +09:00
Alex Shinn
e09fdb7e31 Fix attribute skipping for chibi-doc text rendering.
Closes #996.

Also guard against bad input with proper-list?.
2024-08-15 12:09:46 +09:00
Alex Shinn
020469bdbd
Merge pull request #993 from il-k/manual
README: add link to online manual
2024-06-17 09:19:49 +09:00
ilk
16b11f57b8
README: add link to online manual
It is not uncommon that the git repo is the first encounter with a
project. Having the manual available in the repo makes it easier to
discover.
2024-06-16 13:42:32 +03:00
Alex Shinn
3733b63d5f
Merge pull request #990 from welcome-linja/master
Fix SEXP_USE_ALIGNED_BYTECODE
2024-06-03 10:55:55 +09:00
Eleanor Bartle
243fd41aad Conform to 1/0 style 2024-06-03 11:43:32 +10:00
Alex Shinn
d4028f953b Tentatively manually encoding non-finite f16 values.
Issue #988.
2024-06-02 22:31:25 +09:00
Alex Shinn
3be1603f45 fix srfi 159 loading
Closes #905.
2024-06-02 17:51:34 +09:00
Alex Shinn
b1a370b218 add link to paper for single/half float conversions 2024-06-01 22:18:16 +09:00
Alex Shinn
f1df493c32 Upgrading to Unicode 15.1.0. 2024-05-31 23:57:18 +09:00
Alex Shinn
01d5dd2d55 add missing string-trim in extract-char-set-property 2024-05-31 23:52:54 +09:00
Alex Shinn
f53c642e74 bumping version 2024-05-31 23:04:40 +09:00
Alex Shinn
1bd81c1cb5 updating recent contributors 2024-05-31 22:56:40 +09:00
Alex Shinn
925c044eef Updating AUTHORS. 2024-05-31 19:25:48 +09:00
Alex Shinn
0bbb60060a Fix getgrnam_r error handling.
Closes #884.
2024-05-31 19:05:43 +09:00
Alex Shinn
7885db95cf Use github for homepage.
Closes #906.
2024-05-31 18:51:13 +09:00
Alex Shinn
193424f74d Add assertion for copy-on-failure? type.
Closes #987.
2024-05-31 18:46:39 +09:00
Alex Shinn
0b55c0b718 Fix copying reshape.
Closes #986.
2024-05-31 09:50:07 +09:00
Alex Shinn
4b5ab838e2 record the start dir when loading SRFI 193
Closes #922
2024-05-30 23:09:37 +09:00
Alex Shinn
bfb6b4bf82 updating doc links for new libs
Closes #923
2024-05-30 22:55:26 +09:00
Alex Shinn
414a23139f Fix reshape zero-dimensional and empty arrays.
Issue #986.
2024-05-30 22:37:06 +09:00
Alex Shinn
5e74c5ff54 add data domain checks for generic-storage-class
Closes #985.
2024-05-30 19:09:54 +09:00
Alex Shinn
3558c0f4a6 Add tests and documentation for define-binary-record-type. 2024-05-30 19:08:09 +09:00
Alex Shinn
8e3fd8f00c Add error checking for storage class data.
Closes #981.
2024-05-30 09:28:38 +09:00
Alex Shinn
390122a7bc accept a --quiet option to disable full request logging in http-server
Closes #926
2024-05-29 22:46:52 +09:00
Alex Shinn
5350d0429c export http-send-file
Closes #927
2024-05-29 22:37:43 +09:00
Alex Shinn
26a4ce94a7 Implement look-around assertions for SRFI 115. 2024-05-29 22:30:46 +09:00
Alex Shinn
832d82c494 Fix array-inner-product, fail fast for empty arrays.
Closes #982.
2024-05-29 21:42:20 +09:00
Alex Shinn
648f6b9de6 Fix error reporting for complex inequality comparisons.
Closes #934.
2024-05-29 21:36:30 +09:00
Alex Shinn
045bb1813c reduce bound on equal?/bounded 2024-05-29 14:10:42 +09:00
Alex Shinn
580aaf35ff match sexp_gc_releaseN count in sexp_add_import_binding
The count is not actually used but could be in the future.
2024-05-29 09:26:40 +09:00
Alex Shinn
b5de5eca92 interval-cartesian-product should accept zero args
Closes #983.
2024-05-29 09:08:26 +09:00
Alex Shinn
e737e48955 Fix interval-intersect for degenerate axes.
Closes #984.
2024-05-29 09:04:46 +09:00
Alex Shinn
609c78c0ca Forgot to add file for (srfi 160 mini). 2024-05-28 23:13:18 +09:00
Alex Shinn
2161f0df6e escape backslash 2024-05-28 23:12:09 +09:00
Alex Shinn
9010b2c5be provide a simpler (chibi app) example 2024-05-28 23:11:27 +09:00
Alex Shinn
36d7881763 Update to n-ary array-fold-* with correct arg order.
Closes #973.
2024-05-28 22:35:31 +09:00
Alex Shinn
96f17293f2 install (chibi text) 2024-05-28 22:14:07 +09:00
Alex Shinn
c966dfa7a8 suppress output of ldconfig
Closes #979.
2024-05-28 22:12:32 +09:00
Alex Shinn
c3c65b0309
Merge pull request #978 from arthurgleckler/master
Fix typo in (chibi app) example.
2024-05-28 22:09:56 +09:00
Arthur A. Gleckler
619f63fb5e Fix typo in (chibi app) example.
Backslash needed escaping.
2024-05-27 19:16:36 -07:00
Alex Shinn
78a990c73b Don't pre-filter empty arrays in array-append.
Closes #977.
2024-05-28 09:35:39 +09:00
Alex Shinn
11984c6eb3 Fix flatten-vector->list on empty vectors.
Closes #976.

Complements of Bradley Lucier.
2024-05-27 23:05:15 +09:00
Alex Shinn
2b1d2d99a8 Fix array-append for non-zero based intervals.
Closes #972.
2024-05-27 23:01:34 +09:00
Alex Shinn
a8939fecd0 array-stack should use the specified storage-class
The original code was based on (chibi math linalg)
which preferred the domain of the stacked arrays.
2024-05-27 18:33:24 +09:00
Alex Shinn
07f3301cc8 interval-contains-multi-index? should handle 0 dimensions
Closes #974.

Commit on behalf of Bradley Lucier.
2024-05-27 18:28:41 +09:00
Alex Shinn
4396e8dd4e Handle empty vector. 2024-05-27 13:21:24 +09:00
Alex Shinn
418d5c8a8c Build up empty arrays of higher dimensions for list/vector*->array
Issue #962.
2024-05-27 12:40:13 +09:00
Alex Shinn
f9e3ed1639 guard against mutation in make-interval
Closes #971
2024-05-27 09:29:37 +09:00
Alex Shinn
7923b1c46d Add array-empty?
Closes #969.
2024-05-27 09:27:42 +09:00
Alex Shinn
2f32ec6ba1 vector->array fix for optional args
Closes #968

Thanks Bradley Lucier!
2024-05-27 09:25:39 +09:00
Alex Shinn
db53df7df4 Fix some array-tile domain assertions.
Closes #966.

Fix complements of Bradley Lucier.
2024-05-26 22:04:22 +09:00
Alex Shinn
953f3ada23 allow noop (index-rotate n n)
Closes #965.
2024-05-26 22:00:43 +09:00
Alex Shinn
c96b0123a0 array-reduce should fail for empty arrays
Closes #964.
2024-05-26 21:58:00 +09:00
Alex Shinn
f4add6d188 Fix list/vector*->array for 0 dimensions.
Closes #962.
2024-05-26 21:54:28 +09:00
Alex Shinn
c200ecb21c
Merge pull request #940 from raviqqe/chore/unwind-on-exit
Unwind on exit
2024-05-26 21:51:17 +09:00
Yota Toyama
587f739f76 Import call/cc 2024-05-26 13:10:28 +09:00
Yota Toyama
0673eae46d Fix 2024-05-26 13:06:58 +09:00
Alex Shinn
698dcb2bfb Fix list/vector*->array for list elements.
Issue #962.
2024-05-25 22:41:45 +09:00
Alex Shinn
6c49071833 Factor out (srfi 160 mini) for f8/f16 base.
Closes #961.

Import this instead of the full vector libs for (srfi 231).

Also fix install of full vector libs for (srfi 160).
2024-05-25 22:15:10 +09:00
Alex Shinn
afda4ab979 Fix array-any.
Closes #963.
2024-05-25 22:06:23 +09:00
Alex Shinn
e492e4002f
Merge pull request #932 from aisk/master-1
improve readme for mac users
2024-05-25 21:57:03 +09:00
Alex Shinn
89dd02d55e Fix interval iteration for empty intervals.
Closes #959.
2024-05-24 22:29:44 +09:00
Alex Shinn
0ce4614457 Add array-packed? tests on empty arrays.
Issue #959.
2024-05-24 19:42:00 +09:00
Alex Shinn
09a5c431a2 array-tile widths can exceed the axis width
Closes #958.
2024-05-24 19:35:33 +09:00
Alex Shinn
33a59952a8 Implement and use array-freeze!
Fixes #960.
2024-05-24 19:20:14 +09:00
Alex Shinn
f60298b707 Initial half and quarter precision uniform vectors.
Quarter precision is 1.5.2 format.
Used to implement f16-storage-class and f8-storage-class.
Can be disabled at compile time.
2024-05-24 19:04:44 +09:00
Alex Shinn
e4568bd419 Use #\null as the default for char-storage-class 2024-05-23 21:37:12 +09:00
Alex Shinn
ef4e450af7 Fix element initialization for char arrays.
Closes #957.
2024-05-23 10:47:36 +09:00
Alex Shinn
4677cfb85b fix vector*->array 2024-05-23 10:38:16 +09:00
Alex Shinn
37dda638c3 Implement array-block. 2024-05-22 23:15:43 +09:00
Alex Shinn
65589e3e26 Fix default coeffs for the degenerate dimension case. 2024-05-22 22:02:27 +09:00
Alex Shinn
0d8e91e96c
Merge pull request #956 from 0xJonas/fix_sexp_string_cursor_set_args
Added missing argument to `sexp_string_cursor_set`
2024-05-22 22:01:28 +09:00
Jonas Rinke
ce7d4e1e3a Added missing argument to sexp_string_cursor_set 2024-05-21 21:22:17 +02:00
Alex Shinn
720ec69489 Adding a chibi-<version> feature.
Issue #955.
2024-05-20 22:03:41 +09:00
Alex Shinn
86ef8f5f1d
Merge pull request #954 from petteripiiroinen/fix-unintialised-stack-top-issue
Fix: segmentation fault during GC marking
2024-05-19 22:08:38 +09:00
Alex Shinn
3b6be9d60c Fix cmake build. 2024-05-18 05:45:45 +09:00
Petteri Piiroinen
f3b957c57f Fix: segmentation fault during GC marking
The stack top needs to be initialised before a potential garbage
collection after sexp_apply, SEXP_OP_APPLY1 and SEXP_OP_TAIL_CALL, since
stack top can otherwise be pointing to a stale pointer. This restores
the make_call invariant.
2024-05-17 06:52:02 +03:00
Alex Shinn
017e4b6990 Add feature for architecture.
Issue #955.
2024-05-16 23:28:29 +09:00
Alex Shinn
47f7ab01cf Show source for failed expected value. 2024-05-16 23:27:57 +09:00
Alex Shinn
7ac3cfebe1 Update to new make-specialized-array signature. 2024-05-14 21:46:25 +09:00
Alex Shinn
2e09a082c8 Fix SRFI 231 tests. 2024-05-13 22:10:49 +09:00
Alex Shinn
6ae3a43ee7 Adding memoize-file-loader test. 2024-05-13 22:06:19 +09:00
Alex Shinn
f25329b5aa Adding initial text type. 2024-03-19 23:03:21 +09:00
Alex Shinn
c4611cc33f Add some extended utf8 IO utilities. 2024-03-18 22:47:40 +09:00
Alex Shinn
5b19aab107
Merge pull request #950 from wasamasa/optimize-read-bytevector
Avoid needless allocation in read-bytevector!
2024-03-18 11:56:21 +09:00
Vasilij Schneidermann
0fd351e0b5 Fix read-bytevector logic 2024-03-18 03:15:39 +01:00
Vasilij Schneidermann
c837c7110f Correct let to let* 2024-03-18 02:48:48 +01:00
Vasilij Schneidermann
1b1e8b311b Correct read-bytevector logic for small reads 2024-03-18 02:06:27 +01:00
Vasilij Schneidermann
d0e6dc7556 Avoid needless allocation in read-bytevector!
This change switches the implementation strategy to basing
read-bytevector on top of read-bytevector! rather than the other way
around.
2024-03-18 01:13:57 +01:00
Alex Shinn
b303bf3611 Allow for a chunked regexp API by exposing low-level tools. 2024-03-17 22:21:23 +09:00
Alex Shinn
5b27b01f91 Fix line wrapping in chibi test 2024-03-17 10:39:27 +09:00
Alex Shinn
19c7d4fec2 user/group-information should return #f for unknown users 2024-02-23 15:16:22 +09:00
Alex Shinn
56ef426dfa Catch division edge case of (/ fx-least -1).
Thanks for Jim Rees for reporting.
2024-02-22 16:32:20 +09:00
Alex Shinn
29dd1a3b81 Add more specific warning for error on no import, clarify docs. 2024-01-30 12:31:06 +09:00
Alex Shinn
97a04bd2fc
Merge pull request #946 from ekaitz-zarraga/faster-concatenate!
Reduce iterations in concatenate!
2024-01-10 23:45:28 +09:00
Ekaitz Zarraga
967b888d8c Reduce iterations in concatenate!
This commit should reduce the amount of iterations in concatenate to N
where N is the sum of the lengths of the input lists.

The previous implementation iterated from the beginning in each
concatenation because of `last-pair`.

This implementation is significantly faster in this extreme case:

(concatenate! `(,(iota 50000) ,@(map list (iota 500))))

>> Previous implementation:
real	0m0.671s
user	0m0.658s
sys	0m0.013s

>> This implementation:
real	0m0.175s
user	0m0.174s
sys	0m0.001s

The tests is done using `time`, which is not reliable at all, but using
`(trace last-pair)` shows accurately what happens with the iterations.
2024-01-09 17:18:41 +01:00
Alex Shinn
a67e75926d
Merge pull request #943 from ekaitz-zarraga/master
Add srfi-64
2024-01-09 11:14:49 +09:00
Alex Shinn
cc6a3d10e5
Merge pull request #945 from ekaitz-zarraga/concatenate!
Fix #944: concatenate! work with empty lists in any position
2024-01-09 09:42:27 +09:00
Ekaitz Zarraga
70989e0cef srfi: 1: add tests for append! (and concatenate!) 2024-01-09 01:04:34 +01:00
Ekaitz Zarraga
7bf376b7fb Fix: concatenate! work with empty lists 2024-01-08 22:56:07 +01:00
Ekaitz Zarraga
bd01401a24 doc: add srfi-64 2024-01-07 21:05:25 +01:00
Ekaitz Zarraga
43bfac5884 Add srfi-64 2024-01-07 20:58:46 +01:00
Alex Shinn
af41e2b01d
Merge pull request #942 from dpk/newlines-in-verbose-test-output
`(chibi test)`: Put newlines after test results etc in verbose mode
2023-11-07 14:17:17 +09:00
Daphne Preston-Kendal
a277a5dffc (chibi test): Put newlines after test results etc in verbose mode 2023-11-06 20:59:10 +01:00
Yota Toyama
f41a61f748 Fix windows import 2023-10-13 17:21:11 +11:00
Yota Toyama
77dc8c3524 Refactor 2023-10-13 17:19:36 +11:00
Yota Toyama
70e5aa14a3 Unwind before exit 2023-10-13 16:37:43 +11:00
Alex Shinn
fe93067553
Merge pull request #939 from raviqqe/bug/write-char
Handle basic special characters in `write`
2023-09-29 10:46:02 +09:00
Yota Toyama
4a4a1553f5 Fix 2023-09-27 19:13:57 +10:00
Yota Toyama
0e009d6045 Fix bug 2023-09-27 19:11:41 +10:00
Alex Shinn
f9908f19ee
Merge pull request #937 from gambiteer/231-checks
SRFI 231: Declare char-storage-class, fix interval-projections
2023-08-29 20:54:13 +09:00
Bradley Lucier
e390668961 SRFI 231: Declare char-storage-class, fix interval-projections 2023-08-27 23:22:14 -04:00
AN Long
27ca614b42
improve readme for mac users 2023-08-08 17:51:44 +08:00
Alex Shinn
67fdb283b6 fix init value for make-specialized-array 2023-06-20 22:19:19 +09:00
Alex Shinn
44f8c91931 Fix zero-dimensional array indexing. 2023-06-20 22:16:18 +09:00
Alex Shinn
b06c4cca9d Merge branch 'master' of github.com:ashinn/chibi-scheme 2023-06-04 06:06:47 +09:00
Alex Shinn
4b5e885f31 Fix coeffs in trivial dimensions to work with BLAS. 2023-06-04 06:05:29 +09:00
Alex Shinn
13812f8749
Merge pull request #920 from gambiteer/231-test
SRFI 231: Add index-* tests
2023-06-03 10:43:38 +09:00
Bradley Lucier
7420ba9315 SRFI 231: Add index-* tests
lib/srfi/231/base.scm:

1.  Add argument checks for index-first, index-last, index-rotate, and index-swap.

lib/srfi/231/test.sld:

1.  1,$s/179/231/g (in vim notation)

2.  Add tests for index-first, index-last, index-rotate, and index-swap.

3.  Remove trailing spaces.
2023-05-30 13:08:25 -04:00
Alex Shinn
6ea80c5ea4 add srfi 231 to lib tests 2023-05-30 11:36:36 +09:00
Alex Shinn
8e1ea89ce6
Merge pull request #919 from gambiteer/231-install
Fix SRFI 231 install
2023-05-29 18:34:24 +09:00
Bradley Lucier
732078cde4 Fix SRFI 231 install
Makefile:

When installing chibi, make installation directory and install files for SRFI 231.
When uninstalling chibi, remove installation directory and files for SRFI 231.

lib/srfi/231/transforms.scm:

Move definition of vector-iota from here to ...

lib/srfi/231/base.scm:

Here.

lib/srfi/231/base.sld:

Export vector-iota to use in both base.scm and transforms.scm.
2023-05-28 17:48:32 -04:00
Alex Shinn
ef554024ec
Merge pull request #918 from gambiteer/231-changes
Add index-swap, fix assert in array-append
2023-05-24 09:22:50 +09:00
Bradley Lucier
27ea774e2e Add index-swap, fix assert in array-append 2023-05-23 15:09:25 -04:00
Alex Shinn
06f0cc0225 Add iset-rank/select. 2023-05-23 22:03:19 +09:00
Alex Shinn
d6c58a7e11 Fix array-append signature. 2023-05-20 16:31:23 +09:00
Alex Shinn
870e484b50 provide initial raw-script-file definition in meta-7.scm
Closes #916
2023-05-09 06:50:03 +09:00
Alex Shinn
58a79b09d0
Merge pull request #915 from lassik/srfi-193
Fix broken import in (srfi 193)
2023-05-05 05:28:06 +09:00
Lassi Kortela
be22930896 Fix broken import in (srfi 193)
Fixes #914
2023-05-04 18:35:59 +03:00
Alex Shinn
971f546833
Merge pull request #913 from lassik/patches
Drop (chibi sxml) dependency on let-optionals
2023-04-22 14:17:00 +09:00
Lassi Kortela
561fc1bae0 Drop (chibi sxml) dependency on let-optionals
let-optionals can be provided by the (chibi optional) library or by
SRFI 227. Either dependency is non-trivial and makes it tricky to
incorporate (chibi sxml) into outside projects. Since (chibi sxml)
only makes trivial use of let-optionals, expand the macro by hand.
2023-04-21 16:42:03 +03:00
Alex Shinn
2dc7dd5b68
Merge pull request #912 from lassik/patches
Update .gitignore
2023-04-21 09:07:35 +09:00
Lassi Kortela
18920a9160 Update .gitignore 2023-04-20 14:37:21 +03:00
Alex Shinn
1ba5df1fdf Adding missing length<=? (closes #909). 2023-04-02 22:48:51 +09:00
Alex Shinn
7e511ef8e4 typo s!fx+*/carry!fx*/carry!g (issue #908) 2023-04-02 22:39:25 +09:00
Alex Shinn
5826023de1
Merge pull request #907 from rgherdt/feature/add-guile-support-for-snow
add support for Guile [snow-chibi]
2023-04-02 22:26:29 +09:00
Ricardo G. Herdt
ffe1ae4452 add support for Guile [snow-chibi]
Two recent changes to Guile improved its R7RS support:

- 3.0.7 fixed a bug regarding cond-expand in a define-library form.
- 3.0.8 added support for R7RS' srfi library names, e.g. (srfi 69) instead of
  (srfi srfi-69) used by Guile.

These changes open the possibility for using snow libraries in R7RS Guile
programs. This commit adds support for installing/removing snow libraries for
Guile.
2023-03-31 20:29:35 +02:00
Alex Shinn
d5e85874b3 Merge branch 'master' of github.com:ashinn/chibi-scheme 2023-03-19 23:57:10 +09:00
Alex Shinn
3b8f07b12e Fix array-stack, interval folds and list*->array.
Issue #900.
2023-03-19 23:56:01 +09:00
Alex Shinn
8ea99a9e40
Merge pull request #903 from adamfeuer/feature/httpd-client-server-examples
add simple http client and server examples
2023-03-15 22:51:12 +09:00
Adam Feuer
eecf561e62 add simple http client and server examples 2023-03-14 20:40:37 -07:00
Alex Shinn
e6d7e4fffb sexp_poll_port needs a timeout 2023-03-15 10:18:37 +09:00
Alex Shinn
82dfe95468
Merge pull request #898 from nkoguro/fix-read-number
Fix bug: sexp_read_number can't parse a/b@c-style number correctly.
2023-02-26 21:28:28 +09:00
KOGURO, Naoki
35281cf28e Fix bug: sexp_read_number can't parse a/b@c-style number correctly. 2023-02-25 11:26:51 +09:00
Alex Shinn
dde5f6c88d
Merge pull request #896 from chk-jxcn/chk-jxcn-patch-1
Fix #880
2023-02-20 10:40:09 +09:00
chk-jxcn
767bb8a5f9
Fix #880
Fix issue of can't load symbol when load from image, which cause by add extra "(sexp_proc1)" before function name.
Error message: "dynamic function lookup failure: <static> (sexp_proc1)sexp_get_sha_stub"
2023-02-20 02:53:56 +08:00
Alex Shinn
c026c0884d Encode JSON null as the symbol 'null.
Closes #893.
2023-02-16 21:32:35 +09:00
Alex Shinn
4dab8b81d4 Implementing array-decurry. 2023-02-16 21:20:37 +09:00
Alex Shinn
18c958e836
Merge pull request #887 from mnieper/srfi-211
Provide identifier-syntax and make-variable-transformer through standardized SRFI libraries.
2023-02-08 21:38:00 +09:00
Alex Shinn
b22bcc1fcc don't assume git for building clibs.c (issue #891) 2023-02-08 09:55:54 +09:00
Alex Shinn
8e9b15eda8 Merge branch 'master' of github.com:ashinn/chibi-scheme 2023-02-08 09:38:17 +09:00
Alex Shinn
875cefc686 clarify chibi-scheme-static docs 2023-02-08 09:37:39 +09:00
Alex Shinn
b297e7272b
Merge pull request #888 from smazga/9front-exit
Fix exit call on plan9/9front
2023-02-05 09:48:29 +09:00
McKay Marston
27071e6c8f ifdef the return status so that non-plan9 systems get the real value 2023-02-04 16:36:49 -08:00
McKay Marston
0aa515730f Fix exit call on plan9/9front
* make sure exits is passed a nil on success
* make sure main exits with a proper exits call
2023-02-03 17:19:46 -08:00
Marc Nieper-Wißkirchen
c5615c9b24 Install the new libraries. 2023-02-01 12:58:21 +01:00
Marc Nieper-Wißkirchen
c6db239882 Provide identifier-syntax and make-variable-transformer through standardized SRFI libraries. 2023-02-01 10:33:09 +01:00
Alex Shinn
598dcad547 Error on using only to import an unexported binding.
Closes #865.
2023-01-28 15:47:37 +09:00
Alex Shinn
e93b71990c Cast to int before comparing with EOF (#745). 2022-12-11 22:56:45 +09:00
Alex Shinn
da53f46c93 Merge branch 'master' of github.com:ashinn/chibi-scheme 2022-12-04 23:32:54 +09:00
Alex Shinn
cadae49fec Fix sexp_contains_syntax_p_bound for synclos in dotted rest position.
Closes #464.
2022-12-04 23:31:25 +09:00
Alex Shinn
8653dddeb3
Merge pull request #856 from dpapavas/static-user-libs
Add support for exporting statically compiled libraries from C
2022-10-31 18:54:40 +09:00
Dimitris Papavasiliou
310a04f701 Add support for user exported C libraries
This uses the existing mechanism for statically compiled C libraries,
to allow the user to export their own C libraries in a similar way.
User exported libraries can be added on top of statically compiled C
libraries or exist on their own (by setting SEXP_USE_STATIC_LIBS_EMPTY).
2022-10-30 14:06:18 +02:00
Alex Shinn
4185012205
Merge pull request #870 from dpk/safe-syntax-case-macro-aux
Make macro-aux safe for other things together with syntax-case
2022-10-30 13:43:28 +09:00
Alex Shinn
d29657811c
Merge pull request #871 from dpk/fix-syntax-tests
Fix syntax-tests to use mutable-environment
2022-10-30 13:40:54 +09:00
Daphne Preston-Kendal
dcd2ce9054 Add syntax-tests to test-all 2022-10-28 11:10:51 +02:00
Daphne Preston-Kendal
e4d53fe533 Fix syntax-tests to use mutable-environment 2022-10-28 11:06:21 +02:00
Daphne Preston-Kendal
97adffc8b5 Make macro-aux safe for other things together with syntax-case
If you set the macro-aux of a macro outside of (chibi syntax-case), it
would previously case `syntax` to think that it was a pattern variable
and try to substitute it, even if the macro-aux was being used for
something else.

This patch fixes that by wrapping pattern variable values in an extra
typed box and checking that it has the right type before deciding that
it’s actually a pattern variable.
2022-10-26 11:04:23 +02:00
Alex Shinn
d67fa42d0c
Merge pull request #793 from dpk/string-ref-cache
Add a feature to cache the most recent string index->cursor result
2022-10-19 17:59:08 +09:00
Alex Shinn
ad4dfcb77b add package-page snow-fort utility 2022-10-19 17:53:59 +09:00
Alex Shinn
cee932d2dc add ffi support for movable parameters 2022-10-19 17:53:01 +09:00
Alex Shinn
b1750cee57
Merge pull request #868 from arthurgleckler/master
Fix bug: attributes without values didn't work.
2022-10-12 16:44:55 +09:00
Arthur A. Gleckler
73875cbaf7 Fix bug: attributes without values didn't work.
Before, it was necessary to do something like this:

  (option (@ (selected . #false) (value "any")) "any")

instead of:

  (option (@ (selected) (value "any")) "any")

Only the former is valid SXML, as far as I can tell from the SXML
specification:

  <https://dl.acm.org/doi/pdf/10.1145/571727.571736>
2022-10-11 21:22:39 -07:00
Alex Shinn
6d58f9e3f6
Merge pull request #867 from arthurgleckler/master
Add support for SXML indentation on output.
2022-10-11 23:19:52 +09:00
Arthur A. Gleckler
24339e51e7 Update variable name per Alex's suggestion. 2022-10-11 07:17:31 -07:00
Alex Shinn
fa6d4f7a4f Adding sxml tests. 2022-10-11 22:42:54 +09:00
Alex Shinn
0a050a524a Improve let-keywords docs and add unit tests (issue #866). 2022-10-11 22:32:32 +09:00
Arthur A. Gleckler
4e24ad01e0 Add support for SXML indentation on output. 2022-10-10 13:34:27 -07:00
Alex Shinn
49f95dc107 Fix bug in procedure-flags in (chibi ast) (issue #864)
We were incorrectly boxing an already boxed value.
2022-10-05 09:06:51 +09:00
Alex Shinn
0eeeac7650 Make environment immutable and add mutable-environment alternative (issue #863). 2022-10-04 16:07:36 +09:00
Alex Shinn
e88374aae1 typo s/df/fd (fixes #861) 2022-09-26 22:37:51 +09:00
Alex Shinn
95827a44ed Add immutable-string with copy-on-write semantics (issue #860). 2022-09-16 18:18:20 +09:00
Alex Shinn
1e47c78b8a Fix reversal of results in rounding all leading 9's (issue #859). 2022-09-15 21:24:00 +09:00
Alex Shinn
fa8a506ed5
Merge pull request #858 from okuoku/win32-test-fix
cmake: Exclude `(chibi shell)` test on Win32
2022-09-11 20:02:26 +09:00
okuoku
f887003c30 cmake: Exclude (chibi shell) test on Win32
Exclude `(chibi shell)` test on Win32 since it's not compatible.
2022-09-11 13:40:50 +09:00
Alex Shinn
0a50b305bc string-set! should respect immutability (issue #857) 2022-09-04 16:28:04 +09:00
Alex Shinn
2aa6dc829e
Merge pull request #854 from lockywolf/chibi-shell-return-value-exit-status
Make (shell) in (chibi shell) return exit status of last command.
2022-08-24 14:37:14 +09:00
Lockywolf
6bb62979fd Make (shell) in (chibi shell) return exit status of last command. 2022-08-24 13:17:37 +08:00
Alex Shinn
f367cb86e2 signal an error when we can't change-directory in with-directory (issue #850) 2022-08-11 21:56:35 +09:00
Alex Shinn
7e0b2730f4 snow-post should quote values 2022-08-09 18:43:51 +09:00
Alex Shinn
9993b27486 make-request path should be a string even in failure case 2022-08-09 14:02:19 +09:00
Alex Shinn
51beea2bb6 adding more warnings for bad repos (issue #846) 2022-08-08 18:59:50 +09:00
Alex Shinn
1f1b361010 Using Makefile-configured snow install directories. 2022-08-08 18:43:30 +09:00
Alex Shinn
eac4adc272
Merge pull request #849 from lockywolf/shell.scm-scribble-fixes
Fix scribble documentation for shell.scm
2022-08-04 20:45:39 +09:00
Lockywolf
bf1703e511 Fix scribble documentation for shell.scm 2022-08-03 23:21:50 +08:00
Alex Shinn
c9344debfb Revert "Install manpages in man/man1, not man"
This reverts commit c5446df854.

MANDIR is already defined to include man1.
2022-08-03 22:55:30 +09:00
Alex Shinn
46c4a0cd7c
Merge pull request #847 from lockywolf/master
Install manpages in man/man1, not man
2022-08-03 22:48:09 +09:00
Alex Shinn
70acbf5a08 fix indentation 2022-08-03 22:44:28 +09:00
Alex Shinn
a2daa155e8 comment out failing chicken tests 2022-08-03 22:43:40 +09:00
Alex Shinn
2f50a6cf74
Merge pull request #848 from lockywolf/crutch-for-relative-install-lib-dir
Add a crutch to better detect snow binary extension dir.
2022-08-03 22:42:40 +09:00
Lockywolf
ac5c10c114 Add a crutch to better detect snow binary extension dir. 2022-08-03 21:40:48 +08:00
Alex Shinn
873e1c490f wrap tests in groups 2022-08-03 22:38:39 +09:00
Alex Shinn
97ca7e1799 don't build images by default when DESTDIR is specified 2022-08-03 22:38:27 +09:00
Alex Shinn
66deb6fe3b install-data-file should return the installed path 2022-08-03 22:38:07 +09:00
Alex Shinn
dea22a424b use chroot to install images (issue #844) 2022-08-02 15:00:56 +09:00
Lockywolf
c5446df854 Install manpages in man/man1, not man 2022-08-02 13:10:02 +08:00
Alex Shinn
805fcc7d30 fix (chibi shell) summary 2022-07-30 07:02:37 +09:00
Alex Shinn
b677b287ec
Merge pull request #843 from lockywolf/master
Add (chibi shell) to the documentation.
2022-07-30 07:00:32 +09:00
Lockywolf
b89545df48 Add (chibi shell) to the documentation.
1. Add "shell" to the list of html_docs
2. Add a reference to (chibi shell) to chibi.scribl
2022-07-29 22:25:56 +08:00
Alex Shinn
568519bf6b fleshing out I/O redirection and adding docs 2022-07-29 18:50:42 +09:00
Alex Shinn
1b0566b759 add io redirection to syntax 2022-07-29 07:30:35 +09:00
Alex Shinn
1bea865ec2 more shell utilities 2022-07-16 21:55:59 +09:00
Alex Shinn
bc18b0cc30 allow custom option types for (chibi app) 2022-07-09 14:59:34 +09:00
Alex Shinn
d03202407b fix pipe example 2022-07-09 14:59:17 +09:00
Alex Shinn
701cf1d169 no more flexible arrays (issue #842) 2022-07-04 22:30:49 +09:00
Alex Shinn
658244d64e Add WIP shell library. 2022-07-01 22:39:27 +09:00
Alex Shinn
f5d96939b6 adding optional child-prod arg to call-with-process-io 2022-06-19 08:30:45 +09:00
Alex Shinn
54d3aafc7b update test 2022-06-12 16:11:16 +09:00
Alex Shinn
38fc7e0932 Initial SRFI 231 implementation. 2022-06-12 16:04:38 +09:00
Alex Shinn
4d0ae090b7 http-send-file default mime type should be application/octet-stream 2022-06-12 10:02:38 +09:00
Alex Shinn
566d9a47cf
Merge pull request #839 from rschifflin/rs-bignum-fix-to-sint
Fix SEXP_CUSTOM_LONG_LONGS lsint_to_sint
2022-06-11 08:16:39 +09:00
Mark Schifflin
2f524c59f7 Fix lsint_to_sint 2022-06-08 20:43:44 -07:00
Alex Shinn
35eed62160 the top-level of a macro expansion should preserve the call site source (issue #835) 2022-06-03 13:36:56 +09:00
Alex Shinn
05ee42804a Merge branch 'master' of github.com:ashinn/chibi-scheme 2022-05-29 08:03:48 +09:00
Alex Shinn
3c4ace142c propagate source info manually in let (issue #835) 2022-05-29 08:03:32 +09:00
Alex Shinn
bf225edc8e
Merge pull request #832 from jpellegrini/srfi-144
SRFI-144: accept zero arguments for flmax/flmin
2022-05-15 22:21:56 +09:00
Jeronimo Pellegrini
32ce583927 Add some more unit tests to SRFI-144
Tests for flmin, flmax, fl-least, fl-epsilon, fl-greatest are
included.
2022-05-15 08:30:27 -03:00
Jeronimo Pellegrini
1ecf7f9c8a SRFI-144: accept zero arguments for flmax/flmin
SRFI-144 requires that (flmin) returns +inf.0 and that
(flmax) returns -inf.0, so these procedures can't really
be aliases to the Chibi implementation of R7RS max and min.
2022-05-14 08:14:08 -03:00
Alex Shinn
42332bb04f compute least double properly (issue #831) 2022-05-14 16:30:27 +09:00
Alex Shinn
09200ae13c fix locale-dependent decimal separators (issue #829) 2022-05-12 18:10:38 +09:00
Alex Shinn
b0735b3ca7
Merge pull request #828 from dpk/better-case-lambda-tests
Better case-lambda tests
2022-04-20 21:10:55 +09:00
Daphne Preston-Kendal
92fa73ecab Better case-lambda tests
The problem with the original `case-lambda` tests is that they could
actually pass if the `+` and `*` procedures were implemented correctly
but `case-lambda` itself wasn’t.

Specifically, an attempted optimized `case-lambda` implementation
which looked at the length of its arguments list and subsequently
erroneously always chose the variadic clause of the `plus` procedure
would still pass the test, because `plus` in this case recreated the
behaviour of the `+` procedure used for the test; it was never
actually observable whether the `args` clause or one of the more
specific clauses had been used to generate the result. Similar applies
to the `mult` test: although in that case an implementation could only
have erroneously chosen the `(x y . z)` clause in the two-argument
case, it would still have been an error invisible to the test cases.

I’ve also added a test which attempts to ensure that a redundant
clause will never match. This may cause a warning on Schemes which
detect such clauses at compile time, but R7RS does not explicitly
define such `case-lambda` expressions as erroneous in any way, so it
would be wrong (and non-conformant) for it to stop the tests running
altogether.

(This patch mainly useful because Chibi’s R7RS tests are sometimes
used by other implementations to ensure conformance. Chibi passed
these tests in any case.)
2022-04-18 10:05:40 +02:00
Alex Shinn
d4eb32f8b1 bounds check for parse-stream-debug-info on empty input (fixes issue #826) 2022-04-18 08:55:06 +09:00
Alex Shinn
899a6bace3
Merge pull request #824 from nmeum/parse-commit-fk
`(chibi parse)`: allow (optionally) passing custom fk to parse-commit
2022-04-14 10:16:33 +09:00
Sören Tempel
5fe400c688 (chibi parse): allow (optionally) passing custom fk to parse-commit
Without this patch, parse-commit will unconditionally use a faillure
continuation which simply returns `#f`. This may be undesirable in
some situations. As such, this commit allows (optionally) passing
a custom failure continuation as a second argument. If none is passed
the old behavior is used, hence this commit doesn't cause any backwards
incompatible API changes.

See #822
2022-04-11 18:03:24 +02:00
Alex Shinn
b4471ad6fd
Merge pull request #823 from ztzg/diff-term-ansi-call
lib/chibi/diff.scm: Fix string ANSI coloring call
2022-04-11 11:24:23 +09:00
Damien Diederen
1702162e1f lib/chibi/diff.scm: Fix string ANSI coloring call 2022-04-10 22:44:24 +02:00
Alex Shinn
79abb960a4
Merge pull request #821 from nmeum/parse-string-failure-reason
(chibi parse): Ensure reason is always a string
2022-04-10 10:16:47 +09:00
Sören Tempel
1503217e86 (chibi parse): Ensure reason is always a string
While testing a `(chibi parser)`-based parser I noticed that
`parse-string` is the only provided parser combinator which uses a list,
instead of a string, as a failure reason. It is not explicitly
documented but since all other standard parser combinator use a string
for the error reason I assume this to be a bug and have adjusted the
`parse-string` combinator accordingly in this commit.
2022-04-09 10:55:20 +02:00
Alex Shinn
e7486dd7df allow -S<standard> (issue #819) 2022-03-20 10:02:06 +09:00
Alex Shinn
1d8bd4abdb
Merge pull request #818 from dpk/fix-identifier-syntax
Fix definition of full-match? (Proposed fix for #816)
2022-03-17 11:28:54 +09:00
Daphne Preston-Kendal
c28bbbaa98 Fix definition of full-match?
Fixes #816
2022-03-16 09:16:19 +01:00
Alex Shinn
9fe1e69c23 partial fix for issue #816 2022-03-15 23:45:59 +09:00
Alex Shinn
452b9a528d
Merge pull request #805 from dpk/identifier-macros
Identifier macros
2022-03-15 19:48:49 +09:00
Alex Shinn
9d2875b05e
Merge branch 'master' into identifier-macros 2022-03-15 19:47:40 +09:00
Alex Shinn
4382b9d3fd allow syntax-rules to work with reference patterns 2022-03-15 19:06:49 +09:00
Daphne Preston-Kendal
a4ecace600 Revert "Document the addition of identifier macros"
This reverts commit 83f61aecd2.

[skip ci]
2022-03-15 10:33:07 +01:00
Daphne Preston-Kendal
9a0212efff Move identifier-syntax to (chibi ast) 2022-03-15 10:27:56 +01:00
Daphne Preston-Kendal
86e8b56289 Nix er-macro-transformer*, extend syntax-rules for identifier macros 2022-03-15 09:37:52 +01:00
Daphne Preston-Kendal
7a4e793e49 Move make-variable-transformer to (chibi ast) 2022-03-15 09:25:21 +01:00
Daphne Preston-Kendal
01bd50b6f1 Revert "Document the addition of identifier-syntax to core"
This reverts commit 920ba20a8c.
2022-03-15 09:07:17 +01:00
Daphne Preston-Kendal
70455ed3f8 Revert "Implement identifier-syntax in init-7.scm"
This reverts commit d55d6c619c.
2022-03-15 09:07:11 +01:00
Alex Shinn
b32e6e15d0
Merge pull request #806 from dpapavas/make-opcode-procedure
Expose construction of foreign procedures.
2022-03-13 17:12:55 +09:00
Alex Shinn
18e8575358
Merge pull request #813 from dpapavas/export-get-stack
Export sexp_get_stack_trace
2022-03-13 17:10:05 +09:00
Daphne Preston-Kendal
476ae194a3 Indentation fix
[skip ci]
2022-03-03 18:59:04 +01:00
Alex Shinn
c5cfc5cded fix missing newline in test line wrapping output 2022-02-24 22:43:49 +09:00
Alex Shinn
e587881c2c only add a dummy script name argument for the -R usage, not -r (fixes #814) 2022-02-23 07:44:48 +09:00
Alex Shinn
940f315b67 adding missing commit (issue #815) 2022-02-22 20:25:31 +09:00
Alex Shinn
fae48a3790 properly handling negation of complex numbers with ratio parts (fixes issue #815) 2022-02-22 17:55:54 +09:00
Dimitris Papavasiliou
9c5745b7f3 Export sexp_get_stack_trace 2022-02-16 21:59:52 +02:00
Alex Shinn
82d61b3d8e make mixed inexact/exact ordering consistent, converting to exact for fixnums and ratios instead of just bignums (issue #812) 2022-02-12 07:50:58 +09:00
Alex Shinn
eb6a2eeb78 fix integer type in object-cmp 2022-02-12 07:48:14 +09:00
Daphne Preston-Kendal
abda243d21 Add identifier macro tests to syntax-test.scm 2022-02-04 11:28:31 +01:00
Daphne Preston-Kendal
920ba20a8c Document the addition of identifier-syntax to core
[skip ci]
2022-02-04 11:00:27 +01:00
Daphne Preston-Kendal
51b0203dc5 Ditch the syntax-case version of identifier-syntax now it’s in core 2022-02-04 10:40:21 +01:00
Daphne Preston-Kendal
d6b13db503 Attempt to improve readability of syntax-template-transformer uses
Lipstick on a pig, but seems to be the best option available
2022-02-04 10:40:21 +01:00
Daphne Preston-Kendal
aef1a1b358 Use a less confusing term in the error message for invalid clauses
Since ‘template’ is technically the second part
2022-02-04 10:40:21 +01:00
Daphne Preston-Kendal
bddbdc801d Use the exact set! syntactic-closure from the identifier-syntax form
Without this, set! isn’t recognized correctly as a literal and the
set! form erroneously matches any application form with two arguments
2022-02-04 10:39:34 +01:00
Alex Shinn
e4766f8cac Merge branch 'master' of github.com:ashinn/chibi-scheme 2022-02-04 12:35:14 +09:00
Alex Shinn
07358ff8b7 don't allow trailing data after the number in string->number, even if a valid delimiter (fixes issue #811) 2022-02-04 12:34:55 +09:00
Daphne Preston-Kendal
d55d6c619c Implement identifier-syntax in init-7.scm 2022-02-01 11:57:59 +01:00
Alex Shinn
f126c47c3e
Merge pull request #809 from dpapavas/use-malloc
Build fails with SEXP_USE_MALLOC
2022-01-10 08:01:45 +09:00
Dimitris Papavasiliou
c2a0bdb2c6 Partially fix SEXP_USE_MALLOC. 2022-01-09 14:44:02 +02:00
Alex Shinn
a127a332ac use 0 (configurable) for the C++ size of flexible arrays (fixes #808) 2022-01-09 21:29:00 +09:00
Alex Shinn
4d45583637 removing unused sexp_cpointer_body 2022-01-09 21:19:57 +09:00
Alex Shinn
d642f34f25
Merge pull request #807 from lubgr/docs/small-fixes
Minor documentation improvements (C API)
2022-01-07 00:04:53 +09:00
Lukas Böger
1f2b534be9 Small documentation improvements 2022-01-05 12:19:32 +00:00
Daphne Preston-Kendal
d769a7970c Wrap identifier-syntax output in make-transformer 2022-01-03 09:50:07 +01:00
Daphne Preston-Kendal
eb8582f5b1 Use sexp_make_procedure to sexp_make_variable_transformer_op 2022-01-03 08:28:40 +01:00
Dimitris Papavasiliou
87637c0a0b Expose construction of foreign procedures. 2022-01-02 20:45:39 +02:00
Daphne Preston-Kendal
f32d89175c Typo fix.
[skip ci]
2022-01-02 09:37:37 +01:00
Daphne Preston-Kendal
f63348a4d1 Iteratively expand variable-transformer set! 2022-01-02 08:06:38 +01:00
Daphne Preston-Kendal
83f61aecd2 Document the addition of identifier macros 2021-12-30 11:18:39 +01:00
Daphne Preston-Kendal
4a3c7eaf1f Support identifier-syntax in (chibi syntax-case) 2021-12-30 10:58:26 +01:00
Daphne Preston-Kendal
d17764be29 Add variable transformers 2021-12-30 10:34:54 +01:00
Daphne Preston-Kendal
e97a2debe1 Friendlier error message for misuse of standard macros 2021-12-30 00:12:18 +01:00
Daphne Preston-Kendal
770b4d367b Add basic support for identifier macros 2021-12-29 23:52:46 +01:00
Alex Shinn
6615a74609 undoing unintended commit 2021-12-29 14:27:49 +09:00
Alex Shinn
b769a318ef use unsigned char* in sexp_update_string_index_lookup (fixes issue #804) 2021-12-29 11:55:58 +09:00
Alex Shinn
ab29a2b973 skip common prefix/suffix in diff 2021-12-28 16:07:43 +09:00
Alex Shinn
9cd9ec1cda fix mapn error message 2021-12-28 15:19:10 +09:00
Alex Shinn
92499731bc show procedure arity in primitive write 2021-12-28 08:26:20 +09:00
Alex Shinn
fc9cf93796 type checks on identifier=? 2021-12-28 08:19:05 +09:00
Daphne Preston-Kendal
9dcda90e2e Merge branch 'string-ref-cache' into string-ref-cache-backwards 2021-12-27 19:24:20 +01:00
Daphne Preston-Kendal
9419fb19ed Merge branch 'master' into string-ref-cache 2021-12-27 19:13:39 +01:00
Alex Shinn
f6e8e71c41 Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-12-25 10:56:10 +09:00
Alex Shinn
58e9715c2b handle non-positive numbers in numeric/si (fixes issue #801) 2021-12-25 10:55:58 +09:00
Alex Shinn
f812bbc96b
Merge pull request #797 from dpk/reference-barrier
Fix SRFI 124 imports for reference-barrier
2021-12-15 07:01:43 +09:00
Daphne Preston-Kendal
f9f384c45b Fix SRFI 124 imports for reference-barrier 2021-12-14 15:45:12 +01:00
Alex Shinn
50188a6668
Merge pull request #796 from dpk/reference-barrier
Add reference-barrier to (srfi 124)
2021-12-14 21:36:53 +09:00
Daphne Preston-Kendal
2d8ce631c7 Add reference-barrier to (srfi 124) 2021-12-14 13:04:21 +01:00
Alex Shinn
f51f61098c
Merge pull request #795 from ashinn/srfi-227
Fix SRFI 227 exports
2021-12-11 22:42:14 +09:00
Marc Nieper-Wißkirchen
232dc6ef20 Fix SRFI 227 exports 2021-12-11 14:27:20 +01:00
Daphne Preston-Kendal
a746370431 Make the string cursor able to run backwards as well as forwards 2021-12-11 11:43:23 +01:00
Daphne Preston-Kendal
4e0f10ad21 Use the cursor cache to speed up string-cursor->index as well 2021-12-11 10:44:26 +01:00
Daphne Preston-Kendal
c09897c449 Add a feature to cache the most recent string index->cursor result
This is lighter-weight than building a full index->cursor table for
the string, adding a constant two words to the memory required to
store a string, as opposed to one word for every n characters. The
cached cursor is used for any string-ref operation requesting an index
after the most-recently-requested index, making potentially quadratic
repeated string-ref procedures run in linear time. In theory, it could
also use a heuristic to speed up moving backwards through the string
when it thinks that moving the old cursor backwards would be faster
than starting again at the start of the string. In practice, my
logging of when the cached cursor is actually reused during the Chibi
compilation and startup process shows that the most common case of
moving backwards is going back to the start of the string anyway.

Benchmarks to follow.
2021-12-10 21:24:05 +01:00
Alex Shinn
3080087d8c stop after first compile error in an if (fixes #792) 2021-12-05 09:18:54 +09:00
Alex Shinn
9a17254536 guard against opcodes 2021-12-03 08:33:28 +09:00
Alex Shinn
9a48a110b8 add bounds check 2021-12-02 22:07:57 +09:00
Alex Shinn
0da288d053 implement (srfi 229) 2021-12-02 22:03:58 +09:00
Alex Shinn
71cc9b0d3c add make-procedure to (chibi ast) 2021-12-02 22:02:03 +09:00
Alex Shinn
6e636594a5 simplify opt-lambda def; copy list tail for rest arguments 2021-11-25 22:01:59 +09:00
Alex Shinn
f29af14e2e Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-11-25 00:16:56 +09:00
Alex Shinn
1eee928e67 allow non-optional bindings in let-optionals[*] 2021-11-25 00:14:15 +09:00
Alex Shinn
2820aab6e5
Merge pull request #788 from dpk/srfi-227
Add support for SRFI 227
2021-11-24 18:36:58 +09:00
Daphne Preston-Kendal
427629a43e Add support for SRFI 227 2021-11-24 10:24:21 +01:00
Alex Shinn
7a6aae39a0
Merge pull request #787 from arthurgleckler/master
Fix disconnects.  Support more MIME types.  Fix comment.
2021-11-19 16:17:30 +09:00
Arthur A. Gleckler
9b6099ca87 Support more MIME types for common file types.
In `servlet-respond', the server defaults to Content-Type "text/html;
charset=UTF-8" for extensions that don't appear in
`mime-type-from-extension'.  This meant that CSS files, JavaScript
files, and various types of image files were getting the wrong
Content-Type, which was fine when they were served directly, but
caused clients to close the connection when they were loaded over
HTTP/1.1, which can deliver back-to-back resources on the same
connection.

Sort the types in the `mime-type-from-extension' list now that it is
longer.  It's still not long enough for the order to be material for
performance.
2021-11-18 22:09:47 -08:00
Arthur A. Gleckler
153b4d894a Fix typo in comment. 2021-11-18 18:06:40 -08:00
Alex Shinn
4dde693435 http servers should ignore SIGPIPE by default 2021-11-19 10:49:04 +09:00
Alex Shinn
182048ed9a adjust for rounding up converting from fixnum to double in exact-integer-sqrt (fixes #786) 2021-11-08 09:27:50 +09:00
Alex Shinn
a92289ceb9 use return code from main in SRFI 22 usage (fixes #783) 2021-11-07 10:13:49 +09:00
Alex Shinn
7be38e044a
Merge pull request #780 from jpellegrini/srfi-144-fix
Add missing constants to SRFI-144
2021-11-07 09:56:24 +09:00
Alex Shinn
1f0f07114b fix sqrt of complex negative zero (issue #785) 2021-11-07 09:55:24 +09:00
Jeronimo Pellegrini
ce97808201 Add missing constants to SRFI-144
The following constants were missing from Chibi's SRFI-144
implementation:

 fl-1/e
 fl-e-pi/4
 fl-1/log-2
 fl-log-3
 fl-log-pi
 fl-1/log-10
 fl-2pi
 fl-pi-squared
 fl-degree
 fl-gamma-1/2
 fl-gamma-1/3
 fl-gamma-2/3
2021-09-29 00:57:31 -03:00
Lukas Böger
bf881b3e61 Explicitly add -lm and conditionally -lutil/-ldl on linux 2021-09-19 22:18:12 +09:00
Alex Shinn
9e523b6832
Merge pull request #764 from jgesswein/fix-test-runner-indentation
Fix indentation of test runner output
2021-09-06 14:11:54 +09:00
Jürgen Geßwein
e2c8619a21 Implement review comments
Add comment to procedure indent-string to indicate need for a reset for
a second report.

Correct import of (chibi optional).
2021-09-05 13:15:00 +02:00
Alex Shinn
1881116804 enforce order of let-optionals* val/rest binding in non-chibi impl (issue 778) 2021-09-02 12:58:41 +09:00
Alex Shinn
6be3784db0 nitpick (issue #778) 2021-08-30 17:27:33 +09:00
Alex Shinn
08d2847767 explicitly state that it is an error if the default values mutate the let-optionals list (issue #778) 2021-08-30 16:15:57 +09:00
Alex Shinn
22e89b168a fix array-tile 2021-08-19 19:22:29 +09:00
Alex Shinn
57e4652ea6 Assert same domains in array-for-each, as per the spec and implicitly
depended on by the implementation.
2021-08-16 20:28:03 +09:00
Alex Shinn
a14f2d179a rename bare let in case expansion (issue #772) 2021-08-14 00:03:01 +09:00
Alex Shinn
6cafda8916 Decouple syntax-case from the Chibi core.
This restores third-party (ab)users of the Chibi macro system such
as in https://gist.github.com/baguette/2632464, while allowing us
to break those uses in more interesting ways.

It also keeps the core slightly smaller (both in C and Scheme)
and speeds up the macro expansion process.
2021-08-10 23:19:35 +09:00
Alex Shinn
d10ea607e2
Merge pull request #770 from lassik/snprintf
Simplify snprintf usage
2021-08-10 14:19:23 +09:00
Lassi Kortela
3a5f884144 Simplify snprintf usage
snprintf(buf, sizeof(buf), ...) is the canonical idiom.
2021-08-07 23:17:38 +03:00
Jürgen Geßwein
e0497b3084 Implement review comments
Add some newlines and a comment to improve readability.

Use local string port instead of parameterizing current-output-port.

Pass symbol 'BEGIN to tell test reporter that evaluation of a test
starts.  Adapt documentation of current-test-reporter accordingly.

Use define-opt instead of case-lambda.
2021-08-07 21:14:11 +02:00
Alex Shinn
4907d53922 make pid_t and some other POSIX integer types signed (issue #769) 2021-08-04 16:26:11 +09:00
Alex Shinn
f1b8a5bce9
Merge pull request #768 from ashinn/syntax-rules-parser
Parse syntax-rules more strictly
2021-08-04 00:11:58 +09:00
Marc Nieper-Wißkirchen
1f9b4796d6 Parse syntax-rules more strictly
See issue #767.
2021-08-03 17:05:37 +02:00
Alex Shinn
1f508fbdb5 Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-07-28 17:04:36 +09:00
Alex Shinn
18d0adf13b signal error on improper lists passed to map/for-each 2021-07-28 17:00:40 +09:00
okuoku
5de159a72a
Merge pull request #761 from lubgr/cmake-install-target
CMake update 3/3: provide install target
2021-07-28 10:46:45 +09:00
Alex Shinn
9710962cd2 don't assume map works on improper lists in cpp-define 2021-07-28 10:35:05 +09:00
Alex Shinn
7854371728 ensure ffi assertions are a proper list 2021-07-28 10:25:18 +09:00
Alex Shinn
dd05444d91
Merge pull request #763 from lubgr/fix-unused-variable-warning
Triviality: silence an unused variable warning in compiled test
2021-07-25 22:24:24 +09:00
Jürgen Geßwein
b23db00aed Fix indentation of test runner output
Fix standard test runner so that its output is properly indented and
lines are properly terminated.

Refactor standard test runner so that it is possible to plug in another
runner with different output.
2021-07-25 13:21:34 +02:00
Lukas Böger
2e41cf06b2 don't dump images in static library configurations 2021-07-23 22:47:41 +01:00
Lukas Böger
cbf8cfb392 remove unused variable 2021-07-23 22:19:27 +01:00
Lukas Böger
b827cfb429 Build images and .meta lists with ALL target 2021-07-23 22:13:46 +01:00
Lukas Böger
fe953319ff fix dependencies of package list generation command 2021-07-22 21:08:41 +01:00
Alex Shinn
24fb7585c7 set! should guard against exceptions in the var ref lookup (fixes issue #762) 2021-07-22 21:43:50 +09:00
Lukas Böger
cba39c2ede install an EXPORT set and cooperate with find_package 2021-07-21 21:01:33 +01:00
Lukas Böger
7015657c42 add missing template/helper files for install targets 2021-07-21 21:01:33 +01:00
Lukas Böger
2508c61174 install pkgconfig file, too 2021-07-21 21:01:31 +01:00
Lukas Böger
4c1f10e79e don't manually specify default behaviour for file permissions 2021-07-21 21:00:45 +01:00
Lukas Böger
3b5f08c1da install main targets, images and meta lists 2021-07-21 21:00:45 +01:00
Lukas Böger
8eb0961b40 build images and meta package lists 2021-07-21 21:00:45 +01:00
okuoku
879c16c3d9
Merge pull request #758 from lubgr/cmake-lift-platform-restrictions
CMake update 2/3: lift platform restriction
2021-07-22 02:56:00 +09:00
Lukas Böger
527101a1c2 leave the default module path empty on windows 2021-07-21 18:32:23 +01:00
Lukas Böger
47a6e7fd3c streamline library alias name 2021-07-21 18:29:17 +01:00
Lukas Böger
32e7f0bf7e remove unnecessary left-over flags 2021-07-21 18:29:15 +01:00
Lukas Böger
5fcbb7c15c prefer consistent low caps command names 2021-07-20 22:49:30 +01:00
Lukas Böger
a4a8ba0038 remove outdated platform restriction notice 2021-07-20 22:48:37 +01:00
Lukas Böger
287014e3d6 remove exclusion of weak-test, which works on unix 2021-07-20 22:47:03 +01:00
Lukas Böger
0ae8069a07 fix repeated liblib prefix in library output name 2021-07-20 15:37:56 +01:00
Lukas Böger
699ffe18e9 mostly revert module path handling introduced in 27c421e3
chibi/install.h is included in C source files, and providing a different
install.h upon actual installation is inconsistent and dangerous. When
working with a chibi executable within the build tree (i.e., not an
installed executable), the CHIBI_MODULE_PATH environment tweak can be
used to not always specify -I paths on the command line.
2021-07-20 15:37:56 +01:00
Lukas Böger
16b97a6e26 reduce scope of clib.c within the chibi library 2021-07-20 15:37:56 +01:00
Lukas Böger
e2555e5fed fix paths of includes in clib.c
With the module search path cleverly handled with different install.h
configurations, the genstatic script inserted absolute paths into the
generated clib.c file. This didn't fail on Windows CI as this is an
in-source build. For out-of-source builds, it's crucial that clib.c can
refer to both .c files in the source directory and those generated in
the build directory. As a fix, the genstatic invocation now uses the -I
flag.

This patch also improves the handling of include paths to find the .c.
files mentioned above by trimming down the scope of this property to
clib.c only. Also, there is no need to manually tell the preprocessor
where to look for generated .c, as they live relative to clib.c anyhow.
2021-07-20 15:37:56 +01:00
Lukas Böger
7de835bad8 improve module path handling and provide basic installation 2021-07-20 15:37:56 +01:00
Lukas Böger
86c439a4bb enable more tetst on unix builds 2021-07-20 15:37:56 +01:00
Lukas Böger
fcfd518a0d leave selected zero feature macros undefined 2021-07-20 15:37:56 +01:00
Lukas Böger
9c22b7d1c2 comply with older CMake versions (dependency graph) 2021-07-20 15:37:56 +01:00
Lukas Böger
de4fa6439a use bootstrap exec only for static builds 2021-07-20 15:37:56 +01:00
Lukas Böger
f58dfdb67d shorten sanitizer configuration 2021-07-20 15:37:56 +01:00
Lukas Böger
57410deca9 fix string stream config on windows 2021-07-20 15:37:56 +01:00
Lukas Böger
15be953446 fix missing variable dereferencing syntax 2021-07-20 15:37:56 +01:00
Lukas Böger
46fbc423d3 shorten preprocessor configuration 2021-07-20 15:37:56 +01:00
Lukas Böger
9652d08ae3 reorganize linking of common configuration library 2021-07-20 15:37:56 +01:00
Lukas Böger
1b960f949f add module search path to test runs 2021-07-20 15:37:56 +01:00
Lukas Böger
d06d56154e replace custom function with target_link_libraries 2021-07-20 15:37:56 +01:00
Lukas Böger
82aa16a3f1 compile shared libraries for non-static configurations 2021-07-20 15:37:56 +01:00
Lukas Böger
17ffa4b36c use sensible default module paths for Linux/Unix 2021-07-20 15:37:56 +01:00
Lukas Böger
0bade8de2f refactor library generation from stubs 2021-07-20 15:37:56 +01:00
Lukas Böger
2efcc53098 compile shared libraries for non-static builds 2021-07-20 15:37:56 +01:00
Lukas Böger
3b33a9561a add SEXP_USE_BOEHM configuration option 2021-07-20 15:37:56 +01:00
Lukas Böger
584bfa225c mimic Makefile's option for cygwin build 2021-07-20 15:37:56 +01:00
Lukas Böger
b8a3500222 build with -Wall when using clang or gcc 2021-07-20 15:37:56 +01:00
Lukas Böger
36f7d86cad fix CMake 3.12 list(REMOVE ...) invocation 2021-07-20 15:37:56 +01:00
Lukas Böger
d7c28021c8 set default build type, add sanitizer build support 2021-07-20 15:37:56 +01:00
Lukas Böger
e9391c93fb mimic Makefile's ntp and stdint conditional compilation 2021-07-20 15:37:56 +01:00
Lukas Böger
434a36f0b9 remove error on apple/unix and set platform string 2021-07-20 15:37:56 +01:00
Alex Shinn
83aefd12d0 Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-07-19 21:49:57 +09:00
Alex Shinn
5b8e196e0f parse-seq should check for ignored value in fast paths as well (issue #757) 2021-07-19 21:49:39 +09:00
Alex Shinn
2d21500185 updating copyright year 2021-07-19 21:48:47 +09:00
Alex Shinn
31921b4553
Merge pull request #755 from lubgr/cmake-modernization
CMake update 1/3: basic modernization (preserving all current functionality)
2021-07-19 09:48:38 +09:00
Lukas Böger
92d5f8eae1 apply static flag for bootstrap exec, too
This is required for the Windows configuration to succeed at all. It
should also be beneficial when we start sharing object code between
bootstrap and actual executable.
2021-07-13 14:03:24 +01:00
Lukas Böger
0f1dfad91c eliminate last global flag, move library definition 2021-07-13 14:03:24 +01:00
Lukas Böger
b0c0afcb73 prefer configure_file over manual file(WRITE ...) 2021-07-13 14:03:24 +01:00
Lukas Böger
514d58264f Use builtin variable for shared object suffix 2021-07-13 14:03:24 +01:00
Lukas Böger
2f663dff33 fix repeated target_link_libraries on bootstrap target 2021-07-13 14:03:24 +01:00
Lukas Böger
7595ecbc09 replace more global commands by target-based ones 2021-07-13 14:03:24 +01:00
Lukas Böger
4b5ebffa5b build static libs by default on windows 2021-07-13 14:03:24 +01:00
Lukas Böger
9fab5cf4dd generate and add clibs.c only for static builds 2021-07-13 14:03:24 +01:00
Lukas Böger
5402d86323 remove trailing whitespace 2021-07-13 14:03:24 +01:00
Lukas Böger
7c46c618d0 don't build bootstrap exec by default
This doesn't necessarily have an effect though, as we need the
bootstrapping executable anyhow for building other targets.
2021-07-13 14:03:24 +01:00
Lukas Böger
f6e67edf01 export compilation database 2021-07-13 14:03:24 +01:00
Lukas Böger
4cc384ecac use VERSION file for project settings and lib output 2021-07-13 14:03:24 +01:00
Lukas Böger
b603e04d9e align library name with build artifact 2021-07-13 14:03:24 +01:00
Lukas Böger
76bce1ce1c prefer CMake's builtin BUILD_SHARED_LIBS option 2021-07-13 14:03:23 +01:00
Lukas Böger
eb6c9db857 use unversioned library basename 2021-07-13 14:03:23 +01:00
Lukas Böger
c79145b051 require CMake version >= 3.12 2021-07-13 14:03:23 +01:00
Lukas Böger
3c6ce4e23b don't ignore CMakeLists.txt 2021-07-13 14:03:23 +01:00
Alex Shinn
c05e820d71 adding contributing file 2021-06-30 18:35:24 +09:00
Alex Shinn
77365ccc6f
Merge pull request #752 from wrog/math_prime_fixes
(chibi math prime) fix miller-rabin-composite?, factor, etc (issue #751), add factor-alist
2021-06-30 18:25:30 +09:00
Roger Crew
3337049811 shorter factor (issue #751 cont.) 2021-06-30 00:29:54 -07:00
Roger Crew
2759aaa306 add factor-alist and export it (chibi math prime)
a more useful version of factor
2021-06-29 23:48:12 -07:00
Roger Crew
680aede9ae totient and aliquot rewrite + corrected tests for n=1 (issue #751 cont.) 2021-06-29 23:48:12 -07:00
Roger Crew
b89bd9f889 faster factor, (factor 1) = () (issue #751 cont.)
no need to go up to sqrt(n), Instead track i^2 and quit when that gets
larger than the (remaining) n (i.e., not the original n)
2021-06-29 23:48:12 -07:00
Roger Crew
41aa1a918e miller-rabin-composite? rewrite (issue #751)
modular-root-of-one? is replaced with the correct witness tester
2021-06-29 23:48:09 -07:00
Roger Crew
7d39108e72 factor-twos cps version using first-bit-set
first-bit-set is way faster than looping
2021-06-29 23:43:53 -07:00
Alex Shinn
73da0a88d4 scan for appropriate 2nd element to take the mean with when calling vector-find-median on an even length vector (issue #754) 2021-06-29 21:09:41 +09:00
Alex Shinn
f3bccf1f7b removing unintended export 2021-06-28 17:31:14 +09:00
Alex Shinn
378b56a0c3 adding opt-lambda* and define-opt* 2021-06-28 17:27:22 +09:00
Alex Shinn
0fbd89dd00 ignore keywords in non-keyword positions (issue #753) 2021-06-28 16:19:43 +09:00
Alex Shinn
05c546e38d match fix for (a ...) patterns where a was already bound - thanks to Andy Wingo 2021-06-21 16:44:02 +09:00
Alex Shinn
5207bdfde2 Defining list->u8vector (issue #749). 2021-06-18 13:04:20 +09:00
Alex Shinn
ead366870b
Merge pull request #747 from ilammy/sign-bit
Fix usage of signbit() in SRFI 144
2021-06-06 13:59:13 +09:00
Alexei Lozovsky
6f35aa75f4
Fix usage of signbit() in SRFI 144
C standard defines signbit() as a macro returning "non-zero value" for
negative arguments (see 7.12.3.6 of C11 standard). SRFI 144's flsign-bit
is defined to return exactly 1.

Make sure to convert the result of signbit() call into "boolean int"
which is either 0 or 1.

This is not a theoretical issue. This causes SRFI 144 test suite to fail
on many architectures that are not x86_64.

GCC on x86_64 compiles signbit() as

        movmskpd %xmm0, %eax
        andl     $1, %eax

which indeed returns either 0 or 1. movmskpd extracts 2-bit sign mask
from the FP value in src register and stores that in low-order bits of
the dst register. Then the unneded extra bit is masked out, leaving only
the lowest bit set or unset.

However, other architectures don't have such conveniences and go with
more direct approach. For example, GCC on ARMv7 produces this:

        sub     sp, sp, #8
        vstr.64 d0, [sp]
        ldr     r0, [sp, #4]
        and     r0, r0, #0x80000000
        add     sp, sp, #8
        bx      lr

which effectively returns either 0 or -1. Generated code masks out
everything but the sign bit and returns the result as is. The value
0x80000000 is the representation of -1.

Even on i386 signbit() is compiled as

        fldl    4(%esp)
        fxam
        fnstsw  %ax
        fstp    %st(0)
        andl    $512, %eax
        ret

which effectively returns either 0 or 512: fxam sets C1 bit FPU status
word to the sign of FP value, then the status word is extracted, the
"sign bit" is masked out, and left as is.
2021-06-06 13:49:44 +09:00
Alex Shinn
d9f5eaac61
Merge pull request #748 from ilammy/ffi-failures
Initialize variables in FFI tests
2021-06-06 13:43:09 +09:00
Alexei Lozovsky
cc23efac16
Initialize variables in FFI tests
These ones are used to compute averages. If they are not initialized to
zero, they might contain some garbage. In fact, they almost always do
on platforms other that x86_64, failing the FFI tests. If optimizations
are enabled, these tests usually fail on x86_64 too. The reason this
went unnoticed is contrived set of coincidences.
2021-06-06 11:19:52 +09:00
Alex Shinn
5610653c20 servlets should assume html if no Content-Type is specified 2021-05-28 12:07:23 +09:00
Alex Shinn
0388d9880c Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-05-26 10:06:00 +09:00
Alex Shinn
8247e13baf remove superfluous + when printing complex numbers with negative ratio imaginary parts 2021-05-26 10:05:40 +09:00
Alex Shinn
fa59b289a6
Merge pull request #746 from lubgr/small-doc-fix-on-static-executable
Fix documentation on building a standalone statically linked executable including compiled libs
2021-05-25 11:37:28 +09:00
Lukas Böger
6ffba28b02 use SEXP_USE_STATIC_LIBS_NO_INCLUDE for static build 2021-05-24 22:42:21 +01:00
Alex Shinn
05ca40fa51 chibi doc fixes for irregex manual 2021-05-14 13:49:07 +09:00
Alex Shinn
4a06997978 guard against failed module-ref 2021-05-13 22:10:30 +09:00
Alex Shinn
f817dbaf96 emphasize not to use emmake directly 2021-05-12 08:28:55 +09:00
Alex Shinn
05eb4ebd35 installing SRFI 179 2021-05-11 00:06:24 +09:00
Alex Shinn
f84ddfc02e bumping version 2021-05-10 23:30:26 +09:00
Alex Shinn
89a77540b4 put system module path in front of user module path 2021-05-10 23:24:18 +09:00
Alex Shinn
6c522cc04b package srfis with tests 2021-05-10 23:14:43 +09:00
Alex Shinn
037a7b24fc exporting array-coeffs 2021-05-10 22:56:36 +09:00
Alex Shinn
7b2fbb0bf2 fixing ffi doc extraction for cond-expanded procedures 2021-05-10 18:40:33 +09:00
Alex Shinn
64633d577c adding assert docs 2021-05-10 17:57:06 +09:00
Alex Shinn
3eab7bf226 package SRFI 179 2021-05-10 17:49:02 +09:00
Alex Shinn
6e5278b7a1 separating out SRFI 179 base library 2021-05-07 22:39:53 +09:00
Alex Shinn
ca47a41ccf array simplification and performance tweaks 2021-05-07 16:15:48 +09:00
Alex Shinn
12ad1d37d8 add docs and tests for assert, unify with SRFI 145 2021-05-06 20:34:03 +09:00
Alex Shinn
e3782e35a5 add note about emscripten build 2021-05-06 20:31:29 +09:00
Alex Shinn
249f4f21ba allow tracing macros 2021-05-06 10:17:03 +09:00
Alex Shinn
68a81c8aff typo for non-threads build (issue #731) 2021-05-05 21:14:22 +09:00
Alex Shinn
1db8a573f1 more extensive list of constructs not to descend into 2021-05-05 08:08:12 +09:00
Alex Shinn
9a9f974d69 assert improvements: dedup vars, ignore lambdas, allow report: 2021-05-05 07:56:14 +09:00
Alex Shinn
d5a0f0ddfa
Merge pull request #744 from pclouds/emscripten-shared-flag
Fix emscripten build
2021-05-05 07:14:35 +09:00
Nguyễn Thái Ngọc Duy
12fa4ae601 Fix emscripten build
It looks like the original -shared is ignored for some reason, so emcc
produces the final .wasm and .js code, the latter is named
chibi-scheme-static.bc, which cannot be linked to create
chibi.js. Moving -shared to STATICFLAGS seems to fix that.

I'm new to emscripten so don't trust me too much on this. But I tested
chibi.js and things still seem to work fine.
2021-05-04 18:53:53 +07:00
Alex Shinn
91f26c5313
Merge pull request #743 from pclouds/chibi-b-opt
chibi-scheme.1: document -b
2021-05-04 20:41:40 +09:00
Nguyễn Thái Ngọc Duy
27adc08ba6 chibi-scheme.1: document -b
It's added in fad9e4ca (don't make stdio nonblocking by default, allow
override with -b, 2017-05-07)
2021-05-04 18:06:06 +07:00
Alex Shinn
4df0513d6e
Merge pull request #741 from phillbush/master
Fix typo in comment.
2021-05-03 22:54:47 +09:00
phillbush
681f781208 it's /usr/bin/env 2021-05-02 21:52:21 -03:00
Alex Shinn
e3083062fa Flattening indexing further.
We can pre-subtract each coeff times its lower bound from the
base coefficient in SRFI 179 indexers.
2021-04-30 14:25:39 +09:00
Alex Shinn
d11106b2f7 Fix upper bounds checks in u64vectors. 2021-04-30 14:02:29 +09:00
Alex Shinn
3c138dc808 Fix validation on specialized-array-reshape. 2021-04-30 13:38:53 +09:00
Alex Shinn
76284f79f0 flattening array indexers 2021-04-28 22:53:16 +09:00
Alex Shinn
bf03c1cfa1 restore sexp_make_ephemeron even when not unifying filenos 2021-04-27 19:11:36 +09:00
Alex Shinn
4d22949f71 disable fileno unification by default 2021-04-27 18:30:43 +09:00
Alex Shinn
8fcd4d1f88 remove spurious debug code 2021-04-27 15:50:22 +09:00
Alex Shinn
3cf62f033a store stack traces directly in top-level exceptions to more consistently be able to report them from C 2021-04-26 21:40:39 +09:00
Alex Shinn
ef9daf22c8 handle include-shared in analyze-module 2021-04-26 14:27:11 +09:00
Alex Shinn
42aab7905c enable SEXP_USE_STRICT_TOPLEVEL_BINDINGS by default (issue #699) 2021-04-19 10:46:26 +09:00
Alex Shinn
8b3f5512e1 Merge branch 'master' of github.com:ashinn/chibi-scheme 2021-04-19 10:22:08 +09:00
Alex Shinn
d53bf51fc9 don't assume EOF < 0x80 (issue #731) 2021-04-19 10:22:00 +09:00
Alex Shinn
cd5bf03537
Merge pull request #740 from lassik/219
Add SRFI 219: Define higher-order lambda
2021-04-18 18:58:39 +09:00
Lassi Kortela
7178d22928 Add SRFI 219: Define higher-order lambda 2021-04-18 12:21:32 +03:00
Alex Shinn
ade90906f9 only reify a fileno from an integer if the fileno is still open 2021-04-18 07:01:10 +09:00
Alex Shinn
d0510bebe6 simplify array-reduce 2021-04-16 23:35:16 +09:00
Alex Shinn
c8f5f49890 add initial SRFI 179 implementation 2021-04-16 19:53:51 +09:00
Alex Shinn
487ea21d77 check value domains on uvector-set! ops 2021-04-16 10:13:37 +09:00
Alex Shinn
d64f159608 fix docs on test-group 2021-04-16 10:10:18 +09:00
Alex Shinn
af43c3214f add sexp_user_exception_ls variadic convenience 2021-04-16 10:06:03 +09:00
Alex Shinn
fc6e5da915 make-u1vector takes an optional fill 2021-04-15 17:02:44 +09:00
Alex Shinn
e74614d4b3 removing redundant uvector definitions 2021-04-14 17:06:34 +09:00
Alex Shinn
cfbd64f085 fixing bug in prime-above 2021-04-14 16:47:29 +09:00
Alex Shinn
3fc9c22245 fix regression from shadowed bindings in process->output+error+status 2021-04-09 23:09:53 +09:00
Alex Shinn
4bd4f08b59 fix longstanding todo and get signature from analyzed procedure forms 2021-04-08 23:00:12 +09:00
Alex Shinn
8c45c3fb19 better text display 2021-04-08 22:59:34 +09:00
Alex Shinn
e3078a7c4c start lambda source info at bytecode pos -1 2021-04-08 22:59:18 +09:00
Alex Shinn
d69ffce3f2 sexp_bytecode_source should always be taken from the lambda
This is taken from the read source of the lambda form itself.
Previously it was getting the source of the expanded first expression,
which more often than not was the let definition in init-7.scm
2021-04-08 10:09:58 +09:00
Alex Shinn
f7b546769c update logging tests for fixes in string-split 2021-04-08 10:08:19 +09:00
Alex Shinn
8b27ce9726 add proper grammar support to srfi 130 string-split 2021-04-02 13:51:02 +09:00
Alex Shinn
d80589144d close stdout/err in process->foo utilities
Relying on gc can accumulate many open fd's,
which is bad for code outside of chibi.
2021-03-31 09:23:21 +09:00
Alex Shinn
7ea15f3810 check for wrapping to negative in hash lookup of cell (issue #735)
Without this chibi can crash after 129 open file descriptors.

Note the bug referenced would also indirectly be fixed if
process->string-list properly closed its ports, but we
shouldn't rely on that.
2021-03-31 06:43:27 +09:00
Alex Shinn
13a2a562d9 forgot to specify literals 2021-03-28 23:43:49 +09:00
Alex Shinn
26d3a010df adding assert macro 2021-03-26 23:12:37 +09:00
Alex Shinn
adec61993b adding domain checks on uvector accessors 2021-03-26 17:34:25 +09:00
Alex Shinn
70af1d6394 Friendlier error for bad trace command (issue #733). 2021-03-23 12:13:09 +09:00
Alex Shinn
969f24db96
Merge pull request #722 from flynn162/patch-1
Typo in the documentation
2021-03-04 19:31:09 +09:00
Alex Shinn
2d562bdae1
Merge pull request #730 from smazga/plan9
make 9front "work" again by properly handling 64-bit typedefs
2021-02-21 10:10:46 +09:00
McKay Marston
683554c2ab make 9front "work" again by properly handling 64-bit typedefs 2021-02-20 17:10:43 -07:00
Alex Shinn
de02feb8ff
Merge pull request #729 from lassik/srfi-193
Add SRFI 193 Scheme library
2021-02-05 21:36:20 +09:00
Lassi Kortela
fa52b4987a Add SRFI 193 Scheme library
This was accidentally left out of the previous commit.
2021-02-05 14:08:31 +02:00
Alex Shinn
08a7ec736c
Merge pull request #728 from lassik/command-lines
Re-implement SRFI 193 (Command line)
2021-02-04 23:00:31 +09:00
Lassi Kortela
ac698ce6ae Re-implement SRFI 193 (Command line) 2021-02-01 21:29:26 +02:00
Alex Shinn
19228cbfb8 cleaning up more dirs on uninstall (issue #725) 2021-01-25 11:07:48 +09:00
Alex Shinn
b2bd44eaf0
Merge pull request #724 from ashinn/revert-619-command-lines
Revert "Implement SRFI 193: Command lines"
2021-01-24 19:58:13 +09:00
Alex Shinn
9f0ed1a869
Revert "Implement SRFI 193: Command lines" 2021-01-24 19:57:55 +09:00
Alex Shinn
751675c6b2
Merge pull request #619 from lassik/command-lines
Implement SRFI 193: Command lines
2021-01-24 16:44:35 +09:00
Alex Shinn
e53d79adfd
Merge pull request #723 from lassik/typo
Fix typo
2021-01-18 09:44:53 +09:00
Lassi Kortela
0be78ed7e6 Fix typo 2021-01-17 14:10:41 +02:00
Flynn Liu
0ccfb57833
Typo in the documentation 2021-01-10 14:13:01 -08:00
Alex Shinn
1828ef068e fix env size (issue #453) 2020-12-28 12:07:54 +09:00
Alex Shinn
b4dd757e3f more consistently setting renames (issue #453) 2020-12-28 11:55:10 +09:00
Alex Shinn
4edf3344f8
Merge pull request #721 from ilammy/aliasing-issues
Fix unaligned access in bytevector-{u,s}{16,32,64}-{ref,set!}
2020-11-30 20:11:54 +09:00
Alexei Lozovsky
266a188ce2
More tests for unaligned bytevector access
Make sure that we don't miss anything and cover the rest of bytevector
accessors with tests for unaligned memory access. Include both integers
and floats, in little and big endian flavors.
2020-11-30 17:15:57 +09:00
Alexei Lozovsky
af60b8d937
Fix unaligned access in bytevector-{u,s}{16,32,64}-{ref,set!}
Native code implementing bytevector accessors uses the following access
pattern:

    *(intNN_t*)(base+offset)

This can result in so called "unaligned memory access" if the offset is
not a multiple of 2, 4, 8, or if the base address has not been allocated
at an aligned address (unlikely).

Most popular modern architectures--x86 and ARMs--allow unaligned memory
accesses on the instruction level but they are typically performed a bit
slower than properly aligned accesses.

On the other hand, there are architectures which do not allow unaligned
memory accesses. Each load or store of a value longer than 1 byte should
use properly aligned address on those architectures. That is, u16 should
be loaded from even addresses, s32 should only be stored at an address
which is a multiple of 4, and f64 (aka double) can be located only at
addresses which are multiple of 8. If the address is not aligned, CPU
raises an exception which typically results in the process being killed
by the operating system with a SIGBUS signal.

SPARC is one of those architectures which are strict with alignment. The
current access pattern in bytevector native code can result in unaligned
accesses, which in turn results in crashes. This issue has been found in
this way: Chibi test suite includes some tests for unaligned accesses
and it failed on SPARC.

In order to avoid unaligned accesses, loads and stores need to be
performed a bit differently, doing 'type punning' in a safe way, not
just casting pointers which breaks strict aliasing rules.

The most portable and efficient way to do this is to use memcpy().
Compilers know about this trick and generate very efficient code here,
avoiding the function call and using the most efficient instructions.
(Obviously, only when optimizations are enabled.)

That is, given

    static inline uint32_t ref_u32(const void* p) {
      uint32_t v;
      memcpy(&v, p, sizeof(v));
      return v;
    }

on x86 this will be compiled into a single "movl" instruction because
x86 allows unaligned accesses, similar with ARM where this becomes
a single "ldr" instruction. However, on RISC-V--another platform with
strict alignment rules--this code compiles into 4 "lbu" instructions
fetching 4 bytes, then some more arithmetic to stitch those bytes into
a single 32-bit value.
2020-11-30 16:46:44 +09:00
Alex Shinn
3f228ce731
Merge pull request #716 from amirouche/fix/emscripten-build
Makefile: js: fix build for emscripten 2.0.8.
2020-11-30 13:51:43 +09:00
Alex Shinn
a3afe4e804 don't change dir when generating images (issue #707) 2020-11-25 23:26:18 +09:00
Alex Shinn
56a31f9cb0 don't declare image loading operations if not enabled (issue #714) 2020-11-25 23:16:12 +09:00
Alex Shinn
f9c00e0c21
Merge pull request #713 from mnieper/and-let
Fix and-let* so that it allows bodies according to SRFI 2.
2020-11-25 14:40:16 +09:00
Alex Shinn
0597ea68a5
save a char and a beta reduction 2020-11-25 14:39:49 +09:00
Alex Shinn
54f55569e2 document sexp_lookup_type (issue #718) 2020-11-25 14:36:54 +09:00
Alex Shinn
79e76b295f Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-11-19 13:14:17 +09:00
Alex Shinn
181b7fe7e4 preserve exactness in sqrt of ratios where possible 2020-11-19 13:13:37 +09:00
Alex Shinn
841a8a3167
Merge pull request #717 from bjoli/patch-1
Fix bug in accumulating in (chibi loop)
2020-11-04 21:12:42 +09:00
Linus Björnstam
c896bf90c5
Fix bug in accumulating in (chibi loop)
Accumulating has a bug that makes only lists supported, due to it ignoring the init value and always use the empty list. This fixes that.
2020-11-04 11:56:41 +01:00
Amirouche
f13c826da0 Makefile: js: fix build for emscripten 2.0.8.
$ emcc --version
emcc (Emscripten gcc/clang-like replacement) 2.0.8 (d059fd603d0b45b584f634dc2365bc9e9a6ec1dd)
2020-11-02 11:20:35 +01:00
Marc Nieper-Wißkirchen
306dbd470a Fix and-let* so that it allows bodies according to SRFI 2. 2020-10-22 15:13:04 +02:00
Alex Shinn
12636f4b19
Merge pull request #711 from woodfinisc/patch-1
Fix a typo in README.md
2020-10-17 06:57:39 +09:00
Alex Shinn
b6186d1272
Merge pull request #710 from gahr/freebsd-versioned-so
Produce a versioned so on FreeBSD
2020-10-17 06:41:17 +09:00
Tom Woodfin
0f5f9e3117
Fix a typo in README.md
seemless => seamless
2020-10-16 15:09:29 -04:00
Pietro Cerutti
f48312fad3 Produce a versioned so on FreeBSD 2020-10-16 13:10:58 +00:00
Alex Shinn
30b575debe
Merge pull request #709 from gahr/doc-depends-on-so
Building docs depends on having the shared libraries available
2020-10-14 22:10:09 +09:00
Pietro Cerutti
f85c1a3545 Building docs depends on having the shared libraries available
This unbreaks compiling with multiple make jobs.
2020-10-14 10:06:56 +00:00
Alex Shinn
568206041a Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-10-11 21:31:57 +09:00
Alex Shinn
4e1ff91cbb patch for plan9 build from raingloom 2020-10-11 21:31:42 +09:00
Alex Shinn
3334957956
Merge pull request #708 from pclouds/document-getenv
chibi-scheme.1: document CHIBI_IGNORE_SYSTEM_PATH
2020-10-02 23:00:34 +09:00
Nguyễn Thái Ngọc Duy
78e381ae7d chibi-scheme.1: document CHIBI_IGNORE_SYSTEM_PATH
while at there, spell out the empty CHIBI_MODULE_PATH case. It's obvious
if you really think about it, but it's even better if I don't have to
read between the lines.

I did grep getenv to find if anything was missing. There is
CHIBI_MAX_ALLOC, but I think that one is more about debugging
out-of-memory than to be customized by the user.
2020-09-30 16:15:54 +07:00
Alex Shinn
77aab98784 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-09-22 17:37:33 +09:00
Alex Shinn
4ef6c57d3e propagating #i prefix across radix prefixes (issue #706) 2020-09-22 17:37:22 +09:00
Alex Shinn
7448c22466
Merge pull request #705 from laserswald/fix-arithmetic-exception-filenos
Prevent arithmetic exception when spawning lots of commands
2020-09-19 13:20:39 +09:00
Ben Davenport-Ray
9278222396 Prevent crashing from arithmetic exception when spawning lots of commands
This fix is rather dumb, but it prevents things from crashing when
forking a lot and creating file handles. I assume that this is where
the filehandles go, but I don't have a good guess.
2020-09-18 17:08:25 -04:00
Alex Shinn
993a6469fe fix a ... match pattern when a is already bound 2020-09-06 22:59:42 +09:00
Alex Shinn
9c6020e22d
Merge pull request #702 from pclouds/snow-confirm-before-upload
snow: confirm before uploading packages
2020-09-05 13:21:34 +09:00
Nguyễn Thái Ngọc Duy
f4008c92cf snow: add TODO regarding summary before upload 2020-09-05 09:31:29 +07:00
Nguyễn Thái Ngọc Duy
711c89cd97 snow: confirm before uploading packages
Uploading a package is an irreversible operation. It's not even about
accidentally leaking your secret sauce to the internet. You could upload
a package to snow-fort.org by accident and pullute the package name
space [1].

So let's ask the user first before going ahead uploading stuff. We only
ask once even if we're going to upload a dozen packages, so it's not
that annoying. The target repo is also shown in case you want to upload
to a custom repo and want to make sure it does so.

[1] I did (while attempting to uploading to a local snow-fort instance
    during testing). I guess `(chibi snow commands)` is forever mine
    now.
2020-09-04 19:25:29 +07:00
Alex Shinn
645bf03749 change match names to SRFI 204 2020-09-04 18:33:25 +09:00
Alex Shinn
c82baa3aa9 ignore snow package meta files whose installed files have been removed 2020-09-04 14:04:53 +09:00
Alex Shinn
64ff69e99b include chibi.repl in images 2020-09-03 21:51:04 +09:00
Alex Shinn
d0bd93822e specify encoding meta for docs, include doctype 2020-09-02 15:52:20 +09:00
Alex Shinn
8597c3eda5 better error handling in http-server request parsing 2020-09-02 11:53:49 +09:00
Alex Shinn
24d1f6a8a5 fix not+and combo (issue #701) 2020-09-02 10:01:28 +09:00
Alex Shinn
24b1e5024c
Merge pull request #700 from pclouds/tests-without-chibi-test
make optional-test and diff-test run without (chibi test)
2020-09-01 23:00:19 +09:00
Nguyễn Thái Ngọc Duy
65a1eba878 make optional-test and diff-test run without (chibi test)
Tested with gauche. It's mostly about not importing (chibi test)
unconditionally, and importing (scheme write). And in one case I need to
exclude some tests because gauche catches invalid call forms at compile
time. I'm not sure if that can be caught...
2020-09-01 20:55:03 +07:00
Alex Shinn
e5cf364360 forgot to wrap inline cond-expand defs in begin 2020-09-01 22:27:59 +09:00
Alex Shinn
e7e034dea0 fix previous fix, fk needs to be made cheap, not sk (issue #698) 2020-09-01 17:01:27 +09:00
Alex Shinn
717aeb9e8b fix combinatorial explosion in match-not (issue #698) 2020-09-01 16:38:42 +09:00
Alex Shinn
29df4211ee fix circular expansion (issue #697) 2020-09-01 16:25:00 +09:00
Alex Shinn
9433b8b912 doc style tweaks 2020-09-01 10:59:44 +09:00
Alex Shinn
f6bd8b6266 fix inlined (chibi test) lite 2020-09-01 10:59:25 +09:00
Alex Shinn
217baeeb57 avoid cyclic test deps in snow 2020-08-31 21:52:01 +09:00
Alex Shinn
c0f632504b
Merge pull request #696 from pclouds/snow2-documents
Snow documentation improvements
2020-08-31 21:44:25 +09:00
Nguyễn Thái Ngọc Duy
5833240e34 Snow documentation improvements
This clarifies a bit about some commands, or a few interesting command
line options from my experience with chibi-snow (which is to use it for
another scheme implementation, or separate host from snow-fort.org; but
the latter is mostly for testing)
2020-08-31 18:32:19 +07:00
Alex Shinn
1d21a90275 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-08-31 17:28:43 +09:00
Alex Shinn
6c8bf386ec fixing multi-level menu nesting plus some doc css tweaks 2020-08-31 17:28:12 +09:00
Alex Shinn
8c9a40a7e4
Merge pull request #694 from lubgr/small-doc-fixes
Small documentation fixes
2020-08-31 08:36:53 +09:00
Lukas Böger
922b73b024 Sync documented \var and actual parameter name
The procedure parameter name could equally well be changed from `id` to
`proc`. Not sure which approach is more suitable - here, I chose to
stick to the original procedure signature.
2020-08-30 11:23:17 +01:00
Lukas Böger
2dcf2f0584 Fix broken link to SRFI 188 2020-08-30 11:22:46 +01:00
Lukas Böger
a3a0e67365 Add (chibi optional) to listed library docs 2020-08-30 11:21:40 +01:00
Marc Nieper-Wißkirchen
251464eade Translate assume to a noop when assumptions are disabled 2020-08-29 11:11:46 +02:00
Marc Nieper-Wißkirchen
043e4c2214 Fix generator-find 2020-08-29 10:25:23 +02:00
Alex Shinn
41ba06aa5a
Merge pull request #691 from pclouds/snow-impl-features
snow: extract feature list for cond-expand
2020-08-28 22:48:14 +09:00
Alex Shinn
1413cd1630
Merge pull request #692 from barak/master
typo: s/searchs/searches/
2020-08-28 22:46:52 +09:00
Barak A. Pearlmutter
d7a06322ec typo: s/searchs/searches/ 2020-08-28 12:52:46 +01:00
Nguyễn Thái Ngọc Duy
b52b2024f8 snow: extract feature list for cond-expand
Currently a package's cond-expand contains the symbol of the target
implementation and optionally more from config file. Execute a
command (once) on target implementation to add their full feature list,
making it available for each package to use.

All of these Schemes are tested. Larceny is just too annoying to get the
feature list (no one-liner, and it could take a while) so Larceny stays
the current behavior.

There is a small unrelated change here: the gosh command to get
version. We don't need to call (exit), if stdin is closed properly (it
should) then gosh should exit regardless.
2020-08-28 16:30:00 +07:00
Alex Shinn
a7a115323c s/dist-clean/dist-clean/ 2020-08-28 11:40:52 +09:00
Alex Shinn
b4d2370713 allow either prefix or PREFIX 2020-08-28 09:58:08 +09:00
Alex Shinn
f343708f1f use gnu coding standard make path var names 2020-08-27 22:56:57 +09:00
Alex Shinn
8a6af941ad enforce bound-identifier=? for match rewrite 2020-08-27 17:06:51 +09:00
Alex Shinn
9793fa0edf inc fileno count on sexp_make_input_port (issue #690) 2020-08-27 10:23:56 +09:00
Alex Shinn
5860a65368 track head ids in ellipsis tail 2020-08-26 17:24:38 +09:00
Alex Shinn
dda71763a5 fixing or patterns with different ids in branches 2020-08-26 16:07:52 +09:00
Alex Shinn
11852c6390 don't rewrite quote 2020-08-25 16:09:38 +09:00
Alex Shinn
9d65c61350 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-08-25 15:22:45 +09:00
Alex Shinn
0a503dc3ad use curl for GET as well as POST in snow (i(issue #549) 2020-08-25 15:21:25 +09:00
Alex Shinn
5d6efedc5f
Merge pull request #689 from pclouds/snow-gauche-version-comparison
snow: accept "_" as version separator
2020-08-25 14:28:56 +09:00
Alex Shinn
74cb05aed6
Merge pull request #688 from krzygorz/colors-fix
(srfi 166 color) fix
2020-08-25 14:28:11 +09:00
Alex Shinn
60c4007e6f adding thread-interrupt! so that (chibi repl) can preserve continuations (issue #686) 2020-08-25 14:09:29 +09:00
krzygorz
9067c8b5d5 text attribute resetting fix 2020-08-24 13:52:29 +02:00
Nguyễn Thái Ngọc Duy
0eb0834bbc snow: accept "_" as version separator
$ tools/snow-chibi  implementations
    WARNING: Implementation gauche is an unsupported version,
    0.9.10_pre1, but at least 0.9.4 is required.
    cyclone
    sagittarius

The easy solution is also accept "_" as version separator and consider
"pre1" the forth component. This makes the warning go away, and I don't
think it'll affect version comparison on other schemes.
2020-08-24 18:36:31 +07:00
Alex Shinn
e307c872bf fix include-ci (issue #687) 2020-08-23 00:23:27 +09:00
Alex Shinn
b89db31e37 typo in env-exports (issue #685) 2020-08-22 16:27:20 +09:00
Alex Shinn
006f22ccd7 fixing match-letrec with unhygienic insertion (issue #574) 2020-08-21 10:18:16 +09:00
Alex Shinn
0f6e0f56e0 assume polar tail for inexact complex following / (issue #333) 2020-08-20 10:30:23 +09:00
Alex Shinn
287753f2e3 fix inexact polar notation (issue #333) 2020-08-20 09:54:09 +09:00
Alex Shinn
d75ae9304f forgot to export make-state-variable from composite library 2020-08-17 22:02:15 +09:00
Alex Shinn
6be0e8d059 exporting make-state-variable in SRFI 166 (issue #683) 2020-08-17 21:56:57 +09:00
Alex Shinn
421e357e98 no -lutil for emscripten (issue #681) 2020-08-17 10:07:52 +09:00
Alex Shinn
5ee7ad0230 allow start/end args to uvector->vector conversions (issue #682) 2020-08-16 08:06:22 +09:00
Alex Shinn
d41fac4f73 adding (auto) library for auxiliary syntax 2020-08-14 11:24:25 +09:00
Alex Shinn
440b30cf0b 0.9.1 minor release 2020-08-13 11:03:03 +09:00
Alex Shinn
177a4d22f5
Merge pull request #680 from arvyy/master
add fl-epsilon to srfi 144
2020-08-12 12:04:51 +09:00
Arvydas Silanskas
cf40f1aca1 add fl-epsilon to srfi 144 2020-08-11 21:26:42 +03:00
Alex Shinn
31c2adf8bf hash raw bytes of bignums 2020-08-11 11:12:04 +09:00
Alex Shinn
dc524feabc add missing trailing ? on SRFI 144 inequality ops 2020-08-11 10:37:23 +09:00
Alex Shinn
5616d2fb87 adding uvector-segment test 2020-08-11 10:36:52 +09:00
Alex Shinn
a8e35f90fa s/max/max in vector-segment (issue #677) 2020-08-08 16:20:01 +09:00
Alex Shinn
ffeb960997 fixing uvector-reverse-copy (issue #676); ungeneralize unfold to take exactly one seed 2020-08-08 16:14:57 +09:00
Alex Shinn
90f0425c37 fixing distribution of random bignums, adding uniformity tests on the results (issue #675) 2020-08-07 12:40:07 +09:00
Alex Shinn
449312d3bd restoring hashing of trailing data for uvectors 2020-08-04 18:31:20 +09:00
Alex Shinn
b4520b31f5 hash should not take into account non-sexp trailing data (bug report from Arthur Gleckler) 2020-08-04 12:23:22 +09:00
Lassi Kortela
65b197f7de Implement SRFI 193: Command lines 2020-08-03 13:24:18 +03:00
Arthur A. Gleckler
2e63c53a6b Fix: Install "base.scm", too. 2020-08-02 11:25:55 +09:00
Arthur A. Gleckler
de622eb37e Fix typo. 2020-08-02 11:24:41 +09:00
Alex Shinn
772542694b missing argument in snow package-spec+files 2020-08-01 00:00:38 +09:00
Alex Shinn
1ac1c68047 fixing bytecode accessors 2020-07-31 23:12:59 +09:00
Alex Shinn
54fece36a8 0.9.0 release 2020-07-31 15:47:27 +09:00
Alex Shinn
4335d238fb image options are harmless in non-image build; images not supported on 32-bit arch 2020-07-31 15:32:59 +09:00
Alex Shinn
306cc73bd6 Revert "image options are harmless in non-image build; images not supported on 32-bit arch"
This reverts commit 9b859eda36.
2020-07-31 15:32:18 +09:00
Alex Shinn
9b859eda36 image options are harmless in non-image build; images not supported on 32-bit arch 2020-07-31 15:31:43 +09:00
Alex Shinn
7362578878 attributing lgamma_r 2020-07-31 15:24:24 +09:00
Alex Shinn
5d2a9bcc3d SRFI 160 vector= differs from SRFI 133 in not taking an eq predicate (issue #674) 2020-07-31 15:09:46 +09:00
Alex Shinn
b7ffc4e700 Revert "SRFI 160 vector= differs from SRFI 133 in not taking an eq predicate (issue #674)"
This reverts commit 340c5aa2a8.
2020-07-31 15:08:59 +09:00
Alex Shinn
340c5aa2a8 SRFI 160 vector= differs from SRFI 133 in not taking an eq predicate (issue #674) 2020-07-31 15:00:03 +09:00
Alex Shinn
a559aec9bc pass '() as user exception irritants, not NULL 2020-07-30 18:11:57 +09:00
Alex Shinn
60ee6d70d0 move remaining fields to start of types 2020-07-30 00:19:21 +09:00
Alex Shinn
b60a6a2417 refer to formal srfi docs for srfi packages 2020-07-29 15:48:22 +09:00
Alex Shinn
36f188d274 adding notes about benchmarks for string-ref approaches 2020-07-29 12:28:40 +09:00
Alex Shinn
c726273c3b fixing distribution of random bignums 2020-07-29 12:15:20 +09:00
Alex Shinn
67dcd04d03 speedup snow search 2020-07-29 11:01:56 +09:00
Alex Shinn
a3d0d7a49c fixing pre-commit hook when no c or scheme files are changed 2020-07-29 10:29:24 +09:00
Alex Shinn
e70ebc4f35 forgot to install the shared lib for (scheme bytevector) (issue #673) 2020-07-29 10:27:54 +09:00
Alex Shinn
82acca4772 remove more tabs 2020-07-28 20:10:31 +09:00
Alex Shinn
d22959a40e fix pre-commit diff reference 2020-07-28 20:03:36 +09:00
Alex Shinn
ed4ecd4dca switching to pre-commit hook 2020-07-28 17:23:53 +09:00
Alex Shinn
24c40099f0 adding githooks 2020-07-28 15:59:24 +09:00
Alex Shinn
648f615b77 tabs in srfi 146 2020-07-28 15:29:49 +09:00
Alex Shinn
d593a5cb0a death to tabs 2020-07-28 15:26:42 +09:00
Alex Shinn
113560aeb7 avoid // comments 2020-07-28 15:13:38 +09:00
Alex Shinn
23e62275df fixing scheme bytevector for 32bit arch 2020-07-28 15:09:40 +09:00
Alex Shinn
edcddd7299 fixing 64-bit uvectors 2020-07-27 16:08:24 +09:00
Alex Shinn
99a863c723 forgot to add file 2020-07-26 23:23:19 +09:00
Alex Shinn
54c4b37f0e adding make-json-reader 2020-07-26 23:15:53 +09:00
Alex Shinn
e6229a7f65 fix cc warning on 32-bit arch 2020-07-24 16:19:24 +09:00
Alex Shinn
992544d051 filter history duplicates 2020-07-24 15:59:30 +09:00
Alex Shinn
0f5f552b6d adding ffi unit tests for arrays of pointers 2020-07-24 15:51:12 +09:00
Alex Shinn
ea370db4b4 fixing some cc warnings 2020-07-24 15:35:31 +09:00
Alex Shinn
0b9332ba77 suggesting closest misspelled options (issue #588) 2020-07-24 14:25:15 +09:00
Alex Shinn
8d85bfc5d2 improving docs 2020-07-24 12:53:29 +09:00
Alex Shinn
cb3734c2d1 adding some highlight keywords 2020-07-23 18:26:15 +09:00
Alex Shinn
8540155875 Fixing and documenting test filtering logic.
Use strikethrough for skipped tests.
Assume verbose testing if no group present for easier repl usage.
2020-07-23 17:51:07 +09:00
Alex Shinn
5a54ecce1d adding italic and strikethrough ansi escapes 2020-07-23 17:50:26 +09:00
Alex Shinn
9fd9b88660 documenting (chibi diff) 2020-07-23 17:50:00 +09:00
Alex Shinn
c23bfbc2f6 including example output in (chibi doc), translate ansi escape 2020-07-23 17:47:04 +09:00
Alex Shinn
5fe3ad766f avoid duplicate libraries 2020-07-21 15:48:35 +09:00
Alex Shinn
97ea47686e implementing substring/preserve 2020-07-21 14:05:30 +09:00
Alex Shinn
bde8a618ec comments from adam nelson: fixing numeric/comma arg, wrapped doesn't append final newline 2020-07-20 17:41:34 +09:00
Alex Shinn
58f6509c6f adding some substring-terminal-width tests 2020-07-20 17:16:58 +09:00
Alex Shinn
bcbed04b3b fixing pretty-printed circular lists 2020-07-20 16:38:48 +09:00
Alex Shinn
7366a13413 adding content-type output for http server files 2020-07-17 14:42:28 +09:00
Alex Shinn
983829cab1 better inexact computation for ratios which overflow double (issue #671) 2020-07-15 16:38:56 +09:00
Alex Shinn
9104fcc44e print skipped tests in verbose mode 2020-07-15 16:33:52 +09:00
Alex Shinn
fc33d6ffa3 implementing basic colors for pretty-with-colors 2020-07-14 23:58:27 +09:00
Alex Shinn
3700cfaf91 forgot extern (issue #669) 2020-07-14 20:32:30 +09:00
Alex Shinn
b9a76ad9d8 late cpp definitions should use XCPPFLAGS, not CPPFLAGS (issue #670) 2020-07-14 10:12:07 +09:00
Alex Shinn
e300659662 don't export sexp_primitive_opcodes (issue #669) 2020-07-14 10:08:21 +09:00
Alex Shinn
b4fb077fef random_r doesn't necessarily provide enough bits even for a fixnum (issue #668) 2020-07-13 10:27:04 +09:00
Alex Shinn
9940e0d053 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-07-13 10:02:11 +09:00
Alex Shinn
5d9a53f6e3 adding tmux-256color to list of terms supporting color 2020-07-13 10:02:00 +09:00
Alex Shinn
8020d3e97e
Merge pull request #667 from katterjohn/fix-nan-comparisons
Fix some NaN comparisons: NaNs are not less than every fixnum
2020-07-11 11:53:34 +09:00
Alex Shinn
d4944a75d6 fix typo reported by Arthur Gleckler 2020-07-11 06:41:14 +09:00
Kris Katterjohn
eb9d632dbf Fix some NaN comparisons: NaNs are not less than every fixnum
(< +nan.0 n) was yielding #t for fixnum n, and similarly for
(<= +nan.0 n) and (> n +nan.0) and so on.  This also caused
(negative? +nan.0) to return #t.

It just happened that NaNs were less than all fixnums: if a
conditional was written the other way around then NaNs would
have been greater than all fixnums instead.

The flonum case was sort of "accidentally" correct, but if a
conditional was written the other way around then NaNs would
be both less than or equal to and greater than all or equal
to all flonums (but still not equal).

For both cases check for NaNs after getting the flonum values.
2020-07-10 16:49:56 -04:00
Alex Shinn
f6eeb1c9f6
Merge pull request #666 from katterjohn/delay-wna
Check the number of args to delay and delay-force
2020-07-09 09:53:09 +09:00
Kris Katterjohn
948252517f Check the number of args to delay and delay-force 2020-07-08 19:15:06 -04:00
Alex Shinn
6fabc92b3d
Merge pull request #665 from katterjohn/chown
(chibi filesystem): add chown
2020-07-09 07:06:44 +09:00
Kris Katterjohn
f4526f7fc8 (chibi filesystem): conditionalize chown to fix Windows build 2020-07-08 15:36:21 -04:00
Kris Katterjohn
8ae99cff92 (chibi filesystem): add chown 2020-07-08 15:12:14 -04:00
Alex Shinn
e31e5ffbf3 updating (chibi json) to work on ports 2020-07-08 17:27:05 +09:00
Alex Shinn
2bdaebe8c7 wrap uncaught non-exceptions (issue #664) 2020-07-06 16:20:40 +09:00
Alex Shinn
f2d38e36c7 fixing (srfi 159) after refactoring 2020-07-06 15:09:49 +09:00
Alex Shinn
a6e8e9d7ba env vars are identifiers, not symbols; fix evaluation time (issue #516) 2020-07-06 15:00:27 +09:00
Alex Shinn
47b0a19733 adding point to headers for C API docs 2020-07-06 14:41:50 +09:00
Alex Shinn
72668b6d26 fixing ,@ patterns 2020-07-06 14:24:22 +09:00
Alex Shinn
cb5f523532 adding ..= and ..* patterns to match (issue #535) 2020-07-06 13:42:34 +09:00
Alex Shinn
da5827d889 generate SRFI 166 snowball 2020-07-06 10:55:49 +09:00
Alex Shinn
a9faa6cc7b removing debugging (scheme write) import 2020-07-03 14:51:54 +09:00
Alex Shinn
36c3471fa7 adding substring/width 2020-07-03 14:45:36 +09:00
Alex Shinn
39344bcaa0 adding background colors, as-italic 2020-07-03 10:42:11 +09:00
Alex Shinn
e3fddebb26 even string-cursor->index/index->cursor are polymorphic 2020-07-03 09:43:26 +09:00
Alex Shinn
89a5b97e3c remove duplicate tests 2020-06-27 07:13:07 +09:00
Alex Shinn
25e04e2a35 switch /si default base to 1000, remove show-columns export 2020-06-24 13:08:33 +09:00
Alex Shinn
532fb83e0a don't use nested show in pretty (issue #518); use string-width for computing width (issue #517) 2020-06-24 12:25:36 +09:00
Alex Shinn
cd7480ce45 fixing image search path loading after switching to snprintf 2020-06-23 10:35:12 +09:00
Alex Shinn
06cef55723 guard should use raise-continuable (issue #661) 2020-06-19 17:48:29 +09:00
Alex Shinn
e8f1233e18 cleaning up test names 2020-06-19 17:37:55 +09:00
Alex Shinn
80d2db51d8 fix sexp_opcode_argn_type initialization with gaps between the 3rd arg and k>4th arg 2020-06-19 16:45:41 +09:00
Alex Shinn
afb4a432c9 replace (chibi string) with (srfi 130) in (srfi 166) 2020-06-18 00:00:45 +09:00
Alex Shinn
402e3c8fb1 making (chibi show) an alias of (srfi 166) 2020-06-17 23:39:24 +09:00
Alex Shinn
278bb48b00 error on recursive includes (issue #557) 2020-06-16 11:44:10 +09:00
Alex Shinn
5b7729fbfc fixing whitespace 2020-06-16 11:43:47 +09:00
Alex Shinn
23f93cceb4 better fix for #618 2020-06-16 10:05:26 +09:00
Alex Shinn
d511b8e31d s/VERSION/CHIBI_VERSION to avoid conflicts (issue #659) 2020-06-15 18:54:20 +09:00
Alex Shinn
08c72aca59 handle shared dotted tail in writing lists (issue #618) 2020-06-15 12:22:16 +09:00
Alex Shinn
4734fc1e40 friendlier report for error on module files with the wrong name (issue #624) 2020-06-15 11:51:32 +09:00
Alex Shinn
aa2a87fbba
Merge pull request #658 from lkstl/master
Use r7rs lazy primitives in srfi 41
2020-06-10 08:39:05 +09:00
Lukas Stoll
afba9d8c27 Correct record-type names in srfi 41 2020-06-09 19:50:13 +02:00
Lukas Stoll
4f23fb4e03 Add (scheme lazy) to imports for srfi 41 2020-06-09 15:05:41 +02:00
Lukas Stoll
6e2bd8d4b7 Use r7rs lazy primitives in srfi 41
Rewrite srfi 41 primitive layer in terms of r7rs primitives for delayed
evaluation.
2020-06-09 14:55:44 +02:00
Alex Shinn
2b82ef68d4 fix placement of dl in context (issue #657) 2020-06-09 01:13:28 +09:00
Alex Shinn
32580be0ff fixing test-build on static exe 2020-06-08 11:59:16 +09:00
Alex Shinn
abc3403e0a chibi-scheme-static needs -lutil if (chibi pty) is included 2020-06-08 11:54:12 +09:00
Alex Shinn
4ec2167f62 making the abi a little more stable by default 2020-06-08 00:54:36 +09:00
Alex Shinn
e694f45f71
Merge pull request #656 from okuoku/win32-guess-green-threads
Win32: Guess SEXP_USE_GREEN_THREADS
2020-06-06 17:44:57 +09:00
okuoku
1b46d91053 Win32: Guess SEXP_USE_GREEN_THREADS
Guess SEXP_USE_GREEN_THREADS=0 ifdef `_WIN32`.
2020-06-05 05:59:33 +09:00
Alex Shinn
d42d4d5600 replace define-library-alias with define-library + alias-for 2020-06-04 23:55:37 +09:00
Alex Shinn
c245d6cee8 fix case folding, update to unicode 13 2020-06-04 22:08:07 +09:00
Alex Shinn
6fb0640721 adding (chibi diff), use in tests 2020-06-04 22:06:32 +09:00
Alex Shinn
5beadf7ce8 adding missing files 2020-06-03 11:33:15 +09:00
Alex Shinn
1164ecf9b7 adding unicode-string-width/wide 2020-06-03 10:43:22 +09:00
Alex Shinn
6f1cf6588f fix ffi type annotations 2020-05-31 23:39:55 +09:00
Alex Shinn
6caca77426 adding (scheme bytevector) 2020-05-31 23:24:51 +09:00
Alex Shinn
f1b6e6bf69 adding inline ffi stubs and assertions 2020-05-31 23:23:08 +09:00
Alex Shinn
d5e97ceeb3
Merge pull request #655 from lockywolf/makefile-srfi-166-install
Add srfi 146 and 166 installation to Makefile
2020-05-28 14:52:09 +09:00
Alex Shinn
170201d3e4
Merge pull request #654 from okuoku/github-ci
CI: Add Github Actions
2020-05-28 14:51:36 +09:00
Lockywolf
ca23ec9335 Add srfi 146 and 166 installation to Makefile 2020-05-28 12:33:55 +08:00
okuoku
78f28c69ea CI: Add Github Actions
This workflow tests against the standard Makefile build on
Mac and Linux.
2020-05-28 03:14:50 +09:00
Alex Shinn
daa7263690 remove debug line 2020-05-27 18:37:03 +09:00
Alex Shinn
95310e5823 no more strcpy/sprintf (issue #653) 2020-05-27 18:35:18 +09:00
Alex Shinn
255ee079e5 fix order of arguments in lset= 2020-05-27 14:27:31 +09:00
Alex Shinn
ca52b2ff97 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-05-27 07:54:53 +09:00
Alex Shinn
7b8b534a48 use (chibi test) for srfi 146 tests (issue #651) 2020-05-27 07:54:46 +09:00
Alex Shinn
add9983728
Merge pull request #652 from lassik/fix-printf
Fix printf warning in json.c
2020-05-27 07:51:52 +09:00
Lassi Kortela
c251594f0a Fix printf warning in json.c 2020-05-27 00:51:30 +03:00
Alex Shinn
9901a67b20 adding define-library-alias (issue #650) 2020-05-26 22:20:35 +09:00
Alex Shinn
0957b54f51 adding tangerine names for srfi 160 libs 2020-05-26 17:18:50 +09:00
Alex Shinn
1ee773fa42 adding srfi 146 to lib tests 2020-05-26 17:09:21 +09:00
Alex Shinn
11e0328fef adding (srfi 146 hash) 2020-05-26 17:05:07 +09:00
Alex Shinn
61680088d2 noting Marc's SRFIs 2020-05-26 14:17:07 +09:00
Alex Shinn
3a117b27aa adding srfi 146 2020-05-26 13:57:06 +09:00
Alex Shinn
fb079b2bda adding srfi 188 2020-05-26 10:12:27 +09:00
Alex Shinn
c0933e8255 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-05-25 19:02:03 +09:00
Alex Shinn
b1af52195a adding initial srfi 166 implementation 2020-05-25 19:01:03 +09:00
Alex Shinn
6b449150fc cleanup whitespace 2020-05-25 18:52:33 +09:00
Alex Shinn
7bbbb1fb2c avoid gc recursion on non-pointers 2020-05-25 18:50:47 +09:00
Alex Shinn
2315a11e7f
Merge pull request #648 from ekaitz-zarraga/unparse-json
Unparse json feature
2020-05-24 23:48:01 +09:00
Ekaitz Zarraga
28f3641583 Use SEXP_VOID instead of SEXP_NULL 2020-05-24 16:41:43 +02:00
Alex Shinn
110487b9b2
Merge pull request #649 from okuoku/fix-install
Makefile.detect: Fix installation
2020-05-24 16:57:40 +09:00
okuoku
21708b4cf3 Makefile.detect: Fix installation 2020-05-24 16:04:44 +09:00
Ekaitz Zarraga
6693e6bf18 Add tests 2020-05-23 16:05:02 +02:00
Ekaitz Zarraga
3745c16c8c Avoid using alloca in fixnum 2020-05-23 15:33:29 +02:00
Ekaitz Zarraga
a2312503c4 Flonum support 2020-05-23 15:28:48 +02:00
Ekaitz Zarraga
1ea46958a0 Add possible common error 2020-05-22 12:51:38 +02:00
Ekaitz Zarraga
a843591136 Clean formatting and remove unneeded comments 2020-05-22 12:51:38 +02:00
Ekaitz Zarraga
0e01716827 Exception handling 2020-05-22 12:51:38 +02:00
Ekaitz Zarraga
bb1fdbb719 Unparse Fixnums 2020-05-22 12:10:42 +02:00
Ekaitz Zarraga
57c5940855 Unparse Array and Object types 2020-05-22 12:10:42 +02:00
Ekaitz Zarraga
35cdd287ea Unparse string 2020-05-22 12:10:42 +02:00
Ekaitz Zarraga
de5a4b6b28 Copyright headers 2020-05-22 12:10:42 +02:00
Alex Shinn
62ef654817 clarifying in README that GNU make is used, movign all extensions to Makefile.detect (issue #642) 2020-05-22 15:06:45 +09:00
Alex Shinn
61f2983fad apply an explicit max vector length check (issue #636) 2020-05-22 14:13:48 +09:00
Alex Shinn
b459e11ecf
Merge pull request #647 from ekaitz-zarraga/float_parse
Correct float parsing when exponent has sign
2020-05-22 10:35:13 +08:00
Alex Shinn
bda192f071 cleanup json unicode escape code 2020-05-22 11:32:19 +09:00
Alex Shinn
278657eea4
Merge pull request #644 from ekaitz-zarraga/master
Support multiple \u sequences and add error checking
2020-05-22 10:11:10 +08:00
Ekaitz Zarraga
1cc24e37d9 Fix formatting 2020-05-22 00:30:24 +02:00
Ekaitz Zarraga
ce1996f1a7 Correct float parsing when exponent has sign 2020-05-21 18:10:54 +02:00
Ekaitz Zarraga
64d04f0638 Add JSON tests 2020-05-20 13:11:12 +02:00
Ekaitz Zarraga
e79d2aefea Support multiple \u sequences and check errors 2020-05-19 20:47:19 +02:00
Alex Shinn
8df9f7ca69
Merge pull request #643 from ekaitz-zarraga/master
Support for \u sequences in JSON
2020-05-19 09:18:00 +08:00
Ekaitz Zarraga
c448e8b441 Support for \u sequences in JSON 2020-05-18 22:39:33 +02:00
Alex Shinn
62efe38c70
Merge pull request #641 from amirouche/fix-emscripten-build
Fix build with emscripten to run chibi in the browser.
2020-05-17 19:17:13 +08:00
Amirouche
d2006daa3c Fix build with emscripten to run chibi in the browser.
emcc (Emscripten gcc/clang-like replacement) 1.39.16 (9ecd579ac647c4484e2d9af2ab0bbc1e1505aa95)

Thanks @pmp-p.
2020-05-17 10:52:46 +02:00
Alex Shinn
6e8b9bf59d adding srfi 165 2020-05-17 00:08:00 +09:00
Alex Shinn
af7189e895
Merge pull request #640 from Donaim/601
Prevent stack overflow in sexp_mark_one (issue #601)
2020-05-16 22:13:27 +08:00
Vitaliy Mysak
5726c2e490 Prevent stack overflow in sexp_mark_one (issue #601)
Replace explicit recursion by heap allocations
in sexp_mark_one code.
This prevents crashes caused by stack overflow.
In particular, fixes issue #601.

As an optimization, allocate a fixed sized stack buffer first,
which should be enough for "normal" uses.
When that stack overflows, switch to heap.

Also, store "ranges" on the stack, instead of the actual sexp's,
using the fact that sexp's of a single parent are continous in memory.

This patch doesn't remove recursion on the context saves
because it didn't seem like they overflow in practice.
But changing that is simple having the stack interface.
2020-05-15 20:11:50 +02:00
Alex Shinn
4be920986f
Merge pull request #639 from Donaim/638
Avoid undefined C macro behavior
2020-05-14 08:11:36 +08:00
Donaim
bd62a076c6 Avoid undefined C macro behavior
MacOS and clang compilers complain about undefined behavior
in C macro.
Rewrite macro to solve that.

Fixes issue #638
2020-05-13 22:23:17 +02:00
Alex Shinn
72e70bef88
Merge pull request #637 from Donaim/fix-c89-compilation
Fix c89 compilation and add test build option for it
2020-05-13 18:18:39 +09:00
Vitaliy Mysak
9c680217d7 tests: add std=c89 as build option
Since chibi already compiles with c89,
it should not be too bad to maintain this compatibility.
2020-05-13 11:12:02 +02:00
Vitaliy Mysak
f449bd157d fix compilation under std=c89
There were few things that prevented successful compilation
using c89 standard. (and other c* standards in case of gcc).
Fix them in this small patch.

Changes in 27/rand.c:
- Use __GNU_SOURCE__ instead of __GNU_LIBRARY__
  or else any of -std=c* options don't work with gcc
- Add a check before using rand_r() as suggested in rand_r(3)
- Move _WIN_32 definitions to "else" branch because it uses the most portable version
2020-05-13 11:12:02 +02:00
Alex Shinn
e7e6530c35
Merge pull request #635 from Donaim/uninstall-misses
make: fix uninstall target
2020-05-12 10:43:21 +09:00
Alex Shinn
89201a4e20 remove bad redefinition of sexp_context_gc_count (issue #632) 2020-05-12 10:39:27 +09:00
Donaim
ebfe494147 make: fix uninstall target
uninstall target failed to remove
- share/srfi libraries
- man pages
- include headers

This patch repairs the makefile so that all chibi files
get removed correctly.

In case of man pages, they were actually installed
to a wrong place - "man1/man1" instead of "man1".
This was introduced by 2137fcd3f0
so current commit reverts it.
2020-05-11 23:19:48 +02:00
Alex Shinn
610b6964ce fix log table for integer-length (issue #634) 2020-05-11 21:38:40 +09:00
Alex Shinn
426579eef2 Merge branch 'master' of github.com:ashinn/chibi-scheme 2020-05-11 10:45:24 +09:00
Alex Shinn
83e82f55a7 tweaks for fixed-size heaps, fix issue #632 2020-05-11 10:43:36 +09:00
Alex Shinn
90b0336048 report diff on gc times 2020-05-11 10:28:00 +09:00
Alex Shinn
fe7ae7ca48
Merge pull request #633 from ar-nelson/srfi-133-vector-every-fix
Fix SRFI 133 vector-every crash on empty vector
2020-05-10 01:12:44 +09:00
Adam R. Nelson
18a5776587 Fix SRFI 133 vector-every crash on empty vector 2020-05-09 11:46:10 -04:00
Alex Shinn
abe8ca3b95 obi-wan error 2020-05-07 21:48:51 +09:00
Alex Shinn
e3db106f96 instrumenting alloc times and sizes 2020-05-06 23:39:01 +09:00
Alex Shinn
a4dcd04127
Merge pull request #631 from mnieper/srfi-158
Implement SRFI 158.
2020-05-06 07:48:23 +09:00
Marc Nieper-Wißkirchen
15b3449b85 Implement SRFI 158. 2020-05-05 22:28:10 +02:00
Alex Shinn
9100909ae1 better defaults and debugging for fixed size chunks 2020-05-05 00:41:20 +09:00
Alex Shinn
696bf30f5e check for circular lists in apply (issue #629) 2020-05-03 17:19:24 +09:00
Alex Shinn
156ddf793d better benchmark timing 2020-05-03 17:05:53 +09:00
Alex Shinn
c43285e5f2
Merge pull request #630 from mnieper/srfi-162
Implement SRFI 162.
2020-05-03 08:05:57 +09:00
Marc Nieper-Wißkirchen
d4527d23dc Implement SRFI 162. 2020-05-02 21:05:19 +02:00
Alex Shinn
69aed93502
Merge pull request #627 from lassik/usage
Write usage to stderr when bad options given
2020-04-23 21:31:49 +09:00
Lassi Kortela
bb0a0054c8 Write usage to stderr when bad options given 2020-04-23 13:59:27 +03:00
Alex Shinn
957ffe6a42 return successfully on --help (issue #626) 2020-04-23 19:27:52 +09:00
Alex Shinn
361dc48c62 don't verify duplicate formal parameters for more than 100 params 2020-04-19 19:20:01 +09:00
Alex Shinn
f74c34b99b make-promise is idempotent (issue #625) 2020-04-10 17:17:29 +09:00
Alex Shinn
0a83939866 fix corner case with multi-line comments in non-native read (issue #623) 2020-03-30 01:14:27 +09:00
Alex Shinn
72ea1258e6
Merge pull request #622 from katterjohn/address-info-canonname
(chibi net): add address-info-canonname
2020-03-25 16:16:28 +08:00
Alex Shinn
1795014dae throw an error on get-output-string on non-string-ports (issue #621) 2020-03-25 17:15:06 +09:00
Kris Katterjohn
3de48e0232 (chibi net): add address-info-canonname 2020-03-24 19:03:41 -05:00
Alex Shinn
d19ee75800
Merge pull request #617 from pclouds/tangerine-aliases
Add Tangerine library names
2020-02-22 10:54:35 +08:00
Nguyễn Thái Ngọc Duy
a3eda041a3 Add Tangerine library names
Chibi supports quite a few SRFIs that have been part of Tangerine
edition. These .sld are the same as their counterpart .sld, except the
rename.
2020-02-20 19:12:03 +07:00
Alex Shinn
7656be5043
Merge pull request #616 from pclouds/chibi-run
Allow to run chibi-run from anywhere
2020-02-19 22:25:24 +08:00
Nguyễn Thái Ngọc Duy
b678abbce7 Allow to run chibi-run from anywhere
chibi-run script assumes $(PWD) is at topdir. Let's remove that
assumption so that the script can be used anywhere to launch chibi from
dev environment.
2020-02-19 17:24:12 +07:00
Alex Shinn
3161edbe86
Merge pull request #613 from pclouds/chibi-test-no-protect
chibi/test: remove dead import
2020-02-14 22:19:22 +08:00
Nguyễn Thái Ngọc Duy
58b2ee34dd chibi/test: remove dead import
'protect' used to be renamed to 'guard', after excluding 'guard'
from (scheme base). But that part is now gone. test.scm itself never
uses 'protect' directly. Remove it because it's not used.
2020-02-14 19:03:42 +07:00
Alex Shinn
507e62c3e1 add safety checks on substring-cursor 2020-02-06 23:09:33 +08:00
Alex Shinn
fad3413235
Merge pull request #609 from ilammy/snow-usr-local
Always install Snow libraries to /usr/local
2020-02-06 21:15:39 +08:00
Alex Shinn
9e82ffd462
Merge pull request #612 from pclouds/srfi-159-exports
Correct srfi-159 exported procedures
2020-02-05 21:40:48 +08:00
Nguyễn Thái Ngọc Duy
c68bbf89bd Correct srfi-159 exported procedures
The two procedures pretty and pretty-simply from (chibi show pretty)
should be part of (srfi 159 base). written-shared is removed from 159
because it looks like it's an addition in 166.
2020-02-04 20:28:55 +07:00
Alex Shinn
77dad5af5c
Merge pull request #611 from ilammy/snow-remove
Use sudo when doing "snow-chibi remove"
2020-02-03 22:21:15 +08:00
Alex Shinn
addb859ab2
Merge pull request #610 from ilammy/hide-symbols
Hide unnecessarily exported symbols
2020-02-03 22:19:37 +08:00
Alex Shinn
4f7c3d5637
Merge pull request #608 from ilammy/man-path
Correct man page installation directory
2020-02-03 22:16:38 +08:00
Alex Shinn
12d3c6a504
Merge pull request #607 from ilammy/so-prefix
Common library installation prefixes
2020-02-03 22:15:45 +08:00
Alexei Lozovsky
24f207115c Hide unnecessarily exported symbols
gc_heap_err_str and load_image_header() are never used outside of
gc_heap.c but they are not marked static and are effectively exported
by Chibi's shared library. Since this is unlikely to be intentional,
let's hide them.
2020-02-02 16:59:57 +02:00
Alexei Lozovsky
50a9c9d4d4 Use sudo when doing "snow-chibi remove"
Currently "remove" command does not know how to use sudo to remove
files installed into directories owned by root. By default Snow
installs stuff into /usr/local hierarchy and uses sudo for that.
Let's teach it to remove packages without explicit sudo too.
2020-02-02 16:46:23 +02:00
Alexei Lozovsky
26061930e9 Always install Snow libraries to /usr/local
Snow-Chibi is a local package manager, not a system one. It can install
Scheme packages into system but they are not managed by system package
manager like dpkg, RPM, pacman, ports, etc.

Traditionally (and in accordance with Filesystem Hierarchy Standard),
/usr/local hierarchy should be used for local administrator installs --
and that's what Snow-Chibi provides.

Let's make sure that Snow-Chibi installs snowballs into /usr/local
hierarchy even if Chibi is compiled for installation into the system,
with PREFIX=/usr. Introduce a distinct bunch of variables holding paths
to library installation directories, with "SNOW" prefix:

  - SNOWPREFIX    - default prefix for Snow-installed stuff
  - SNOWLIBDIR    - custom libraries required for Snow itself
  - SNOWSOLIBDIR  - shared libraries required for Snow itself
  - SNOWMODDIR    - Snow installs Scheme modules here
  - SNOWBINMODDIR - Snow installs native libraries here

All of these are set to /use/local by default, just as they are now.
However, they are not affected by regular PREFIX, LIBDIR, MODDIR, etc.
which affect only libraries bundled with Chibi.

And in order for these to work, they need to be added into the current
module path so that they can be used in parallel with system libraries.
Furthermore, we need to tweak "get-install-library-dir" function to use
those paths instead of hardcoded "/usr/local/lib" by default. Introduce
a new helper "get-install-library-dirs", similar to "get-install-dirs".
It will look up the correct installation directories in current module
path, giving preference to the ones with "/lib" in them.

With these defaults, Snow will install Scheme modules into
/usr/local/share/snow and native libraries go into /usr/local/lib/snow,
similar to how built-it libraries are installed into
/usr/local/share/chibi and /usr/local/lib/chibi is used for native code.
Of course, this can be overriden at build time by setting SNOWPREFIX or
individual SNOWMODDIR, SNOWBINMODDIR variables.
2020-02-02 16:21:21 +02:00
Alexei Lozovsky
2137fcd3f0 Correct man page installation directory
According to the Filesystem Hierarchy Standard (see "man 7 hier")
man pages should be installed into an appropriate subdirectory for
their section. Fix the installation path so that our documentation
goes into the right place.

All UNIX-like systems supported by Chibi follow FHS for man pages:

  - FreeBSD
  - GNU/Linux
  - macOS
  - Plan 9
2020-02-02 11:34:24 +02:00
Alexei Lozovsky
04ce3700d7 Shared library installation prefixes
Both SOLIBDIR and BINMODDIR install into $(PREFIX)/lib which is the same
value as LIBDIR -- the traditional name of the directory for installed
libraries. Current duplication is fine for the default installation
(with PREFIX = /usr/local) but it does not play nicely with systems
supporing multiple architectures.

For example, Debian systems allow the users to install libraries for
multiple architectures simultaneously: e.g., 32-bit and 64-bit libraries
for AMD-64 CPUs go into separate directories:

  - 64-bit: /usr/lib/x86_64-linux-gnu/libchibi-scheme.so.0.8.0
  - 32-bit: /usr/lib/i386-linux-gnu/libchibi-scheme.so.0.8.0

Other Linux systems (Red Hat family) use different paths like /usr/lib64
and /usr/lib, but the general idea is the same.

In order to achive this, packaging toolchain supplies appropriate value
of LIBDIR which takes care of these details more or less automagically.

However, with Chibi you currently need to additionally override SOLIBDIR
and BINMODDIR to have all the libraries installed into multiarch-enabled
locations. While definitely doable, it's not convenient.

Redefine SOLIBDIR and BINMODDIR in terms of LIBDIR so that you only need
to override LIBDIR to get the packaging correctly. This does not change
the default installation paths and it is still possible to override
these values individually if necessary.
2020-02-02 10:48:39 +02:00
Alex Shinn
2b7927b9bc allow indexes instead of cursors for cursor-next/prev and string-any/every 2020-01-31 23:26:38 +08:00
Alex Shinn
708f57ffed SRFI 151 fixes: bitwise-if arg order swapped from SRFI 33; bit-set? on negative integers should extend infinite 1s; bit-field-every? should compare only bits within mask 2020-01-31 23:12:20 +08:00
Alex Shinn
a88a1ad244 adding ffi test with unsigned-char param 2020-01-27 22:19:51 +08:00
Alex Shinn
6a2ed9cdb4 fix iset-intersection on large trees in the first argument (issue #606) 2020-01-27 21:52:17 +08:00
Alex Shinn
5e3d2284ed
Merge pull request #604 from ar-nelson/srfi-128-hash-fix
Fix make-comparator hash function arity in SRFI 128
2020-01-12 22:46:26 +08:00
Adam R. Nelson
6aacffc0e8 fix make-comparator hash function arity in SRFI 128 2020-01-12 09:45:38 -05:00
Alex Shinn
82654b4c46 make install shouldn't fail if there are issues with images (fixes issue #603) 2020-01-12 22:43:36 +08:00
Alex Shinn
48d6c35548 nans aren't rational 2020-01-02 22:40:49 +08:00
Alex Shinn
c174465aa1 fix rational? for some boundary cases 2020-01-02 22:35:33 +08:00
Alex Shinn
a9f9b3dd8a
Merge pull request #596 from lassik/apropos
Add (chibi apropos) module
2019-12-31 00:36:10 +08:00
Lassi Kortela
60f22c978f Add (chibi apropos) module 2019-12-28 17:44:32 +02:00
Alex Shinn
6f28159667 regexp-replace should respect start/end also for pre/post substitutions 2019-12-28 22:48:44 +08:00
Alex Shinn
3c8402d4fb re-run scheduler if only thread was still waiting (issue #594) 2019-12-26 23:42:15 +08:00
Alex Shinn
588d63d901 don't escape html in sxml-display-as-text, add newline after li (issue #592) 2019-12-26 22:49:18 +08:00
Alex Shinn
d79f557d46 fix variadic foreign functions with more than 4 params 2019-12-19 23:58:51 +08:00
Alex Shinn
d5b5a079f4 initial uvector ffi support 2019-12-17 23:48:26 +08:00
Alex Shinn
5b60641f43 small documentation fixes 2019-12-17 23:47:53 +08:00
Alex Shinn
e10d82987a adding ignored failing match-letrec test case 2019-12-17 23:47:19 +08:00
Alex Shinn
33d6cfd0ac
Merge pull request #591 from krzygorz/ansi-fix
(chibi show): Make ANSI escape codes work with col state variable
2019-11-08 18:54:41 +08:00
krzygorz
5c43ca7720 move the col+ansi test to color section 2019-11-07 22:37:33 +01:00
krzygorz
15fef988af add a test for col with unicode and ANSI escapes 2019-11-07 22:31:29 +01:00
krzygorz
05521e5e1d use string-append for building ansi escape codes 2019-11-07 18:34:41 +01:00
Alex Shinn
abfa6a724e Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-11-04 20:15:40 +08:00
Alex Shinn
7b6a928974 adding levenshtein distance 2019-11-04 20:15:32 +08:00
Alex Shinn
10b713284c
Merge pull request #589 from ekaitz-zarraga/docs
Update sxml docs
2019-10-31 23:17:28 +08:00
Ekaitz Zárraga
bbe279b825 Update sxml docs 2019-10-30 10:15:52 +01:00
Alex Shinn
6f57d6ac71
Merge pull request #586 from amirouche/wasm-improvements
WASM improvements
2019-10-29 21:58:32 +08:00
Amirouche
9604fa361b Makefile: js/chibi.js: ALLOW_MEMORY_GROWTH=1
`ALLOW_MEMORY_GROWTH=1` allows to grow the wasm vm memory space as
needed and avoid out-of-memory issues. This is for development
purpose, production build will want to set memory size to something
that is fit the application (I don't remember the actual option name,
but removing ALLOW_MEMORY_GROWTH=1 from the compilation, and
re-running the app will display the good option to use).
2019-10-28 12:21:37 +01:00
Amirouche
61684647d6 Makefile: js/chibi.js: disable optimization
Optimizations will (sometime) lead to broken build.
2019-10-28 12:19:37 +01:00
Amirouche
9acd71735c Makefile: whitespace cleanup 2019-10-28 12:18:09 +01:00
Alex Shinn
4ad228a0f6
Merge pull request #585 from ekaitz-zarraga/safe-string
[WIP] Add option to ignore escaping
2019-10-24 21:00:29 +08:00
Ekaitz Zárraga
12f941dbfe Add option to ignore escaping 2019-10-24 09:56:08 +02:00
Alex Shinn
b33df19274
Merge pull request #583 from ekaitz-zarraga/patch-2
Correct typo
2019-10-24 10:27:35 +08:00
Ekaitz Zárraga
5dfc3b7909
Correct typo 2019-10-23 18:29:48 +02:00
Alex Shinn
c836311918
Merge pull request #582 from ekaitz-zarraga/patch-1
Missing ) in code example
2019-10-21 23:39:47 +08:00
Ekaitz Zárraga
cb63e9130c
Missing ) in code example 2019-10-19 13:01:10 +02:00
Alex Shinn
f4b0277d01 allow rest param in let-optionals 2019-10-14 22:04:23 +08:00
Alex Shinn
58e10b2a7d assert types in boolean=? and symbol=? (fixes issue #579) 2019-10-06 22:29:58 +08:00
Alex Shinn
544eaa79c7
Merge pull request #578 from katterjohn/mmap-heap-fixes
Fixes for mmapped heaps
2019-10-06 08:26:16 +08:00
Alex Shinn
e3935695a1
Merge pull request #577 from katterjohn/fix-mime-type
(chibi net server-util): file-mime-type: fix load-mime-types call
2019-10-06 08:20:45 +08:00
Kris Katterjohn
a1473f69ba mmapped heaps: fix for systems with W^X policies
Using read/write/exec causes an error (or possibly abort) on systems
with W^X policies (like OpenBSD and NetBSD have by default).

Since the heap does not need to be executable, just use read/write.
2019-10-04 20:50:41 -05:00
Kris Katterjohn
25d4807f50 mmapped heaps: fix the file descriptor argument to mmap for the BSDs
On the BSDs, the file descriptor passed to mmap when using MAP_ANON
must be -1.  Passing 0 causes mmap to fail.
2019-10-04 20:39:37 -05:00
Kris Katterjohn
650be6adc0 mmapped heaps: correctly check for mmap failure
When mmap fails it returns MAP_FAILED, not NULL.  POSIX does not
define the value for MAP_FAILED, but on at least the BSDs and Linux
its value is ((void *) -1).
2019-10-04 20:38:15 -05:00
Kris Katterjohn
9bbf48d084 (chibi net server-util): file-mime-type: fix load-mime-types call
Use find instead of any so load-mime-types will get the filename
instead of #t when a mime.types file is found.  Otherwise an error
occurs in load-mime-types.
2019-10-01 20:00:36 -05:00
Alex Shinn
3749d29883
Merge pull request #576 from katterjohn/memv-fix
memv: compare using eqv? instead of equal?
2019-09-24 22:07:17 +08:00
Kris Katterjohn
ea92d228b3 memv: compare using eqv? instead of equal?
memv has been defined to be member, so it has been comparing
using equal? (by default) instead of eqv?.
2019-09-23 20:43:25 -05:00
Alex Shinn
e2d43bceb8
Merge pull request #575 from katterjohn/listener-socket-leak
(chibi net): make-listener-socket: close the socket on error
2019-09-23 16:52:48 +08:00
Alex Shinn
eaf8e90e8c fix inexact json parsing 2019-09-23 12:09:52 +08:00
Alex Shinn
72971fd4f4 pipes should be escaped in symbols (fixes issue #571) 2019-09-23 11:53:54 +08:00
Kris Katterjohn
a28da66990 (chibi net): make-listener-socket: close the socket on error
A socket was leaked in the case where setting socket-opt/reuseaddr
failed.  (The socket was closed in the cases where bind or listen
failed.)
2019-09-22 19:18:18 -05:00
Alex Shinn
144581b834
Merge pull request #573 from katterjohn/net-export-addrinfo-flags
(chibi net): export address-info-flags
2019-09-20 23:02:19 +08:00
Alex Shinn
41d1f11dd3
Merge pull request #572 from katterjohn/system-export-groupp
(chibi system): export group?
2019-09-20 23:01:52 +08:00
Kris Katterjohn
407d420c21 (chibi system): export the struct group predicate group? 2019-09-19 15:47:41 -05:00
Kris Katterjohn
bb4239bac8 (chibi net): export the struct addrinfo getter address-info-flags 2019-09-19 15:45:26 -05:00
Alex Shinn
b9c25ab3f1
Merge pull request #567 from katterjohn/sockaddr-port-fix
(chibi net): sockaddr-port: return the port number in host byte order
2019-09-17 00:10:42 +08:00
Alex Shinn
dc18568236 forgot the factor of 8 in the range 2019-09-13 23:31:40 +08:00
Alex Shinn
713c6f7135 fix range check in unicode-string-width from edit-line 2019-09-13 23:10:39 +08:00
Alex Shinn
aa85d53989
Merge pull request #568 from katterjohn/sockaddr-name-fix
(chibi net): sockaddr-name: fix support for IPv6 addresses
2019-09-12 10:59:46 +08:00
Kris Katterjohn
fd7ff6d33f (chibi net): sockaddr-name: fix support for IPv6 addresses
The buffer was too small to hold all IPv6 addresses in string form
2019-09-10 18:04:01 -05:00
Kris Katterjohn
a7a620af1a (chibi net): sockaddr-port: return the port number in host byte order 2019-09-10 17:54:14 -05:00
Alex Shinn
197894eb87 fix (expt fixnum flonum) by reverting ce9c60c1 2019-09-09 23:25:27 +08:00
Alex Shinn
af686a8b50 Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-09-03 19:57:12 +08:00
Alex Shinn
e9c8bed95a random-integer should check for positive bounds 2019-09-03 19:56:59 +08:00
Alex Shinn
00d084414e
Merge pull request #563 from fisherro/chicken-5-support
Change snow-chibi to work with Chicken 5
2019-08-31 22:37:50 +08:00
Alex Shinn
ae98680259
Merge pull request #564 from katterjohn/process-bsd-fix
(chibi process): fix process-running? on OpenBSD, NetBSD and DragonFly
2019-08-31 22:36:49 +08:00
Kris Katterjohn
3da3f3cab3 (chibi process): fix process-running? on OpenBSD, NetBSD and DragonFly
tl;dr process-running? would always return #f on OpenBSD and
NetBSD, and in the one-argument case it would always return #t
on DragonFly.

To get the process information from the process table on OpenBSD
and NetBSD, we need to pass 6 level names to sysctl instead of 4.
Passing the wrong number of level names to sysctl has caused it
to always fail, which in turn caused process-running? to always
return #f:

  (process-running? 1)                        =>  #f
  (process-running? (current-process-id))     =>  #f

and so on.

After the above fix, we also need to check the amount of data
actually filled in by sysctl.  It appears that on OpenBSD, NetBSD
and DragonFly, if the requested process doesn't exist then sysctl
will return with a return value of 0 and just not actually fill in
the given structure.  This caused process-running? to return #t
when no process with the given PID existed:

  (process-running? -1)                       =>  #t
  (process-running? <other nonexistent pid>)  =>  #t

and so on.

I have tested on OpenBSD, NetBSD, DragonFly BSD and FreeBSD, and
process-running? now behaves as expected on all of them.
2019-08-30 13:05:32 -05:00
Robert Fisher
7f3d322407 Fix installation for Chicken 5
To get the repository path in Chicken 5, we not only have to require the
chicken.platform module, we also need to take the car of the result
since it now returns a list.
2019-08-29 11:42:21 -05:00
Robert Fisher
13d4bbf1d1 Change snow-chibi to work with Chicken 5
The method snow-chibi used to get the version of Chicken installed
doesn't work with Chicken 5. Adding "-R chicken.platform" would make it
work with Chicken 5, but then it wouldn't work with Chicken 4.

In both Chicken 4 & 5, however, csi has a -release option that will just
give the version number. So, I've changed the Chicken version detection
in snow-chibi to use this option.

Testing with...

	./chibi-scheme tools/snow-chibi.scm implementations

...then seemed to work with both Chicken 4 & 5.
2019-08-29 09:16:36 -05:00
Alex Shinn
0bfc31a1e5 check for too many args to if (issue #561) 2019-08-29 21:56:00 +08:00
Alex Shinn
4282a6da0d
Merge pull request #562 from katterjohn/git-ignore-pty
Add lib/chibi/pty.c to .gitignore
2019-08-29 21:50:25 +08:00
Kris Katterjohn
789abbabb3 Add lib/chibi/pty.c to .gitignore 2019-08-28 19:38:08 -05:00
Alex Shinn
19f408a041 Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-08-24 22:34:30 +08:00
Alex Shinn
e7b9510656 allowing required args in opt-lambda, adding define-opt 2019-08-24 22:34:20 +08:00
Alex Shinn
8645b23d42 fixing bug in pp-with-indent on dotted list 2019-08-24 16:00:47 +08:00
Alex Shinn
31cea4af6d
Merge pull request #560 from okuoku/disable-pty-cmake
(chibi pty): Disable in CMake build
2019-08-24 11:18:11 +08:00
okuoku
753e9e89d1 (chibi pty): Disable in CMake build
Disable `(chibi pty)` build with CMake.
2019-08-24 07:08:47 +09:00
Alex Shinn
cc1ca2622d
Merge pull request #559 from katterjohn/pty-bsd-fix
(chibi pty): fix compilation errors on the BSDs
2019-08-23 20:08:46 +08:00
Kris Katterjohn
8b6e236b09 (chibi pty): fix compilation errors on the BSDs
* Include util.h instead of pty.h on OpenBSD and NetBSD

* Include libutil.h instead of pty.h on FreeBSD and DragonFly BSD

* Include utmp.h only on non-BSD systems (FreeBSD does not have that
  header and none of these BSDs require it)

Tested on all four of these BSDs.
2019-08-22 16:33:10 -05:00
Alex Shinn
a9cebfb8da adding wip json parser 2019-08-23 00:45:58 +08:00
Alex Shinn
c7d2638fbc s/pty.h/util.h on macosx (fixes issue #558) 2019-08-22 23:53:42 +08:00
Alex Shinn
8ea1852ac1 adding (chibi pty) 2019-08-19 23:03:09 +08:00
Alex Shinn
ec09e0eed4 Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-08-19 21:53:12 +08:00
Alex Shinn
4aac80e41b
Merge pull request #555 from richlowe/sunos-build
build on Solaris-like systems
2019-08-17 21:56:07 +08:00
Alex Shinn
42b6eeff1b fix string-mismatch usage in (chibi repl) 2019-08-16 23:39:36 +08:00
Alex Shinn
56acd0eb56
Merge pull request #556 from katterjohn/bsd-detection
Fix NetBSD, DragonFly BSD and Darwin feature detection
2019-08-16 22:35:14 +08:00
Kris Katterjohn
4c1af8c92a Fix NetBSD, DragonFly BSD and Darwin feature detection
On NetBSD systems the netbsd feature identifier was not actually
provided because the macro SEXP_NETBSD was defined twice and the
second value was 0.

On DragonFly systems the dragonfly feature identifier was not actually
provided because the macro SEXP_DRAGONFLY was defined twice and the
second value was 0.  Also on DragonFly systems the darwin feature
identifier was incorrectly provided because SEXP_DARWIN had a value of
1 instead of 0.
2019-08-15 19:03:57 -05:00
Alex Shinn
83cfc7dd53 adding len limit on ffi auto-expand vars (issue #553) 2019-08-15 23:42:17 +08:00
Alex Shinn
39f34ffffb adding port-source?[-set!] to ast 2019-08-15 23:18:07 +08:00
Alex Shinn
93b718f7c3 adding set-source to ast 2019-08-15 23:11:39 +08:00
Richard Lowe
2311e41003 build on Solaris-like systems 2019-08-11 22:30:17 +00:00
Alex Shinn
a01de232b2
Merge pull request #554 from apg/apg/bsd-feature-expansion
Add features for the various BSDs.
2019-08-03 11:45:43 +08:00
Andrew Gwozdziewycz
e5ae89c9c6 Define / detect explicit features for BSD platforms 2019-08-02 11:33:59 -07:00
Andrew Gwozdziewycz
ac467ea314 Add features for the various BSDs.
This could and should be done cleaner. Works as a proof of concept at
this point in time.
2019-08-02 01:56:51 -07:00
Alex Shinn
a8680bb0b4
Merge pull request #551 from v01dXYZ/master
Fix include-shared for process
2019-07-24 22:54:30 +08:00
Alex Shinn
2a9bb14d2d
Merge pull request #548 from pclouds/sre-error-check
More error checking on some SRE syntax
2019-07-24 22:47:36 +08:00
v01dXYZ
94ca5a95ca
Fix include-shared for process
`chibi-genstatic` doesn't support expansion of `cond-expand` when the pattern is `(cond-expand (cond) (else (include-shared "module")))`
2019-07-24 11:10:04 +00:00
Nguyễn Thái Ngọc Duy
829d963a9d More error checking on some SRE syntax
When char-set, w/case, w/nocase, w/ascii or w/unicode is applied on a
<cset-sre>, only (cadr sre) is taken, the rest is ignored. Which is the
right thing to do only if (null? (cddr sre)). If there are more
arguments, error out instead of silently ignoring them.
2019-07-21 10:46:44 +07:00
Alex Shinn
b3831c3995
Merge pull request #544 from okuoku/win32-dll
Properly support DLL build on Win32
2019-07-12 00:06:31 +08:00
Alex Shinn
27e67b0ae4 Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-07-12 00:05:10 +08:00
Alex Shinn
597df2e931 missing space before quote (issue #545) 2019-07-12 00:04:52 +08:00
okuoku
205bda5ab4 cmake: Support shared-library builds
Support shared-library (DLL on Win32) builds and defaults on it.
2019-06-23 05:46:25 +09:00
okuoku
3d4e8bb3e6 Introduce SEXP_STATIC_LIBRARY
Introduce SEXP_STATIC_LIBRARY to support static-library build on
Win32/Win64. On Win32, symbol visibility is enforced on DLL builds so we
need to dedicated ABI on static-library builds.
2019-06-23 05:46:22 +09:00
Alex Shinn
6a35a95dfc
Merge pull request #540 from wasamasa/read-error-for-unterminated-strings
Consider unterminated strings as read-error
2019-05-23 14:33:51 +08:00
Alex Shinn
bbcb571ba5 fix comparison of negative bignums (issue #541) 2019-05-21 22:26:37 +08:00
Vasilij Schneidermann
ab39f12904 Consider unterminated strings as read-error 2019-05-17 10:55:22 +02:00
Alex Shinn
104811942f fixing read-line on network ports 2019-05-04 13:18:27 +08:00
Alex Shinn
26ceb64434 fix exact neg check for ratio in rounding (issue #539) 2019-05-03 00:37:30 +08:00
Alex Shinn
624b54c05c
Merge pull request #537 from lassik/fix-printf-warning
Avoid compiler warning about mismatched printf types
2019-04-26 22:33:14 +08:00
Lassi Kortela
2dc4353604 Avoid compiler warning about mismatched printf types
Under Unix with SEXP_64_BIT defined, sexp_sint_t is defined as 'long'.
But we would get the equivalent format specifier SEXP_PRIdFIXNUM from
the OS-defined PRId64 in <inttypes.h>. MacOS defines it as "lld". This
causes the clang printf checker to emit a warning about the 'long' and
'long long' mismatch.

Fix by avoiding system-defined PRId32 and PRId64 format specifiers and
always defining SEXP_PRIdFIXNUM as "d", "ld" or "lld" according to our
definition of sexp_sint_t as int, long or long long. This also means
we don't need to include <inttypes.h> any more.
2019-04-24 12:26:01 +03:00
Alex Shinn
105a4672e7 more helpful error messages on missing libraries 2019-04-21 22:11:11 +08:00
Alex Shinn
4cba9d3e6c Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-04-02 22:31:45 +08:00
Alex Shinn
08140baa3e making builtin write bounded to avoid cycles (fixes issue #532) 2019-04-02 22:31:33 +08:00
Alex Shinn
8b4acbcf71
Merge pull request #530 from Oxyd/win-fixes
Fix tests on Windows
2019-03-14 21:19:11 +08:00
Ondřej Majerech
7d82b76bc3 Fix tests on Windows 2019-03-13 22:56:06 +01:00
Alex Shinn
cd10668b3c adding true color ansi support 2019-03-13 23:57:22 +08:00
Alex Shinn
cf1f333731 fixing edge cases 2019-03-12 00:37:00 +08:00
Alex Shinn
80b360b800 Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-03-12 00:20:53 +08:00
Alex Shinn
956e7ba761 allow proper list for comma-rule 2019-03-11 23:51:42 +08:00
Alex Shinn
2e43aea7fc
Merge pull request #528 from katterjohn/readme-openbsd
Note that chibi works on OpenBSD in the README
2019-03-11 18:30:28 +08:00
Alex Shinn
269c8daf87
Merge pull request #527 from katterjohn/sysctl-inclusion
Remove duplicate sys/sysctl.h inclusion
2019-03-11 18:29:59 +08:00
Kris Katterjohn
c2615bc906 Note that chibi works on OpenBSD in the README
I have been successfully building and using chibi on both 32-bit
and 64-bit OpenBSD for over a year.
2019-03-10 15:03:48 -05:00
Kris Katterjohn
93ec1b0875 Remove duplicate sys/sysctl.h inclusion 2019-03-10 14:08:35 -05:00
Alex Shinn
bd78ebeed7 updating sign-rule to respect finalized SRFI 159 2019-03-10 14:50:44 +08:00
Alex Shinn
e921fdb95c
Merge pull request #526 from Oxyd/master
Fix typo in sexp_get_output_string documentation
2019-03-09 09:41:41 +08:00
Ondřej Majerech
801bffc3ab Fix typo in sexp_get_output_string documentation 2019-03-09 02:01:39 +01:00
Alex Shinn
80bf4013f9 exact zero minus a number is negation (fixes issue #523) 2019-03-05 23:35:15 +08:00
Alex Shinn
09b564ed7b catch failure to grow heap 2019-03-03 23:30:00 +08:00
Alex Shinn
d1bb4c27a4 removing undocumented upcased and downcased 2019-02-28 00:19:01 +08:00
Alex Shinn
7380564933 inserting commas in numerator and denominator separately for rationals 2019-02-28 00:09:08 +08:00
Alex Shinn
4c5bdcb22c allowing strings for decimal-sep; s/fn-fork/forked/g 2019-02-27 23:59:10 +08:00
Alex Shinn
2c3dfbd295 fixing default padding/trimming to be left, matching the spec (from SRFI 13 convention) 2019-02-27 22:52:18 +08:00
Alex Shinn
a126417ebe fleshing out srfi 160 api 2019-02-26 23:08:52 +08:00
Alex Shinn
a94a2c7902 uvector fixes 2019-02-25 23:01:35 +08:00
Alex Shinn
7b3413ec1a fixing bounds checks on u32 and u64 vectors 2019-02-21 02:55:35 +08:00
Alex Shinn
a5a7345df9 add 0085 (NEXT LINE) to char-set:whitespace (fixes #515 2019-02-10 22:36:23 +08:00
Alex Shinn
456853921b typos (fixing issue #512) 2019-02-05 22:49:10 +08:00
Alex Shinn
017bb1c2a0 adding -Dsafe-string-cursors feature to perform extra checks on string cursors 2019-02-01 00:31:13 +08:00
Alex Shinn
ef0a8bd199 restoring efficient read-line 2019-01-27 22:10:35 +08:00
Alex Shinn
e9ce08da78 adding note that marc wrote syntax-case in AUTHORS 2019-01-26 17:52:37 +08:00
Alex Shinn
77a964d16e Merge branch 'master' of github.com:ashinn/chibi-scheme 2019-01-26 05:35:32 +08:00
Alex Shinn
9569460a58 add compile-time option to store precomputed index->cursor tables for strings 2019-01-26 05:35:27 +08:00
Alex Shinn
08930ff41f
Merge pull request #511 from Oxyd/fix-makefile
Fix Makefile
2019-01-21 23:47:16 +08:00
Ondřej Majerech
fa7a35abae Add lib/srfi/160/uvprims.c to .gitignore 2019-01-20 20:36:52 +01:00
Ondřej Majerech
f08a6503b2 Create $prefix/lib/chibi/srfi/160 when installing
Otherwise, the Makefile installs lib/srfi/160/base.sld as
$prefix/lib/chici/srfi/160 instead of installing it into that directory.
2019-01-20 20:32:25 +01:00
Alex Shinn
677ccdce68
Merge pull request #509 from y-stm/fix-typo
typo in Makefile
2019-01-18 01:58:49 +08:00
anergy
cfcc0b021f typo in Makefile 2019-01-17 22:06:16 +09:00
Alex Shinn
d24d75621d fixing nofeature build 2019-01-16 08:33:04 +08:00
Alex Shinn
8c0c57ae6c typo in Makefile 2019-01-16 07:13:27 +08:00
Alex Shinn
2b4394ea74 adding initial support for SRFI 160 uniform vectors 2019-01-15 23:43:50 +08:00
Alex Shinn
afd887e672 update-repository shouldn't exit 2019-01-11 08:48:45 +08:00
Alex Shinn
1b3ccdaf1c fixing link to http-server docs 2019-01-06 08:52:11 +08:00
Alex Shinn
6b18b70b44 adding link to http-server docs 2019-01-06 08:47:03 +08:00
Alex Shinn
003d3d3328 clarifying default config params for http-server 2019-01-06 08:45:48 +08:00
Alex Shinn
ec0b6e98f6 also print error 2019-01-06 08:22:43 +08:00
Alex Shinn
c3189ebc9d warn when config fails to load 2019-01-06 08:19:43 +08:00
Alex Shinn
5f80618544 make-conf should validate it gets an alist 2019-01-04 01:53:49 +08:00
Alex Shinn
c9b4786648 fix default chibi.net.http-server file server for paths other than . 2019-01-03 07:39:08 +08:00
Alex Shinn
336a69a416 -R needs interpreter name, not SRFI 22 2019-01-01 23:18:49 +08:00
Alex Shinn
2962f68ced fix -R usage 2019-01-01 22:49:50 +08:00
Alex Shinn
74eb616c50 noting NetBSD support (thanks Riastradh) 2018-12-29 10:51:46 +08:00
Alex Shinn
b782ee575b removing duplicate revomal of program-name in (chibi app) 2018-12-28 23:48:13 +08:00
Alex Shinn
479efcdc33 don't start thread checking for leap seconds if env var is unspecified 2018-12-28 23:40:55 +08:00
Alex Shinn
ec345fe370 typo, export ellipsis-identifier? 2018-12-28 23:40:26 +08:00
Alex Shinn
43d6d20598 fix -xchibi.primitive and spurious output in snow-chibi (thanks Martin Hayman) 2018-12-28 23:29:13 +08:00
Alex Shinn
264cbc756f
Merge pull request #506 from edw/srfi-159
SRFI 159 definition has a typo
2018-12-24 11:15:13 +08:00
Edwin Watkeys
d256ebd368 fix typo update!->with in srfi-159 2018-12-23 11:25:45 +01:00
Edwin Watkeys
ddc8b39e7e Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-12-23 11:13:49 +01:00
Alex Shinn
c250685607 updating names of core types in (chibi ast) docs after switching to upper-case (fixes issue #505) 2018-12-17 01:11:27 +08:00
Edwin Watkeys
7635cefe4f Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-12-14 15:20:48 +01:00
Alex Shinn
90ed977202 Merge branch 'master' of github.com:ashinn/chibi-scheme 2018-12-11 22:54:18 +08:00
Alex Shinn
e0f23d4286
Merge pull request #504 from edw/args
Fix invocation of main caused by fix for #484
2018-12-11 22:54:00 +08:00
Alex Shinn
7b428d2a54
Merge pull request #503 from edw/parse->list
Parse->list calls parse->fold with incorrect argument order
2018-12-11 22:44:59 +08:00
Edwin Watkeys
2be201a2c1 Merge branch 'parse->list' of https://github.com/edw/chibi-scheme 2018-12-11 14:15:56 +01:00
Edwin Watkeys
6c9e5d3c54 fix invocation of main 2018-12-11 14:08:45 +01:00
Edwin Watkeys
c912f1e24f fix order of arguments to parse-fold 2018-12-11 12:46:42 +01:00
Alex Shinn
960c39c4bf ignore generated file with derived char-sets 2018-12-11 00:28:27 +08:00
Alex Shinn
670cd82488 ignore generated file with derived char-sets 2018-12-10 23:58:33 +08:00
Alex Shinn
06c27d81ce command-line shouldn't include interpreter name (fixes issue #484) 2018-12-10 23:44:39 +08:00
Alex Shinn
f0a8930ab4
Merge pull request #502 from mnieper/with-ellipsis
with-ellipsis
2018-12-10 22:10:42 +08:00
Marc Nieper-Wißkirchen
d2fbd59ae5 Export ellipsis-identifier? 2018-12-09 19:06:24 +01:00
Marc Nieper-Wißkirchen
5d978dd37b Implement with-ellipsis 2018-12-09 19:05:22 +01:00
Alex Shinn
2c37dfedd3
Merge pull request #500 from mnieper/syntax-case
Implement syntax-case
2018-12-09 04:08:31 +08:00
Alex Shinn
77a6ca8ea7 supporting ber encoding in bytevectors 2018-12-09 03:44:19 +08:00
Alex Shinn
3aae0e8481 supporting non-native endianness and non-finite floating values 2018-12-06 23:25:18 +08:00
Alex Shinn
9af77c9b4f adding CHIBI_IGNORE_SYSTEM_PATH=1 env var (fixes issue #501) 2018-12-06 00:54:21 +08:00
Marc Nieper-Wisskirchen
5c963df96f Move datum->syntax back to init-7.scm. Don't crash when renamer not present in syntactic closure. 2018-12-05 15:59:39 +01:00
Marc Nieper-Wißkirchen
081a2a7b3f Construct constructor/predicate names in the syntactic context of the record name, not the context of the invokation of define-record-type 2018-12-05 12:15:17 +01:00
Alex Shinn
d513bdc977 adding floating point utils for bytevectors 2018-12-04 00:43:08 +08:00
Alex Shinn
11ccfcb5de support exact scaling of bignum literals via moderate sized exponents 2018-12-03 23:05:00 +08:00
Alex Shinn
13311e78c5 Merge branch 'master' of github.com:ashinn/chibi-scheme 2018-12-02 12:23:17 +08:00
Alex Shinn
521e23e3c7 Reduce error in sexp_read_float_tail (from Taylor R Campbell)
scale*10 is computed exactly until scale exceeds 2^54/10; in
contrast, scale*0.1 may not be computed exactly, and fl(0.1) is not
even 0.1.

WARNING: This change is not complete -- it does nothing to prevent
overflow with very long strings of digits after the decimal point.
2018-12-02 12:22:14 +08:00
Marc Nieper-Wisskirchen
152b20f244 Implement syntax-case 2018-12-01 13:48:25 +01:00
Alex Shinn
3c4d839c71
Merge pull request #498 from amirouche/emsdk-update
Emsdk update
2018-11-27 23:12:09 +08:00
Alex Shinn
5bbef040c5 BSD portability fixes from Taylor Campbell 2018-11-27 23:01:23 +08:00
Amirouche
80dea6ce19 Makefile: export 'cwrap' and 'ccall' from emscripten 2018-11-25 19:12:05 +01:00
Amirouche
13dacf870a js/exported_functions.json: make it proper json 2018-11-25 19:10:35 +01:00
Alex Shinn
b5331233cb adding missing status response in http-send-directory (thanks to Martin Hayman) 2018-11-19 22:06:43 +08:00
Alex Shinn
7435174d3b
Merge pull request #493 from mnieper/master
Make write/display output bytevectors with hex constants (issue #483)
2018-11-08 23:24:52 +08:00
Marc Nieper-Wisskirchen
5519679dcd Display zeros in bytevectors as '0' 2018-11-08 16:16:07 +01:00
Marc Nieper-Wisskirchen
f9be5c8d46 Make write/display output bytevectors with hex constants (issue #483) 2018-11-06 14:22:38 +01:00
Alex Shinn
3f9dfb7837 fixing call to call-with-temp-file for HEAD requests 2018-11-06 15:09:18 +08:00
Alex Shinn
59e5584ab2
Merge pull request #492 from edw/repl-history
add history support as $0...9
2018-11-04 23:10:47 +08:00
Edwin Watkeys
cbe1b045b4 add history documentation 2018-10-31 14:51:49 -04:00
Edwin Watkeys
5bcd37477f add history support as $0...9 2018-10-31 13:12:30 -04:00
Alex Shinn
78c757af4b
Merge pull request #487 from vaartis/gc-heap-extern-c
Add C++ extern "C" to gc_heap.h
2018-10-05 02:43:08 +08:00
Ekaterina Vaartis
5f161d03ce Add C++ extern "C" to gc_heap.h 2018-10-04 10:49:30 +03:00
Alex Shinn
a7584ae647 allow zero-or-more (*) combining characters in the 'grapheme SRE rather than one-or-more (+) 2018-09-18 23:21:27 +08:00
Alex Shinn
7830ca1654 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-08-24 10:27:39 +08:00
Alex Shinn
9c0d8d0a86 adding docs for sexp_env_import 2018-08-24 10:27:06 +08:00
Alex Shinn
96de49efb8
Merge pull request #481 from katterjohn/master
Avoid undefined C macro behavior
2018-07-30 10:37:53 +08:00
Kris Katterjohn
f32def466b Avoid undefined C macro behavior
A C macro expanding to a `defined' has undefined behavior.  The
clang compiler was issuing warnings.
2018-07-29 19:58:37 -05:00
Alex Shinn
bce1e6a4d2 adding define-c-strerror 2018-07-23 23:59:52 +08:00
Alex Shinn
17102697e9 no need to zero out calloc result in ffi 2018-07-16 23:33:00 +08:00
Alex Shinn
b52df76e8a
Merge pull request #480 from Hamayama/synrule
Fix syntax-rules on ellipsis escape templates
2018-07-08 22:25:04 +08:00
Hamayama
216d6a8d87 Revert and fix syntax-rules by reflecting review 2018-07-05 00:53:17 +09:00
Hamayama
fdc1f86f09 Fix syntax-rules on ellipsis escape templates 2018-07-03 12:41:00 +09:00
Alex Shinn
0efa071672 use PRId64/32 where available for printing fixnums (issue #479) 2018-06-29 22:44:16 +08:00
Alex Shinn
f5a228ee9e fixing bug in flushed output on custom ports 2018-06-23 19:21:38 +08:00
Alex Shinn
f16e889e04
Merge pull request #478 from okuoku/win32-cmake
Activate Win64 platform with MSVC
2018-06-21 22:36:56 +08:00
okuoku
961131d5e1 doc: Update README-win32.md to reflect recent changes 2018-06-20 21:22:36 +09:00
okuoku
dcf23aaa02 AppVeyor: Add MSVC x64 configuration to CI 2018-06-20 21:22:36 +09:00
okuoku
432b763555 cmake: Use SEXP_64BIT on Win64
Do not override SEXP_64BIT on Win64 as now we have custom-long-long for
it.
2018-06-20 21:16:40 +09:00
Alex Shinn
f9bd4f9c0e
Merge pull request #477 from tramboi/expt_fix
Expt fix
2018-06-20 18:46:11 +08:00
Alex Shinn
12d7c1638e
Merge pull request #475 from tramboi/master
More portable bignums
2018-06-20 18:45:38 +08:00
Bertrand Augereau
952d7c806b More portable bignums that don't have to rely on gcc 128bit arithmetics extension
SEXP_USE_CUSTOM_LONG_LONGS currently needs SEXP_64_BIT
2018-06-19 04:46:05 +02:00
Bertrand Augereau
ce9c60c1e8 Fix (expt 3 -1) when SEXP_USE_BIGNUMS 2018-06-16 09:41:09 +02:00
Alex Shinn
5f428d1299 limit waiting in thread scheduler to 10ms 2018-06-13 22:33:39 +08:00
Alex Shinn
e8c10ce259
Merge pull request #476 from tramboi/expt_neg
(expt bignum -k) was equal to (expt bignum k)
2018-06-10 22:39:07 +08:00
Bertrand Augereau
d88dfeb172 Fix (expt bignum -k) 2018-06-10 03:21:00 +02:00
Bertrand Augereau
4d8933119f Test that (expt bignum -k) is correct 2018-06-10 03:20:35 +02:00
Alex Shinn
39043bc47c support infinite real with exact zero imaginary literals (issue #474) 2018-06-09 18:02:50 +08:00
Alex Shinn
22f87f67ab char names should obey case-(in)sensitivity (issue #471) 2018-05-12 19:43:02 +08:00
Alex Shinn
bfcab41056 add cc command line to ffi debug output 2018-05-12 07:39:26 +08:00
Alex Shinn
10ed000e1b
Merge pull request #469 from jacius/invalid_apply
Raise error if apply is called with invalid args.
2018-04-15 22:02:14 +09:00
John Croisant
42dd447a06 Raise error if apply is called with invalid args.
* If called with only the procedure, but no args list.
* If called with a final arg that is not a proper list.
2018-04-14 20:49:03 -05:00
Alex Shinn
d8e2e4aa54 add support for user-defined error types and functions in ffi, address-of, frameworks 2018-04-14 23:22:02 +09:00
Alex Shinn
10759e8bdb moving some scripts to tools/ 2018-04-05 22:21:33 +09:00
Alex Shinn
72de3ba12f exit codes should be exact (issue #467) 2018-04-05 22:11:05 +09:00
Alex Shinn
278911e93c
Merge pull request #466 from okuoku/fix-pull-465
test: Do not create file under /tmp in show-test
2018-04-04 23:35:11 +09:00
okuoku
583c45a6c1 test: Do not create file under /tmp in show-test
Do not create test file under /tmp as it might break
concurrent builds. Creating file on the current directory should
suffice.
2018-04-04 05:27:03 +09:00
Alex Shinn
656efad587 updating note about thread status in TODO 2018-04-03 07:53:36 +09:00
Alex Shinn
ecbaa9939a require proof of the presence of synclos before stripping them with quote (issue #464) 2018-04-01 21:38:21 +09:00
Alex Shinn
f67f63d570 fixing number->string for numbers within an ulp of round numbers 2018-04-01 21:01:58 +09:00
Alex Shinn
060cfd550e
Merge pull request #465 from jimrees/master
changes from jim rees
2018-04-01 15:32:32 +09:00
Alex Shinn
502a011b18 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-04-01 10:47:02 +09:00
Alex Shinn
757b8969dd
Merge pull request #463 from katterjohn/master
Avoid placing duplicate feature identifiers in the features list
2018-04-01 10:46:51 +09:00
Kris Katterjohn
5e80cb2c2b In my last commit, make the feature variable a gc variable 2018-03-31 20:23:00 -05:00
Kris Katterjohn
dc80bf4f04 Avoid placing duplicate feature identifiers in the (features) list
In my case "bsd" was present twice on my *BSD boxes
2018-03-31 14:19:18 -05:00
Alex Shinn
731c544872
Merge pull request #462 from katterjohn/master
Check for valid "rest" parameters in parameter lists
2018-03-29 18:45:23 +09:00
Kris Katterjohn
439e35da61 Check for valid "rest" parameters in parameter lists
Checks for invalid parameter names and duplicate parameters were
being performed on parameter lists, but these checks were not
considering any rest parameters.  This means that

  ((lambda (x . x) x) 'foo 'bar)   =>  foo
  ((lambda (x . 0) x) 'foo 'bar)   =>  foo
  ((lambda (x . #t) x) 'foo 'bar)  =>  foo
  ((lambda 0 'foo))                =>  foo
  ((lambda #t 'foo))               =>  foo

and so on.  Now these all produce errors.
2018-03-28 21:11:33 -05:00
Jim Rees
9b72412e4e Added additional show-tests which demonstrate recent bugs & fixes. 2018-03-27 14:47:14 -04:00
Jim Rees
b3100857fd Fixed escaped to support the documented double-quoting functionality
when esc-char is #f.
2018-03-26 06:44:37 -04:00
Jim Rees
88e8d89460 Fixed integer-log-base to use exact arithmetic so rounding doesn't cause
a wrong result to things like (numeric (- (* 36 36 36) 1) 36).

Fixed a bug in numeric that caused comma-sep and dec-sep to get
initialized wrongly.

Fixed maybe-trim-zeros to leave behind at least a ".0" on
inexact numbers that otherwise would have been output without
the decimal point.  This is for consistency with number->string
which is used when the radix is 10.

In gen-general, fixed a bug in the digit-generating loop for the
whole part of the number.  Previously, an integer that should
have looked like 5003 would be emitted as 5300.

Switched the order of application of maybe-round and
maybe-trim-zeros so that a number that should round to
.0000000000000001 doesn't get emitted as 0.1.

In gen-positive-real, fixed the ratio case to not call
number->string with a radix that might not be in {2,8,10,16}.

Also in gen-positive-real, fixed the call to number->string to
include the radix which was missing previously.

Fixed wrap-sign to correctly handle the case of -0.0.

In numeric/si, always emit the supplied separator even if the
number is too small for an SI-suffix to be emitted.  The
examples in the SRFI document depend on this.
2018-03-23 12:22:03 -04:00
Jim Rees
17eb19e43d Changed sexp_double_to_bignum to extract "digits" in base-16 rather
than base 10 so no round-off errors occur at each step.  This is
assuming FLT_RADIX is 2,4,8 or 16.
2018-03-23 10:50:15 -04:00
Jim Rees
b25e46b11b Introduced a second version of sexp_double_to_ratio, named
sexp_double_to_ratio_2, which converts without introducing
round-off errors the way sexp_double_to_ratio does when it
multiplies by 10.

Changed sexp_inexact_to_exact to use this new function when
a non-zero fractional part of the input exists.
2018-03-22 22:19:39 -04:00
Jim Rees
406aacf4dd try-fitted2/output* calls output on the argument string if it's
determined the string will not exceed the column width.  But
output is the caller environment's output state variable.  A
better choice is output-default.

In two places (length+ form) is replaced with (or (length+ form) +inf.0)
so that arithmetic can be performed on the result.

To support cyclic structures in pretty-simply (wrapped with
trimmed/lazy), the call-with-output form in pp-with-indent needs to be
wrapped with an appropriate trimmed/lazy.

In pp-pair, call (pp (car ls)) instead of (pretty (car ls)).

In pretty-simply, don't use call-with-output, that prevents
(trimmed/lazy n (pretty-simply ...)) from working at all on cyclic
input.
2018-03-22 11:06:55 -04:00
Jim Rees
b947e4ef47 Fixed trivial bug in padded/both where the "odd space" was being emitted
on the left rather than the right as specified.

Fixed trivial bug in padded/left where a string longer than the provided
width would result in a call to make-string with a negative length.

Fixed trivial bug in trimmed/lazy around an fn-binding for the output
state variable.
2018-03-22 10:41:52 -04:00
Jim Rees
ece2d470c3 Fixed from-file so that it produces more than just one line of output. 2018-03-22 09:50:34 -04:00
Alex Shinn
098d50d4e4 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-03-17 17:01:42 +09:00
Alex Shinn
933aeb5654 tests which expect an inexact value can accept an equivalent exact value 2018-03-17 16:50:41 +09:00
Alex Shinn
d0b63109e8
Merge pull request #461 from jacius/remainder_inf
Regression tests for remainder with infinity
2018-03-16 22:40:32 +09:00
John Croisant
fe85ccc94a Add regression tests for remainder with infinity. 2018-03-15 21:48:19 -05:00
John Croisant
3c41f9d3e2 Add "test-division" Makefile target.
Runs tests/division-tests.scm. The "test-all" target now also runs
test-division.
2018-03-15 21:43:21 -05:00
John Croisant
c5345a5b48 Fix errors in tests/division-tests.scm.
Import (scheme base) to get the basic division procedures.

The "centered" procedures were renamed to "balanced" in commit
975dc690a1.

Also cleaned up some trailing whitespace.
2018-03-15 21:37:08 -05:00
Alex Shinn
d167f90802
Merge pull request #460 from jacius/remainder_inf
Raise type error if remainder called with infinity.
2018-03-15 21:46:25 +09:00
John Croisant
e5d9ccb69f Raise type error if remainder called with infinity.
To prevent an infinite loop, raise a type error if the remainder
procedure is called with +inf.0 or -inf.0 as either argument.
2018-03-15 02:42:26 -05:00
Alex Shinn
f0c9f0e705 adding chibi-version variable to (chibi ast) 2018-03-11 23:47:33 +09:00
Alex Shinn
e4cc2dd33c default comparator compares numbers with = (issue #459) 2018-03-10 11:11:59 +09:00
Alex Shinn
d07170d6c3 Documenting sexp_register_c_type and sexp_make_cpointer. 2018-02-18 09:19:36 +09:00
Alex Shinn
e5f6c1bbba adding better debugging for zero-sized object warning 2018-02-16 17:01:21 +09:00
Alex Shinn
dc76aee1d6 s/sexp_init/sexp_scheme_init/ 2018-02-15 10:15:26 +09:00
Alex Shinn
1658cf66d6 adding sexp_init() (noop by default) to C example in docs 2018-02-15 10:13:18 +09:00
Alex Shinn
7ae96fdba5 typo in vector-select! 2018-02-01 15:43:46 +09:00
Alex Shinn
13a8c50373 install (srfi 135 kernel8) 2018-01-25 11:40:53 +09:00
Alex Shinn
1a2c504c5f typo, make cleaner should remove versioned so's 2018-01-25 01:27:18 +09:00
Alex Shinn
ea2e3d7e0a updating install files 2018-01-25 01:24:41 +09:00
Alex Shinn
cd0b6e32af fixing test-build 2018-01-25 01:07:49 +09:00
Alex Shinn
351e6562a0 updating trace in oom tests 2018-01-25 00:11:44 +09:00
Alex Shinn
5b5ca24a15 add repl to red image 2018-01-25 00:08:53 +09:00
Alex Shinn
5023e88897 don't include-shared hash multiple times 2018-01-24 23:58:30 +09:00
Alex Shinn
eb38a5836a extending (scheme red) 2018-01-24 23:54:09 +09:00
Alex Shinn
ab88f53e48 adding srfi 113 2018-01-24 23:47:28 +09:00
Alex Shinn
7cd26b9823 advanced repl should use (scheme small) by default 2018-01-16 21:23:21 +09:00
Alex Shinn
03544833dc rename (chibi show) update! to with! as in srfi 159 2018-01-16 21:15:54 +09:00
Alex Shinn
309c591d66 adding doc link to (srfi 159) 2018-01-16 19:55:39 +09:00
Alex Shinn
73734c7010 adding (srfi 159) wrapper around (chibi show) 2018-01-16 19:54:59 +09:00
Alex Shinn
f6f470c3e5 adding (srfi 135) 2018-01-16 01:14:40 +09:00
Alex Shinn
bd9ea1d3ac adding (srfi 134) 2018-01-16 00:00:48 +09:00
Alex Shinn
0c27921f51 adding (srfi 101) 2018-01-15 23:51:16 +09:00
Alex Shinn
b91022afea adding (srfi 127) 2018-01-15 23:15:14 +09:00
Alex Shinn
f8cc1402c2 adding (srfi 41) 2018-01-14 00:22:14 +09:00
Alex Shinn
9e4eb03fb4 only use ape/limits.h on plan9 2018-01-13 22:01:36 +09:00
Alex Shinn
2b8380323d
Merge pull request #452 from joe9/master
patch to compile on 9front
2018-01-13 11:32:30 +09:00
joe9
b85201f81d patch to compile on 9front 2018-01-12 19:26:17 -07:00
Alex Shinn
bf4760fa46 skip chibi log tests in windows 2018-01-13 10:57:44 +09:00
Alex Shinn
bf23dc655f adding chibi log tests to lib tests 2018-01-11 22:43:19 +09:00
Alex Shinn
b0e5f70355 adding (chibi log) tests 2018-01-11 22:42:18 +09:00
Alex Shinn
1f805fd3ae log ip address of clients in net servers 2018-01-11 22:05:44 +09:00
Alex Shinn
08a6962c98
Merge pull request #449 from Hamayama/syntax
Several changes of syntax-rules in init-7.scm
2018-01-11 22:02:04 +09:00
Alex Shinn
f5b2ba6fe3 nicer error for bad images 2018-01-07 23:54:31 +09:00
Alex Shinn
fd3e1f10d3 last arg of fn body should be displayed 2018-01-07 15:05:29 +09:00
Alex Shinn
a328b3fb4a re-enable fixed tests 2018-01-07 14:53:03 +09:00
Alex Shinn
f29a404324 buffer pretty output to work in columnar 2018-01-07 14:42:52 +09:00
Alex Shinn
b9172a366c
Merge pull request #450 from okuoku/win32-cmake
Misc. fixes for Windows build
2018-01-04 14:09:19 +09:00
Alex Shinn
13a28c3090 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2018-01-03 22:31:46 +09:00
okuoku
12751c8d7b Update .gitignore 2017-12-31 07:32:23 +09:00
okuoku
98d73d0da2 cmake: Exclude (chibi process) test on CTest
(chibi process) is not implemented on Win32.
2017-12-31 07:32:22 +09:00
okuoku
9e773f3daf (chibi filesystem): Stub out several features on Win32
- Win32 does not support symbolic links generally (NTFS does support it
  but it is not available for non-root users until Win10)
- Win32 does not have block size on stat() API
2017-12-31 07:32:22 +09:00
okuoku
3ea5b51c6c cmake: Remove debug messages 2017-12-31 07:32:22 +09:00
okuoku
6f64a8ae0e AppVeyor: Add CMake x64 MinGW configuration to check 2017-12-31 07:32:22 +09:00
Alex Shinn
eeaace2c50 adding (chibi show c) 2017-12-30 18:36:28 +09:00
Hamayama
ae85ef2980 Several changes of syntax-rules in init-7.scm 2017-12-30 09:46:51 +09:00
Alex Shinn
3aeb753fd8
Merge pull request #448 from weinholt/leap-seconds
Update leap second list
2017-12-25 12:16:31 +09:00
Göran Weinholt
49e9f0e532
Update leap second list 2017-12-24 20:03:37 +01:00
Alex Shinn
779b0cf02a
Merge pull request #447 from okuoku/win32-cmake
Makefile: Fix Cygwin build
2017-12-14 20:46:13 +09:00
okuoku
c3cbd9a2e2 Makefile: Fix Cygwin build
Fix Cygwin build; gmake's $(OS) will yield Windows_NT even on Cygwin.
2017-12-14 20:32:15 +09:00
Alex Shinn
27d8174518
Merge pull request #446 from okuoku/win32-cmake
Win32: Wrap-up
2017-12-14 20:05:21 +09:00
okuoku
daaf011bbd cmake: Autodetect library tests 2017-12-14 19:20:21 +09:00
okuoku
1cd679e3fa README-win32.md: Character-case problem was fixed 2017-12-14 18:03:27 +09:00
okuoku
1cba43a220 SRFI-151: Fix bit-set? on Win64 which uses long long
Most "1UL" references on bitwise operations should be replaced with
explicit C cast.
2017-12-14 18:03:23 +09:00
okuoku
dee6f190d9 doc: Update document for Win32 support 2017-12-13 23:42:18 +09:00
okuoku
7c45b4ab0e Makefile: Prefer Win32 native over MSYS
Prefer Win32 native over MSYS on default build. MSYS still can be
choosen with "PLATFORM=msys".
2017-12-13 22:00:13 +09:00
okuoku
d313f85b16 (chibi disasm): Use %I64d on Win64 2017-12-13 22:00:13 +09:00
okuoku
4d4b6f0474 ast.c Win32: Workaround for MinGW header file
getenv_s should be in <stdlib.h> but it seem MinGW header lacks it.
2017-12-13 22:00:13 +09:00
okuoku
070f2925c4 (chibi filesystem) Win32: A bit more shims
Implement more shims.
2017-12-13 22:00:07 +09:00
okuoku
e46bd03239 (chibi win32 process-win32): New library
Implement Win32 specific process library. Currently the library only
provides `exit` procedure.
2017-12-13 19:04:04 +09:00
okuoku
da7b68f82e SRFI-98: Do not decl. environ as extern on Win32
On Win32, environ definition is included in <stdlib.h>.
2017-12-13 17:30:36 +09:00
okuoku
d51a9e976b (chibi io) Win32: Include <io.h> on port.c
Include <io.h> to use various POSIX-like functions.
2017-12-13 17:27:16 +09:00
okuoku
960c962798 Win32: Include <io.h> on sexp.c
Use POSIX-like functions(open, read and write) from its
compatibility library.
2017-12-13 17:20:53 +09:00
okuoku
51f24ed36e Win32: Import Ruby's lgamma_r implementation (Public Domain)
Import Ruby's lgamma_r implementation as MSVCRT missing lgamma_r
implementation. Non Windows platforms should continue to use lgamma_r
implementation which provided with its C runtime library.
2017-12-13 17:20:53 +09:00
okuoku
e45f142b6a sexp.h: chmod -x 2017-12-13 17:20:53 +09:00
Alex Shinn
9cc2192026 additional format fixes 2017-12-10 15:51:18 +09:00
Alex Shinn
79f08129b2 fixing formatting with 0 precision 2017-11-24 22:57:10 +09:00
Alex Shinn
dec0f3b1a5
Merge pull request #444 from okuoku/fix-Makefile
Makefile: Fix (chibi time) installation
2017-11-18 22:02:58 +09:00
okuoku
3bcf3d7d94 Makefile: Fix (chibi time) installation
Fix make install regression which was introduced in #438
2017-11-18 20:08:59 +09:00
Alex Shinn
8111f17825
Merge pull request #443 from okuoku/win32-cmake
Win32: Visual Studio 2017 support using CMake
2017-11-18 18:21:20 +09:00
Alex Shinn
86fb983ec0
Merge branch 'master' into win32-cmake 2017-11-18 18:20:53 +09:00
Alex Shinn
6a09c87c98
Merge branch 'master' into win32-cmake 2017-11-18 18:19:46 +09:00
Alex Shinn
63b6151230 fix patch for scheme-r7rs 2017-11-18 18:17:45 +09:00
okuoku
51a73231de win32: Disable #435 for Win32
Disable #435 for Win32 as it is only meant for UNIX platforms.
2017-11-18 16:46:20 +09:00
okuoku
aed9d4da32 appveyor.yml: Update appveyor.yml to include CMake configurations 2017-11-18 16:46:14 +09:00
okuoku
1112f49605 chibi-scheme.vcproj: Remove
Remove chibi-scheme.vcproj to prevent interfere with CMake builds.
2017-11-18 16:28:35 +09:00
okuoku
2763f8a201 cmake: Add CMakeLists.txt
This CMakeLists.txt only meant for Win32 MSVC builds.
For POSIX platforms, it is recommended using Makefile.
2017-11-18 16:28:31 +09:00
okuoku
7693881125 sexp.c: Use strncasecmp instead of strcasestr
strcasestr is not available on MS C runtime. Use strncasecmp instead
which is in POSIX. MS C runtime has _strnicmp().
2017-11-18 15:24:28 +09:00
Alex Shinn
231c4bc04b Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-11-18 14:36:25 +09:00
Alex Shinn
e0dcb88b8a
Merge pull request #435 from omasanori/srfi-22-scheme-r7rs
[RFC] Treat `scheme-r7rs` command name as in SRFI 22.
2017-11-18 14:36:07 +09:00
Alex Shinn
a59fc49140
Merge pull request #438 from okuoku/win64
Win32: Fix win32 port
2017-11-18 14:34:32 +09:00
Alex Shinn
0e4b4d6127 adding (chibi show color) and (chibi show unicode) 2017-11-18 14:26:51 +09:00
Alex Shinn
7562cc195e
Merge pull request #442 from okuoku/patch-ast
ast.c: #include <stdlib.h> for setenv()
2017-11-13 22:08:55 +09:00
Alex Shinn
afcae50d26
Merge pull request #441 from okuoku/patch-main
main: Silence warning with !SEXP_USE_GREEN_THREADS
2017-11-13 22:08:36 +09:00
okuoku
396c54ca58 ast.c: #include <stdlib.h> for setenv() 2017-11-11 04:52:06 +09:00
okuoku
5558da5d2b main: Silence warning with !SEXP_USE_GREEN_THREADS 2017-11-11 04:46:25 +09:00
okuoku
2ff4400041 Appveyor: Add appveyor.yml
Appveyor.yml now includes three platforms:

 - x86  : Win32
 - x64  : Win64
 - msys : MSYS (64bits)
2017-11-11 04:33:32 +09:00
okuoku
e092923aac Win32: Fix win32 port
Try to fix win32 port. Now it runs both on Win32/Win64.

Win64 port currently depends on 128bits arithmetic thus it does not run on
MSVC.

Makefile now have EXCLUDE_POSIX_LIBS knob to exclude posix related library
from build.

Introduce msys PLATFORM for Makefile.detect to use MSYS's POSIX
emulation layer. It is intended for linking against MSYS tools; it is
not for embedding to Win32 applications.
2017-11-11 04:31:06 +09:00
Alex Shinn
905d43fe62
Merge pull request #440 from chaw/master
Add mkdir and install commands for SRFI 117 to Makefile.
2017-11-10 22:46:04 +09:00
Sudarshan S Chawathe
c6ee681948 Add mkdir and install commands for SRFI 117 to Makefile. 2017-11-08 18:05:28 -05:00
Alex Shinn
8d51cf053c Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-11-08 23:00:02 +09:00
Alex Shinn
4a35499894
Merge pull request #439 from okuoku/win32-lib
RFC: Win32 feature identifier / library changes
2017-11-08 22:59:47 +09:00
Alex Shinn
affe06c6e5 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-11-08 22:56:45 +09:00
Alex Shinn
80c69291ba updating (chibi show) with srfi changes 2017-11-08 22:56:40 +09:00
Alex Shinn
bc3fa73ec4 adding unambiguous promise? to core 2017-11-08 22:56:02 +09:00
Alex Shinn
9604ab260c
Merge pull request #437 from okuoku/genstatic-patch
chibi-genstatic: Remove inline? override
2017-11-08 22:48:52 +09:00
okuoku
bfec8b9f4e chibi-genstatic: Add --no-inline option
Add --no-inline option to improve debuggability.
2017-11-08 01:12:54 +09:00
okuoku
735719d9d6 Win32: Port/Stub-out libraries
- (scheme time): Win32 stub impl
 - (chibi filesystem): Win32 stubbing
 - (chibi process): ditto
 - (chibi time): ditto
 - SRFI-144: lgamma is not in C99 standard
 - SRFI-27: Win32 INSECURE rand
2017-11-06 04:10:28 +09:00
okuoku
307c3aeecf chibi-genstatic: Remove inline? override
Remove inline? binding here; it was effectively no-op'ed
`--inline` option.
2017-11-06 04:07:50 +09:00
okuoku
a2a77e902b Tentative MinGW support on makefile 2017-11-06 04:07:06 +09:00
Alex Shinn
887100b8ab install (srfi 1 immutable) 2017-10-28 08:44:09 +09:00
Alex Shinn
52b18ca665 fix bug in error reporint in verbose mode of (chibi test) 2017-10-22 22:25:05 +09:00
Alex Shinn
e4eadba355 sprintf precision ranges from 15 to 17 2017-10-22 22:24:15 +09:00
Alex Shinn
c5effc536f adding some additional precision tests 2017-10-14 21:49:47 +09:00
Alex Shinn
768a37c7a0 fixing empty match handling in regexp-split/partition 2017-10-11 22:59:55 +09:00
Alex Shinn
b2cdeba142 allow empty strings in regexp-split 2017-10-11 22:41:39 +09:00
Alex Shinn
334539f1fc bumping version 2017-10-06 23:56:31 +09:00
Alex Shinn
cc92ecf2bc adding (scheme red) and associated srfi aliases 2017-10-06 23:53:22 +09:00
Alex Shinn
70d61e1fcc removing duplicates from repl completion 2017-10-06 23:23:22 +09:00
Alex Shinn
befd7b5eff adding (srfi 154) 2017-10-06 22:54:32 +09:00
Alex Shinn
d4e45dc260 avoid left shifts for string cursors 2017-10-06 22:40:28 +09:00
Alex Shinn
b4b6d508d1 don't try to read polar notation when math is disabled 2017-09-01 16:56:55 +09:00
Alex Shinn
56a6a0b0b4 fixing asin/acos when complex numbers are disabled 2017-09-01 16:56:26 +09:00
Alex Shinn
ad487c7d03 marking some todos done 2017-08-30 23:14:50 +09:00
Alex Shinn
f83bc9969b adding single precision numeric representations in r7rs-tests 2017-08-30 23:09:43 +09:00
Alex Shinn
8a0e1d0ea4 updating man page 2017-08-30 23:03:04 +09:00
Alex Shinn
eeb4beb571 adding alignment detection for sparc and mips 2017-08-29 23:07:50 +09:00
Alex Shinn
8f635161d6 #define _REENTRANT to enable lgamma_r from math.h 2017-08-29 22:58:55 +09:00
Alex Shinn
b1307a67f5 use fabsl instead of abs on long double 2017-08-29 22:50:52 +09:00
Alex Shinn
8a9d8c0979 don't arithmetic shift signed ints (fixed issue #425) 2017-08-29 22:47:44 +09:00
Alex Shinn
fd28b5438b removing redundant renaming to same name execvp 2017-08-28 23:41:34 +09:00
Alex Shinn
03907a053c adding error checking for null lists in execute, improving (chibi process) docs 2017-08-28 23:39:14 +09:00
Alex Shinn
a5066eaec6 adding alternate representations of floats in read/write precision tests 2017-08-28 22:48:28 +09:00
Alex Shinn
4a7a809c8d distinguishing lowercase and foldcase (fixes issue #420) 2017-08-27 14:10:05 +09:00
Alex Shinn
ed0be227cc -iimage should be non-fatal for a missing image 2017-08-27 10:28:24 +09:00
Alex Shinn
7a94a31e72 adding note about snow-chibi --noimage to docs 2017-08-27 10:23:38 +09:00
Alex Shinn
34104aed70 updating AUTHORS 2017-08-26 23:29:45 +09:00
Alex Shinn
1ac4473942 removing tabs 2017-08-26 23:29:02 +09:00
Alex Shinn
17b7ee3f98 include dlerror if we can't find sexp_init_library 2017-08-26 23:05:33 +09:00
Alex Shinn
917387616e don't set RLDFLAGS for android 2017-08-26 22:21:00 +09:00
Alex Shinn
d9a40fbc61 conditionally using 17 digits of precision in flonum output when needed 2017-08-26 21:35:43 +09:00
Alex Shinn
f1eab48fd1 clarifying contexts can't be freed 2017-08-26 20:55:43 +09:00
Alex Shinn
6d447d6c15 adding doc links to newer builtin SRFIs 2017-08-26 20:47:45 +09:00
Alex Shinn
0f84fac70d adding (srfi 14) 2017-08-26 20:34:56 +09:00
Alex Shinn
ba0d15ec14 adding (print-stack-trace exn) for http internal errors 2017-08-25 00:01:03 +09:00
Alex Shinn
22af18dd18 adding (srfi 116) 2017-08-24 21:29:33 +09:00
Alex Shinn
32bd7fbad6 fixing corner cases in pair-fold, alist-delete and reduce-right 2017-08-24 21:27:08 +09:00
Alex Shinn
1c3f2bd6d5 adding (srfi 145) 2017-08-21 23:16:55 +09:00
Alex Shinn
b61c1b7077 better round-off reading floating point numbers with large exponents 2017-08-21 23:01:39 +09:00
Alex Shinn
6d3ae7a28e replacing (srfi 142) with (srfi 151) 2017-08-21 22:32:57 +09:00
Alex Shinn
ab57bb7681 renaming counted line-numbers 2017-08-21 22:08:29 +09:00
Alex Shinn
8470534c39 using 16 decimal places of precision in number->string (issue #433) 2017-08-20 15:00:24 +09:00
Alex Shinn
7114148121 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-08-09 22:47:24 +09:00
Alex Shinn
836ddf6397 adding missing flonum to (srfi 144) (fixes issue #434) 2017-08-09 22:46:46 +09:00
Alex Shinn
a24a26cd25 Merge pull request #432 from briancaine/briancaine/ffi-cflags-global
More explicit ways to add compiler flags in chibi-ffi .stub files
2017-08-08 14:34:26 +09:00
Brian Caine
a0dfe647cd Just went with the existing string-split 2017-08-08 01:19:19 -04:00
Brian Caine
90e2cb1aa6 Added c-flags-from-script to chibi-ffi 2017-08-06 04:04:08 -04:00
Brian Caine
212231dca6 Added *cflags* global to chibi-ffi 2017-08-06 03:49:55 -04:00
Alex Shinn
2a712b0715 support (import (only (rename ...))) in addition to the other way around (fixes #431) 2017-08-05 17:31:24 +09:00
Alex Shinn
da28ca8953 Merge pull request #430 from mnieper/srfi-139
Implement SRFI 139
2017-08-05 16:40:30 +09:00
Marc Nieper-Wißkirchen
34701f6df5 Implement SRFI 139 2017-08-01 19:22:12 +02:00
Alex Shinn
d381c53438 Merge pull request #429 from mnieper/emscripten
Repair Emscripten building process
2017-07-25 23:19:15 +09:00
Marc Nieper-Wißkirchen
0078ae2e83 Repair emscripten build 2017-07-25 16:06:59 +02:00
Alex Shinn
8f52f457d6 updating previous commit to include using bound=? to exlude literals from extracted pattern vars 2017-07-22 20:11:04 +09:00
Alex Shinn
e3678edbdc Identifiers in patterns should be checked against literals using bound-identifier=?, not free-identifier=?. 2017-07-22 19:50:56 +09:00
Alex Shinn
cdd5ffa406 installing recent libs (issue #427) 2017-07-20 22:21:13 +09:00
Alex Shinn
d93f7265e2 fixing test after jn/yn signature change 2017-07-20 22:18:05 +09:00
Alex Shinn
071aa725fd updating (srfi 144) with final changes (issue #426) 2017-07-20 22:12:01 +09:00
Alex Shinn
700380ebe4 don't expand into defined (issue #423) 2017-07-09 08:07:19 +09:00
Alex Shinn
8589333868 fix previous change for inline docs 2017-07-03 07:00:25 +09:00
Alex Shinn
c3e298757b Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-07-03 06:57:13 +09:00
Alex Shinn
7b68f141c6 allow urls for snow docs 2017-07-03 06:57:09 +09:00
Alex Shinn
29e1c262c5 Merge pull request #422 from arthurmaciel/snow-cyclone
Added support for Cyclone to Snow
2017-07-03 06:56:22 +09:00
arthurmaciel
264a4a4ede Added support for Cyclone to Snow 2017-07-02 16:55:38 -03:00
Alex Shinn
db186784e3 don't include underscore in ellipsis pattern vars (issue #421) 2017-07-02 22:10:03 +09:00
Alex Shinn
c80a1ece92 moving make-generated-binary-input-port to (chibi io) 2017-06-29 14:17:58 +09:00
Alex Shinn
f2f6aadb3d fixing sexp_port_size after buffered read on non-custom ports 2017-06-29 14:17:34 +09:00
Alex Shinn
582c46935e documenting -D, -t and -T options 2017-06-29 14:14:39 +09:00
Alex Shinn
39bf3cecc7 fixing make-generated-binary-input-port for non-zero buffer start, including query in http-get (issue #418) 2017-06-26 23:32:04 +09:00
Alex Shinn
da410523b0 fixing peek-char on non-ascii chars 2017-06-26 22:23:38 +09:00
Alex Shinn
3197969d3e adding missing export regexp-match->list (issue #419) 2017-06-26 10:36:38 +09:00
Alex Shinn
dc4559d692 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-06-17 21:53:39 +09:00
Alex Shinn
97716e8125 initial (chibi show column) impl 2017-06-17 21:53:35 +09:00
Masanori Ogino
76bd596aba Treat scheme-r7rs command name as in SRFI 22.
When the interpreter is named `scheme-r7rs`, SRFI 22's semantics is
assumed, invoking `main` procedure regardless of `-r` option.

Fix #416.

Signed-off-by: Masanori Ogino <masanori.ogino@gmail.com>
2017-06-13 22:26:55 +09:00
Alex Shinn
1a468244f1 Merge pull request #414 from omasanori/srfi-22
Remove argv[0] from the arguments of main_symbol.
2017-06-11 15:50:21 +09:00
Alex Shinn
08ef033a45 Merge pull request #415 from omasanori/gitignore
Update .gitignore.
2017-06-11 15:47:44 +09:00
Masanori Ogino
683aa13b14 Update .gitignore.
Signed-off-by: Masanori Ogino <masanori.ogino@gmail.com>
2017-06-10 10:38:13 +09:00
Masanori Ogino
361e8e6590 Remove argv[0] from the arguments of main_symbol.
While the (command-line) in (scheme process-context) contains the
command name (argv[0]), SRFI 22 specifies that the interpreter passes
the command-line arguments except argv[0] to the script.

Fix #413.

Signed-off-by: Masanori Ogino <masanori.ogino@gmail.com>
2017-06-10 08:54:49 +09:00
Alex Shinn
b52711cac8 adding (srfi 144) 2017-06-03 16:49:09 +09:00
Alex Shinn
4e14c53ddb bring memoize-to-file up-to-date with string-cursor api 2017-05-30 15:35:57 +09:00
Alex Shinn
79a5952ee1 adding (srfi 143) 2017-05-27 22:50:35 +09:00
Alex Shinn
9a21154041 fixing bit-field-rotate/reverse 2017-05-27 22:49:14 +09:00
Alex Shinn
e0fe160f46 fixing off-by-one error in first-set-bit 2017-05-19 23:04:06 +09:00
Alex Shinn
d3c2306220 check bignum type before deref in sexp_[su]int_value (issue #410) 2017-05-18 22:36:33 +09:00
Alex Shinn
5fb3217ada updating more bitwise corner cases (issue #408) 2017-05-15 23:45:06 +09:00
Alex Shinn
383c6cba62 fixing off-by-one error in arithmetic-shift 2017-05-08 23:49:55 +09:00
Alex Shinn
779c60ac35 add check for empty second list in list= (fixes issue #407) 2017-05-08 12:04:13 +09:00
Alex Shinn
fad9e4ca8b don't make stdio nonblocking by default, allow override with -b 2017-05-07 19:42:59 +09:00
Alex Shinn
5e4fa52185 bug in string-titlecase, string-cursor>=? doesn't take a string arg 2017-05-07 17:20:09 +09:00
Alex Shinn
9cf8a3ddf3 catching more bitwise-xor cases 2017-05-07 16:45:18 +09:00
Alex Shinn
cb7eaa7fe6 fixing bitwise-xor for negative bignum cases 2017-05-07 16:36:12 +09:00
Alex Shinn
bddb28ace7 fixing bitwise-ior for the bignum|negative-fixnum case 2017-05-07 16:17:06 +09:00
Alex Shinn
1e25dda078 preserving source info in quasiquote (restores line number reporting for (chibi test)) 2017-05-07 14:26:49 +09:00
Alex Shinn
37178eacd5 adding (srfi 125) 2017-04-18 23:24:56 +09:00
Alex Shinn
f37429d510 adding new srfi tests to lib-tests 2017-04-16 22:15:58 +09:00
Alex Shinn
dc3283a13b adding (srfi 121) 2017-04-16 22:07:51 +09:00
Alex Shinn
eb79e98d20 adding (srfi 142), using that in place of (srfi 33) 2017-04-16 22:06:56 +09:00
Alex Shinn
8feb1e761e alternate approach to handling renamed forward refs 2017-04-10 22:36:53 +09:00
Alex Shinn
40d322ca5f removing duplicate definition of ixon (issue #402) 2017-04-10 22:19:40 +09:00
Alex Shinn
9698d64ae5 adding missing file 2017-04-06 13:47:57 +09:00
Alex Shinn
22b39432b4 test-exit should return non-zero for failures outside test* forms 2017-04-04 22:54:00 +09:00
Alex Shinn
ceb2345b68 fixing docs for chibi ffi 2017-04-03 23:23:07 +09:00
Alex Shinn
f3f30f59b6 add immutable? to (chibi ast) 2017-04-03 23:15:46 +09:00
Alex Shinn
1bd9fe437a don't retroactively resolve unbound renamed references with a renamed definition 2017-04-03 23:13:14 +09:00
Alex Shinn
c3713540d0 fix multiple levels of synclo forward references (issue #399) 2017-04-03 15:48:57 +09:00
Alex Shinn
63688d79b6 fixing bug in get-value-signature 2017-04-03 00:12:06 +09:00
Alex Shinn
28d119426c fixing rest parsing 2017-04-03 00:06:48 +09:00
Alex Shinn
014aa253d1 adding new srfis to lib tests 2017-04-01 22:20:21 +09:00
Alex Shinn
ae1704883c adding (srfi 117) 2017-04-01 22:15:08 +09:00
Alex Shinn
975dc690a1 renaming centered/ balanced/ 2017-04-01 22:14:29 +09:00
Alex Shinn
4193742fe5 adding explicit (srfi 23) 2017-04-01 21:47:34 +09:00
Alex Shinn
90abe23663 remove tab 2017-04-01 20:43:43 +09:00
Alex Shinn
efc6426a59 adding (srfi 141) 2017-04-01 20:42:32 +09:00
Alex Shinn
08b586b7f9 adding (srfi 147) 2017-04-01 20:33:13 +09:00
Alex Shinn
6ed3bd4cc3 adding (srfi 128) 2017-04-01 20:26:00 +09:00
Alex Shinn
04ed6e1388 adding (srfi 133) 2017-03-31 00:48:35 +09:00
Alex Shinn
67712e5624 adding (srfi 132) 2017-03-30 01:17:30 +09:00
Alex Shinn
6e2013153a updating to Unicode 9 and adding SRFI 129 2017-03-28 23:42:47 +09:00
Alex Shinn
fad7662d83 s/display/write-string 2017-03-26 22:54:21 +09:00
Alex Shinn
30486cb6b6 fixing bug in char-up/downcase bsearch 2017-03-26 22:52:34 +09:00
Alex Shinn
c08aa4e93b adding (srfi 111) 2017-03-26 22:02:43 +09:00
Alex Shinn
806d92aa15 adding --scheme-script and --scheme-program-command args to snow (issue #400) 2017-03-26 21:30:53 +09:00
Alex Shinn
ae1a2aa6be match undefined hygienically wrapper forward refs on define (fixes issue #399) 2017-03-26 21:16:36 +09:00
Alex Shinn
c03ae08bbd various portability improvements 2017-03-26 16:00:31 +09:00
Alex Shinn
3b2e694372 removing own username from tar tests 2017-03-25 19:44:36 +09:00
Alex Shinn
be907a31e3 porting (chibi temp-file) and (chibi zlib) to chicken 2017-03-25 18:26:35 +09:00
Alex Shinn
e8c9def652 add type-printer-set! to (chibi ast) (fixes issue #401) 2017-03-25 17:52:53 +09:00
Alex Shinn
d482daa106 provide a nicer binary type interface 2017-03-25 17:46:30 +09:00
Alex Shinn
ae76cc7149 adding version of define-binary-record-type that works with chicken 2017-03-25 17:29:42 +09:00
Alex Shinn
938af37a2b Merge pull request #398 from VermillionAzure/master
Arranged definitions to prevent double definition
2017-03-12 18:15:32 +09:00
Alex Shinn
2c93246f34 converting (chibi binary-record) to pure syntax-rules 2017-03-12 18:14:11 +09:00
VermillionAzure
b955dc2698 Arranged definitions to prevent double definition
- It is possible to define `strcasecmp` and
  `strncasecmp` twice if `__MINGW32__` is defined.
  However, the same definition is used if it's not.
  Therefore, I just moved it inside of the "if-defined"
  case. It removes the errors pertaining to that header.

- Additional compilation errors related to the filesystem
  implementation and POSIX definitions of constants still
  are brought up when compiling on Windows 10, MSYS2-mingw-w64
  with gcc.
2017-03-06 00:11:25 -10:00
Alex Shinn
d152dd6237 import (scheme base) 2017-02-20 22:24:49 +09:00
Alex Shinn
e1d58eb84a adding SHUT_{RD,WR} from mkeeter 2017-02-20 22:14:15 +09:00
Alex Shinn
dbf322b1d2 windows fixes from mkeeter 2017-02-17 23:13:24 +09:00
Alex Shinn
63767bce2b Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2017-02-13 22:43:30 +09:00
Alex Shinn
87ac9fd633 port (chibi filesystem) to chicken 2017-02-13 22:43:08 +09:00
Alex Shinn
652f350c54 Merge pull request #397 from nmve/patch-1
Update README.md
2017-02-01 22:37:30 +09:00
nmve
6310129cb0 Update README.md 2017-02-01 10:22:00 +02:00
Alex Shinn
1a1dfc64ca supporting installing srfi's for chicken 2017-01-31 22:47:01 +09:00
Alex Shinn
57f1b44d14 chicken workarounds 2017-01-30 23:08:04 +09:00
Alex Shinn
1a86331335 making regexp tests portable 2017-01-30 22:57:24 +09:00
Alex Shinn
812dc59b20 removing debug output 2017-01-30 22:51:52 +09:00
Alex Shinn
7c12b0aaf3 sort libs within a package before installing,
plus other small fixes for (chibi iset) for chicken
2017-01-30 22:48:02 +09:00
Alex Shinn
374034d7e0 adding (srfi 115) wrapper around (chibi regexp) 2017-01-25 00:30:10 +09:00
Alex Shinn
421ef0b010 strip syntactic closures for unquoted vector literals 2017-01-24 23:49:13 +09:00
Alex Shinn
9ca33d82f4 removing (chibi) import from prime tests 2017-01-23 23:32:32 +09:00
Alex Shinn
46687d7307 removing (chibi) import from sha2 tests 2017-01-23 23:29:26 +09:00
Alex Shinn
cd258bfc08 removing (chibi) import from md5 tests 2017-01-23 23:26:31 +09:00
Alex Shinn
7b936e4190 adding dummy with-raw-io and get-terminal-width defs 2017-01-23 23:21:06 +09:00
Alex Shinn
ac6d0124c4 making (chibi term edit-line) portable, using from (chibi snow interface) 2017-01-23 23:12:58 +09:00
Alex Shinn
92daa43114 allowing --noimage option to snow-chibi 2017-01-23 23:12:25 +09:00
Alex Shinn
d1eaf80ce8 fixing typo in handling of TEST_VERBOSE env var 2017-01-23 22:10:48 +09:00
Alex Shinn
63cea7ccb5 fixing sexp_make_random_source type tag on linux 2017-01-20 23:24:44 +09:00
Alex Shinn
260f55adec Use a context global instead of a static C global for the default random source.
Fixes issue #385.
2017-01-20 00:49:11 +09:00
Alex Shinn
29328bfc9d Fixing snow doc extraction for multiple levels of includes. 2017-01-19 23:58:09 +09:00
Alex Shinn
a169e19159 Create example env lazily to avoid spurious warnings.
Also allow example-import-only to disable importing of the default env.
Fixes issue #390.
2017-01-14 23:16:58 +09:00
Alex Shinn
0fa1179c2f add -T option to disable TCO 2017-01-14 16:51:07 +09:00
Alex Shinn
2f1b730f65 strip syntactic-closures in quoted vectors (fixes issue #389) 2017-01-14 16:34:16 +09:00
Alex Shinn
789b448e54 recursively install library-include-declarations 2017-01-14 16:23:17 +09:00
Alex Shinn
302ee50075 fixing path resolution for include-library-declarations 2017-01-14 15:52:06 +09:00
Alex Shinn
2735b36c87 adding type checks for random-source-make-* 2017-01-14 15:08:14 +09:00
Alex Shinn
f691ae6a76 determining chicken-binary-version from (##sys#fudge 42) 2017-01-14 15:00:21 +09:00
Alex Shinn
396baa752f Updating chicken install path to 8. 2017-01-14 14:54:06 +09:00
Alex Shinn
dc9284d47c updating snow tests to use lib/chicken/8 2017-01-12 02:00:09 +09:00
Alex Shinn
0a3c689abe Merge pull request #391 from mnieper/let-values
fixed let(*)-values when no bindings are given
2017-01-11 08:18:29 +09:00
Marc Nieper-Wißkirchen
7197accf1f fixed let(*)-values when no bindings are given 2017-01-10 22:59:00 +01:00
Alex Shinn
6e99306ccd Only include up to 4 octal digits of file mode info in tar files.
The fifth digit (S_IFMT) is used for the file type (e.g. S_IFDIR=040000
for a directory), which in the tar format is handled separately in
the type field.  This digit is generally ignored by GNU tar and
other implementations, but confuses midnight commander.
Fixes issue #384.
2017-01-10 22:17:25 +09:00
Alex Shinn
71b00779bc Merge pull request #388 from ecraven/stderr
Display warning on stderr, not stdout.
2017-01-10 00:34:41 +09:00
Alex Shinn
def23d647e Merge pull request #387 from ecraven/add-rxvt-unicode-256color
Return #t from ansi-escapes-enabled? for $TERM rxvt-unicode-256color
2017-01-10 00:31:44 +09:00
Alex Shinn
9788132c6a add procedure-flags 2017-01-10 00:26:46 +09:00
Peter
ccc4b87bc9 Display warning on stderr, not stdout.
Right now, a part of the warning (undefined variable: foo, is exported by: ..)
is displayed to stdout. This patch makes the entire message show up on stderr,
not split up between the two output streams.
2017-01-09 08:27:14 +01:00
Peter
a0b8409fe7 Return #t from ansi-escapes-enabled? for $TERM rxvt-unicode-256color 2017-01-08 00:37:25 +01:00
Alex Shinn
9fa8d8c1f0 Don't treat underscore as a pattern variable. Fixes issue #382. 2017-01-01 09:48:34 +09:00
Alex Shinn
71f4db7d17 don't strip syntax for unknown refs 2016-12-30 10:53:22 +09:00
Alex Shinn
1d9038d3ca removing leftover noops from debugging 2016-12-18 16:06:56 +09:00
Alex Shinn
3e796be258 adding initial non-greedy match support 2016-12-15 00:33:57 +09:00
Alex Shinn
ef57cd76ec fixing env var refs from previous commit 2016-11-29 01:22:26 +09:00
Alex Shinn
efcb12d8e3 setting LD_LIBRARY_PATH for installing into a non-standard directory 2016-11-29 01:15:56 +09:00
Alex Shinn
0281c590f0 Don't use flexible array member syntax when compiling with C++.
Fixes issue #378.
2016-10-27 21:29:13 +09:00
Alex Shinn
50b17ac397 working towards snow portability 2016-10-17 23:00:14 +09:00
Alex Shinn
74d4fa3199 match should treat keywords as literals, not identifiers, in Chicken 2016-10-05 23:13:29 +09:00
Alex Shinn
38b8a6056c fixing typo in conf-verify-match 2016-09-28 23:31:06 +09:00
Alex Shinn
70c85542e2 portability fixes for (chibi log) 2016-09-28 23:24:08 +09:00
Alex Shinn
6b5c2c3d0b struct tm year is offset by 1900 2016-09-28 23:23:22 +09:00
Alex Shinn
7b0cca9403 fixing portable string-join definition to allow a separator 2016-09-28 23:22:44 +09:00
Alex Shinn
ca1a2bd3ae replace problematic ::: which may be interpreted as a keyword with ooo 2016-09-28 22:21:25 +09:00
Alex Shinn
76211609ff portability changes 2016-09-26 23:10:09 +09:00
Alex Shinn
9dd1be86e2 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2016-08-06 15:42:47 +09:00
Alex Shinn
13fbdd781f Fixing bitwise-ior/xor on negative bignums (issue #375). 2016-08-06 15:42:01 +09:00
Alex Shinn
9010b16708 Merge pull request #373 from Jasu/master
Remove a spurious semi-colon from the macro sexp_make_vector
2016-07-28 20:43:10 +09:00
Jasu
0bb88f97ed Remove a spurious semi-colon from the macro sexp_make_vector 2016-07-27 19:27:37 +03:00
Alex Shinn
57c6d7c1ec don't try printing a potentially corrupt stack after OOS (issue #371) 2016-07-10 08:30:30 +09:00
Alex Shinn
50d7cedb3f Fixing constructors and setters for nested structs (issue #370). 2016-07-06 23:22:04 +09:00
Alex Shinn
62ca18c1a4 compare record field names with eq?
Fixes issue #367.
2016-06-25 22:53:37 +09:00
Alex Shinn
d0cb74bef4 Identifiers in the template should only match pattern variables
from the same expansion step.  Fixes issue #366.
2016-06-25 15:20:39 +09:00
Alex Shinn
6d6654fd13 adding informational configure script 2016-06-24 22:55:08 +09:00
Alex Shinn
2301601b6a wrong filename 2016-06-24 22:51:36 +09:00
Alex Shinn
49304e189a readme updates 2016-06-24 22:46:16 +09:00
Alex Shinn
8c238a5beb adding .travis.yaml file (issue #368) 2016-06-24 22:37:58 +09:00
Alex Shinn
01bd48d932 only build image files on install 2016-06-24 22:36:22 +09:00
Alex Shinn
9abf508800 removing unused var (issue #364) 2016-06-21 05:03:27 +09:00
Alex Shinn
047f35432b detecting variable uses in the wrong phase (issue #259) 2016-06-19 14:24:42 +09:00
Alex Shinn
5a770c4909 adding tests from issue #363 2016-06-19 13:14:00 +09:00
Alex Shinn
18b41bcda0 make-rtd expects a symbol record name, not string 2016-06-19 13:09:45 +09:00
Alex Shinn
b88f13ef4a preserving hygienie in define-record-type 2016-06-18 23:02:25 +09:00
Alex Shinn
99b39a183f Fixing type-slot-offset computation. 2016-06-16 23:09:28 +09:00
Alex Shinn
021c7dd0d2 Use strstr instead of strnstr. 2016-06-16 23:01:10 +09:00
Alex Shinn
c953f2ed1d Check the module search path to handle relocated shared libraries
when loading an image.  Fixes issue #345.
2016-06-15 22:50:30 +09:00
Alex Shinn
84edaf75a2 Lookup slot offset in reverse order to support shadowing fields.
Fixes issue #361.
2016-06-14 00:04:30 +09:00
Alex Shinn
b5a91955e8 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2016-06-12 22:58:58 +09:00
Alex Shinn
82ebd3cbc3 remove unused vars, restore endianess feature 2016-06-12 22:58:35 +09:00
Alex Shinn
23a5b4a2fa Merge pull request #360 from mnieper/ephemerons
Add SRFI 124 interface to Chibi's ephemerons.
2016-06-12 14:26:26 +09:00
Alex Shinn
08494037ea making features a context global 2016-06-12 14:25:46 +09:00
Marc Nieper-Wißkirchen
00d50d59f5 Add SRFI 124 interface to Chibi's ephemerons.
(Note that although Chibi's implementation of proper ephemerons is not
complete, it still counts as an implementation of SRFI 124, which even
allows a trivial implementation.)
2016-06-10 18:40:25 +02:00
Alex Shinn
8359b48a59 commenting out complex asin tests 2016-06-08 07:24:03 +09:00
Alex Shinn
bb636b9b83 PRIoff is also "%lld" for cygwin64 (issue #358) 2016-06-08 07:22:09 +09:00
Alex Shinn
1278c9b3f6 removing debug line 2016-06-07 23:45:55 +09:00
Alex Shinn
9c14ee2dea fix complex asin (issue #359) 2016-06-07 23:42:48 +09:00
Alex Shinn
16eae5341e adding -Dfeature command-line option (issue #356) 2016-06-07 23:03:38 +09:00
Alex Shinn
2aa87f4522 fixing complex sqrt near branch cut (issue #353) 2016-06-07 22:47:43 +09:00
Alex Shinn
f5c47c467d preserve -0.0 when added to exact 0 2016-06-07 22:43:49 +09:00
Alex Shinn
ab3f3ad3a0 PRIoff is also "%lld" for Win64. Fixes issue #358. 2016-06-07 22:36:01 +09:00
Alex Shinn
8ac14b5f91 Fixing printing of x-0.0i (issue #352). 2016-06-06 22:18:47 +09:00
Alex Shinn
be3c76b43f Merge pull request #355 from mnieper/trace-option
Prevent segfault when '-t' option is given without argument
2016-06-06 20:51:36 +09:00
Alex Shinn
d9484f8969 Merge pull request #354 from mnieper/asin
Handle imaginary values of inverse of sine and cosine on the real axis.
2016-06-06 20:50:32 +09:00
Marc Nieper-Wißkirchen
fb14733921 Prevent segfault when '-t' option is given without argument 2016-06-06 08:57:45 +02:00
Marc Nieper-Wißkirchen
fdf537902b Handle imaginary values of inverse of sine and cosine on the real axis.
Fixes #167.
2016-06-05 18:38:05 +02:00
Alex Shinn
d975aac7ed Hashes in symbol names need to be escaped with |...|.
Fixes issue #348.
2016-06-05 22:34:39 +09:00
Alex Shinn
fdab1188c1 The #!fold-case directive is always case-insensitive.
Fixes issue #349.
2016-06-05 22:29:52 +09:00
Alex Shinn
7cb15a7191 Handling exact zero imaginary parts in complex asin.
Fixes issue #350.
2016-06-05 22:25:18 +09:00
Alex Shinn
60448d1d3b "\xNN;" inline hex escapes should also support uppercase \X.
Fixes issue #347.
2016-06-04 22:19:43 +09:00
Alex Shinn
0a0db861ed Fixing intraline whitespace parsing followed immediately by another escape.
Fixes issue #343.
2016-06-04 22:06:35 +09:00
Alex Shinn
28148e52b7 guard should raise, not raise-continuable, as the default
Fixes issue #346.
2016-06-04 21:49:12 +09:00
Alex Shinn
b238edb0cd fixing tar-create (bad timestamps and wrong args to directory-fold-tree)
Fixes issue #344.
2016-06-01 00:42:43 +09:00
Alex Shinn
dbeb784701 Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2016-05-19 23:38:27 +09:00
Alex Shinn
5804493889 additional string-cursor fixes for snow 2016-05-19 23:38:13 +09:00
Alex Shinn
8cf8d4394c Merge pull request #342 from vmanis/master
Modify makefiles to make LDCONFIG optional, support systems with no s…
2016-05-19 08:06:49 +09:00
Vincent Manis
e73c888279 Modify makefiles to make LDCONFIG optional, support systems with no symlinks.
- Makefile.libs: changed definition of LN to LN -sf, so can be overridden
    with LN=cp on systems with no symlinks; introduced LDCONFIG, so can be
    overridden if desired.

  - Makefile: changed uses of $(LN) -sf to $(LN); replaced two occurrences
    of ldconfig by $(LDCONFIG); suppress install of $(IMAGE_FILES) if variable
    is empty.

Note: the IMAGE_FILES change was to enable Chibi to be compiled on GNURoot+Android,
and can be reasonably reverted if an alternate way of dealing with image files
is chosen.
2016-05-18 14:11:39 -07:00
Alex Shinn
3d8fbafab9 fixing disjoint cursor bug 2016-05-19 00:56:02 +09:00
Alex Shinn
1d0b67586a more intersection/difference tests 2016-05-18 23:17:26 +09:00
Alex Shinn
cccfe33f7f patch from kipples for ffi struct args (fixes issue #330) 2016-05-18 22:36:59 +09:00
Alex Shinn
25a8e4f11a adding more srfi 130 tests 2016-05-17 23:38:45 +09:00
Alex Shinn
09dc9f89af optimizing iset-intersection 2016-05-17 23:38:29 +09:00
Alex Shinn
ee90f25d7f Avoid stripping syntactic closures in more cases. Fixes issue #339. 2016-05-17 00:53:57 +09:00
Alex Shinn
c1e7e1f23a duplicate labels only forbidden for definition, not referencing 2016-05-16 23:25:52 +09:00
Alex Shinn
1e76e39b9a don't allow redefining reader labels
Fixes issue #337.
2016-05-16 22:56:51 +09:00
Alex Shinn
8a8705693e overdue optimization for iset-diff (and char-set-complement) 2016-05-16 08:12:56 +09:00
Alex Shinn
c7b9cb0879 Fix #x#i... numeric parsing (fixes issue #332). 2016-05-15 20:27:36 +09:00
Alex Shinn
046f22a33d adding optional third argument to default (non-chibi, non-srfi-23) string-contains 2016-05-15 20:11:21 +09:00
Alex Shinn
f1a2a8a8e0 s/string-cursor-backward/string-cursor-back/g 2016-05-15 20:07:26 +09:00
Alex Shinn
19f6ea6054 s/string-cursor-backward/string-cursor-back 2016-05-15 07:40:38 +09:00
Alex Shinn
d019c05150 adding a 3-arg string-contains test 2016-05-15 07:37:49 +09:00
Alex Shinn
c005459335 removing string-split-right 2016-05-12 08:11:41 +09:00
Alex Shinn
2165f19af5 more srfi 130 tests and fixes 2016-05-12 00:14:50 +09:00
Alex Shinn
5ab99635c5 Corner cases in complex infinities. Fixes issue #331. 2016-05-11 23:19:22 +09:00
Alex Shinn
0113e1e5d5 fixing string-contains-right 2016-05-11 08:07:32 +09:00
Alex Shinn
1621d481f3 adding initial chibi version of SRFI 130 2016-05-10 22:49:31 +09:00
Alex Shinn
757ff7733e making string-contains accept/return cursors 2016-05-10 22:48:32 +09:00
Alex Shinn
dba286d130 string-contains should return a string-cursor 2016-05-09 23:52:38 +09:00
Alex Shinn
7b88bdca36 disjoint cursor bugs in server-util 2016-05-08 16:03:43 +09:00
Alex Shinn
90a13333e1 updating default language in manpage to (scheme small) 2016-05-07 23:44:21 +09:00
Alex Shinn
2a05db5382 Zero angle polars are real. Fixes issue #329. 2016-05-04 21:31:55 +09:00
Alex Shinn
64b8e5f8a3 fixing negative fixnum exponents in expt
Fixes issue #328.
2016-05-04 20:59:23 +09:00
Alex Shinn
345da04e72 Fix containing-module on opcodes (fixes issue #326). 2016-05-01 16:50:27 +09:00
Alex Shinn
b9244e39f6 fixing doc typos 2016-05-01 16:43:52 +09:00
Alex Shinn
0763d47d1c fixing disjoint cursor bug in create-directory* 2016-04-29 09:13:17 +09:00
Alex Shinn
e6bddd9199 module-defines? should analyze the module if needed 2016-04-29 09:07:02 +09:00
Alex Shinn
1258c12f34 correcting register-simple-type documentation 2016-04-14 22:45:17 +09:00
Alex Shinn
3b57a78f98 Merge pull request #322 from mnieper/emscripten
Exclude unsupported functions in Emscripten version
2016-04-10 13:11:36 +09:00
Marc Nieper-Wißkirchen
92c74a566a Update system.sld
Remove unconditional exports
2016-04-09 16:13:43 +02:00
Alex Shinn
ed9b0b5a70 Merge pull request #319 from mnieper/patch-1
Update r5rs.sld
2016-04-09 20:36:23 +09:00
Alex Shinn
78e8a04dd6 Conditionally defining PRIoff for off_t printf.
Fixes issue #320.
2016-04-09 20:09:57 +09:00
Alex Shinn
d8a29fed49 fixing disjoint cursor type bug in string-common-prefix-length 2016-04-08 22:56:53 +09:00
Marc Nieper-Wisskirchen
11f5a5473e Exclude unsupported functions in Emscripten version 2016-04-08 15:48:45 +02:00
Alex Shinn
f32e3086b5 fixing bug in string-find? 2016-04-08 22:05:46 +09:00
Marc Nieper-Wißkirchen
578f205eff Update r5rs.sld
Add missing identifiers from erratum 22 of http://trac.sacrideo.us/wg/wiki/R7RSSmallErrata.
2016-04-07 16:36:19 +02:00
Alex Shinn
d1a7f54114 ignoring image files 2016-04-05 00:41:54 +09:00
Alex Shinn
7f22b61cf2 removing non-portable passing of improper list to macro
Fixes issue #318.
2016-04-02 18:10:44 +09:00
Alex Shinn
1ec9d578d0 fixing number->string for non-full-numeric-tower builds 2016-03-30 22:33:29 +09:00
Alex Shinn
0c80f38a19 making string-cursors a disjoint type 2016-03-29 22:25:09 +09:00
Alex Shinn
3dcac282ad removing test-error cases that would trigger a compile-time error in chicken 2016-03-19 15:40:00 +09:00
Alex Shinn
2e0aa1b36d adding missing ; in string hex escapes required by r7rs 2016-03-19 15:26:10 +09:00
Alex Shinn
0251d14653 making (chibi term ansi) tests standalone to avoid circular dep on (chibi test) 2016-03-19 15:15:28 +09:00
Alex Shinn
57dd5464c5 Handling ratios, inexact and complex in number->string.
Fixes issue #317.
2016-03-19 15:12:09 +09:00
Alex Shinn
fec1016254 Fix for additional edge cases in escaping symbols on output. 2016-03-19 15:01:05 +09:00
Alex Shinn
55257b75e3 Write should pipe-escape symbols beginning with a number.
Fixes issue #316.
2016-03-14 09:09:00 +09:00
Alex Shinn
ec430071eb default snow-chibi command uses snow.img 2016-03-13 15:42:47 +09:00
Alex Shinn
4599766346 use search path for image files 2016-03-13 15:25:42 +09:00
Alex Shinn
22bfa48698 fix escaping |.| on write, and funny symbols in srfi 38 in general 2016-03-13 09:33:24 +09:00
Alex Shinn
eed963381c allow loading images from offsets 2016-03-13 09:08:41 +09:00
Alex Shinn
524179388d making image save/load functions public 2016-03-08 23:13:16 +09:00
Alex Shinn
3714964cff adding a type check to make-syntactic-closure
Fixes issue #315.
2016-03-07 08:54:23 +09:00
Alex Shinn
6fe952e108 fixing named match-let 2016-03-06 22:54:28 +09:00
Alex Shinn
45c03c5dcb restoring renaming of ... 2016-03-05 00:28:09 +09:00
Alex Shinn
fb24b831b8 fix reading circular refs inside vectors 2016-03-04 23:41:16 +09:00
Alex Shinn
97297221fa When an alternate syntax-rules ellipsis is specified, we must bind this
locally around the macro transformer.  Fixes issue #313.
2016-03-02 23:34:39 +09:00
Alex Shinn
38385c52eb removing bashisms from makefile 2016-03-02 22:57:09 +09:00
Alex Shinn
255b167597 make out-of-order define warning less zealous for begin/include
Fixes issue #312.
2016-03-01 07:44:24 +09:00
Alex Shinn
f66797ecdf Warn on out-of-order defines in bodies (error in strict mode).
Fixes issue #236.
2016-02-28 18:12:32 +09:00
Alex Shinn
b60a9a28a7 move definitions to start of body 2016-02-28 18:05:02 +09:00
Alex Shinn
8ea51a77ce Include current buffered offset in file-position for output ports.
Fixes issue #273.
2016-02-28 17:36:40 +09:00
Alex Shinn
64f3e0fc56 installing chibi and snow images by default 2016-02-27 22:29:19 +09:00
Alex Shinn
fb78ec1d1c removing double renaming of explicit ellipsis in syntax-rules 2016-02-27 16:14:10 +09:00
Alex Shinn
207ae1f24e making syntactic closure free variable handling agree with mit-scheme 2016-02-27 16:06:20 +09:00
Alex Shinn
36651c4115 allow define-syntax inside core let-syntax to splice 2016-02-23 22:28:01 +09:00
Alex Shinn
1f5d816f59 let[rec]-syntax should not splice 2016-02-22 23:05:12 +09:00
Alex Shinn
11ad0c3e3d fixing boehm build, excluding image code when not used 2016-02-20 23:49:28 +09:00
Alex Shinn
710d1584ba Adding credit to Chris. 2016-02-20 23:39:04 +09:00
Alex Shinn
8ff6d7f4b8 remove // comments, uneeded checks 2016-02-20 23:35:41 +09:00
Alex Shinn
6fc3d15653 Merge pull request #310 from cwds/image
Image
2016-02-20 23:29:02 +09:00
Chris Walsh
9db22a4f7a Made static definitions for srfi/95 and srfi/27 so work with images. Put makefile back to -O3 so optimized binaries made by default 2016-02-20 09:16:58 -05:00
Chris Walsh
bc82f836a3 Previous checkin incomplete - fixed omissions 2016-02-17 12:15:36 -05:00
Chris Walsh
948070eedc Sorted heaps in memory order to allow for arbitrarily allocated heaps to be packed. Tests passing on Ubuntu now, which allocates memory top to bottom 2016-02-17 11:22:40 -05:00
Chris Walsh
9f10e3656c Bit better error reporting 2016-02-16 12:10:28 -05:00
Chris Walsh
2005c19ea0 Added full support for packed images, both for static and dynamic libraries. 2016-02-15 21:12:58 -05:00
Alex Shinn
83c5792673 handle #x+0 (fixes issue #309) 2016-02-05 01:30:32 +09:00
Alex Shinn
8a739d2698 handle [+-].[^0-9] symbols (fixes issue #307) 2016-02-04 23:30:39 +09:00
Alex Shinn
3cf21ee8db Mark unterminated strings and symbols in (srfi 38) as read-incomplete errors.
Fixes issue #305.
2016-02-02 22:55:30 +09:00
Alex Shinn
65150a5583 Merge pull request #306 from okuoku/issue302-2
test/ffi: Complete removal of delete-file on shared object
2016-02-02 22:21:36 +09:00
okuoku
c7cf34fc6f tests/ffi: Complete removal of delete-file on .dll
This delete-file would lead test failure on Cygwin and defer actual file
deletion.
2016-02-02 08:24:48 +09:00
Alex Shinn
47381d8802 Fix border case in bignum division when the estimate gives a zero
remainder immediately after having overshot the previous estimate.
Fixes issue #303.
2016-02-01 22:06:26 +09:00
Alex Shinn
3e9092cfcc Raise an error on direct reader label self-references like #1=#1#.
Fixes issue #303.
2016-02-01 21:39:48 +09:00
Alex Shinn
c6ffc27959 patch from okuoku fixing ffi tests on cygwin 2016-02-01 21:29:25 +09:00
Alex Shinn
9a9202716c don't try to create an image for a chunked heap 2016-01-26 23:36:55 +09:00
Alex Shinn
3e28bdef8b wrap delete-file in protect for cygwin
The file may still be referenced by the parent process.
Fixes issue #302.
2016-01-25 22:04:14 +09:00
Alex Shinn
557b31e1dd allow internal defines in guard 2016-01-20 07:03:41 +09:00
Alex Shinn
a01ca4bad6 Adding (scheme process-context) to (scheme small).
Fixes issue #300.
2016-01-13 21:59:59 +09:00
Alex Shinn
4578fb25d5 Merge pull request #299 from t6/patch-1
Provide overridable PKGCONFDIR and INSTALL_EXE variables in Makefile
2016-01-07 09:04:39 +09:00
Tobias Kortkamp
bd584435cd Provide overridable PKGCONFDIR and INSTALL_EXE variables in Makefile
Adding these options will simplify the FreeBSD port of chibi-scheme
(https://freshports.org/lang/chibi-scheme) because I can get rid of
most of the custom patches currently needed.  In FreeBSD pkg-config
files need to be installed into libdata/pkgconfig.  INSTALL_EXE
provides a hook for replacing the normal 'install' program with
'install -s' for stripping the binaries/libraries.  Adding these
options should have no impact on the default build process.
2016-01-06 22:36:07 +01:00
Alex Shinn
2c2ff588df Smarter polling in blocked output without threads, enable polling in blocked input.
Fixes issue #295.
2015-12-30 14:07:50 +09:00
Alex Shinn
72de1df228 push, don't define, for let{rec}-syntax bindings
Fixes issue #298.
2015-12-30 13:33:12 +09:00
Alex Shinn
82c5035b23 handling syntactic closures in repl tab completion 2015-12-23 17:33:36 +09:00
Alex Shinn
b4ab726e8e Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2015-12-23 17:27:07 +09:00
Alex Shinn
e21736ac5d fixing bug in type inference 2015-12-23 17:26:51 +09:00
Alex Shinn
8cbeb0cd87 Merge pull request #294 from cwds/issue_293
Fixed argument name typo active when SEXP_USE_STATIC_LIBS selected
2015-12-18 07:32:06 +09:00
Chris Walsh
8022c7c98d Fixed argument name typo active when SEXP_USE_STATIC_LIBS selected 2015-12-17 00:05:00 -05:00
Alex Shinn
27f17a54f6 Merge pull request #290 from frerejerome/patch-1
Patch-1 for MinGW
2015-12-13 20:24:14 +09:00
Frère Jérôme
2f19dc69b1 Exclude socket.h on Windows (unless using Cygwin) 2015-11-19 09:55:23 +01:00
Frère Jérôme
584f74dbd9 Handle missing strcasestr() in MinGW 2015-11-19 09:37:37 +01:00
Alex Shinn
ac3ae13bcd Merge pull request #289 from frerejerome/patch-1
Remove unnecessary variable referencing
2015-11-04 08:23:22 +09:00
Frère Jérôme
d93f885fd0 Remove unnecessary variable quotation
Those variables are now correctly detected when defined in the parent makefile.
2015-11-03 14:51:49 +01:00
Alex Shinn
3992f14101 A redef is a set!, it doesn't matter what the previous value was.
Fixes issue #285.
2015-11-02 23:00:00 +09:00
Alex Shinn
fdc0396962 quote expr in unnamed time macro
The time was still reported correctly, but took longer and had the wrong name.
Fixes issue #288.
2015-11-02 22:44:48 +09:00
Alex Shinn
344680f3b2 Merge pull request #287 from lexi-lambda/r7rs-tests-asin-acos-exactness
Allow asin and acos to return an exact zero result in the R7RS tests
2015-11-01 22:35:47 +09:00
Alexis King
c5f24c64ce Allow asin and acos to return an exact zero result in the R7RS tests 2015-10-31 18:10:58 -07:00
Alex Shinn
701c752d61 Update homepage url.
Fixes issue #286.
2015-10-31 23:38:18 +09:00
Alex Shinn
856930a12d Merge pull request #283 from frerejerome/patch-1
Emacs syntax highlighting and keyword completion
2015-10-22 23:32:06 +09:00
Frère Jérôme
ae7abd1b58 Update scheme-keywords.el 2015-10-21 18:04:32 +02:00
Frère Jérôme
1a889890c9 Emacs syntax highlighting and keyword completion
Simple highlighting and completion for all R7RS-small "keywords", extracted from the official specification TeX source (stdmod-raw.tex)
2015-10-21 15:29:20 +02:00
Alex Shinn
8d46cc6842 Propagate error message from unfound dynamic lib when not found as builtin either.
Fixes issue #282.
2015-10-11 23:24:00 +09:00
Alex Shinn
23ac772e3a fix boundary case in arithmetic-shift for negative word sized shifts 2015-09-30 22:21:22 +09:00
Alex Shinn
5a7094e2ef fix typo not handling uppercase I in some complex numbers 2015-09-21 15:23:51 +09:00
Alex Shinn
7c333f43da Always push a new env cell on define unless the previous cell was undefined. 2015-09-13 21:49:58 +09:00
Alex Shinn
da845032e5 open-net-io should ior flags w/ non-block, not and them 2015-08-28 23:37:37 +09:00
Alex Shinn
d40ae87fe9 Removing sexp_display from docs. 2015-08-10 22:23:14 +09:00
Alex Shinn
830b016276 removing declarations for sexp_display, now implemented in scheme
Fixes issue #275.
2015-08-10 22:22:07 +09:00
Alex Shinn
3e8872dc48 partial writes are successful 2015-07-29 22:38:25 +09:00
Alex Shinn
1956e38ba0 adding set-syn type 2015-07-29 22:35:15 +09:00
Alex Shinn
05362f3d21 adding meta info for source file for (meta) library 2015-07-26 23:02:35 +09:00
Alex Shinn
2500569861 accepting identifiers to derefence as args to disasm, for macros 2015-07-26 22:26:09 +09:00
Alex Shinn
4382df2fbb Merge branch 'master' of https://github.com/ashinn/chibi-scheme 2015-07-24 22:14:38 +09:00
Alex Shinn
7f1786f854 Merge pull request #274 from wsxiaoys/patch-1
Update AUTHORS
2015-07-24 22:11:52 +09:00
Meng Zhang
ec663c1c39 Update AUTHORS
I guess Meng Zhang and Zhang Meng are referring to the sample person(me)
2015-07-23 14:35:28 -07:00
Alex Shinn
1313daaf15 adding object->integer utility 2015-07-22 23:10:14 +09:00
Alex Shinn
b9b222b2b3 shorter printed names for ast types 2015-07-11 21:15:12 +09:00
Alex Shinn
fe75dbfff5 fixing brace literals for primitive objects containing non-trailing raw nulls 2015-07-11 21:07:17 +09:00
Alex Shinn
9959f90b7a fixing reader labels in core reader for non-trivial cycles
Cycles like #0=(a #1=(#0#) #1#) with an inner cycle looping back to
an outer cycle would cause infinite loops.  We fix these by marking
objects as we patch reader labels, then clearing the marks.
2015-07-11 21:06:28 +09:00
Alex Shinn
76d088d260 adding simple example http server to docs 2015-07-06 23:33:00 +09:00
Alex Shinn
2ee9b3098d servlet uri query parsing should handle + as space 2015-07-06 23:26:00 +09:00
Alex Shinn
bc262aa7ad adding support for reader labels in core reader 2015-07-06 23:18:33 +09:00
Alex Shinn
9b4cadd33f don't bother evaluating literals in (chibi repl) 2015-07-06 20:46:42 +09:00
Alex Shinn
1a2b71688d error instead of segfault for invalid/forged brace literals 2015-07-05 23:15:45 +09:00
Alex Shinn
42c14af4b9 removing support for SEXP_USE_STRING_STREAMS 2015-07-04 23:25:40 +09:00
Alex Shinn
94067a1ffe replacing quick sort in SRFI 95 with a stable merge sort 2015-07-04 23:18:01 +09:00
Alex Shinn
b93aa9cad9 when extracting optional parameter names, offset cadr by 1 2015-07-04 23:17:15 +09:00
Alex Shinn
2a203e9ff5 Replace use of malloc in string ports with a heap-allocated bytevector.
Without this, if SEXP_USE_FINALIZERS=0, constructing output string ports
without closing them would leak memory.  SEXP_USE_FINALIZERS=0 still
requires caution when working with file-backed ports.
2015-07-04 16:54:25 +09:00
Alex Shinn
841bf95509 supporting email stripping for multiple authors 2015-07-01 07:41:47 +09:00
Alex Shinn
0c856a1bba fixing debug_gc build 2015-06-28 16:37:30 +09:00
Alex Shinn
2ecbe98aaf fixing build for non-timed gc 2015-06-27 22:41:23 +09:00
Alex Shinn
f256fc219e optimizing type lookup in sexp_mark 2015-06-27 20:54:30 +09:00
Alex Shinn
49505b4849 adding count to gc timer 2015-06-27 20:43:43 +09:00
Alex Shinn
8b46509ab5 Merge pull request #272 from mnieper/emscripten
Integrate emscripten build process in Makefile
2015-06-24 07:53:49 +09:00
Marc Nieper-Wißkirchen
899a15b725 Integrate emscripten build process in Makefile
Move Emscripten dependencies into separate directory
2015-06-23 19:57:07 +02:00
Alex Shinn
2e4d0aed91 Handling non-pointer struct return types in the ffi. We do a flat memcopy
of the struct to heap.  Only the base case is supported - combining with
multiple values or returning fixed-size arrays of structs won't work.
Fixes issue #270.
2015-06-22 23:01:44 +09:00
Alex Shinn
64f3be9c99 use blocking io by default in snow 2015-06-22 20:51:20 +09:00
Alex Shinn
fdc2558a76 Don't load all of (scheme small) for scripts. 2015-06-21 23:39:18 +09:00
Alex Shinn
854f2f09ed Adding command-line option tests. 2015-06-21 23:14:38 +09:00
Alex Shinn
74cc4372be Fixing -x combined with -m. 2015-06-21 22:47:21 +09:00
Alex Shinn
ad2b9efcdc Allow normal module names for -m, -x, -R, -t. 2015-06-21 15:38:31 +09:00
Alex Shinn
3fe810c86a Fixing weak references. 2015-06-20 23:03:44 +09:00
Alex Shinn
0ceb3726c1 sexp_object_compare should sort different numeric types together.
Fixes issue #271.
2015-06-20 22:40:04 +09:00
Alex Shinn
4ab97dd9bd adding experimental --use-curl option 2015-06-19 00:02:05 +09:00
Alex Shinn
7e634f3b66 procedure-signature should strip synclos from parameters 2015-06-18 23:33:01 +09:00
Alex Shinn
8cf38672cf identifier->symbol should handle nested syntactic closures 2015-06-18 23:32:21 +09:00
Alex Shinn
402828c8e9 adding Steele's three-part test and including numeric tests in test-libs 2015-06-16 22:33:33 +09:00
Alex Shinn
c9a856b8f6 fix path adjustment of inline test files in snow-chibi package command 2015-06-15 23:39:38 +09:00
Alex Shinn
4fc7181c2c Fix in sexp_bignum_quot_rem when the numerator and divisor are equal.
Fixes issue #269.
2015-06-15 23:31:46 +09:00
Alex Shinn
dfc5ca6913 fixing free chunk calculation and counting more sizes 2015-06-15 21:53:34 +09:00
Alex Shinn
c33df79004 adding free-sizes complement to heap-sizes 2015-06-15 21:34:25 +09:00
Alex Shinn
f5326fafc3 adding heap-sizes to check distribution of chunk sizes in heap 2015-06-15 21:04:25 +09:00
Alex Shinn
bd42ffaecd with fixed sized chunk heaps, grow a new heap for the chunk size when applicable 2015-06-14 23:18:36 +09:00
Alex Shinn
950312f13b adding optional tracking of gc time 2015-06-14 23:03:19 +09:00
Alex Shinn
b4c7a7081d Don't bother resetting weak references if none have been allocated. 2015-06-14 16:58:48 +09:00
Alex Shinn
d1c71adb40 Reporting time spec in GC when SEXP_USE_DEBUG_GC > 0. 2015-06-14 16:35:54 +09:00
Alex Shinn
6db194171e Adding option to disable automatic running of finalizers altogether. 2015-06-14 16:19:55 +09:00
Alex Shinn
4527c772c5 (chibi weak) library is a noop when not compiling with weak references. 2015-06-14 15:27:21 +09:00
Alex Shinn
19df6e7578 strip leading parents in package test 2015-06-13 22:06:12 +09:00
Alex Shinn
eab76ce8c1 Fixing #; comments as the last element in a list for (scheme read). 2015-06-13 21:57:31 +09:00
Alex Shinn
a05b94f3c2 fixing bug in extract-program-dependencies 2015-06-13 20:59:01 +09:00
Alex Shinn
ef1ae88b7a Fixing bug in let-optionals option parsing. 2015-06-11 22:52:50 +09:00
Alex Shinn
aeb881412c Fixing regexp-replace substring index error on non-ascii inputs. 2015-06-09 23:19:58 +09:00
Alex Shinn
c52873e8b9 Prefer SRFI 33 over SRFI 60, preventing import cycles when a user has
a SRFI 60 installed which imports (scheme base).  This can still break
in theory if a user installs a third-party SRFI 33 in the search path
in front of the Chibi SRFI 33, but we can't always be safe against
such behavior.
Fixes issue #267.
2015-06-09 00:14:03 +09:00
Alex Shinn
4a19a5161a Removing plain text README since we have README.md. 2015-06-09 00:01:30 +09:00
Alex Shinn
35279b45c3 adding tests for first..tenth 2015-06-08 23:59:55 +09:00
Alex Shinn
a31da07a25 Merge pull request #265 from frerejerome/patch-1
Correction to the 8-10th selector aliases in SRFI-1
2015-06-08 23:55:29 +09:00
Frère Jérôme
749d58eeb4 Shortened logo URI & added Emscripten link 2015-06-07 12:06:33 +02:00
Frère Jérôme
27a4d68d8a Correction to the project logo
Hosted on GitHub
2015-06-07 09:50:43 +02:00
Frère Jérôme
7492964312 Remove warning for inexistant static library
Simple tweak using the *test* system command. Might not be portable enough?
2015-06-07 09:38:40 +02:00
Frère Jérôme
b748174072 Added the proposed project logo 2015-06-06 21:10:23 +02:00
Frère Jérôme
af52cd3690 Initial markdown README 2015-06-06 20:06:08 +02:00
Frère Jérôme
453c0f1a1d Correction to the 8-10th selector aliases 2015-06-06 17:19:45 +02:00
Alex Shinn
2b10080f64 fixing bug in interaction-environment binding for -q quick repl 2015-06-05 23:00:11 +09:00
Alex Shinn
a3f5b10d62 Allowing option parsing to fallback to top-level options from within subcommands. 2015-06-05 22:46:45 +09:00
Alex Shinn
a1c8862aba adding missing stack field_len_base adjustment from f0ee48fc4c 2015-06-04 07:48:16 +09:00
Alex Shinn
438346fc26 When aligning bytecode, pad the skipped bytes with the previous opcode.
This allows for instructions which want to save the previous ip to simply
subtract their operands without needing to preserve the original ip in advance.
2015-06-03 22:29:38 +09:00
Alex Shinn
6d6adc0cbf Fixing string streams build on linux. 2015-06-03 21:50:07 +09:00
Alex Shinn
f0ee48fc4c Fixing type slot specifications. Report from ilammy in issue #235.
- SEXP_STACK had an off by one sexp_type_field_len_base past the top of stack
- SEXP_EXCEPTION claimed 6 slots but only 5 were present
- sexp_type_struct should have had "dl" slot at end
2015-06-03 21:42:57 +09:00
Alex Shinn
577bdeb2b3 Merge pull request #263 from justinethier/master
Update meta-7.scm
2015-06-01 22:41:54 +09:00
Justin Ethier
1e1b9d01b8 Update meta-7.scm
Fix a simple spelling mistake.
2015-05-22 13:42:44 -04:00
Alex Shinn
9f565d77c5 Allow optional sxml for the head section in page. 2015-05-20 21:23:12 +09:00
Alex Shinn
f255c35695 Fixing bug in invalid-signature-reason, allowing a proc value in update-repo-package. 2015-05-19 22:46:36 +09:00
Alex Shinn
ad59eee89f sexp_emit_word should align before expanding 2015-05-12 23:16:58 +09:00
Alex Shinn
607d70c6a0 When directly incrementing or aligning bytecode pos during code generation,
ensure there is enough space just as when emitting.
2015-05-12 23:03:48 +09:00
Alex Shinn
d6b66a32fd Reduce the number of calls to fcntl in sexp_read. 2015-05-12 07:30:44 +09:00
Alex Shinn
09b1e3041c Setting utf-8 charset by default. 2015-05-11 20:40:21 +09:00
613 changed files with 66267 additions and 8062 deletions

30
.githooks/pre-commit Executable file
View file

@ -0,0 +1,30 @@
#!/bin/bash
if git rev-parse --verify HEAD >/dev/null 2>&1; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# fail if we add any new lines to C or Scheme source containing a tab
if git diff --name-only "$against" | egrep -q '\.(cpp|h|scm|sld|stub)$' &&\
git diff --name-only "$against" |\
egrep '\.(cpp|h|scm|sld|stub)$' |\
xargs -d'\n' git diff -U0 --no-color "$against" -- |\
grep -q $'^+ *\t'; then
echo "Error: Attempting to add a source file using tabs for indentation."
echo
echo -n " "
git diff --name-only "$against" |\
egrep '\.(cpp|h|scm|sld|stub)$' |\
xargs -d'\n' git diff -U0 "$against" -- |\
grep $'^+ *\t' | head -1
echo
cat <<EOF
It's important for arguments to line up vertically to a precise column.
Since there is no standard tab width, using tabs for indentation makes
this impossible in general. Please use spaces.
EOF
exit 1
fi

23
.github/workflows/CI.yaml vendored Normal file
View file

@ -0,0 +1,23 @@
name: CI
on: [push, pull_request]
jobs:
build:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Build
run: make # assumes GNUMake
- name: Test
run: make test-all
- name: Setup
run: sudo make install
- name: Run in PATH
run: chibi-scheme r7rs-tests.scm
working-directory: tests

26
.gitignore vendored
View file

@ -1,5 +1,6 @@
# Object files
*.o
*.bc
*.ko
*.obj
*.elf
@ -16,6 +17,7 @@
# Shared objects (inc. Windows DLLs)
*.dll
*.dll.*
*.so
*.so.*
*.dylib
@ -36,6 +38,7 @@ lib/.*.meta
# Generated files
chibi-scheme
chibi-scheme-emscripten
chibi-scheme.pc
include/chibi/install.h
lib/chibi/emscripten.c
@ -43,12 +46,30 @@ lib/chibi/filesystem.c
lib/chibi/io/io.c
lib/chibi/net.c
lib/chibi/process.c
lib/chibi/pty.c
lib/chibi/snow/install.sld
lib/chibi/stty.c
lib/chibi/system.c
lib/chibi/time.c
lib/chibi/win32/process-win32.c
lib/scheme/bytevector.c
lib/srfi/144/math.c
lib/srfi/160/uvprims.c
*.tgz
*.bz2
*.xz
*.html
*.img
*.err
*.fasl
*.txt
!CMakeLists.txt
*.test
*.train
*.h5
!index.html
benchmarks/gabriel/times.tsv
examples/snow-fort
examples/synthcode
tests/snow/repo-cache
@ -58,3 +79,8 @@ tmp
/lib/chibi/crypto/crypto.c
/chibi-scheme-ulimit
/clibs.c
js/chibi.*
build-lib/chibi/char-set/derived.scm
build-lib/chibi/char-set/width.scm

4
.travis.yml Normal file
View file

@ -0,0 +1,4 @@
language: c
compiler:
- clang
- gcc

40
AUTHORS
View file

@ -1,6 +1,11 @@
Alex Shinn wrote the initial version of chibi-scheme and all
distributed modules.
The Emscripten build, syntax-case and SRFI 139 implementation, and
various other patches were contributed by Marc Nieper-Wißkirchen.
The image handling code in gc_heap.c was written by Chris Walsh.
The `dynamic-wind' implementation is adapted from the implementation
in the appendix to the Scheme48 reference manual, reportedly first
written by Chris Hanson and John Lamping.
@ -9,6 +14,17 @@ The (scheme time) module includes code for handling leap seconds
from Alan Watson's Scheme clock library at
http://code.google.com/p/scheme-clock/ under the same license.
The lgamma_r implementation for Windows builds is based on code by
Haruhiko Okumura via Ruby.
The following distributed SRFIs use the reference implementations:
(srfi 101) is adapted from David van Horn's implementation
(srfi 134) is Shiro Kawai's implementation
(srfi 135) is Will Clinger's implementation
(srfi 139), (srfi 146), (srfi 154), (srfi 165) are Marc Nieper-Wißkirchen's implementations
(srfi 146 hash) is Arthur Gleckler's Hash Array Mapped Trie implementation
The benchmarks are based on the Racket versions of the classic
Gabriel benchmarks from
http://www.cs.utah.edu/~mflatt/benchmarks-20100126/log3/index.html.
@ -16,36 +32,58 @@ They are not installed or needed but are included for convenience.
Thanks to the following people for patches and bug reports:
* Adam Feuer
* Alan Watson
* Alexei Lozovsky
* Alexander Shendi
* Andreas Rottman
* Arthur Gleckler
* Bakul Shah
* Ben Davenport-Ray
* Ben Mather
* Ben Weaver
* Bertrand Augereau
* Bradley Lucier
* Bruno Deferrari
* Damien Diederen
* Daphne Preston-Kendal
* Doug Currie
* Derrick Eddington
* Dmitry Chestnykh
* Eduardo Cavazos
* Ekaitz Zarraga
* Felix Winkelmann
* Gregor Klinke
* Jeremy Wolff
* Jeronimo Pellegrini
* John Cowan
* John Samsa
* Jonas Rinke
* Kris Katterjohn
* Lars J Aas
* Lassi Kortela
* Lorenzo Campedelli
* Lukas Böger
* Marc Nieper-Wißkirchen
* McKay Marston
* Meng Zhang
* Michal Kowalski (sladegen)
* Miroslav Urbanek
* Naoki Koguro
* Nguyễn Thái Ngọc Duy
* Petteri Piiroinen
* Rajesh Krishnan
* Ricardo G. Herdt
* Roger Crew
* Seth Alves
* Sören Tempel
* Stephen Lewis
* Taylor Venable
* Travis Cross
* Zhang Meng
* Vasilij Schneidermann
* Vitaliy Mysak
* Yota Toyama
* Yuki Okumura
If you would prefer not to be listed, or are one of the users listed
without a full name, please contact me. If you've made a contribution

603
CMakeLists.txt Normal file
View file

@ -0,0 +1,603 @@
cmake_minimum_required(VERSION 3.12)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/VERSION version)
string(STRIP ${version} version)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/RELEASE release)
string(STRIP ${release} release)
project(chibi-scheme LANGUAGES C VERSION ${version}
DESCRIPTION "Chibi-Scheme: minimal r7rs implementation, release: ${release}")
include(CheckIncludeFile)
include(CheckSymbolExists)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Build type: None, Debug, Release, RelWithDebInfo, MinSizeRel, or Sanitizer." FORCE)
if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt AND NOT CMAKE_BUILD_TYPE)
# CMake doesn't have a default build type, so set one manually
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
endif()
#
# Features
#
check_include_file(poll.h HAVE_POLL_H)
check_symbol_exists(ntp_gettime sys/timex.h HAVE_NTP_GETTIME)
check_symbol_exists(int_least8_t inttypes.h HAVE_STDINT_H)
if (WIN32 AND NOT CYGWIN)
set(DEFAULT_SHARED_LIBS OFF)
else()
set(DEFAULT_SHARED_LIBS ON)
endif()
option(BUILD_SHARED_LIBS "Build chibi-scheme as a shared library" ${DEFAULT_SHARED_LIBS})
option(SEXP_USE_BOEHM "Use Boehm garbage collection library" OFF)
if(SEXP_USE_BOEHM)
find_library(BOEHMGC gc REQUIRED)
find_path(BOEHMGC_INCLUDE NAMES gc/gc.h)
endif()
set(chibi-scheme-exclude-modules)
if(WIN32)
set(chibi-scheme-exclude-modules
# Following modules are not compatible with Win32
lib/chibi/net.sld
lib/chibi/process.sld
lib/chibi/stty.sld
lib/chibi/system.sld
lib/chibi/time.sld
lib/chibi/pty.sld)
endif()
#
# Default settings for all targets. We use an interface library here to not
# pollute/mutate global settings. Any configuration applied to this library
# is propagated to its client targets.
#
add_library(libchibi-common
INTERFACE)
target_compile_definitions(libchibi-common
INTERFACE
SEXP_STATIC_LIBRARY=$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>
SEXP_USE_DL=$<BOOL:${BUILD_SHARED_LIBS}>
$<$<PLATFORM_ID:Windows>:BUILDING_DLL=$<BOOL:${BUILD_SHARED_LIBS}>>
SEXP_USE_INTTYPES=$<BOOL:${HAVE_STDINT_H}>
SEXP_USE_NTPGETTIME=$<BOOL:${HAVE_NTP_GETTIME}>
$<$<NOT:$<BOOL:${HAVE_POLL_H}>>:SEXP_USE_GREEN_THREADS=0>
$<$<PLATFORM_ID:Windows>:SEXP_USE_STRING_STREAMS=0>
$<$<BOOL:${SEXP_USE_BOEHM}>:SEXP_USE_BOEHM=1>)
target_compile_options(libchibi-common
INTERFACE
$<$<C_COMPILER_ID:GNU>:-Wall>
$<$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>:-Wall>
$<$<CONFIG:SANITIZER>:-g
-fsanitize=address,undefined,integer,float-divide-by-zero,float-cast-overflow,return
-fno-omit-frame-pointer>)
target_include_directories(libchibi-common
INTERFACE
${BOEHMGC_INCLUDE}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_link_libraries(libchibi-common INTERFACE
${BOEHMGC}
$<$<CONFIG:SANITIZER>:-fsanitize=address,undefined>
$<$<PLATFORM_ID:Windows>:ws2_32>
$<$<AND:$<PLATFORM_ID:Linux>,$<BOOL:${BUILD_SHARED_LIBS}>>:${CMAKE_DL_LIBS}>
$<$<PLATFORM_ID:Linux>:m>)
#
# Sources
#
set(chibi-scheme-srcs
# SEXP
gc.c
sexp.c
bignum.c
gc_heap.c
# Eval
opcodes.c
vm.c
eval.c
simplify.c)
#
# Bootstrap
#
add_executable(chibi-scheme-bootstrap
EXCLUDE_FROM_ALL
${chibi-scheme-srcs}
main.c)
target_link_libraries(chibi-scheme-bootstrap PRIVATE libchibi-common)
#
# Core library
#
add_library(libchibi-scheme
${chibi-scheme-srcs})
target_link_libraries(libchibi-scheme
PUBLIC libchibi-common)
set_target_properties(libchibi-scheme
PROPERTIES
PREFIX "" # It's liblibchibi-scheme otherwise
SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR}
VERSION ${CMAKE_PROJECT_VERSION})
#
# Generate modules
#
file(GLOB_RECURSE slds RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
CONFIGURE_DEPENDS lib/*.sld)
if (chibi-scheme-exclude-modules)
# CMake doesn't complain anymore about an empty 2nd argument, but 3.12 does. When we require a
# more recent version, the if-guard should go.
list(REMOVE_ITEM slds ${chibi-scheme-exclude-modules})
endif()
set(chibi-ffi ${CMAKE_CURRENT_SOURCE_DIR}/tools/chibi-ffi)
set(chibi-genstatic ${CMAKE_CURRENT_SOURCE_DIR}/tools/chibi-genstatic)
add_custom_target(chibi-compiled-libs)
function(add_compiled_library cfile)
if (NOT BUILD_SHARED_LIBS)
return()
endif()
set(link-libraries LINK_LIBRARIES)
cmake_parse_arguments(compiledlib-options "" "" "${link-libraries}" ${ARGN})
get_filename_component(basename ${cfile} NAME_WE)
get_filename_component(libdir ${cfile} DIRECTORY)
if(NOT IS_ABSOLUTE ${libdir})
set(libdir ${CMAKE_CURRENT_BINARY_DIR}/${libdir})
endif()
file(RELATIVE_PATH libname ${CMAKE_CURRENT_BINARY_DIR} ${libdir}/${basename})
string(REPLACE "/" "-" libname ${libname})
add_library(${libname} ${cfile})
target_link_libraries(${libname} PRIVATE libchibi-scheme ${compiledlib-options_LINK_LIBRARIES})
add_dependencies(chibi-compiled-libs ${libname})
set_target_properties(${libname} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${libdir}
LIBRARY_OUTPUT_NAME ${basename}
PREFIX "")
file(RELATIVE_PATH installsubdir ${CMAKE_CURRENT_BINARY_DIR}/lib ${libdir})
install(TARGETS ${libname}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/chibi/${installsubdir})
endfunction()
if(BUILD_SHARED_LIBS)
# This makes sure we only use the separate bootstrap executable for static
# builds. With dynamic linking, the default executable is fine. The dispatch
# is not a generator expression within the actual custom command to process
# the stubs, as older CMake versions fail to properly construct the dependency
# on the bootstrap executable from the generator expression.
set(bootstrap chibi-scheme)
else()
set(bootstrap chibi-scheme-bootstrap)
endif()
function(add_stubs_library stub)
set(link-libraries LINK_LIBRARIES)
cmake_parse_arguments(stubs-options "" "" "${link-libraries}" ${ARGN})
get_filename_component(stubdir ${stub} PATH)
get_filename_component(basename ${stub} NAME_WE)
set(stubfile ${CMAKE_CURRENT_SOURCE_DIR}/${stub})
set(stubdir ${CMAKE_CURRENT_BINARY_DIR}/${stubdir})
set(stubout ${stubdir}/${basename}.c)
set(stubouts ${stubouts} ${stubout} PARENT_SCOPE)
set(stublinkedlibs ${stublinkedlibs} ${stubs-options_LINK_LIBRARIES} PARENT_SCOPE)
file(MAKE_DIRECTORY ${stubdir})
add_custom_command(OUTPUT ${stubout}
COMMAND ${bootstrap} ${chibi-ffi} ${stubfile} ${stubout}
DEPENDS ${stubfile} ${chibi-ffi}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_compiled_library(${stubout} LINK_LIBRARIES ${stubs-options_LINK_LIBRARIES})
endfunction()
add_stubs_library(lib/chibi/crypto/crypto.stub)
add_stubs_library(lib/chibi/emscripten.stub)
add_stubs_library(lib/chibi/filesystem.stub)
add_stubs_library(lib/chibi/io/io.stub)
add_stubs_library(lib/scheme/bytevector.stub)
add_stubs_library(lib/srfi/144/math.stub)
add_stubs_library(lib/srfi/160/uvprims.stub)
if(NOT WIN32)
add_stubs_library(lib/chibi/net.stub)
add_stubs_library(lib/chibi/process.stub)
add_stubs_library(lib/chibi/pty.stub LINK_LIBRARIES util)
add_stubs_library(lib/chibi/stty.stub)
add_stubs_library(lib/chibi/system.stub)
add_stubs_library(lib/chibi/time.stub)
else()
add_stubs_library(lib/chibi/win32/process-win32.stub)
endif()
add_custom_target(chibi-scheme-stubs DEPENDS ${stubouts})
if (NOT BUILD_SHARED_LIBS)
add_dependencies(libchibi-scheme chibi-scheme-stubs)
endif()
add_compiled_library(lib/chibi/weak.c)
add_compiled_library(lib/chibi/heap-stats.c)
add_compiled_library(lib/chibi/disasm.c)
add_compiled_library(lib/chibi/ast.c)
add_compiled_library(lib/chibi/json.c)
add_compiled_library(lib/srfi/18/threads.c)
add_compiled_library(lib/chibi/optimize/rest.c)
add_compiled_library(lib/chibi/optimize/profile.c)
add_compiled_library(lib/srfi/27/rand.c)
add_compiled_library(lib/srfi/151/bit.c)
add_compiled_library(lib/srfi/39/param.c)
add_compiled_library(lib/srfi/69/hash.c)
add_compiled_library(lib/srfi/95/qsort.c)
add_compiled_library(lib/srfi/98/env.c)
add_compiled_library(lib/scheme/time.c)
#
# Generate clib.c for SEXP_USE_STATIC_LIBS
#
if (NOT BUILD_SHARED_LIBS)
string(REPLACE ";" "\n" genstatic-input "${slds}")
set(clibin ${CMAKE_CURRENT_BINARY_DIR}/clib-in.txt)
set(clibout ${CMAKE_CURRENT_BINARY_DIR}/clib.c)
set(genstatic-helper
${CMAKE_CURRENT_LIST_DIR}/contrib/chibi-genstatic-helper.cmake)
file(WRITE ${clibin} "${genstatic-input}")
add_custom_command(OUTPUT ${clibout}
COMMAND
${CMAKE_COMMAND}
-DEXEC=$<TARGET_FILE:chibi-scheme-bootstrap>
-DGENSTATIC=${chibi-genstatic}
-DSTUBS=${clibin}
-DOUT=${clibout}
-P ${genstatic-helper}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
chibi-scheme-bootstrap
${chibi-genstatic}
${genstatic-helper}
${slds})
# The generated file will #include both manually written files in
# the source directory as well as files generated by chibi-ffi in
# the build directory. The latter can be found without special flags,
# as they are relative to the clib.c, but the preprocessor needs
# help for the former. As only clib.c needs this flag, we set it
# as locally as possible, i.e., not as a target property.
set_source_files_properties(${clibout}
PROPERTIES
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(libchibi-scheme
PUBLIC
SEXP_USE_STATIC_LIBS=1)
target_sources(libchibi-scheme
PRIVATE
${clibout})
target_link_libraries(libchibi-scheme
PRIVATE
${stublinkedlibs})
endif()
#
# Interpreter
#
add_executable(chibi-scheme
main.c)
target_link_libraries(chibi-scheme
PRIVATE libchibi-scheme)
#
# Generate "chibi/install.h"
#
if(WIN32)
set(platform "windows")
elseif(CYGWIN)
set(platform "cygwin")
elseif(APPLE)
set(platform "macosx")
elseif(CMAKE_SYSTEM MATCHES "[Bb][Ss][Dd]")
set(platform "bsd")
elseif(CMAKE_SYSTEM MATCHES "[Aa]ndroid")
set(platform "android")
elseif(CMAKE_SYSTEM MATCHES "[Ss]un[Oo][Ss]")
set(platform "solaris")
elseif (CMAKE_SYSTEM MATCHES "[Ll]inux")
set(platform "linux")
else()
set(platform "unix")
endif()
if(WIN32)
# Leave this empty for now, as the default GNU install directories won't
# help on Windows.
set(default_module_path "")
else()
string(JOIN ":" default_module_path
${CMAKE_INSTALL_FULL_DATAROOTDIR}/chibi
${CMAKE_INSTALL_FULL_LIBDIR}/chibi
${CMAKE_INSTALL_FULL_DATAROOTDIR}/snow
${CMAKE_INSTALL_FULL_LIBDIR}/snow)
endif()
configure_file(include/chibi/install.h.in include/chibi/install.h)
#
# Testing
#
enable_testing()
set(chibi-scheme-tests
r7rs-tests
division-tests
syntax-tests
unicode-tests)
foreach(e ${chibi-scheme-tests})
add_test(NAME "${e}"
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib tests/${e}.scm
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endforeach()
add_test(NAME r5rs-test
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib -xchibi tests/r5rs-tests.scm
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB_RECURSE srfi_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/lib
CONFIGURE_DEPENDS lib/srfi/*/test.sld)
file(GLOB_RECURSE chibi_scheme_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/lib
CONFIGURE_DEPENDS lib/chibi/*-test.sld)
set(win32testexcludes
# Excluded tests
chibi/filesystem-test
chibi/memoize-test
chibi/term/ansi-test
chibi/weak-test
# Not ported to Win32
srfi/18/test # Threading
chibi/doc-test # Depends (chibi time)
chibi/log-test
chibi/system-test
chibi/tar-test # Depends (chibi system)
chibi/process-test # Not applicable
chibi/pty-test # Depends (chibi pty)
chibi/shell-test # Depends Linux procfs
)
foreach(e ${srfi_tests} ${chibi_scheme_tests})
get_filename_component(pth ${e} PATH)
get_filename_component(nam ${e} NAME_WE)
list(APPEND testlibs ${pth}/${nam})
endforeach()
if(WIN32)
list(REMOVE_ITEM testlibs ${win32testexcludes})
endif()
foreach(e ${testlibs})
string(REGEX REPLACE "/" "_" testname ${e})
string(REGEX REPLACE "/" " " form ${e})
add_test(NAME "lib_${testname}"
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib
-e "(import (${form}))"
-e "(run-tests)"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endforeach()
#
# Testing (embedding)
#
add_executable(test-foreign-apply-loop
tests/foreign/apply-loop.c)
target_link_libraries(test-foreign-apply-loop
PRIVATE libchibi-scheme)
add_test(NAME "foreign-apply-loop"
COMMAND test-foreign-apply-loop
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_executable(test-foreign-typeid
tests/foreign/typeid.c)
target_link_libraries(test-foreign-typeid
PRIVATE libchibi-scheme)
add_test(NAME "foreign-typeid"
COMMAND test-foreign-typeid
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
#
# Image, pkgconfig and meta file generation
#
add_custom_command(OUTPUT chibi.img
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib -mchibi.repl
-d ${CMAKE_CURRENT_BINARY_DIR}/chibi.img
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_command(OUTPUT red.img
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib -xscheme.red -mchibi.repl
-d ${CMAKE_CURRENT_BINARY_DIR}/red.img
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_command(OUTPUT snow.img
COMMAND chibi-scheme -I ${CMAKE_CURRENT_BINARY_DIR}/lib
-mchibi.snow.commands -mchibi.snow.interface -mchibi.snow.package -mchibi.snow.utils
-d ${CMAKE_CURRENT_BINARY_DIR}/snow.img
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
if(BUILD_SHARED_LIBS)
# Currently, image dumps only work with shared library builds, which includes Windows
add_custom_target(chibi-images ALL
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/chibi.img
${CMAKE_CURRENT_BINARY_DIR}/red.img
${CMAKE_CURRENT_BINARY_DIR}/snow.img
# The dependency on libchibi-scheme is crucial here:
chibi-compiled-libs)
endif()
configure_file(contrib/chibi-scheme.pc.cmake.in chibi-scheme.pc @ONLY)
function(generate_package_list libdir output)
add_custom_command(OUTPUT ${output}
COMMAND
${CMAKE_COMMAND}
-DEXEC=$<TARGET_FILE:chibi-scheme>
-DLIBDIR=${libdir}
-DGENMETA=tools/generate-install-meta.scm
-DVERSION=${CMAKE_PROJECT_VERSION}
-DOUT=${CMAKE_CURRENT_BINARY_DIR}/${output}
-P contrib/chibi-generate-install-meta-helper.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
chibi-scheme
tools/generate-install-meta.scm
contrib/chibi-generate-install-meta-helper.cmake)
endfunction()
generate_package_list(lib/chibi .chibi.meta)
generate_package_list(lib/scheme .scheme.meta)
generate_package_list(lib/srfi .srfi.meta)
add_custom_target(chibi-meta-lists ALL
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/.chibi.meta
${CMAKE_CURRENT_BINARY_DIR}/.scheme.meta
${CMAKE_CURRENT_BINARY_DIR}/.srfi.meta)
#
# Installation
#
install(DIRECTORY include/chibi
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
PATTERN "sexp-*.[hc]" EXCLUDE
PATTERN "*.h.in" EXCLUDE)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/chibi/install.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/chibi)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/chibi-scheme.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
add_library(chibi::libchibi-scheme ALIAS libchibi-scheme)
install(TARGETS libchibi-scheme libchibi-common chibi-scheme
EXPORT chibi-scheme-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES
tools/chibi-ffi
tools/chibi-doc
tools/snow-chibi
tools/snow-chibi.scm
DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES
doc/chibi-scheme.1
doc/chibi-ffi.1
doc/chibi-doc.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
if(BUILD_SHARED_LIBS)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/chibi.img
${CMAKE_CURRENT_BINARY_DIR}/red.img
${CMAKE_CURRENT_BINARY_DIR}/snow.img
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/chibi)
endif()
install(DIRECTORY
lib/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/chibi
PATTERN "*win32" EXCLUDE
PATTERN "*test.sld" EXCLUDE
PATTERN "*.c" EXCLUDE
PATTERN "*.stub" EXCLUDE)
# This is to revert the above exclusion pattern
install(FILES lib/chibi/test.sld
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/chibi/chibi)
if(WIN32)
install(DIRECTORY
lib/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/chibi
FILES_MATCHING
PATTERN "*win32/*.scm"
PATTERN "*win32/*.sld")
endif()
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/.chibi.meta
${CMAKE_CURRENT_BINARY_DIR}/.scheme.meta
${CMAKE_CURRENT_BINARY_DIR}/.srfi.meta
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/chibi)
install(EXPORT chibi-scheme-targets
FILE chibi-scheme-targets.cmake
NAMESPACE chibi::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/chibi)
write_basic_package_version_file(chibi-scheme-config-version.cmake
VERSION ${CMAKE_PROJECT_VERSION}
COMPATIBILITY ExactVersion)
install(FILES
contrib/chibi-scheme-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/chibi-scheme-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/chibi)

13
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,13 @@
# Contributing to Chibi-Scheme
Thanks for your interest!
Chibi-Scheme is fun and easy to hack. If you want to contribute your
changes back upstream, there are just a few guidelines:
* Code must be released following the license in COPYING.
* New modules likely belong on snow-fort.org, not the core distribution.
* Chibi values small size over speed.
* Features should be built up in layers, not added directly to the core.
* Once you're ready to contribute, run `make init-dev` to install some
local settings (currently only git submit hooks).

View file

@ -1,4 +1,4 @@
Copyright (c) 2009-2015 Alex Shinn
Copyright (c) 2009-2021 Alex Shinn
All rights reserved.
Redistribution and use in source and binary forms, with or without

363
Makefile
View file

@ -1,94 +1,112 @@
# -*- makefile-gmake -*-
.PHONY: dist mips-dist cleaner test test-all test-dist checkdefs debian snowballs
.PHONY: dist mips-dist cleaner distclean dist-clean test test-all test-dist checkdefs debian snowballs init-dev
.DEFAULT_GOAL := all
VERSION ?= $(shell cat VERSION)
SOVERSION ?= $(VERSION)
CHIBI_VERSION ?= $(shell cat VERSION)
SOVERSION ?= $(CHIBI_VERSION)
SOVERSION_MAJOR ?= $(shell echo "$(SOVERSION)" | sed "s/\..*//")
CHIBI_FFI ?= $(CHIBI) -q tools/chibi-ffi
CHIBI_FFI_DEPENDENCIES ?= $(CHIBI_DEPENDENCIES) tools/chibi-ffi
CHIBI_DOC ?= $(CHIBI) tools/chibi-doc
CHIBI_DOC_DEPENDENCIES ?= $(CHIBI_DEPENDENCIES) tools/chibi-doc
CHIBI_DOC_DEPENDENCIES ?= $(CHIBI_DEPENDENCIES) tools/chibi-doc $(COMPILED_LIBS)
GENSTATIC ?= ./tools/chibi-genstatic
CHIBI ?= LD_LIBRARY_PATH=".:$(LD_LIBRARY_PATH)" DYLD_LIBRARY_PATH=".:$(DYLD_LIBRARY_PATH)" CHIBI_MODULE_PATH=lib ./chibi-scheme$(EXE)
CHIBI ?= LD_LIBRARY_PATH=".:$(LD_LIBRARY_PATH)" DYLD_LIBRARY_PATH=".:$(DYLD_LIBRARY_PATH)" CHIBI_IGNORE_SYSTEM_PATH=1 CHIBI_MODULE_PATH=lib ./chibi-scheme$(EXE)
CHIBI_DEPENDENCIES = ./chibi-scheme$(EXE)
SNOW_CHIBI ?= $(CHIBI) tools/snow-chibi
SNOW_CHIBI ?= tools/snow-chibi
########################################################################
CHIBI_COMPILED_LIBS = lib/chibi/filesystem$(SO) lib/chibi/process$(SO) \
lib/chibi/time$(SO) lib/chibi/system$(SO) lib/chibi/stty$(SO) \
lib/chibi/weak$(SO) lib/chibi/heap-stats$(SO) lib/chibi/disasm$(SO) \
lib/chibi/net$(SO) lib/chibi/ast$(SO) lib/chibi/emscripten$(SO)
CHIBI_COMPILED_LIBS = lib/chibi/filesystem$(SO) lib/chibi/weak$(SO) \
lib/chibi/heap-stats$(SO) lib/chibi/disasm$(SO) lib/chibi/ast$(SO) \
lib/chibi/json$(SO) lib/chibi/emscripten$(SO)
CHIBI_POSIX_COMPILED_LIBS = lib/chibi/process$(SO) lib/chibi/time$(SO) \
lib/chibi/system$(SO) lib/chibi/stty$(SO) lib/chibi/pty$(SO) \
lib/chibi/net$(SO) lib/srfi/18/threads$(SO)
CHIBI_WIN32_COMPILED_LIBS = lib/chibi/win32/process-win32$(SO)
CHIBI_CRYPTO_COMPILED_LIBS = lib/chibi/crypto/crypto$(SO)
CHIBI_IO_COMPILED_LIBS = lib/chibi/io/io$(SO)
CHIBI_OPT_COMPILED_LIBS = lib/chibi/optimize/rest$(SO) \
lib/chibi/optimize/profile$(SO)
EXTRA_COMPILED_LIBS ?=
COMPILED_LIBS = $(CHIBI_COMPILED_LIBS) $(CHIBI_IO_COMPILED_LIBS) \
$(CHIBI_OPT_COMPILED_LIBS) $(CHIBI_CRYPTO_COMPILED_LIBS) \
$(EXTRA_COMPILED_LIBS) \
lib/srfi/18/threads$(SO) lib/srfi/27/rand$(SO) lib/srfi/33/bit$(SO) \
lib/srfi/27/rand$(SO) lib/srfi/151/bit$(SO) \
lib/srfi/39/param$(SO) lib/srfi/69/hash$(SO) lib/srfi/95/qsort$(SO) \
lib/srfi/98/env$(SO) lib/scheme/time$(SO)
lib/srfi/98/env$(SO) lib/srfi/144/math$(SO) lib/srfi/160/uvprims$(SO) \
lib/scheme/bytevector$(SO) lib/scheme/time$(SO)
BASE_INCLUDES = include/chibi/sexp.h include/chibi/features.h include/chibi/install.h include/chibi/bignum.h
INCLUDES = $(BASE_INCLUDES) include/chibi/eval.h
INCLUDES = $(BASE_INCLUDES) include/chibi/eval.h include/chibi/gc_heap.h
MODULE_DOCS := app ast config disasm equiv filesystem generic heap-stats io \
loop match mime modules net parse pathname process repl scribble stty \
system test time trace type-inference uri weak monad/environment \
show show/base crypto/sha2
MODULE_DOCS := app assert ast base64 binary-record bytevector config \
crypto/md5 crypto/rsa crypto/sha2 diff disasm doc edit-distance \
equiv filesystem generic heap-stats io \
iset/base iset/constructors iset/iterators json loop \
match math/prime memoize mime modules net net/http-server net/servlet \
optional parse pathname process repl scribble string stty sxml system \
temp-file test time trace type-inference uri weak monad/environment \
crypto/sha2 shell
HTML_LIBS = $(MODULE_DOCS:%=doc/lib/chibi/%.html)
IMAGE_FILES = lib/chibi.img lib/red.img lib/snow.img
HTML_LIBS = $(MODULE_DOCS:%=doc/lib/chibi/%.html) doc/lib/srfi/166/base.html
META_FILES = lib/.chibi.meta lib/.srfi.meta lib/.scheme.meta
########################################################################
# This includes the rules to build optional libraries.
# It also pulls in Makefile.detect for platform detection.
include Makefile.libs
########################################################################
# Library config.
#
# This is to allow "make SEXP_USE_BOEHM=1" and "make SEXP_USE_DL=0" to
# automatically include the necessary compiler and linker flags in
# addition to setting those features. If not using GNU make just
# comment out the ifs and use the else branches for the defaults.
ifeq ($(SEXP_USE_BOEHM),1)
GCLDFLAGS := -lgc
XCPPFLAGS := $(CPPFLAGS) -Iinclude $(D:%=-DSEXP_USE_%) -DSEXP_USE_BOEHM=1
else
GCLDFLAGS :=
XCPPFLAGS := $(CPPFLAGS) -Iinclude $(D:%=-DSEXP_USE_%)
endif
ifeq ($(SEXP_USE_DL),0)
XLDFLAGS := $(LDFLAGS) $(RLDFLAGS) $(GCLDFLAGS) -lm
XCFLAGS := -Wall -DSEXP_USE_DL=0 -g -g3 -O3 $(CFLAGS)
else
XLDFLAGS := $(LDFLAGS) $(RLDFLAGS) $(GCLDFLAGS) $(LIBDL) -lm
XCFLAGS := -Wall -g -g3 -O3 $(CFLAGS)
endif
########################################################################
all: chibi-scheme$(EXE) all-libs chibi-scheme.pc $(META_FILES)
include/chibi/install.h: Makefile
# Please run this if you want to contribute.
init-dev:
git config core.hooksPath .githooks
js: js/chibi.js
js/chibi.js: chibi-scheme-emscripten chibi-scheme-static.bc js/pre.js js/post.js js/exported_functions.json
emcc -O0 chibi-scheme-static.bc -o $@ -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s EXPORT_NAME=\"Chibi\" -s EXPORTED_FUNCTIONS=@js/exported_functions.json `find lib -type f \( -name "*.scm" -or -name "*.sld" \) -printf " --preload-file %p"` -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]' --pre-js js/pre.js --post-js js/post.js
chibi-scheme-static.bc:
emmake $(MAKE) PLATFORM=emscripten CHIBI_DEPENDENCIES= CHIBI=./chibi-scheme-emscripten PREFIX= CFLAGS=-O2 SEXP_USE_DL=0 EXE=.bc SO=.bc STATICFLAGS=-shared CPPFLAGS="-DSEXP_USE_STRICT_TOPLEVEL_BINDINGS=1 -DSEXP_USE_ALIGNED_BYTECODE=1 -DSEXP_USE_STATIC_LIBS=1 -DSEXP_USE_STATIC_LIBS_NO_INCLUDE=0" clibs.c chibi-scheme-static.bc VERBOSE=1
chibi-scheme-emscripten: VERSION
$(MAKE) distclean
$(MAKE) chibi-scheme-static PLATFORM=emscripten SEXP_USE_DL=0
(tempfile="`mktemp -t chibi.XXXXXX`" && \
mv chibi-scheme-static$(EXE) "$$tempfile" && \
$(MAKE) distclean; \
mv "$$tempfile" chibi-scheme-emscripten)
include/chibi/install.h: Makefile.libs Makefile.detect
echo '#define sexp_so_extension "'$(SO)'"' > $@
echo '#define sexp_default_module_path "'$(MODDIR):$(BINMODDIR)'"' >> $@
echo '#define sexp_default_module_path "'$(MODDIR):$(BINMODDIR):$(SNOWMODDIR):$(SNOWBINMODDIR)'"' >> $@
echo '#define sexp_platform "'$(PLATFORM)'"' >> $@
echo '#define sexp_version "'$(VERSION)'"' >> $@
echo '#define sexp_architecture "'$(ARCH)'"' >> $@
echo '#define sexp_version "'$(CHIBI_VERSION)'"' >> $@
echo '#define sexp_release_name "'`cat RELEASE`'"' >> $@
lib/chibi/snow/install.sld: Makefile.libs Makefile.detect
echo '(define-library (chibi snow install)' > $@
echo ' (import (scheme base))' >> $@
echo ' (export snow-module-directory snow-binary-module-directory)' >> $@
echo ' (begin' >> $@
echo ' (define snow-module-directory "'$(SNOWMODDIR)'")' >> $@
echo ' (define snow-binary-module-directory "'$(SNOWBINMODDIR)'")))' >> $@
%.o: %.c $(BASE_INCLUDES)
$(CC) -c $(XCPPFLAGS) $(XCFLAGS) $(CLIBFLAGS) -o $@ $<
@ -101,8 +119,8 @@ sexp-ulimit.o: sexp.c $(BASE_INCLUDES)
main.o: main.c $(INCLUDES)
$(CC) -c $(XCPPFLAGS) $(XCFLAGS) -o $@ $<
SEXP_OBJS = gc.o sexp.o bignum.o
SEXP_ULIMIT_OBJS = gc-ulimit.o sexp-ulimit.o bignum.o
SEXP_OBJS = gc.o sexp.o bignum.o gc_heap.o
SEXP_ULIMIT_OBJS = gc-ulimit.o sexp-ulimit.o bignum.o gc_heap.o
EVAL_OBJS = opcodes.o vm.o eval.o simplify.o
libchibi-sexp$(SO): $(SEXP_OBJS)
@ -112,25 +130,29 @@ libchibi-scheme$(SO_VERSIONED_SUFFIX): $(SEXP_OBJS) $(EVAL_OBJS)
$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(LIBCHIBI_FLAGS) -o $@ $^ $(XLDFLAGS)
libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX): libchibi-scheme$(SO_VERSIONED_SUFFIX)
$(LN) -sf $< $@
$(LN) $< $@
libchibi-scheme$(SO): libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX)
$(LN) -sf $< $@
$(LN) $< $@
libchibi-scheme.a: $(SEXP_OBJS) $(EVAL_OBJS)
$(AR) rcs $@ $^
chibi-scheme$(EXE): main.o libchibi-scheme$(SO)
$(CC) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< -L. -lchibi-scheme
$(CC) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< -L. $(RLDFLAGS) -lchibi-scheme
chibi-scheme-static$(EXE): main.o $(SEXP_OBJS) $(EVAL_OBJS)
$(CC) $(XCFLAGS) $(STATICFLAGS) -o $@ $^ $(LDFLAGS) $(GCLDFLAGS) -lm
$(CC) $(XCFLAGS) $(STATICFLAGS) -o $@ $^ $(LDFLAGS) $(GCLDFLAGS) $(STATIC_LDFLAGS)
chibi-scheme-ulimit$(EXE): main.o $(SEXP_ULIMIT_OBJS) $(EVAL_OBJS)
$(CC) $(XCFLAGS) $(STATICFLAGS) -o $@ $^ $(LDFLAGS) $(GCLDFLAGS) -lm
$(CC) $(XCFLAGS) $(STATICFLAGS) -o $@ $^ $(LDFLAGS) $(GCLDFLAGS) $(STATIC_LDFLAGS)
clibs.c: $(GENSTATIC) $(CHIBI_DEPENDENCIES) $(COMPILED_LIBS:%$(SO)=%.c)
$(FIND) lib -name \*.sld | $(CHIBI) -q $(GENSTATIC) > $@
if [ -d .git ]; then \
$(GIT) ls-files lib | $(GREP) .sld | $(CHIBI) -q $(GENSTATIC) > $@; \
else \
$(FIND) lib -name \*.sld | $(CHIBI) -q $(GENSTATIC) > $@; \
fi
chibi-scheme.pc: chibi-scheme.pc.in
echo "# pkg-config" > chibi-scheme.pc
@ -138,23 +160,39 @@ chibi-scheme.pc: chibi-scheme.pc.in
echo "exec_prefix=\$${prefix}" >> chibi-scheme.pc
echo "libdir=$(LIBDIR)" >> chibi-scheme.pc
echo "includedir=\$${prefix}/include" >> chibi-scheme.pc
echo "version=$(VERSION)" >> chibi-scheme.pc
echo "version=$(CHIBI_VERSION)" >> chibi-scheme.pc
echo "" >> chibi-scheme.pc
cat chibi-scheme.pc.in >> chibi-scheme.pc
# A special case, this needs to be linked with the LDFLAGS in case
# we're using Boehm.
lib/chibi/ast$(SO): lib/chibi/ast.c $(INCLUDES) libchibi-scheme$(SO)
-$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< $(GCLDFLAGS) -L. -lchibi-scheme
-$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< $(GCLDFLAGS) -L. $(RLDFLAGS) -lchibi-scheme
lib/chibi/crypto/crypto.c: lib/chibi/crypto/sha2.c
lib/chibi/filesystem.c: lib/chibi/filesystem_win32_shim.c
lib/chibi/io/io.c: lib/chibi/io/port.c
lib/chibi/net.c: lib/chibi/accept.c
lib/chibi/process.c: lib/chibi/signal.c
lib/srfi/144/math.c: lib/srfi/144/lgamma_r.c
lib/chibi.img: $(CHIBI_DEPENDENCIES) all-libs
$(CHIBI) -d $@
lib/snow.img: $(CHIBI_DEPENDENCIES) all-libs
$(CHIBI) -mchibi.snow.commands -d $@
lib/red.img: $(CHIBI_DEPENDENCIES) all-libs
$(CHIBI) -xscheme.red -mchibi.repl -d $@
doc: doc/chibi.html doc-libs
%.html: %.scrbl $(CHIBI_DOC_DEPENDENCIES)
$(CHIBI_DOC) --html $< > $@
lib/.%.meta: lib/%/ tools/generate-install-meta.scm
lib/.%.meta: lib/%/ tools/generate-install-meta.scm $(CHIBI_DEPENDENCIES)
-$(FIND) $< -name \*.sld | \
$(CHIBI) tools/generate-install-meta.scm $(VERSION) > $@
$(CHIBI) tools/generate-install-meta.scm $(CHIBI_VERSION) > $@
########################################################################
# Dist builds - rules to build generated files included in distribution
@ -167,14 +205,25 @@ data/%.txt:
build-lib/chibi/char-set/derived.scm: data/UnicodeData.txt data/DerivedCoreProperties.txt chibi-scheme$(EXE)
$(CHIBI) tools/extract-unicode-props.scm --default > $@
build-lib/chibi/char-set/width.scm: data/UnicodeData.txt data/EastAsianWidth.txt chibi-scheme$(EXE)
$(CHIBI) tools/extract-unicode-props.scm Zero-Width=Mn > $@
$(CHIBI) tools/extract-unicode-props.scm -d data/EastAsianWidth.txt Full-Width=F@1,W@1 Ambiguous-Width=A@1 >> $@
lib/chibi/char-set/ascii.scm: build-lib/chibi/char-set/derived.scm chibi-scheme$(EXE)
$(CHIBI) -Abuild-lib tools/optimize-char-sets.scm --ascii chibi.char-set.compute > $@
lib/chibi/char-set/full.scm: build-lib/chibi/char-set/derived.scm chibi-scheme$(EXE)
$(CHIBI) -Abuild-lib tools/optimize-char-sets.scm chibi.char-set.compute > $@
lib/scheme/char/case-offsets.scm: data/CaseFolding.txt chibi-scheme$(EXE) all-libs
$(CHIBI) tools/extract-case-offsets.scm $< > $@
lib/chibi/show/width.scm: build-lib/chibi/char-set/width.scm chibi-scheme$(EXE)
$(CHIBI) -Abuild-lib tools/optimize-char-sets.scm --predicate chibi.char-set.width > $@
lib/scheme/char/case-offsets.scm: data/UnicodeData.txt data/CaseFolding.txt chibi-scheme$(EXE) all-libs
$(CHIBI) tools/extract-case-offsets.scm data/UnicodeData.txt data/CaseFolding.txt > $@
# WARNING: this has a line for ß added by hand
lib/scheme/char/special-casing.scm: data/CaseFolding.txt data/SpecialCasing.txt chibi-scheme$(EXE) all-libs
$(CHIBI) tools/extract-special-casing.scm data/CaseFolding.txt data/SpecialCasing.txt > $@
########################################################################
# Tests
@ -202,22 +251,23 @@ test-memory: chibi-scheme-ulimit$(EXE)
test-build:
MAKE=$(MAKE) ./tests/build/build-tests.sh
test-run:
./tests/run/command-line-tests.sh
test-ffi: chibi-scheme$(EXE)
$(CHIBI) tests/ffi/ffi-tests.scm
test-snow: chibi-scheme$(EXE)
test-snow: chibi-scheme$(EXE) $(IMAGE_FILES)
$(CHIBI) tests/snow/snow-tests.scm
test-numbers: chibi-scheme$(EXE)
$(CHIBI) -xchibi tests/numeric-tests.scm
test-flonums: chibi-scheme$(EXE)
$(CHIBI) -xchibi tests/flonum-tests.scm
test-unicode: chibi-scheme$(EXE)
$(CHIBI) -xchibi tests/unicode-tests.scm
test-division: chibi-scheme$(EXE)
$(CHIBI) tests/division-tests.scm
test-libs: chibi-scheme$(EXE)
@echo "\e[1mloading tests first, it may take a while to see output...\e[0m"
$(CHIBI) tests/lib-tests.scm
test-r5rs: chibi-scheme$(EXE)
@ -226,9 +276,16 @@ test-r5rs: chibi-scheme$(EXE)
test-r7rs: chibi-scheme$(EXE)
$(CHIBI) tests/r7rs-tests.scm
test-syntax: chibi-scheme$(EXE)
$(CHIBI) tests/syntax-tests.scm
test: test-r7rs
test-all: test test-libs test-ffi
test-safe-string-cursors: chibi-scheme$(EXE)
$(CHIBI) -Dsafe-string-cursors tests/r7rs-tests.scm
$(CHIBI) -Dsafe-string-cursors tests/lib-tests.scm
test-all: test test-syntax test-libs test-ffi test-division
test-dist: test-all test-memory test-build
@ -239,25 +296,33 @@ bench-gabriel: chibi-scheme$(EXE)
# Packaging
clean: clean-libs
-$(RM) *.o *.i *.s *.8 tests/basic/*.out tests/basic/*.err
-$(RM) *.o *.i *.s *.bc *.8 tests/basic/*.out tests/basic/*.err \
tests/run/*.out tests/run/*.err
cleaner: clean
-$(RM) chibi-scheme$(EXE) chibi-scheme-static$(EXE) chibi-scheme-ulimit$(EXE) \
libchibi-scheme$(SO)* *.a *.pc include/chibi/install.h lib/.*.meta \
$(IMAGE_FILES) libchibi-scheme*$(SO) *.a *.pc \
libchibi-scheme$(SO_VERSIONED_SUFFIX) \
libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX) \
include/chibi/install.h lib/.*.meta \
chibi-scheme-emscripten \
js/chibi.* \
$(shell $(FIND) lib -name \*.o)
dist-clean: dist-clean-libs cleaner
distclean: dist-clean-libs cleaner
dist-clean: distclean
install: all
install-base: all
$(MKDIR) $(DESTDIR)$(BINDIR)
$(INSTALL) -m0755 chibi-scheme$(EXE) $(DESTDIR)$(BINDIR)/
$(INSTALL_EXE) -m0755 chibi-scheme$(EXE) $(DESTDIR)$(BINDIR)/
$(INSTALL) -m0755 tools/chibi-ffi $(DESTDIR)$(BINDIR)/
$(INSTALL) -m0755 tools/chibi-doc $(DESTDIR)$(BINDIR)/
$(INSTALL) -m0755 tools/snow-chibi $(DESTDIR)$(BINDIR)/
$(MKDIR) $(DESTDIR)$(MODDIR)/chibi/char-set $(DESTDIR)$(MODDIR)/chibi/crypto $(DESTDIR)$(MODDIR)/chibi/io $(DESTDIR)$(MODDIR)/chibi/iset $(DESTDIR)$(MODDIR)/chibi/loop $(DESTDIR)$(MODDIR)/chibi/match $(DESTDIR)$(MODDIR)/chibi/math $(DESTDIR)$(MODDIR)/chibi/monad $(DESTDIR)$(MODDIR)/chibi/net $(DESTDIR)$(MODDIR)/chibi/optimize $(DESTDIR)$(MODDIR)/chibi/parse $(DESTDIR)$(MODDIR)/chibi/regexp $(DESTDIR)$(MODDIR)/chibi/show $(DESTDIR)$(MODDIR)/chibi/snow $(DESTDIR)$(MODDIR)/chibi/term
$(INSTALL) -m0755 tools/snow-chibi.scm $(DESTDIR)$(BINDIR)/
$(MKDIR) $(DESTDIR)$(MODDIR)/chibi/char-set $(DESTDIR)$(MODDIR)/chibi/crypto $(DESTDIR)$(MODDIR)/chibi/io $(DESTDIR)$(MODDIR)/chibi/iset $(DESTDIR)$(MODDIR)/chibi/loop $(DESTDIR)$(MODDIR)/chibi/match $(DESTDIR)$(MODDIR)/chibi/math $(DESTDIR)$(MODDIR)/chibi/monad $(DESTDIR)$(MODDIR)/chibi/net $(DESTDIR)$(MODDIR)/chibi/optimize $(DESTDIR)$(MODDIR)/chibi/parse $(DESTDIR)$(MODDIR)/chibi/regexp $(DESTDIR)$(MODDIR)/chibi/show $(DESTDIR)$(MODDIR)/chibi/snow $(DESTDIR)$(MODDIR)/chibi/term $(DESTDIR)$(MODDIR)/chibi/text
$(MKDIR) $(DESTDIR)$(MODDIR)/scheme/char
$(MKDIR) $(DESTDIR)$(MODDIR)/scheme/time
$(MKDIR) $(DESTDIR)$(MODDIR)/srfi/1 $(DESTDIR)$(MODDIR)/srfi/18 $(DESTDIR)$(MODDIR)/srfi/27 $(DESTDIR)$(MODDIR)/srfi/33 $(DESTDIR)$(MODDIR)/srfi/39 $(DESTDIR)$(MODDIR)/srfi/69 $(DESTDIR)$(MODDIR)/srfi/95 $(DESTDIR)$(MODDIR)/srfi/99 $(DESTDIR)$(MODDIR)/srfi/99/records
$(MKDIR) $(DESTDIR)$(MODDIR)/srfi/1 $(DESTDIR)$(MODDIR)/srfi/18 $(DESTDIR)$(MODDIR)/srfi/27 $(DESTDIR)$(MODDIR)/srfi/151 $(DESTDIR)$(MODDIR)/srfi/39 $(DESTDIR)$(MODDIR)/srfi/69 $(DESTDIR)$(MODDIR)/srfi/95 $(DESTDIR)$(MODDIR)/srfi/99 $(DESTDIR)$(MODDIR)/srfi/99/records $(DESTDIR)$(MODDIR)/srfi/113 $(DESTDIR)$(MODDIR)/srfi/117 $(DESTDIR)$(MODDIR)/srfi/121 $(DESTDIR)$(MODDIR)/srfi/125 $(DESTDIR)$(MODDIR)/srfi/128 $(DESTDIR)$(MODDIR)/srfi/129 $(DESTDIR)$(MODDIR)/srfi/132 $(DESTDIR)$(MODDIR)/srfi/133 $(DESTDIR)$(MODDIR)/srfi/135 $(DESTDIR)$(MODDIR)/srfi/143 $(DESTDIR)$(MODDIR)/srfi/144 $(DESTDIR)$(MODDIR)/srfi/159 $(DESTDIR)$(MODDIR)/srfi/160 $(DESTDIR)$(MODDIR)/srfi/166 $(DESTDIR)$(MODDIR)/srfi/146 $(DESTDIR)$(MODDIR)/srfi/179 $(DESTDIR)$(MODDIR)/srfi/211 $(DESTDIR)$(MODDIR)/srfi/231
$(INSTALL) -m0644 $(META_FILES) $(DESTDIR)$(MODDIR)/
$(INSTALL) -m0644 lib/*.scm $(DESTDIR)$(MODDIR)/
$(INSTALL) -m0644 lib/chibi/*.sld lib/chibi/*.scm $(DESTDIR)$(MODDIR)/chibi/
@ -276,51 +341,87 @@ install: all
$(INSTALL) -m0644 lib/chibi/show/*.sld lib/chibi/show/*.scm $(DESTDIR)$(MODDIR)/chibi/show/
$(INSTALL) -m0644 lib/chibi/snow/*.sld lib/chibi/snow/*.scm $(DESTDIR)$(MODDIR)/chibi/snow/
$(INSTALL) -m0644 lib/chibi/term/*.sld lib/chibi/term/*.scm $(DESTDIR)$(MODDIR)/chibi/term/
$(INSTALL) -m0644 lib/chibi/text/*.sld lib/chibi/text/*.scm $(DESTDIR)$(MODDIR)/chibi/text/
$(INSTALL) -m0644 lib/scheme/*.sld lib/scheme/*.scm $(DESTDIR)$(MODDIR)/scheme/
$(INSTALL) -m0644 lib/scheme/char/*.sld lib/scheme/char/*.scm $(DESTDIR)$(MODDIR)/scheme/char/
$(INSTALL) -m0644 lib/scheme/time/*.sld $(DESTDIR)$(MODDIR)/scheme/time/
$(INSTALL) -m0644 lib/srfi/*.sld lib/srfi/*.scm $(DESTDIR)$(MODDIR)/srfi/
$(INSTALL) -m0644 lib/srfi/1/*.sld $(DESTDIR)$(MODDIR)/srfi/1/
$(INSTALL) -m0644 lib/srfi/1/*.scm $(DESTDIR)$(MODDIR)/srfi/1/
$(INSTALL) -m0644 lib/srfi/18/*.scm $(DESTDIR)$(MODDIR)/srfi/18/
$(INSTALL) -m0644 lib/srfi/27/*.scm $(DESTDIR)$(MODDIR)/srfi/27/
$(INSTALL) -m0644 lib/srfi/33/*.scm $(DESTDIR)$(MODDIR)/srfi/33/
$(INSTALL) -m0644 lib/srfi/39/*.scm $(DESTDIR)$(MODDIR)/srfi/39/
$(INSTALL) -m0644 lib/srfi/69/*.scm $(DESTDIR)$(MODDIR)/srfi/69/
$(INSTALL) -m0644 lib/srfi/95/*.scm $(DESTDIR)$(MODDIR)/srfi/95/
$(INSTALL) -m0644 lib/srfi/99/*.sld $(DESTDIR)$(MODDIR)/srfi/99/
$(INSTALL) -m0644 lib/srfi/99/records/*.sld lib/srfi/99/records/*.scm $(DESTDIR)$(MODDIR)/srfi/99/records/
$(INSTALL) -m0644 lib/srfi/113/*.scm $(DESTDIR)$(MODDIR)/srfi/113/
$(INSTALL) -m0644 lib/srfi/117/*.scm $(DESTDIR)$(MODDIR)/srfi/117/
$(INSTALL) -m0644 lib/srfi/121/*.scm $(DESTDIR)$(MODDIR)/srfi/121/
$(INSTALL) -m0644 lib/srfi/125/*.scm $(DESTDIR)$(MODDIR)/srfi/125/
$(INSTALL) -m0644 lib/srfi/128/*.scm $(DESTDIR)$(MODDIR)/srfi/128/
$(INSTALL) -m0644 lib/srfi/129/*.scm $(DESTDIR)$(MODDIR)/srfi/129/
$(INSTALL) -m0644 lib/srfi/132/*.scm $(DESTDIR)$(MODDIR)/srfi/132/
$(INSTALL) -m0644 lib/srfi/133/*.scm $(DESTDIR)$(MODDIR)/srfi/133/
$(INSTALL) -m0644 lib/srfi/135/*.sld lib/srfi/135/*.scm $(DESTDIR)$(MODDIR)/srfi/135/
$(INSTALL) -m0644 lib/srfi/143/*.scm $(DESTDIR)$(MODDIR)/srfi/143/
$(INSTALL) -m0644 lib/srfi/144/*.scm $(DESTDIR)$(MODDIR)/srfi/144/
$(INSTALL) -m0644 lib/srfi/151/*.scm $(DESTDIR)$(MODDIR)/srfi/151/
$(INSTALL) -m0644 lib/srfi/159/*.scm $(DESTDIR)$(MODDIR)/srfi/159/
$(INSTALL) -m0644 lib/srfi/159/*.sld $(DESTDIR)$(MODDIR)/srfi/159/
$(INSTALL) -m0644 lib/srfi/160/*.sld $(DESTDIR)$(MODDIR)/srfi/160/
$(INSTALL) -m0644 lib/srfi/160/*.scm $(DESTDIR)$(MODDIR)/srfi/160/
$(INSTALL) -m0644 lib/srfi/166/*.sld $(DESTDIR)$(MODDIR)/srfi/166/
$(INSTALL) -m0644 lib/srfi/166/*.scm $(DESTDIR)$(MODDIR)/srfi/166/
$(INSTALL) -m0644 lib/srfi/146/*.sld $(DESTDIR)$(MODDIR)/srfi/146/
$(INSTALL) -m0644 lib/srfi/146/*.scm $(DESTDIR)$(MODDIR)/srfi/146/
$(INSTALL) -m0644 lib/srfi/179/*.sld $(DESTDIR)$(MODDIR)/srfi/179/
$(INSTALL) -m0644 lib/srfi/179/*.scm $(DESTDIR)$(MODDIR)/srfi/179/
$(INSTALL) -m0644 lib/srfi/211/*.sld $(DESTDIR)$(MODDIR)/srfi/211/
$(INSTALL) -m0644 lib/srfi/231/*.sld lib/srfi/231/*.scm $(DESTDIR)$(MODDIR)/srfi/231/
$(MKDIR) $(DESTDIR)$(BINMODDIR)/chibi/crypto/
$(MKDIR) $(DESTDIR)$(BINMODDIR)/chibi/io/
$(MKDIR) $(DESTDIR)$(BINMODDIR)/chibi/optimize/
$(MKDIR) $(DESTDIR)$(BINMODDIR)/scheme/
$(MKDIR) $(DESTDIR)$(BINMODDIR)/srfi/18 $(DESTDIR)$(BINMODDIR)/srfi/27 $(DESTDIR)$(BINMODDIR)/srfi/33 $(DESTDIR)$(BINMODDIR)/srfi/39 $(DESTDIR)$(BINMODDIR)/srfi/69 $(DESTDIR)$(BINMODDIR)/srfi/95 $(DESTDIR)$(BINMODDIR)/srfi/98
$(INSTALL) -m0755 $(CHIBI_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/
$(INSTALL) -m0755 $(CHIBI_CRYPTO_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/crypto/
$(INSTALL) -m0755 $(CHIBI_IO_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/io/
$(INSTALL) -m0755 $(CHIBI_OPT_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/optimize/
$(INSTALL) -m0755 lib/scheme/time$(SO) $(DESTDIR)$(BINMODDIR)/scheme/
$(INSTALL) -m0755 lib/srfi/18/threads$(SO) $(DESTDIR)$(BINMODDIR)/srfi/18
$(INSTALL) -m0755 lib/srfi/27/rand$(SO) $(DESTDIR)$(BINMODDIR)/srfi/27
$(INSTALL) -m0755 lib/srfi/33/bit$(SO) $(DESTDIR)$(BINMODDIR)/srfi/33
$(INSTALL) -m0755 lib/srfi/39/param$(SO) $(DESTDIR)$(BINMODDIR)/srfi/39
$(INSTALL) -m0755 lib/srfi/69/hash$(SO) $(DESTDIR)$(BINMODDIR)/srfi/69
$(INSTALL) -m0755 lib/srfi/95/qsort$(SO) $(DESTDIR)$(BINMODDIR)/srfi/95
$(INSTALL) -m0755 lib/srfi/98/env$(SO) $(DESTDIR)$(BINMODDIR)/srfi/98
$(MKDIR) $(DESTDIR)$(BINMODDIR)/srfi/18 $(DESTDIR)$(BINMODDIR)/srfi/27 $(DESTDIR)$(BINMODDIR)/srfi/151 $(DESTDIR)$(BINMODDIR)/srfi/39 $(DESTDIR)$(BINMODDIR)/srfi/69 $(DESTDIR)$(BINMODDIR)/srfi/95 $(DESTDIR)$(BINMODDIR)/srfi/98 $(DESTDIR)$(BINMODDIR)/srfi/144 $(DESTDIR)$(BINMODDIR)/srfi/160
$(INSTALL_EXE) -m0755 $(CHIBI_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/
$(INSTALL_EXE) -m0755 $(CHIBI_CRYPTO_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/crypto/
$(INSTALL_EXE) -m0755 $(CHIBI_IO_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/io/
$(INSTALL_EXE) -m0755 $(CHIBI_OPT_COMPILED_LIBS) $(DESTDIR)$(BINMODDIR)/chibi/optimize/
$(INSTALL_EXE) -m0755 lib/scheme/time$(SO) $(DESTDIR)$(BINMODDIR)/scheme/
$(INSTALL_EXE) -m0755 lib/scheme/bytevector$(SO) $(DESTDIR)$(BINMODDIR)/scheme/
$(INSTALL_EXE) -m0755 lib/srfi/18/threads$(SO) $(DESTDIR)$(BINMODDIR)/srfi/18
$(INSTALL_EXE) -m0755 lib/srfi/27/rand$(SO) $(DESTDIR)$(BINMODDIR)/srfi/27
$(INSTALL_EXE) -m0755 lib/srfi/39/param$(SO) $(DESTDIR)$(BINMODDIR)/srfi/39
$(INSTALL_EXE) -m0755 lib/srfi/69/hash$(SO) $(DESTDIR)$(BINMODDIR)/srfi/69
$(INSTALL_EXE) -m0755 lib/srfi/95/qsort$(SO) $(DESTDIR)$(BINMODDIR)/srfi/95
$(INSTALL_EXE) -m0755 lib/srfi/98/env$(SO) $(DESTDIR)$(BINMODDIR)/srfi/98
$(INSTALL_EXE) -m0755 lib/srfi/144/math$(SO) $(DESTDIR)$(BINMODDIR)/srfi/144
$(INSTALL_EXE) -m0755 lib/srfi/151/bit$(SO) $(DESTDIR)$(BINMODDIR)/srfi/151
$(INSTALL_EXE) -m0755 lib/srfi/160/uvprims$(SO) $(DESTDIR)$(BINMODDIR)/srfi/160
$(MKDIR) $(DESTDIR)$(INCDIR)
$(INSTALL) -m0644 $(INCLUDES) $(DESTDIR)$(INCDIR)/
$(MKDIR) $(DESTDIR)$(LIBDIR)
$(MKDIR) $(DESTDIR)$(SOLIBDIR)
$(INSTALL) -m0755 libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/
$(LN) -s -f libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX)
$(LN) -s -f libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO)
-$(INSTALL) -m0644 libchibi-scheme.a $(DESTDIR)$(SOLIBDIR)/
$(MKDIR) $(DESTDIR)$(SOLIBDIR)/pkgconfig
$(INSTALL) -m0644 chibi-scheme.pc $(DESTDIR)$(SOLIBDIR)/pkgconfig/
$(INSTALL_EXE) -m0755 libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/
$(LN) libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX)
$(LN) libchibi-scheme$(SO_VERSIONED_SUFFIX) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO)
-if test -f libchibi-scheme.a; then $(INSTALL) -m0644 libchibi-scheme.a $(DESTDIR)$(SOLIBDIR)/; fi
$(MKDIR) $(DESTDIR)$(PKGCONFDIR)
$(INSTALL) -m0644 chibi-scheme.pc $(DESTDIR)$(PKGCONFDIR)
$(MKDIR) $(DESTDIR)$(MANDIR)
$(INSTALL) -m0644 doc/chibi-scheme.1 $(DESTDIR)$(MANDIR)/
$(INSTALL) -m0644 doc/chibi-ffi.1 $(DESTDIR)$(MANDIR)/
$(INSTALL) -m0644 doc/chibi-doc.1 $(DESTDIR)$(MANDIR)/
-if type ldconfig >/dev/null 2>/dev/null; then ldconfig; fi
-if type $(LDCONFIG) >/dev/null 2>/dev/null; then $(LDCONFIG) >/dev/null 2>/dev/null; fi
install: install-base
ifneq "$(IMAGE_FILES)" ""
echo "Generating images"
-[ -z "$(DESTDIR)" ] && LD_LIBRARY_PATH="$(SOLIBDIR):$(LD_LIBRARY_PATH)" DYLD_LIBRARY_PATH="$(SOLIBDIR):$(DYLD_LIBRARY_PATH)" CHIBI_MODULE_PATH="$(MODDIR):$(BINMODDIR)" $(BINDIR)/chibi-scheme$(EXE) -mchibi.repl -d $(MODDIR)/chibi.img
-[ -z "$(DESTDIR)" ] && LD_LIBRARY_PATH="$(SOLIBDIR):$(LD_LIBRARY_PATH)" DYLD_LIBRARY_PATH="$(SOLIBDIR):$(DYLD_LIBRARY_PATH)" CHIBI_MODULE_PATH="$(MODDIR):$(BINMODDIR)" $(BINDIR)/chibi-scheme$(EXE) -xscheme.red -mchibi.repl -d $(MODDIR)/red.img
-[ -z "$(DESTDIR)" ] && LD_LIBRARY_PATH="$(SOLIBDIR):$(LD_LIBRARY_PATH)" DYLD_LIBRARY_PATH="$(SOLIBDIR):$(DYLD_LIBRARY_PATH)" CHIBI_MODULE_PATH="$(MODDIR):$(BINMODDIR)" $(BINDIR)/chibi-scheme$(EXE) -mchibi.snow.commands -mchibi.snow.interface -mchibi.snow.package -mchibi.snow.utils -d $(DESTDIR)$(MODDIR)/snow.img
endif
uninstall:
-$(RM) $(DESTDIR)$(BINDIR)/chibi-scheme$(EXE)
@ -328,15 +429,20 @@ uninstall:
-$(RM) $(DESTDIR)$(BINDIR)/chibi-ffi
-$(RM) $(DESTDIR)$(BINDIR)/chibi-doc
-$(RM) $(DESTDIR)$(BINDIR)/snow-chibi
-$(RM) $(DESTDIR)$(BINDIR)/snow-chibi.scm
-$(RM) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO)
-$(RM) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO_VERSIONED_SUFFIX)
-$(RM) $(DESTDIR)$(SOLIBDIR)/libchibi-scheme$(SO_MAJOR_VERSIONED_SUFFIX)
-$(RM) $(DESTDIR)$(LIBDIR)/libchibi-scheme$(SO).a
-$(RM) $(DESTDIR)$(SOLIBDIR)/pkgconfig/chibi-scheme.pc
-$(CD) $(DESTDIR)$(INCDIR) && $(RM) $(INCLUDES)
-$(RM) $(DESTDIR)$(MODDIR)/srfi/99/records/*.{sld,scm}
-$(RM) $(DESTDIR)$(PKGCONFDIR)/chibi-scheme.pc
-$(CD) $(DESTDIR)$(PREFIX) && $(RM) $(INCLUDES)
-$(RMDIR) $(DESTDIR)$(INCDIR)
-$(RM) $(DESTDIR)$(MODDIR)/srfi/99/records/*.sld
-$(RM) $(DESTDIR)$(MODDIR)/srfi/99/records/*.scm
-$(RM) $(DESTDIR)$(MODDIR)/.*.meta
-$(RM) $(DESTDIR)$(MODDIR)/*.{sld,scm} $(DESTDIR)$(MODDIR)/*/*.{sld,scm} $(DESTDIR)$(MODDIR)/*/*/*.{sld,scm}
-$(RM) $(DESTDIR)$(MODDIR)/*.img
-$(RM) $(DESTDIR)$(MODDIR)/*.sld $(DESTDIR)$(MODDIR)/*/*.sld $(DESTDIR)$(MODDIR)/*/*/*.sld
-$(RM) $(DESTDIR)$(MODDIR)/*.scm $(DESTDIR)$(MODDIR)/*/*.scm $(DESTDIR)$(MODDIR)/*/*/*.scm
-$(CD) $(DESTDIR)$(MODDIR) && $(RM) $(COMPILED_LIBS:lib/%=%)
-$(CD) $(DESTDIR)$(BINMODDIR) && $(RM) $(COMPILED_LIBS:lib/%=%)
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi/char-set $(DESTDIR)$(BINMODDIR)/chibi/char-set
@ -354,6 +460,7 @@ uninstall:
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi/show $(DESTDIR)$(BINMODDIR)/chibi/show
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi/snow $(DESTDIR)$(BINMODDIR)/chibi/snow
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi/term $(DESTDIR)$(BINMODDIR)/chibi/term
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi/text $(DESTDIR)$(BINMODDIR)/chibi/text
-$(RMDIR) $(DESTDIR)$(MODDIR)/chibi $(DESTDIR)$(BINMODDIR)/chibi
-$(RMDIR) $(DESTDIR)$(MODDIR)/scheme/char $(DESTDIR)$(BINMODDIR)/scheme/char
-$(RMDIR) $(DESTDIR)$(MODDIR)/scheme/time $(DESTDIR)$(BINMODDIR)/scheme/time
@ -361,26 +468,44 @@ uninstall:
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/1 $(DESTDIR)$(BINMODDIR)/srfi/1
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/18 $(DESTDIR)$(BINMODDIR)/srfi/18
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/27 $(DESTDIR)$(BINMODDIR)/srfi/27
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/33 $(DESTDIR)$(BINMODDIR)/srfi/33
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/39 $(DESTDIR)$(BINMODDIR)/srfi/39
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/69 $(DESTDIR)$(BINMODDIR)/srfi/69
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/95 $(DESTDIR)$(BINMODDIR)/srfi/95
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/98 $(DESTDIR)$(BINMODDIR)/srfi/98
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/99/records $(DESTDIR)$(BINMODDIR)/srfi/99/records
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/99 $(DESTDIR)$(BINMODDIR)/srfi/99
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/113 $(DESTDIR)$(BINMODDIR)/srfi/113
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/117 $(DESTDIR)$(BINMODDIR)/srfi/117
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/121 $(DESTDIR)$(BINMODDIR)/srfi/121
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/125 $(DESTDIR)$(BINMODDIR)/srfi/125
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/128 $(DESTDIR)$(BINMODDIR)/srfi/128
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/129 $(DESTDIR)$(BINMODDIR)/srfi/129
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/132 $(DESTDIR)$(BINMODDIR)/srfi/132
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/133 $(DESTDIR)$(BINMODDIR)/srfi/133
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/135 $(DESTDIR)$(BINMODDIR)/srfi/135
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/143 $(DESTDIR)$(BINMODDIR)/srfi/143
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/151 $(DESTDIR)$(BINMODDIR)/srfi/151
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/144 $(DESTDIR)$(BINMODDIR)/srfi/144
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/146 $(DESTDIR)$(BINMODDIR)/srfi/146
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/159 $(DESTDIR)$(BINMODDIR)/srfi/159
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/160 $(DESTDIR)$(BINMODDIR)/srfi/160
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/166 $(DESTDIR)$(BINMODDIR)/srfi/166
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/179 $(DESTDIR)$(BINMODDIR)/srfi/179
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/211 $(DESTDIR)$(BINMODDIR)/srfi/211
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi/231 $(DESTDIR)$(BINMODDIR)/srfi/231
-$(RMDIR) $(DESTDIR)$(MODDIR)/srfi $(DESTDIR)$(BINMODDIR)/srfi
-$(RMDIR) $(DESTDIR)$(MODDIR) $(DESTDIR)$(BINMODDIR)
-$(RM) $(DESTDIR)$(MANDIR)/chibi-scheme.1 $(DESTDIR)$(MANDIR)/chibi-ffi.1 $(DESTDIR)$(MANDIR)/chibi-doc.1
-$(RM) $(DESTDIR)$(SOLIBDIR)/pkgconfig/chibi-scheme.pc
-$(RM) $(DESTDIR)$(PKGCONFDIR)/chibi-scheme.pc
dist: dist-clean
$(RM) chibi-scheme-$(VERSION).tgz
$(MKDIR) chibi-scheme-$(VERSION)
@for f in `git ls-files | grep -v ^benchmarks/`; do $(MKDIR) chibi-scheme-$(VERSION)/`dirname $$f`; $(SYMLINK) `pwd`/$$f chibi-scheme-$(VERSION)/$$f; done
$(TAR) cphzvf chibi-scheme-$(VERSION).tgz chibi-scheme-$(VERSION)
$(RM) -r chibi-scheme-$(VERSION)
dist: distclean
$(RM) chibi-scheme-$(CHIBI_VERSION).tgz
$(MKDIR) chibi-scheme-$(CHIBI_VERSION)
@for f in `git ls-files | grep -v ^benchmarks/`; do $(MKDIR) chibi-scheme-$(CHIBI_VERSION)/`dirname $$f`; $(SYMLINK) `pwd`/$$f chibi-scheme-$(CHIBI_VERSION)/$$f; done
$(TAR) cphzvf chibi-scheme-$(CHIBI_VERSION).tgz chibi-scheme-$(CHIBI_VERSION)
$(RM) -r chibi-scheme-$(CHIBI_VERSION)
mips-dist: dist-clean
mips-dist: distclean
$(RM) chibi-scheme-`date +%Y%m%d`-`git log HEAD^..HEAD | head -1 | cut -c8-`.tgz
$(MKDIR) chibi-scheme-`date +%Y%m%d`-`git log HEAD^..HEAD | head -1 | cut -c8-`
@for f in `git ls-files | grep -v ^benchmarks/`; do $(MKDIR) chibi-scheme-`date +%Y%m%d`-`git log HEAD^..HEAD | head -1 | cut -c8-`/`dirname $$f`; $(SYMLINK) `pwd`/$$f chibi-scheme-`date +%Y%m%d`-`git log HEAD^..HEAD | head -1 | cut -c8-`/$$f; done
@ -388,33 +513,47 @@ mips-dist: dist-clean
$(RM) -r chibi-scheme-`date +%Y%m%d`-`git log HEAD^..HEAD | head -1 | cut -c8-`
debian:
sudo checkinstall -D --pkgname chibi-scheme --pkgversion $(VERSION) --maintainer "http://groups.google.com/group/chibi-scheme" -y make PREFIX=/usr install
sudo checkinstall -D --pkgname chibi-scheme --pkgversion $(CHIBI_VERSION) --maintainer "http://groups.google.com/group/chibi-scheme" -y make PREFIX=/usr install
# Libraries in the standard distribution we want to make available to
# other Scheme implementations. Note this is run with my own
# ~/.snow/config.scm, which specifies myself own settings regarding
# ~/.snow/config.scm, which specifies my own settings regarding
# author, license, extracting docs from scribble, etc.
snowballs:
$(SNOW_CHIBI) package --license public-domain lib/chibi/char-set/boundary.sld
$(SNOW_CHIBI) package --license public-domain lib/chibi/match.sld
$(SNOW_CHIBI) package -r lib/chibi/char-set.sld
$(SNOW_CHIBI) package -r lib/chibi/iset.sld
$(SNOW_CHIBI) package -r lib/chibi/show.sld lib/chibi/show/pretty.sld
$(SNOW_CHIBI) package -r lib/chibi/iset.sld lib/chibi/iset/optimize.sld
$(SNOW_CHIBI) package --doc https://srfi.schemers.org/srfi-115/srfi-115.html --test-library lib/srfi/115.sld
$(SNOW_CHIBI) package -r --doc https://srfi.schemers.org/srfi-166/srfi-166.html --test-library lib/srfi/166/test.sld lib/srfi/166.sld lib/chibi/show/shared.sld
$(SNOW_CHIBI) package -r --doc https://srfi.schemers.org/srfi-179/srfi-179.html --test-library lib/srfi/179/test.sld lib/srfi/179.sld
$(SNOW_CHIBI) package lib/chibi/app.sld
$(SNOW_CHIBI) package lib/chibi/assert.sld
$(SNOW_CHIBI) package lib/chibi/base64.sld
$(SNOW_CHIBI) package lib/chibi/binary-record.sld
$(SNOW_CHIBI) package lib/chibi/bytevector.sld
$(SNOW_CHIBI) package lib/chibi/config.sld
$(SNOW_CHIBI) package lib/chibi/crypto/md5.sld
$(SNOW_CHIBI) package lib/chibi/crypto/rsa.sld
$(SNOW_CHIBI) package lib/chibi/crypto/sha2.sld
$(SNOW_CHIBI) package lib/chibi/diff.sld
$(SNOW_CHIBI) package lib/chibi/edit-distance.sld
$(SNOW_CHIBI) package lib/chibi/filesystem.sld
$(SNOW_CHIBI) package lib/chibi/math/prime.sld
$(SNOW_CHIBI) package lib/chibi/mime.sld
$(SNOW_CHIBI) package lib/chibi/monad/environment.sld
$(SNOW_CHIBI) package lib/chibi/optional.sld
$(SNOW_CHIBI) package lib/chibi/parse.sld lib/chibi/parse/common.sld
$(SNOW_CHIBI) package lib/chibi/pathname.sld
$(SNOW_CHIBI) package lib/chibi/quoted-printable.sld
$(SNOW_CHIBI) package lib/chibi/regexp.sld lib/chibi/regexp/pcre.sld
$(SNOW_CHIBI) package lib/chibi/scribble.sld
$(SNOW_CHIBI) package lib/chibi/string.sld
$(SNOW_CHIBI) package lib/chibi/sxml.sld
$(SNOW_CHIBI) package lib/chibi/tar.sld
$(SNOW_CHIBI) package lib/chibi/temp-file.sld
$(SNOW_CHIBI) package lib/chibi/term/ansi.sld
$(SNOW_CHIBI) package lib/chibi/term/edit-line.sld
$(SNOW_CHIBI) package lib/chibi/test.sld
$(SNOW_CHIBI) package lib/chibi/uri.sld
$(SNOW_CHIBI) package lib/chibi/zlib.sld

View file

@ -9,6 +9,7 @@ PLATFORM=macosx
else
ifeq ($(shell uname),FreeBSD)
PLATFORM=bsd
LIBCHIBI_FLAGS = -Wl,-soname,libchibi-scheme$(SO).$(SOVERSION_MAJOR)
else
ifeq ($(shell uname),NetBSD)
PLATFORM=bsd
@ -20,7 +21,7 @@ ifeq ($(shell uname),DragonFly)
PLATFORM=bsd
else
ifeq ($(shell uname -o),Msys)
PLATFORM=mingw
PLATFORM=windows
SOLIBDIR = $(BINDIR)
DIFFOPTS = -b
else
@ -29,9 +30,15 @@ PLATFORM=cygwin
SOLIBDIR = $(BINDIR)
DIFFOPTS = -b
else
ifeq ($(shell uname -o),Android)
PLATFORM=android
else
ifeq ($(shell uname -o),GNU/Linux)
PLATFORM=linux
else
ifeq ($(shell uname),SunOS)
PLATFORM=solaris
else
PLATFORM=unix
endif
endif
@ -41,6 +48,13 @@ endif
endif
endif
endif
endif
endif
endif
ifndef ARCH
ARCH = $(shell uname -m)
endif
########################################################################
# Set default variables for the platform.
@ -48,6 +62,7 @@ endif
LIBDL = -ldl
SO_VERSIONED_SUFFIX = $(SO).$(SOVERSION)
SO_MAJOR_VERSIONED_SUFFIX = $(SO).$(SOVERSION_MAJOR)
STATIC_LDFLAGS = -lm -ldl -lutil
ifeq ($(PLATFORM),macosx)
SO = .dylib
@ -65,17 +80,37 @@ EXE =
CLIBFLAGS = -fPIC
CLINKFLAGS = -shared
LIBDL =
RLDFLAGS=-Wl,-R$(LIBDIR)
else
ifeq ($(PLATFORM),mingw)
ifeq ($(PLATFORM),solaris)
SO = .so
EXE =
CLIBFLAGS = -fPIC
CLINKFLAGS = -shared
LIBDL = -ldl
RLDFLAGS=-Wl,-R$(LIBDIR)
else
ifeq ($(PLATFORM),windows)
SO = .dll
EXE = .exe
CC ?= gcc
CLIBFLAGS =
CLINKFLAGS = -shared
CPPFLAGS += -DSEXP_USE_STRING_STREAMS=0 -DSEXP_USE_GREEN_THREADS=0 -DSEXP_USE_GC_FILE_DESCRIPTORS=0 -DBUILDING_DLL
LIBCHIBI_FLAGS = -Wl,--out-implib,libchibi-scheme$(SO).a
STATICFLAGS =
STATIC_LDFLAGS = -lm -ldl
LIBDL = -lws2_32
else
ifeq ($(PLATFORM),msys)
SO = .dll
EXE = .exe
CC = gcc
CLIBFLAGS =
CLINKFLAGS = -shared
CPPFLAGS += -DSEXP_USE_STRING_STREAMS=0 -DBUILDING_DLL
CPPFLAGS += -DSEXP_USE_STRING_STREAMS=0
LIBCHIBI_FLAGS = -Wl,--out-implib,libchibi-scheme$(SO).a
STATICFLAGS = -DSEXP_USE_DL=0
LIBDL =
STATIC_LDFLAGS = -lm -ldl
else
ifeq ($(PLATFORM),cygwin)
SO = .dll
@ -85,6 +120,7 @@ CLIBFLAGS =
CLINKFLAGS = -shared
CPPFLAGS += -DSEXP_USE_STRING_STREAMS=0
LIBCHIBI_FLAGS = -Wl,--out-implib,libchibi-scheme$(SO).a
STATIC_LDFLAGS = -lm -ldl
else
SO = .so
EXE =
@ -92,9 +128,6 @@ CLIBFLAGS = -fPIC
CLINKFLAGS = -shared
STATICFLAGS = -static -DSEXP_USE_DL=0
LIBCHIBI_FLAGS = -Wl,-soname,libchibi-scheme$(SO).$(SOVERSION_MAJOR)
ifeq ($(PLATFORM),BSD)
LIBDL=
RLDFLAGS=-Wl,-R$(DESTDIR)$(LIBDIR)
endif
endif
endif
@ -102,26 +135,83 @@ endif
endif
endif
ifeq ($(PLATFORM),emscripten)
STATIC_LDFLAGS = -lm -ldl
endif
ifeq ($(PLATFORM),unix)
#RLDFLAGS=-rpath $(LIBDIR)
RLDFLAGS=-Wl,-R$(DESTDIR)$(LIBDIR)
RLDFLAGS=-Wl,-R$(LIBDIR)
endif
########################################################################
# Library config.
#
# This is to allow "make SEXP_USE_BOEHM=1" and "make SEXP_USE_DL=0" to
# automatically include the necessary compiler and linker flags in
# addition to setting those features. If not using GNU make just
# comment out the ifs and use the else branches for the defaults.
ifeq ($(SEXP_USE_BOEHM),1)
GCLDFLAGS := -lgc
XCPPFLAGS := $(CPPFLAGS) -Iinclude $(D:%=-DSEXP_USE_%) -DSEXP_USE_BOEHM=1
else
GCLDFLAGS :=
XCPPFLAGS := $(CPPFLAGS) -Iinclude $(D:%=-DSEXP_USE_%)
endif
ifeq ($(SEXP_USE_DL),0)
XLDFLAGS := $(LDFLAGS) $(RLDFLAGS) $(GCLDFLAGS) -lm
XCFLAGS := -Wall -DSEXP_USE_DL=0 -g -g3 -O3 $(CFLAGS)
else
XLDFLAGS := $(LDFLAGS) $(RLDFLAGS) $(GCLDFLAGS) $(LIBDL) -lm
XCFLAGS := -Wall -g -g3 -O3 $(CFLAGS)
endif
ifeq ($(PLATFORM),solaris)
XLDFLAGS += -lsocket
XCPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS
endif
# Choose compiled library on MSYS
ifeq ($(OS), Windows_NT)
ifeq ($(PLATFORM),msys)
EXCLUDE_WIN32_LIBS=1
else
ifeq ($(shell uname -o),Cygwin)
EXCLUDE_WIN32_LIBS=1
else
EXCLUDE_POSIX_LIBS=1
endif
endif
endif
CHIBI_POSIX_COMPILED_LIBS = lib/chibi/process$(SO) lib/chibi/time$(SO) \
lib/chibi/system$(SO) lib/chibi/stty$(SO) lib/chibi/pty$(SO) \
lib/chibi/net$(SO) lib/srfi/18/threads$(SO)
CHIBI_WIN32_COMPILED_LIBS = lib/chibi/win32/process-win32$(SO)
ifndef EXCLUDE_POSIX_LIBS
CHIBI_COMPILED_LIBS += $(CHIBI_POSIX_COMPILED_LIBS)
else
CHIBI_COMPILED_LIBS += $(CHIBI_WIN32_COMPILED_LIBS)
endif
########################################################################
# Check for headers (who needs autoconf?)
ifndef $(SEXP_USE_NTP_GETTIME)
SEXP_USE_NTP_GETTIME := $(shell echo "main(){struct ntptimeval n; ntp_gettime(&n);}" | gcc -fsyntax-only -include sys/timex.h -xc - >/dev/null 2>/dev/null && echo 1 || echo 0)
ifndef SEXP_USE_NTP_GETTIME
SEXP_USE_NTP_GETTIME := $(shell echo "int main(){struct ntptimeval n; ntp_gettime(&n);}" | $(CC) -fsyntax-only -include sys/timex.h -xc - >/dev/null 2>/dev/null && echo 1 || echo 0)
endif
ifeq ($(SEXP_USE_NTP_GETTIME),1)
CPPFLAGS += -DSEXP_USE_NTPGETTIME
XCPPFLAGS += -DSEXP_USE_NTPGETTIME
endif
ifndef $(SEXP_USE_INTTYPES)
SEXP_USE_INTTYPES := $(shell echo "main(){int_least8_t x;}" | gcc -fsyntax-only -include inttypes.h -xc - >/dev/null 2>/dev/null && echo 1 || echo 0)
ifndef SEXP_USE_INTTYPES
SEXP_USE_INTTYPES := $(shell echo "int main(){int_least8_t x;}" | $(CC) -fsyntax-only -include inttypes.h -xc - >/dev/null 2>/dev/null && echo 1 || echo 0)
endif
ifeq ($(SEXP_USE_INTTYPES),1)
CPPFLAGS += -DSEXP_USE_INTTYPES
XCPPFLAGS += -DSEXP_USE_INTTYPES
endif

View file

@ -14,25 +14,49 @@ CD ?= cd
RM ?= rm -f
LS ?= ls
CP ?= cp
LN ?= ln
LN ?= ln -sf
INSTALL ?= install
INSTALL_EXE ?= $(INSTALL)
MKDIR ?= $(INSTALL) -d
RMDIR ?= rmdir
TAR ?= tar
DIFF ?= diff
GIT ?= git
GREP ?= grep
FIND ?= find
SYMLINK ?= ln -s
LDCONFIG ?= ldconfig
PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/lib
SOLIBDIR ?= $(PREFIX)/lib
INCDIR ?= $(PREFIX)/include/chibi
MODDIR ?= $(PREFIX)/share/chibi
BINMODDIR ?= $(PREFIX)/lib/chibi
MANDIR ?= $(PREFIX)/share/man/man1
# gnu coding standards
prefix ?= /usr/local
PREFIX ?= $(prefix)
exec_prefix ?= $(PREFIX)
bindir ?= $(exec_prefix)/bin
libdir ?= $(exec_prefix)/lib
includedir ?= $(PREFIX)/include
datarootdir ?= $(PREFIX)/share
datadir ?= $(datarootdir)
mandir ?= $(datarootdir)/man
man1dir ?= $(mandir)/man1
# hysterical raisins
BINDIR ?= $(bindir)
LIBDIR ?= $(libdir)
SOLIBDIR ?= $(libdir)
INCDIR ?= $(includedir)/chibi
MODDIR ?= $(datadir)/chibi
BINMODDIR ?= $(SOLIBDIR)/chibi
PKGCONFDIR ?= $(SOLIBDIR)/pkgconfig
MANDIR ?= $(man1dir)
# allow snow to be configured separately
SNOWPREFIX ?= /usr/local
SNOWLIBDIR ?= $(SNOWPREFIX)/lib
SNOWSOLIBDIR ?= $(SNOWLIBDIR)
SNOWMODDIR ?= $(SNOWPREFIX)/share/snow
SNOWBINMODDIR ?= $(SNOWSOLIBDIR)/snow
# for packaging tools
DESTDIR ?=
########################################################################
@ -43,13 +67,16 @@ include Makefile.detect
########################################################################
all-libs: $(COMPILED_LIBS)
all-libs: $(COMPILED_LIBS) lib/chibi/snow/install.sld
lib/%.c: lib/%.stub $(CHIBI_FFI_DEPENDENCIES)
$(CHIBI_FFI) $<
lib/chibi/pty$(SO): lib/chibi/pty.c $(INCLUDES) libchibi-scheme$(SO)
$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< -L. $(RLDFLAGS) $(XLIBS) -lchibi-scheme -lutil
lib/%$(SO): lib/%.c $(INCLUDES) libchibi-scheme$(SO)
$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< -L. $(XLIBS) -lchibi-scheme
$(CC) $(CLIBFLAGS) $(CLINKFLAGS) $(XCPPFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ $< -L. $(RLDFLAGS) $(XLIBS) -lchibi-scheme
doc-libs: $(HTML_LIBS)

40
README
View file

@ -1,40 +0,0 @@
Chibi-Scheme
--------------
Minimal Scheme Implementation for use as an Extension Language
http://synthcode.com/wiki/chibi-scheme/
Chibi-Scheme is a very small library intended for use as an extension
and scripting language in C programs. In addition to support for
lightweight VM-based threads, each VM itself runs in an isolated heap
allowing multiple VMs to run simultaneously in different OS threads.
The default repl language contains all bindings from R7RS small,
available explicitly as the (scheme small) library.
Support for additional languages such as JavaScript, Go, Lua and Bash
are planned for future releases. Scheme is chosen as a substrate
because its first class continuations and guaranteed tail-call
optimization makes implementing other languages easy.
To build on most platforms just run "make && make test". This will
provide a shared library "libchibi-scheme", as well as a sample
"chibi-scheme" command-line repl. You can then run
sudo make install
to install the binaries and libraries. You can optionally specify a
PREFIX for the installation directory:
make PREFIX=/path/to/install/
sudo make PREFIX=/path/to/install/ install
By default files are installed in /usr/local.
If you want to try out chibi-scheme without installing, be sure to set
LD_LIBRARY_PATH so it can find the shared libraries.
For more detailed documentation, run "make doc" and see the generated
"doc/chibi.html".

81
README-win32.md Normal file
View file

@ -0,0 +1,81 @@
Chibi-scheme for Windows
========================
Chibi-scheme provides limited support for native desktop Windows. To use
fully-featured Chibi-scheme on Windows, consider using POSIX layer such as
Windows Subsytem for Linux(WSL), Cygwin or MSYS.
Currently, only R7RS Small libraries are available for the platform.
Supported Environments
----------------------
Chibi-scheme can be compiled with following platforms:
* Microsoft Visual Studio 2017
* MinGW32
* MinGW64
* MSYS
Known Issues
------------
Following libraries are not ported yet:
* `(chibi net)`
* `(chibi process)` : `exit` is available through `(scheme process-context)`
* `(chibi stty)`
* `(chibi system)`
* `(chibi time)`
Following library is not completely ported:
* `(chibi filesystem)`
Other issues:
* SRFI-27: Due to C Runtime limitation, the library is not thread-safe
* `make install` is not supported on Windows platforms
* On MSVC, flonum precision is degraded when compared with other compilers
* Cross compilation is not supported
Build with MinGW(Makefile)
--------------------------
The top-level `Makefile` can be used with MinGW.
1. Open MinGW64 or MinGW32 command prompt
2. `make`
3. `make test`
Currently, `make doc` is not supported on these platforms.
Build with MSYS(Makefile)
-------------------------
By default, the Makefile will compile against native Windows API. To use
MSYS's own POSIX emulation layer, specify `PLATFORM=msys`.
1. Open MSYS command prompt
2. `make PLATFORM=msys`
3. `make PLATFORM=msys test`
Build with Visual Studio(CMake)
-------------------------------
Minimal `CMakeLists.txt` is provided as an example to build Chibi-scheme on
Windows platforms. This is only intended to be used with Windows platforms;
currently it does not provide features provided with standard `Makefile` nor
it does not support UNIX/APPLE platforms either.
1. (Make sure CMake was selected with Visual Studio installer)
2. Open this directory with "Open with Visual Studio"
3. Choose "x86-" or "x64-" configuration
4. "CMake" => "Build all"
5. "CMake" => "Tests" => "Run chibi-scheme Tests"

60
README.md Normal file
View file

@ -0,0 +1,60 @@
# ![Chibi-Scheme](https://goo.gl/ZDtn4q)
**Minimal Scheme Implementation for use as an Extension Language**
https://github.com/ashinn/chibi-scheme
Chibi-Scheme is a very small library intended for use as an extension
and scripting language in C programs. In addition to support for
lightweight VM-based threads, each VM itself runs in an isolated heap
allowing multiple VMs to run simultaneously in different OS threads.
There are no external dependencies so is relatively easy to drop into
any project.
Despite the small size, Chibi-Scheme attempts to do The Right Thing.
The default settings include:
* a full numeric tower, with rational and complex numbers
* full and seamless Unicode support
* low-level and high-level hygienic macros
* an extensible module system
Specifically, the default repl language contains all bindings from
[R7RS small](https://small.r7rs.org/), available explicitly as the
`(scheme small)` library. The language is built in layers, however -
see the manual for instructions on compiling with fewer features or
requesting a smaller language on startup.
Chibi-Scheme is known to work on **32** and **64-bit** Linux, FreeBSD,
NetBSD, OpenBSD, DragonFlyBSD, OS X, Plan 9, Windows, iOS, Android,
ARM and [Emscripten](https://kripken.github.io/emscripten-site). Basic
support for native Windows desktop also exists. See README-win32.md
for details and build instructions.
To build on most platforms just run `make && make test`. This has a
few conditionals assuming GNU make. If using another make, there are
a few parameters in Makefile.detect you need to set by hand.
This will provide a shared library *libchibi-scheme*, as well as a
sample *chibi-scheme* command-line repl. You can then run
sudo make install
to install the binaries and libraries. You can optionally specify a
**PREFIX** for the installation directory:
make PREFIX=/path/to/install/
sudo make PREFIX=/path/to/install/ install
By default files are installed in **/usr/local**.
If you want to try out chibi-scheme without installing, be sure to set
`LD_LIBRARY_PATH` (`DYLD_LIBRARY_PATH` on macOS) so it can find the
shared libraries.
To make the emscripten build run `make js` (_not_ `emmake make js`).
For more detailed documentation, run `make doc` and see the generated
*doc/chibi.html* or read the [manual](http://synthcode.com/scheme/chibi/)
online.

View file

@ -1 +1 @@
nitrogen
sodium

14
TODO
View file

@ -10,7 +10,8 @@
** TODO native x86 backend
API redesign in preparation complete, initial
tests on native factorial and closures working.
** TODO fasl/image files
** DONE fasl/image files
- State "DONE" from "TODO" [2017-08-30 Wed 23:13]
sexp_copy_context() can form the basis for images,
FASL for arbitrary modules will need additional
help with resolving external references.
@ -18,7 +19,8 @@
- State "DONE" from "TODO" [2011-11-10 Thu 20:44]
*** TODO static image compiled into library
With this you'll be able to run Chibi without any filesystem.
*** TODO external tool to compact and optimize images
*** DONE external tool to compact and optimize images
- State "DONE" from "TODO" [2017-08-30 Wed 23:13]
The current GC is mark&sweep, which can cause fragmentation,
but we can at at least compact the initial fixed image.
*** TODO fasl versions of modules
@ -89,8 +91,6 @@
- State "DONE" from "TODO" [2010-07-11 Sun 15:31]
VM now supports an optional hook for green threads,
and a SRFI-18 interface is provided as a separate module.
I/O operations will currently block all threads though,
this needs to be addressed.
*** DONE thread-local parameters
CLOSED: [2010-12-06 Mon 21:52]
*** TODO efficient priority queues
@ -125,7 +125,8 @@
- State "DONE" [2009-12-08 Tue 14:39]
** DONE only/except/rename/prefix modifiers
- State "DONE" [2009-12-16 Wed 18:57]
** TODO scheme-complete.el support
** DONE scheme-complete.el support
- State "DONE" from "TODO" [2017-08-30 Wed 23:14]
** DONE access individual modules from repl
- State "DONE" [2009-12-26 Sat 01:49]
@ -181,7 +182,8 @@
* miscellaneous
** DONE user documentation
- State "DONE" from "TODO" [2011-11-10 Thu 20:45]
** TODO full test suite for libraries
** DONE full test suite for libraries
- State "DONE" from "TODO" [2017-08-30 Wed 23:14]
** TODO thorough source documentation
* distribution

View file

@ -1 +1 @@
0.7.3
0.11.0

53
appveyor.yml Normal file
View file

@ -0,0 +1,53 @@
image: Visual Studio 2017
environment:
matrix:
- ARCH: x64
TOOLCHAIN: MinGW
BUILDSYSTEM: MSYS2
- ARCH: x64
TOOLCHAIN: MSYS
BUILDSYSTEM: MSYS2
- ARCH: x86
TOOLCHAIN: MinGW
BUILDSYSTEM: MSYS2
- ARCH: x86
TOOLCHAIN: MinGW
BUILDSYSTEM: CMAKE
- ARCH: x64
TOOLCHAIN: MinGW
BUILDSYSTEM: CMAKE
- ARCH: x86
TOOLCHAIN: MSVC
BUILDSYSTEM: CMAKE
- ARCH: x64
TOOLCHAIN: MSVC
BUILDSYSTEM: CMAKE
install:
- if %BUILDSYSTEM%.==CMAKE. cinst ninja
- if %BUILDSYSTEM%.==CMAKE. set PATH=c:/tools/ninja;%PATH%
- if %TOOLCHAIN%%ARCH%.==MSVCx86. call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
- if %TOOLCHAIN%%ARCH%.==MSVCx64. call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
before_build:
- set BUILDTYPE= %ARCH%%TOOLCHAIN%
- if %BUILDTYPE%.==x64MinGW. set PATH=c:\msys64\usr\bin;c:\msys64\mingw64\bin;%PATH%
- if %BUILDTYPE%.==x86MinGW. set PATH=c:\msys64\usr\bin;c:\msys64\mingw32\bin;%PATH%
- if %BUILDTYPE%.==x64MSYS. set PATH=c:\msys64\usr\bin;%PATH%
- if %BUILDTYPE%.==x64MinGW. set CC=c:/msys64/mingw64/bin/gcc
- if %BUILDTYPE%.==x86MinGW. set CC=c:/msys64/mingw32/bin/gcc
- if %BUILDTYPE%.==x64MSYS. set CC=gcc
- if %TOOLCHAIN%.==MSVC. set CC=cl.exe
- if %TOOLCHAIN%%BUILDSYSTEM%.==MinGWMSYS2. set EXARG=
- if %TOOLCHAIN%%BUILDSYSTEM%.==MSYSMSYS2. set EXARG=PLATFORM=msys
- if %BUILDSYSTEM%.==CMAKE. cmake -G Ninja .
build_script:
- if %BUILDSYSTEM%.==MSYS2. make CC=%CC% %EXARG%
- if %BUILDSYSTEM%.==CMAKE. ninja
test_script:
- if %BUILDSYSTEM%.==MSYS2. make CC=%CC% %EXARG% test
- if %BUILDSYSTEM%.==CMAKE. ctest --verbose .

View file

@ -1,25 +1,47 @@
(import (chibi time) (scheme cxr) (srfi 33) (srfi 39))
(import (chibi ast) (chibi time) (scheme cxr) (srfi 33) (srfi 39))
(define (timeval->milliseconds tv)
(quotient (+ (* 1000000 (timeval-seconds tv)) (timeval-microseconds tv))
1000))
(define (timeval-diff start end)
(- (timeval->milliseconds end)
(timeval->milliseconds start)))
(define (time* thunk)
(call-with-output-string
(lambda (out)
(gc)
(let* ((start (car (get-time-of-day)))
(start-rusage (get-resource-usage))
(gc-start (gc-usecs))
(gc-start-count (gc-count))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(result (parameterize ((current-output-port out)) (thunk)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(end (car (get-time-of-day)))
(msecs (- (timeval->milliseconds end)
(timeval->milliseconds start))))
(end-rusage (get-resource-usage))
(gc-end (gc-usecs))
(gc-msecs (quotient (- gc-end gc-start) 1000))
(real-msecs (timeval-diff start end))
(user-msecs
(timeval-diff (resource-usage-time start-rusage)
(resource-usage-time end-rusage)))
(system-msecs
(timeval-diff (resource-usage-system-time start-rusage)
(resource-usage-system-time end-rusage))))
(display "user: ")
(display msecs)
(display " system: 0")
(display user-msecs)
(display " system: ")
(display system-msecs)
(display " real: ")
(display msecs)
(display " gc: 0")
(newline)
(display real-msecs)
(display " gc: ")
(display gc-msecs)
(display " (")
(display (- (gc-count) gc-start-count))
(display " times)\n")
(display "result: ")
(write result)
(newline)

34
benchmarks/gabriel/difftimes.sh Executable file
View file

@ -0,0 +1,34 @@
#!/bin/bash
# set -ex
BENCHDIR=$(dirname $0)
if [ "${BENCHDIR%%/*}" = "." ]; then
BENCHDIR="$(pwd)${BENCHDIR#.}"
fi
TS1="${1:--2}"
TS2="${2:--1}"
DB="${3:-${BENCHDIR}/times.tsv}"
if [ "$TS1" -lt 1000000000 ]; then
SORT_OPTS='-nu'
if [ "$TS1" -lt 0 ]; then
SORT_OPTS='-nru'
TS1=$((0 - TS1))
fi
TS1=$(cut -f 7 "$DB" | sort "$SORT_OPTS" | tail -n +$TS1 | head -1)
fi
if [ "$TS2" -lt 1000000000 ]; then
SORT_OPTS='-nu'
if [ "$TS2" -lt 0 ]; then
SORT_OPTS='-nru'
TS2=$((0 - TS2))
fi
TS2=$(cut -f 7 "$DB" | sort "$SORT_OPTS" | tail -n +$TS2 | head -1)
fi
join -t $'\t' \
<(grep $'\t'"$TS1"$'\t' "$DB" | cut -f 1-2,5) \
<(grep $'\t'"$TS2"$'\t' "$DB" | cut -f 1-2,5) \
| perl -F'\t' -ane 'sub gain{($_[0]<=0)?0:100*($_[1]-$_[0])/$_[0]} $u=gain($F[1], $F[3]); $g=gain($F[2], $F[4]); printf STDOUT "%s\t%d\t%d\t%.2f%%\t%d\t%d\t%.2f%%\n", $F[0], $F[1], $F[3], $u, $F[2], $F[4], $g'

View file

@ -1,16 +1,32 @@
#!/bin/sh
BENCHDIR=$(dirname $0)
if [ "${BENCHDIR%%/*}" == "." ]; then
BENCHDIR=$(pwd)${BENCHDIR#.}
fi
CHIBIHOME=${BENCHDIR%%/benchmarks/gabriel}
CHIBI="${CHIBI:-${CHIBIHOME}/chibi-scheme} -I$CHIBIHOME"
# set -ex
cd $BENCHDIR
BENCHDIR=$(dirname $0)
if [ "${BENCHDIR%%/*}" = "." ]; then
BENCHDIR="$(pwd)${BENCHDIR#.}"
fi
OUTPUT="$BENCHDIR/out.txt"
DB="$BENCHDIR/times.tsv"
CHIBIHOME="${BENCHDIR%%/benchmarks/gabriel}"
CHIBI="${CHIBI:-${CHIBIHOME}/chibi-scheme} -I$CHIBIHOME"
HEAP="2M"
cd "$BENCHDIR"
for t in *.sch; do
echo "${t%%.sch}"
echo "program: ${t%%.sch}"
LD_LIBRARY_PATH="$CHIBIHOME" DYLD_LIBRARY_PATH="$CHIBIHOME" \
$CHIBI -I"$CHIBIHOME/lib" -q -lchibi-prelude.scm $t
done
$CHIBI -I"$CHIBIHOME/lib" -h"$HEAP" -q -lchibi-prelude.scm "$t"
done | tee "$OUTPUT"
cd -
if [ ! -f "$DB" ]; then
echo $'program\tuser_ms\tsystem_ms\treal_ms\tgc_ms\tgc_count\ttimestamp\tcommit\tfeatures\tinit_heap\tcpu' > "$DB"
fi
#DATE=$(date -Iseconds)
DATE=$(date +%s)
COMMIT=$(git -C "$CHIBIHOME" rev-parse HEAD)
FEATURES=$(LD_LIBRARY_PATH="$CHIBIHOME" DYLD_LIBRARY_PATH="$CHIBIHOME" $CHIBI -q -p'(cddr *features*)' | tr ' ' , | tr -d '()')
CPU=$(lscpu | perl -ne 'if (s/^Model name:\s*//){s/\b(Intel|Core|Atom|AMD|CPU)(\s*\(\w+\))?\s*//gi;s/\s*@\s*[.\d]+[KMGT]Hz\b\s*//gi;print}')
perl -ane 'if (/^program:\s*(\w+)/) {$p=$1} elsif (/^user:\s*(\d+)\s*system:\s*(\d+)\s*real:\s*(\d+)(?:\s*gc:\s*(\d+)\s*(?:\((\d+)\s*times\))?)?/) {print"$p\t$1\t$2\t$3\t$4\t$5\t'"$DATE"'\t'"$COMMIT"'\t'"$FEATURES"'\t'"$HEAP"'\t'"$CPU"'\n"}' "$OUTPUT" >> "$DB"

460
bignum.c
View file

@ -35,38 +35,91 @@ sexp sexp_fixnum_to_bignum (sexp ctx, sexp a) {
return res;
}
sexp sexp_make_integer (sexp ctx, sexp_lsint_t x) {
sexp sexp_make_integer_from_lsint (sexp ctx, sexp_lsint_t x) {
sexp res;
if ((SEXP_MIN_FIXNUM <= x) && (x <= SEXP_MAX_FIXNUM)) {
res = sexp_make_fixnum(x);
} else {
if (lsint_is_fixnum(x)) {
res = sexp_make_fixnum(lsint_to_sint(x));
} else if (sexp_lsint_fits_sint(x)) {
res = sexp_make_bignum(ctx, 1);
if (x < 0) {
if (lsint_lt_0(x)) {
sexp_bignum_sign(res) = -1;
sexp_bignum_data(res)[0] = -x;
sexp_bignum_data(res)[0] = (sexp_uint_t)-lsint_to_sint(x);
} else {
sexp_bignum_sign(res) = 1;
sexp_bignum_data(res)[0] = x;
sexp_bignum_data(res)[0] = (sexp_uint_t)lsint_to_sint(x);
}
} else {
res = sexp_make_bignum(ctx, 2);
if (lsint_lt_0(x)) {
sexp_bignum_sign(res) = -1;
sexp_bignum_data(res)[0] = (sexp_uint_t)-lsint_to_sint(x);
sexp_bignum_data(res)[1] = (sexp_uint_t)~lsint_to_sint_hi(x);
} else {
sexp_bignum_sign(res) = 1;
sexp_bignum_data(res)[0] = (sexp_uint_t)lsint_to_sint(x);
sexp_bignum_data(res)[1] = (sexp_uint_t)lsint_to_sint_hi(x);
}
}
return res;
}
sexp sexp_make_unsigned_integer (sexp ctx, sexp_luint_t x) {
sexp sexp_make_unsigned_integer_from_luint (sexp ctx, sexp_luint_t x) {
sexp res;
if (x <= SEXP_MAX_FIXNUM) {
res = sexp_make_fixnum(x);
} else {
if (luint_is_fixnum(x)) {
res = sexp_make_fixnum(luint_to_uint(x));
} else if (sexp_luint_fits_uint(x)) {
res = sexp_make_bignum(ctx, 1);
sexp_bignum_sign(res) = 1;
sexp_bignum_data(res)[0] = x;
sexp_bignum_data(res)[0] = luint_to_uint(x);
} else {
res = sexp_make_bignum(ctx, 2);
sexp_bignum_sign(res) = 1;
sexp_bignum_data(res)[0] = luint_to_uint(x);
sexp_bignum_data(res)[1] = luint_to_uint_hi(x);
}
return res;
}
#if SEXP_USE_CUSTOM_LONG_LONGS
sexp sexp_make_integer(sexp ctx, long long x) {
return sexp_make_integer_from_lsint(ctx, lsint_from_sint(x));
}
sexp sexp_make_unsigned_integer(sexp ctx, unsigned long long x) {
return sexp_make_unsigned_integer_from_luint(ctx, luint_from_uint(x));
}
#else
sexp sexp_make_integer (sexp ctx, sexp_lsint_t x) {
return sexp_make_integer_from_lsint(ctx, x);
}
sexp sexp_make_unsigned_integer (sexp ctx, sexp_luint_t x) {
return sexp_make_unsigned_integer_from_luint(ctx, x);
}
#endif
#if !SEXP_64_BIT
long long sexp_bignum_to_sint(sexp x) {
if (!sexp_bignump(x))
return 0;
if (sexp_bignum_length(x) > 1)
return sexp_bignum_sign(x) * (
(((long long)(sexp_bignum_data(x)[1]))<<(8*sizeof(sexp_bignum_data(x)[0]))) + sexp_bignum_data(x)[0]);
return sexp_bignum_sign(x) * sexp_bignum_data(x)[0];
}
unsigned long long sexp_bignum_to_uint(sexp x) {
if (!sexp_bignump(x))
return 0;
if (sexp_bignum_length(x) > 1)
return (((unsigned long long)(sexp_bignum_data(x)[1]))<<(8*sizeof(sexp_bignum_data(x)[0]))) + sexp_bignum_data(x)[0];
return sexp_bignum_data(x)[0];
}
#endif
#define double_trunc_10s_digit(f) (trunc((f)/10.0)*10.0)
#define double_10s_digit(f) ((f)-double_trunc_10s_digit(f))
#define double_16s_digit(f) fmod(f,16.0)
sexp sexp_double_to_bignum (sexp ctx, double f) {
int sign;
sexp_gc_var3(res, scale, tmp);
@ -74,10 +127,10 @@ sexp sexp_double_to_bignum (sexp ctx, double f) {
res = sexp_fixnum_to_bignum(ctx, SEXP_ZERO);
scale = sexp_fixnum_to_bignum(ctx, SEXP_ONE);
sign = (f < 0 ? -1 : 1);
for (f=fabs(f); f >= 1.0; f=trunc(f/10)) {
tmp = sexp_bignum_fxmul(ctx, NULL, scale, double_10s_digit(f), 0);
for (f=fabs(f); f >= 1.0; f=trunc(f/16)) {
tmp = sexp_bignum_fxmul(ctx, NULL, scale, (sexp_uint_t)double_16s_digit(f), 0);
res = sexp_bignum_add(ctx, res, res, tmp);
scale = sexp_bignum_fxmul(ctx, NULL, scale, 10, 0);
scale = sexp_bignum_fxmul(ctx, NULL, scale, 16, 0);
}
sexp_bignum_sign(res) = sign;
sexp_gc_release3(ctx);
@ -135,7 +188,8 @@ sexp_sint_t sexp_bignum_compare_abs (sexp a, sexp b) {
sexp_sint_t sexp_bignum_compare (sexp a, sexp b) {
if (sexp_bignum_sign(a) != sexp_bignum_sign(b))
return sexp_bignum_sign(a);
return sexp_bignum_compare_abs(a, b);
sexp_sint_t cmp = sexp_bignum_compare_abs(a, b);
return sexp_bignum_sign(a) < 0 ? -cmp : cmp;
}
sexp sexp_bignum_normalize (sexp a) {
@ -198,9 +252,9 @@ sexp sexp_bignum_fxmul (sexp ctx, sexp d, sexp a, sexp_uint_t b, int offset) {
tmp = d;
data = sexp_bignum_data(d);
for (i=0; i<len; i++) {
n = (sexp_luint_t)adata[i]*b + carry;
data[i+offset] = (sexp_uint_t)n;
carry = n >> (sizeof(sexp_uint_t)*8);
n = luint_add(luint_mul_uint(luint_from_uint(adata[i]), b), luint_from_uint(carry));
data[i+offset] = luint_to_uint(n);
carry = luint_to_uint(luint_shr(n, (sizeof(sexp_uint_t)*8)));
}
if (carry) {
if (sexp_bignum_length(d) <= len+offset)
@ -214,13 +268,13 @@ sexp sexp_bignum_fxmul (sexp ctx, sexp d, sexp a, sexp_uint_t b, int offset) {
sexp_uint_t sexp_bignum_fxdiv (sexp ctx, sexp a, sexp_uint_t b, int offset) {
sexp_uint_t len=sexp_bignum_hi(a), *data=sexp_bignum_data(a), q, r=0;
int i;
sexp_luint_t n = 0;
sexp_luint_t n = luint_from_uint(0);
for (i=len-1; i>=offset; i--) {
n = (n << sizeof(sexp_uint_t)*8) + data[i];
q = n / b;
r = n - (sexp_luint_t)q * b;
n = luint_add(luint_shl(n, sizeof(sexp_uint_t)*8), luint_from_uint(data[i]));
q = luint_to_uint(luint_div_uint(n, b));
r = luint_to_uint(luint_sub(n, luint_mul_uint(luint_from_uint(q), b)));
data[i] = q;
n = r;
n = luint_from_uint(r);
}
return r;
}
@ -228,32 +282,35 @@ sexp_uint_t sexp_bignum_fxdiv (sexp ctx, sexp a, sexp_uint_t b, int offset) {
sexp sexp_bignum_fxrem (sexp ctx, sexp a, sexp_sint_t b) {
sexp_uint_t len=sexp_bignum_hi(a), *data=sexp_bignum_data(a), q, b0;
int i;
sexp_luint_t n = 0;
sexp_luint_t n = luint_from_uint(0);
if (b > 0) {
q = b - 1;
if ((b & q) == 0)
return sexp_make_fixnum(sexp_bignum_sign(a) * (data[0] & q));
}
b0 = (b >= 0) ? b : -b;
for (i=len-1; i>=0; i--) {
n = (n << sizeof(sexp_uint_t)*8) + data[i];
q = n / b0;
n -= (sexp_luint_t)q * b0;
if (b0 == 0) {
return sexp_xtype_exception(ctx, NULL, "divide by zero", a);
}
return sexp_make_fixnum(sexp_bignum_sign(a) * (sexp_sint_t)n);
for (i=len-1; i>=0; i--) {
n = luint_add(luint_shl(n, sizeof(sexp_uint_t)*8), luint_from_uint(data[i]));
q = luint_to_uint(luint_div_uint(n, b0));
n = luint_sub(n, luint_mul_uint(luint_from_uint(q), b0));
}
return sexp_make_fixnum(sexp_bignum_sign(a) * (sexp_sint_t)luint_to_uint(n));
}
sexp sexp_read_bignum (sexp ctx, sexp in, sexp_uint_t init,
signed char sign, sexp_uint_t base) {
int c, digit;
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
sexp_gc_var3(res, tmp, imag);
sexp_gc_preserve3(ctx, res, tmp, imag);
res = sexp_make_bignum(ctx, SEXP_INIT_BIGNUM_SIZE);
sexp_bignum_sign(res) = sign;
sexp_bignum_data(res)[0] = init;
for (c=sexp_read_char(ctx, in); sexp_isxdigit(c); c=sexp_read_char(ctx, in)) {
digit = digit_value(c);
if ((digit < 0) || (digit >= base))
if ((digit < 0) || (digit >= (int)base))
break;
res = sexp_bignum_fxmul(ctx, res, res, base, 0);
res = sexp_bignum_fxadd(ctx, res, digit);
@ -261,9 +318,32 @@ sexp sexp_read_bignum (sexp ctx, sexp in, sexp_uint_t init,
if (c=='.' || c=='e' || c=='E') {
if (base != 10) {
res = sexp_read_error(ctx, "found non-base 10 float", SEXP_NULL, in);
} else {
if (c!='.') sexp_push_char(ctx, c, in); /* push the e back */
} else if (c=='.') {
res = sexp_read_float_tail(ctx, in, sexp_bignum_to_double(res), (sign==-1));
} else {
tmp = sexp_read_number(ctx, in, base, 0);
#if SEXP_USE_COMPLEX
if (sexp_complexp(tmp)) {
imag = sexp_complex_imag(tmp);
tmp = sexp_complex_real(tmp);
} else {
imag = SEXP_ZERO;
}
#endif
if (sexp_exceptionp(tmp)) {
res = tmp;
} else if (sexp_fixnump(tmp) && labs(sexp_unbox_fixnum(tmp)) < 100*1024*1024) {
tmp = sexp_expt(ctx, SEXP_TEN, tmp);
res = sexp_mul(ctx, res, tmp);
} else {
tmp = sexp_exact_to_inexact(ctx, NULL, 2, tmp);
tmp = sexp_expt(ctx, SEXP_TEN, tmp);
res = sexp_mul(ctx, res, tmp);
}
#if SEXP_USE_COMPLEX
if (imag != SEXP_ZERO && !sexp_exceptionp(res))
res = sexp_make_complex(ctx, res, imag);
#endif
}
#if SEXP_USE_RATIOS
} else if (c=='/') {
@ -284,7 +364,7 @@ sexp sexp_read_bignum (sexp ctx, sexp in, sexp_uint_t init,
} else {
sexp_push_char(ctx, c, in);
}
sexp_gc_release1(ctx);
sexp_gc_release3(ctx);
return sexp_bignum_normalize(res);
}
@ -303,6 +383,9 @@ sexp sexp_write_bignum (sexp ctx, sexp a, sexp out, sexp_uint_t base) {
sexp_gc_preserve2(ctx, b, str);
b = sexp_copy_bignum(ctx, NULL, a, 0);
sexp_bignum_sign(b) = 1;
if (lg_base < 1) {
return sexp_xtype_exception(ctx, NULL, "number base too small", a);
}
i = str_len = (sexp_bignum_length(b)*sizeof(sexp_uint_t)*8 + lg_base - 1)
/ lg_base + 1;
str = sexp_make_string(ctx, sexp_make_fixnum(str_len),
@ -512,44 +595,44 @@ sexp sexp_bignum_quot_rem (sexp ctx, sexp *rem, sexp a, sexp b) {
sexp_bignum_sign(b1) = 1;
q = SEXP_ZERO;
x = sexp_make_bignum(ctx, sexp_bignum_length(a));
while (sexp_bignum_compare_abs(a1, b1) > 0) { /* a1, b1 at least 2 bigits */
while (sexp_bignum_compare_abs(a1, b1) >= 0) { /* a1, b1 at least 2 bigits */
/* guess divisor x */
alen = sexp_bignum_hi(a1);
sexp_bignum_data(x)[off] = 0;
if (off > 0) sexp_bignum_data(x)[off-1] = 0;
off = alen - blen + 1;
dn = (((sexp_luint_t)sexp_bignum_data(a1)[alen-1]
<< (sizeof(sexp_uint_t)*8))
+ sexp_bignum_data(a1)[alen-2]);
dd = (((sexp_luint_t)sexp_bignum_data(b1)[blen-1]
<< (sizeof(sexp_uint_t)*8))
+ sexp_bignum_data(b1)[blen-2]);
dn = luint_add_uint(luint_shl(luint_from_uint(sexp_bignum_data(a1)[alen-1])
, (sizeof(sexp_uint_t)*8))
, sexp_bignum_data(a1)[alen-2]);
dd = luint_add_uint(luint_shl(luint_from_uint(sexp_bignum_data(b1)[blen-1])
, (sizeof(sexp_uint_t)*8))
, sexp_bignum_data(b1)[blen-2]);
if (alen > 2 && blen > 2 &&
sexp_bignum_data(a1)[alen-1] < (1uL<<(sizeof(sexp_uint_t)*4)) &&
sexp_bignum_data(b1)[blen-1] < (1uL<<(sizeof(sexp_uint_t)*4))) {
dn = (dn << (sizeof(sexp_uint_t)*4))
+ (sexp_bignum_data(a1)[alen-3] >> (sizeof(sexp_uint_t)*4));
dd = (dd << (sizeof(sexp_uint_t)*4))
+ (sexp_bignum_data(b1)[blen-3] >> (sizeof(sexp_uint_t)*4));
luint_lt(luint_from_uint(sexp_bignum_data(a1)[alen-1]), luint_shl(luint_from_uint(1), (sizeof(sexp_uint_t)*4))) &&
luint_lt(luint_from_uint(sexp_bignum_data(b1)[blen-1]), luint_shl(luint_from_uint(1), (sizeof(sexp_uint_t)*4)))) {
dn = luint_add_uint(luint_shl(dn, (sizeof(sexp_uint_t)*4))
, (sexp_bignum_data(a1)[alen-3] >> (sizeof(sexp_uint_t)*4)));
dd = luint_add_uint(luint_shl(dd, (sizeof(sexp_uint_t)*4))
, (sexp_bignum_data(b1)[blen-3] >> (sizeof(sexp_uint_t)*4)));
}
d = dn / dd;
if (d == 0) {
dn = (((sexp_luint_t)sexp_bignum_data(a1)[alen-1]
<< (sizeof(sexp_uint_t)*8))
+ sexp_bignum_data(a1)[alen-2]);
dd = sexp_bignum_data(b1)[blen-1];
if (sexp_bignum_data(a1)[alen-1] < (1uL<<(sizeof(sexp_uint_t)*4)) &&
sexp_bignum_data(b1)[blen-1] < (1uL<<(sizeof(sexp_uint_t)*4))) {
dn = (dn << (sizeof(sexp_uint_t)*4))
+ (sexp_bignum_data(a1)[alen-3] >> (sizeof(sexp_uint_t)*4));
dd = (dd << (sizeof(sexp_uint_t)*4))
+ (sexp_bignum_data(b1)[blen-2] >> (sizeof(sexp_uint_t)*4));
d = luint_div(dn, dd);
if (luint_eq(d, luint_from_uint(0))) {
dn = luint_add_uint(luint_shl(luint_from_uint(sexp_bignum_data(a1)[alen-1])
, (sizeof(sexp_uint_t)*8))
, sexp_bignum_data(a1)[alen-2]);
dd = luint_from_uint(sexp_bignum_data(b1)[blen-1]);
if (luint_lt(luint_from_uint(sexp_bignum_data(a1)[alen-1]), (luint_shl(luint_from_uint(1), (sizeof(sexp_uint_t)*4)))) &&
luint_lt(luint_from_uint(sexp_bignum_data(b1)[blen-1]), (luint_shl(luint_from_uint(1), (sizeof(sexp_uint_t)*4))))) {
dn = luint_add_uint(luint_shl(dn, (sizeof(sexp_uint_t)*4))
, (sexp_bignum_data(a1)[alen-3] >> (sizeof(sexp_uint_t)*4)));
dd = luint_add_uint(luint_shl(dd, (sizeof(sexp_uint_t)*4))
, (sexp_bignum_data(b1)[blen-2] >> (sizeof(sexp_uint_t)*4)));
}
d = dn / dd;
d = luint_div(dn, dd);
off--;
}
dhi = d >> (sizeof(sexp_uint_t)*8);
dlo = d & (((sexp_luint_t)1<<(sizeof(sexp_uint_t)*8))-1);
dhi = luint_to_uint(luint_shr(d, (sizeof(sexp_uint_t)*8)));
dlo = luint_to_uint(luint_and(d, luint_sub(luint_shl(luint_from_uint(1), (sizeof(sexp_uint_t)*8)), luint_from_uint(1))));
sexp_bignum_data(x)[off] = dhi;
if (off > 0) sexp_bignum_data(x)[off-1] = dlo;
/* update quotient q and remainder a1 estimates */
@ -563,12 +646,13 @@ sexp sexp_bignum_quot_rem (sexp ctx, sexp *rem, sexp a, sexp b) {
}
/* flip the sign if we overshot in our estimate */
if (sexp_bignum_sign(a1) != sign) {
sexp_bignum_sign(a1) = -sign;
sexp_bignum_sign(a1) = (char)(-sign);
sign *= -1;
}
}
/* adjust signs */
if (sign < 0) {
a1 = sexp_bignum_normalize(a1);
if (sign < 0 && a1 != SEXP_ZERO) {
q = sexp_sub(ctx, q, SEXP_ONE);
a1 = sexp_add(ctx, a1, b1);
}
@ -601,14 +685,21 @@ sexp sexp_bignum_remainder (sexp ctx, sexp a, sexp b) {
}
sexp sexp_bignum_expt (sexp ctx, sexp a, sexp b) {
sexp_sint_t e = sexp_unbox_fx_abs(b);
sexp_sint_t e = sexp_unbox_fixnum(b);
sexp_sint_t abs_e;
if (e < 0)
abs_e = -e;
else
abs_e = e;
sexp_gc_var2(res, acc);
sexp_gc_preserve2(ctx, res, acc);
res = sexp_fixnum_to_bignum(ctx, SEXP_ONE);
acc = sexp_copy_bignum(ctx, NULL, a, 0);
for (; e; e>>=1, acc=sexp_bignum_mul(ctx, NULL, acc, acc))
if (e & 1)
for (; abs_e; abs_e>>=1, acc=sexp_bignum_mul(ctx, NULL, acc, acc))
if (abs_e & 1)
res = sexp_bignum_mul(ctx, NULL, res, acc);
if (e < 0)
res = sexp_div(ctx, sexp_fixnum_to_bignum(ctx, SEXP_ONE), res);
sexp_gc_release2(ctx);
return sexp_bignum_normalize(res);
}
@ -644,7 +735,7 @@ sexp sexp_bignum_sqrt (sexp ctx, sexp a, sexp* rem_out) {
if (! sexp_bignump(a)) return sexp_type_exception(ctx, NULL, SEXP_BIGNUM, a);
sexp_gc_preserve4(ctx, res, rem, tmp, tmpa);
/* initial estimate via flonum, ignoring signs */
if (sexp_negativep(a)) {
if (sexp_exact_negativep(a)) {
tmpa = sexp_copy_bignum(ctx, NULL, a, 0);
a = tmpa;
sexp_negate(a);
@ -688,12 +779,25 @@ sexp sexp_bignum_sqrt (sexp ctx, sexp a, sexp* rem_out) {
#if SEXP_USE_RATIOS
double sexp_ratio_to_double (sexp rat) {
double sexp_ratio_to_double (sexp ctx, sexp rat) {
sexp_gc_var1(quot);
sexp num = sexp_ratio_numerator(rat), den = sexp_ratio_denominator(rat);
return (sexp_bignump(num) ? sexp_bignum_to_double(num)
double res = (sexp_bignump(num) ? sexp_bignum_to_double(num)
: sexp_fixnum_to_double(num))
/ (sexp_bignump(den) ? sexp_bignum_to_double(den)
: sexp_fixnum_to_double(den));
if (!isfinite(res)) {
sexp_gc_preserve1(ctx, quot);
if (sexp_unbox_fixnum(sexp_compare(ctx, sexp_ratio_numerator(rat), sexp_ratio_denominator(rat))) < 0) {
quot = sexp_quotient(ctx, sexp_ratio_denominator(rat), sexp_ratio_numerator(rat));
res = 1 / sexp_to_double(ctx, quot);
} else {
quot = sexp_quotient(ctx, sexp_ratio_numerator(rat), sexp_ratio_denominator(rat));
res = sexp_to_double(ctx, quot);
}
sexp_gc_release1(ctx);
}
return res;
}
sexp sexp_double_to_ratio (sexp ctx, double f) {
@ -709,7 +813,7 @@ sexp sexp_double_to_ratio (sexp ctx, double f) {
for (i=0, f=fabs(f-trunc(f)); f != trunc(f) && i < 15; i++) {
res = sexp_bignum_fxmul(ctx, NULL, res, 10, 0);
f = f * 10;
res = sexp_bignum_fxadd(ctx, res, double_10s_digit(f));
res = sexp_bignum_fxadd(ctx, res, (sexp_uint_t)double_10s_digit(f));
f = f - trunc(f);
scale = sexp_mul(ctx, scale, SEXP_TEN);
}
@ -723,6 +827,41 @@ sexp sexp_double_to_ratio (sexp ctx, double f) {
return res;
}
/*
* For conversion that does not introduce round-off error,
* no matter what FLT_RADIX is.
*/
sexp sexp_double_to_ratio_2 (sexp ctx, double f) {
int sign,i;
sexp_gc_var3(res, whole, scale);
if (f == trunc(f))
return sexp_bignum_normalize(sexp_double_to_bignum(ctx, f));
sexp_gc_preserve3(ctx, res, whole, scale);
whole = sexp_double_to_bignum(ctx, trunc(f));
res = sexp_fixnum_to_bignum(ctx, SEXP_ZERO);
scale = SEXP_ONE;
sign = (f < 0 ? -1 : 1);
f = fabs(f-trunc(f));
while(f) {
res = sexp_bignum_fxmul(ctx, NULL, res, FLT_RADIX, 0);
scale = sexp_mul(ctx, scale, sexp_make_fixnum(FLT_RADIX));
f *= FLT_RADIX;
i = trunc(f);
if (i) {
f -= i;
res = sexp_bignum_fxadd(ctx, res, i);
}
}
sexp_bignum_sign(res) = sign;
res = sexp_bignum_normalize(res);
scale = sexp_bignum_normalize(scale);
res = sexp_make_ratio(ctx, res, scale);
res = sexp_ratio_normalize(ctx, res, SEXP_FALSE);
res = sexp_add(ctx, res, whole);
sexp_gc_release3(ctx);
return res;
}
sexp sexp_ratio_add (sexp ctx, sexp a, sexp b) {
sexp_gc_var3(res, num, den);
sexp_gc_preserve3(ctx, res, num, den);
@ -773,13 +912,13 @@ sexp sexp_ratio_round (sexp ctx, sexp a) {
sexp_gc_preserve2(ctx, q, r);
q = sexp_quotient(ctx, sexp_ratio_numerator(a), sexp_ratio_denominator(a));
if ((sexp_ratio_denominator(a) == SEXP_TWO) && sexp_oddp(q)) {
q = sexp_add(ctx, q, (sexp_positivep(q) ? SEXP_ONE : SEXP_NEG_ONE));
q = sexp_add(ctx, q, (sexp_exact_positivep(q) ? SEXP_ONE : SEXP_NEG_ONE));
} else {
r = sexp_remainder(ctx, sexp_ratio_numerator(a), sexp_ratio_denominator(a));
r = sexp_mul(ctx, r, SEXP_TWO);
if (sexp_negativep(r)) {sexp_negate(r);}
if (sexp_exact_negativep(r)) {sexp_negate(r);}
if (sexp_unbox_fixnum(sexp_compare(ctx, r, sexp_ratio_denominator(a))) > 0)
q = sexp_add(ctx, q, (sexp_positivep(q) ? SEXP_ONE : SEXP_NEG_ONE));
q = sexp_add(ctx, q, (sexp_exact_negativep(sexp_ratio_numerator(a)) ? SEXP_NEG_ONE : SEXP_ONE));
}
sexp_gc_release2(ctx);
return q;
@ -793,7 +932,7 @@ sexp sexp_ratio_floor (sexp ctx, sexp a) {
sexp_gc_var1(q);
sexp_gc_preserve1(ctx, q);
q = sexp_quotient(ctx, sexp_ratio_numerator(a), sexp_ratio_denominator(a));
if (sexp_negativep(sexp_ratio_numerator(a)))
if (sexp_exact_negativep(sexp_ratio_numerator(a)))
q = sexp_add(ctx, q, SEXP_NEG_ONE);
sexp_gc_release1(ctx);
return q;
@ -803,7 +942,7 @@ sexp sexp_ratio_ceiling (sexp ctx, sexp a) {
sexp_gc_var1(q);
sexp_gc_preserve1(ctx, q);
q = sexp_quotient(ctx, sexp_ratio_numerator(a), sexp_ratio_denominator(a));
if (sexp_positivep(sexp_ratio_numerator(a)))
if (sexp_exact_positivep(sexp_ratio_numerator(a)))
q = sexp_add(ctx, q, SEXP_ONE);
sexp_gc_release1(ctx);
return q;
@ -811,6 +950,21 @@ sexp sexp_ratio_ceiling (sexp ctx, sexp a) {
#endif
double sexp_to_double (sexp ctx, sexp x) {
if (sexp_flonump(x))
return sexp_flonum_value(x);
else if (sexp_fixnump(x))
return sexp_fixnum_to_double(x);
else if (sexp_bignump(x))
return sexp_bignum_to_double(x);
#if SEXP_USE_RATIOS
else if (sexp_ratiop(x))
return sexp_ratio_to_double(ctx, x);
#endif
else
return 0.0;
}
/************************ complex numbers ****************************/
#if SEXP_USE_COMPLEX
@ -845,8 +999,8 @@ sexp sexp_complex_sub (sexp ctx, sexp a, sexp b) {
sexp_gc_var2(res, tmp);
sexp_gc_preserve2(ctx, res, tmp);
tmp = sexp_complex_copy(ctx, b);
sexp_negate(sexp_complex_real(tmp));
sexp_negate(sexp_complex_imag(tmp));
sexp_negate_maybe_ratio(sexp_complex_real(tmp));
sexp_negate_maybe_ratio(sexp_complex_imag(tmp));
res = sexp_complex_add(ctx, a, tmp);
sexp_gc_release2(ctx);
return res;
@ -892,21 +1046,6 @@ sexp sexp_complex_div (sexp ctx, sexp a, sexp b) {
return sexp_complex_normalize(res);
}
static double sexp_to_double (sexp x) {
if (sexp_flonump(x))
return sexp_flonum_value(x);
else if (sexp_fixnump(x))
return sexp_fixnum_to_double(x);
else if (sexp_bignump(x))
return sexp_bignum_to_double(x);
#if SEXP_USE_RATIOS
else if (sexp_ratiop(x))
return sexp_ratio_to_double(x);
#endif
else
return 0.0;
}
static sexp sexp_to_complex (sexp ctx, sexp x) {
#if SEXP_USE_RATIOS
sexp_gc_var1(tmp);
@ -917,7 +1056,7 @@ static sexp sexp_to_complex (sexp ctx, sexp x) {
} else if (sexp_ratiop(x)) {
sexp_gc_preserve1(ctx, tmp);
tmp = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
sexp_complex_real(tmp) = sexp_make_flonum(ctx, sexp_to_double(x));
sexp_complex_real(tmp) = sexp_make_flonum(ctx, sexp_to_double(ctx, x));
sexp_gc_release1(ctx);
return tmp;
#endif
@ -927,8 +1066,8 @@ static sexp sexp_to_complex (sexp ctx, sexp x) {
}
sexp sexp_complex_exp (sexp ctx, sexp z) {
double e2x = exp(sexp_to_double(sexp_complex_real(z))),
y = sexp_to_double(sexp_complex_imag(z));
double e2x = exp(sexp_to_double(ctx, sexp_complex_real(z))),
y = sexp_to_double(ctx, sexp_complex_imag(z));
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
@ -939,8 +1078,8 @@ sexp sexp_complex_exp (sexp ctx, sexp z) {
}
sexp sexp_complex_log (sexp ctx, sexp z) {
double x = sexp_to_double(sexp_complex_real(z)),
y = sexp_to_double(sexp_complex_imag(z));
double x = sexp_to_double(ctx, sexp_complex_real(z)),
y = sexp_to_double(ctx, sexp_complex_imag(z));
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
@ -964,21 +1103,21 @@ sexp sexp_complex_expt (sexp ctx, sexp a, sexp b) {
#if SEXP_USE_MATH
sexp sexp_complex_sqrt (sexp ctx, sexp z) {
double x = sexp_to_double(sexp_complex_real(z)),
y = sexp_to_double(sexp_complex_imag(z)), r;
double x = sexp_to_double(ctx, sexp_complex_real(z)),
y = sexp_to_double(ctx, sexp_complex_imag(z)), r;
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
r = sqrt(x*x + y*y);
res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
sexp_complex_real(res) = sexp_make_flonum(ctx, sqrt((x+r)/2));
sexp_complex_imag(res) = sexp_make_flonum(ctx, (y<0?-1:1)*sqrt((-x+r)/2));
sexp_complex_imag(res) = sexp_make_flonum(ctx, ((y<-0.0)?-1:1)*sqrt((-x+r)/2));
sexp_gc_release1(ctx);
return res;
}
sexp sexp_complex_sin (sexp ctx, sexp z) {
double x = sexp_to_double(sexp_complex_real(z)),
y = sexp_to_double(sexp_complex_imag(z));
double x = sexp_to_double(ctx, sexp_complex_real(z)),
y = sexp_to_double(ctx, sexp_complex_imag(z));
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
@ -989,8 +1128,8 @@ sexp sexp_complex_sin (sexp ctx, sexp z) {
}
sexp sexp_complex_cos (sexp ctx, sexp z) {
double x = sexp_to_double(sexp_complex_real(z)),
y = sexp_to_double(sexp_complex_imag(z));
double x = sexp_to_double(ctx, sexp_complex_real(z)),
y = sexp_to_double(ctx, sexp_complex_imag(z));
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
res = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
@ -1012,22 +1151,19 @@ sexp sexp_complex_tan (sexp ctx, sexp z) {
}
sexp sexp_complex_asin (sexp ctx, sexp z) {
sexp_gc_var2(res, tmp);
sexp_gc_preserve2(ctx, res, tmp);
sexp_gc_var3(res, tmp, tmp2);
sexp_gc_preserve3(ctx, res, tmp, tmp2);
res = sexp_complex_mul(ctx, z, z);
tmp = sexp_make_complex(ctx, SEXP_ONE, SEXP_ZERO);
res = sexp_complex_sub(ctx, tmp, res);
res = sexp_complex_sqrt(ctx, res);
/* tmp = iz */
sexp_complex_real(tmp) = sexp_complex_imag(z);
sexp_negate(sexp_complex_real(tmp));
res = sexp_sub(ctx, SEXP_ONE, res);
res = sexp_sqrt(ctx, NULL, 1, res);
tmp = sexp_make_complex(ctx, SEXP_ZERO, SEXP_ZERO);
sexp_complex_real(tmp) = sexp_mul(ctx, SEXP_NEG_ONE, sexp_complex_imag(z));
sexp_complex_imag(tmp) = sexp_complex_real(z);
res = sexp_complex_add(ctx, tmp, res);
tmp = sexp_complex_log(ctx, res);
/* res = -i*tmp */
res = sexp_complex_copy(ctx, tmp);
sexp_negate(sexp_complex_imag(res));
sexp_gc_release2(ctx);
res = sexp_add(ctx, tmp, res);
res = sexp_log(ctx, NULL, 1, res);
tmp = sexp_make_complex(ctx, SEXP_ZERO, SEXP_NEG_ONE);
res = sexp_mul(ctx, res, tmp);
sexp_gc_release3(ctx);
return res;
}
@ -1191,7 +1327,7 @@ sexp sexp_add (sexp ctx, sexp a, sexp b) {
r = sexp_make_fixnum(sum);
break;
case SEXP_NUM_FIX_FLO:
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)+sexp_flonum_value(b));
r = a == SEXP_ZERO ? b : sexp_make_flonum(ctx, sexp_fixnum_to_double(a)+sexp_flonum_value(b));
break;
case SEXP_NUM_FIX_BIG:
r = sexp_bignum_normalize(sexp_bignum_add_fixnum(ctx, b, a));
@ -1207,7 +1343,7 @@ sexp sexp_add (sexp ctx, sexp a, sexp b) {
break;
#if SEXP_USE_RATIOS
case SEXP_NUM_FLO_RAT:
r = sexp_make_flonum(ctx, sexp_flonum_value(a) + sexp_ratio_to_double(b));
r = sexp_make_flonum(ctx, sexp_flonum_value(a) + sexp_ratio_to_double(ctx, b));
break;
case SEXP_NUM_FIX_RAT:
case SEXP_NUM_BIG_RAT:
@ -1267,7 +1403,7 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) {
r = sexp_fx_sub(a, b); /* VM catches this case */
break;
case SEXP_NUM_FIX_FLO:
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)-sexp_flonum_value(b));
r = sexp_make_flonum(ctx, a==SEXP_ZERO ? -sexp_flonum_value(b) : sexp_fixnum_to_double(a)-sexp_flonum_value(b));
break;
case SEXP_NUM_FIX_BIG:
tmp1 = sexp_fixnum_to_bignum(ctx, a);
@ -1296,10 +1432,10 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) {
break;
#if SEXP_USE_RATIOS
case SEXP_NUM_FLO_RAT:
r = sexp_make_flonum(ctx, sexp_flonum_value(a) - sexp_ratio_to_double(b));
r = sexp_make_flonum(ctx, sexp_flonum_value(a) - sexp_ratio_to_double(ctx, b));
break;
case SEXP_NUM_RAT_FLO:
r = sexp_make_flonum(ctx, sexp_ratio_to_double(a) - sexp_flonum_value(b));
r = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, a) - sexp_flonum_value(b));
break;
case SEXP_NUM_RAT_FIX:
case SEXP_NUM_RAT_BIG:
@ -1317,21 +1453,17 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) {
sexp_negate_exact(sexp_ratio_numerator(tmp2));
r = sexp_ratio_add(ctx, a, tmp2);
if (negatep) {
if (sexp_ratiop(r)) {
sexp_negate_exact(sexp_ratio_numerator(r));
} else {
sexp_negate_exact(r);
}
sexp_negate_maybe_ratio(r);
}
break;
#endif
#if SEXP_USE_COMPLEX
#if SEXP_USE_RATIOS
case SEXP_NUM_RAT_CPX:
a = tmp1 = sexp_make_flonum(ctx, sexp_ratio_to_double(a));
a = tmp1 = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, a));
goto complex_sub;
case SEXP_NUM_CPX_RAT:
b = tmp1 = sexp_make_flonum(ctx, sexp_ratio_to_double(b));
b = tmp1 = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, b));
/* ... FALLTHROUGH ... */
#endif
case SEXP_NUM_CPX_FLO:
@ -1353,10 +1485,10 @@ sexp sexp_sub (sexp ctx, sexp a, sexp b) {
if (negatep) {
if (sexp_complexp(r)) {
r = sexp_complex_copy(ctx, r);
sexp_negate(sexp_complex_real(r));
sexp_negate(sexp_complex_imag(r));
sexp_negate_maybe_ratio(sexp_complex_real(r));
sexp_negate_maybe_ratio(sexp_complex_imag(r));
} else {
sexp_negate(r);
sexp_negate_maybe_ratio(r);
}
}
break;
@ -1382,11 +1514,11 @@ sexp sexp_mul (sexp ctx, sexp a, sexp b) {
r = sexp_type_exception(ctx, NULL, SEXP_NUMBER, a);
break;
case SEXP_NUM_FIX_FIX:
prod = (sexp_lsint_t)sexp_unbox_fixnum(a) * sexp_unbox_fixnum(b);
if ((prod < SEXP_MIN_FIXNUM) || (prod > SEXP_MAX_FIXNUM))
prod = lsint_mul_sint(lsint_from_sint(sexp_unbox_fixnum(a)), sexp_unbox_fixnum(b));
if (!lsint_is_fixnum(prod))
r = sexp_mul(ctx, tmp=sexp_fixnum_to_bignum(ctx, a), b);
else
r = sexp_make_fixnum(prod);
r = sexp_make_fixnum(lsint_to_sint(prod));
break;
case SEXP_NUM_FIX_FLO:
r = (a==SEXP_ZERO ? a : sexp_make_flonum(ctx, sexp_fixnum_to_double(a)*sexp_flonum_value(b)));
@ -1407,7 +1539,7 @@ sexp sexp_mul (sexp ctx, sexp a, sexp b) {
break;
#if SEXP_USE_RATIOS
case SEXP_NUM_FLO_RAT:
r = sexp_make_flonum(ctx, sexp_flonum_value(a) * sexp_ratio_to_double(b));
r = sexp_make_flonum(ctx, sexp_flonum_value(a) * sexp_ratio_to_double(ctx, b));
break;
case SEXP_NUM_FIX_RAT:
case SEXP_NUM_BIG_RAT:
@ -1514,10 +1646,10 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
break;
#if SEXP_USE_RATIOS
case SEXP_NUM_FLO_RAT:
r = sexp_make_flonum(ctx, sexp_flonum_value(a) / sexp_ratio_to_double(b));
r = sexp_make_flonum(ctx, sexp_flonum_value(a) / sexp_ratio_to_double(ctx, b));
break;
case SEXP_NUM_RAT_FLO:
r = sexp_make_flonum(ctx, sexp_ratio_to_double(a) / sexp_flonum_value(b));
r = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, a) / sexp_flonum_value(b));
break;
case SEXP_NUM_RAT_FIX:
case SEXP_NUM_RAT_BIG:
@ -1535,7 +1667,7 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
#if SEXP_USE_COMPLEX
#if SEXP_USE_RATIOS
case SEXP_NUM_CPX_RAT:
b = tmp = sexp_make_flonum(ctx, sexp_ratio_to_double(b));
b = tmp = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, b));
/* ... FALLTHROUGH ... */
#endif
case SEXP_NUM_CPX_FLO:
@ -1546,7 +1678,7 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
#if SEXP_USE_RATIOS
case SEXP_NUM_RAT_CPX:
if (sexp_ratiop(a))
a = tmp = sexp_make_flonum(ctx, sexp_ratio_to_double(a));
a = tmp = sexp_make_flonum(ctx, sexp_ratio_to_double(ctx, a));
/* ... FALLTHROUGH ... */
#endif
case SEXP_NUM_FLO_CPX:
@ -1630,6 +1762,9 @@ sexp sexp_quotient (sexp ctx, sexp a, sexp b) {
break;
case SEXP_NUM_FIX_FIX:
r = sexp_fx_div(a, b);
if ((sexp_sint_t)a < 0 && (sexp_sint_t)b < 0 && (sexp_sint_t)r < 0) {
r = sexp_quotient(ctx, tmp=sexp_fixnum_to_bignum(ctx, a), b);
}
break;
case SEXP_NUM_FIX_BIG:
r = SEXP_ZERO;
@ -1663,8 +1798,11 @@ sexp sexp_remainder (sexp ctx, sexp a, sexp b) {
#if SEXP_USE_RATIOS
case SEXP_NUM_FLO_RAT:
#endif
if (sexp_flonum_value(a) != trunc(sexp_flonum_value(a))) {
if (isinf(sexp_flonum_value(a)) ||
sexp_flonum_value(a) != trunc(sexp_flonum_value(a))) {
r = sexp_type_exception(ctx, NULL, SEXP_FIXNUM, a);
} else if (bt == SEXP_NUM_FLO && isinf(sexp_flonum_value(b))) {
r = sexp_type_exception(ctx, NULL, SEXP_FIXNUM, b);
} else {
tmp = sexp_bignum_normalize(sexp_double_to_bignum(ctx, sexp_flonum_value(a)));
tmp = sexp_remainder(ctx, tmp, b);
@ -1687,7 +1825,8 @@ sexp sexp_remainder (sexp ctx, sexp a, sexp b) {
#if SEXP_USE_RATIOS
case SEXP_NUM_RAT_FLO:
#endif
if (sexp_flonum_value(b) != trunc(sexp_flonum_value(b))) {
if (isinf(sexp_flonum_value(b)) ||
sexp_flonum_value(b) != trunc(sexp_flonum_value(b))) {
r = sexp_type_exception(ctx, NULL, SEXP_FIXNUM, b);
} else {
tmp = sexp_bignum_normalize(sexp_double_to_bignum(ctx, sexp_flonum_value(b)));
@ -1728,16 +1867,16 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) {
sexp_gc_preserve1(ctx, tmp);
if (at > bt) {
r = sexp_compare(ctx, b, a);
sexp_negate(r);
if (!sexp_exceptionp(r)) { sexp_negate(r); }
} else {
switch ((at * SEXP_NUM_NUMBER_TYPES) + bt) {
case SEXP_NUM_NOT_NOT: case SEXP_NUM_NOT_FIX:
case SEXP_NUM_NOT_FLO: case SEXP_NUM_NOT_BIG:
#if SEXP_USE_COMPLEX
case SEXP_NUM_CPX_CPX: case SEXP_NUM_CPX_FIX:
case SEXP_NUM_CPX_FLO: case SEXP_NUM_CPX_BIG:
case SEXP_NUM_CPX_CPX: case SEXP_NUM_FIX_CPX:
case SEXP_NUM_FLO_CPX: case SEXP_NUM_BIG_CPX:
#if SEXP_USE_RATIOS
case SEXP_NUM_CPX_RAT:
case SEXP_NUM_RAT_CPX:
#endif
#endif
r = sexp_type_exception(ctx, NULL, SEXP_NUMBER, a);
@ -1746,9 +1885,13 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) {
r = sexp_make_fixnum(sexp_unbox_fixnum(a) - sexp_unbox_fixnum(b));
break;
case SEXP_NUM_FIX_FLO:
f = sexp_fixnum_to_double(a);
g = sexp_flonum_value(b);
r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1);
if (isinf(sexp_flonum_value(b))) {
r = sexp_flonum_value(b) > 0 ? SEXP_NEG_ONE : SEXP_ONE;
} else if (isnan(sexp_flonum_value(b))) {
r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", b);
} else {
r = sexp_compare(ctx, a, tmp=sexp_inexact_to_exact(ctx, NULL, 1, b));
}
break;
case SEXP_NUM_FIX_BIG:
if ((sexp_bignum_hi(b) > 1) ||
@ -1760,6 +1903,11 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) {
case SEXP_NUM_FLO_FLO:
f = sexp_flonum_value(a);
g = sexp_flonum_value(b);
if (isnan(f))
r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", a);
else if (isnan(g))
r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", b);
else
r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1);
break;
case SEXP_NUM_FLO_BIG:
@ -1785,8 +1933,7 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) {
} else if (isnan(f)) {
r = sexp_xtype_exception(ctx, NULL, "can't compare NaN", a);
} else {
g = sexp_ratio_to_double(b);
r = sexp_make_fixnum(f < g ? -1 : f == g ? 0 : 1);
r = sexp_compare(ctx, tmp=sexp_inexact_to_exact(ctx, NULL, 1, a), b);
}
break;
case SEXP_NUM_FIX_RAT:
@ -1797,6 +1944,9 @@ sexp sexp_compare (sexp ctx, sexp a, sexp b) {
r = sexp_ratio_compare(ctx, a, b);
break;
#endif
default:
r = sexp_xtype_exception(ctx, NULL, "unknown comparison", a);
break;
}
}
sexp_gc_release1(ctx);

View file

@ -0,0 +1,12 @@
;; Don't import this - it's temporarily used to compute optimized
;; char-set representations.
(define-library (chibi char-set width)
(import (chibi) (chibi iset) (chibi char-set))
(include "width.scm")
(export
char-set:zero-width
char-set:full-width
char-set:ambiguous-width
))

View file

@ -1,206 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chibi-scheme"
ProjectGUID="{38DC39DA-5328-4FFE-84E2-E16FF1864945}"
RootNamespace="chibi-scheme"
Keyword="Win32Proj"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CHIBISCHEME_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CHIBISCHEME_EXPORTS;"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\eval.c"
>
</File>
<File
RelativePath=".\main.c"
>
</File>
<File
RelativePath=".\sexp.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="-DPLATFORM=mingw;-DSEXP_USE_STRING_STREAMS=0;-DSEXP_USE_DEBUG=0;-DSEXP_USE_DL=0;-DBUILDING_DLL"
/>
</FileConfiguration>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

5
configure vendored Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
echo "Autoconf is an evil piece bloatware encouraging cargo-cult programming."
echo "Make, on the other hand, is a beautiful little prolog for the filesystem."
echo "Just run 'make'."

View file

@ -0,0 +1,10 @@
execute_process(
COMMAND find ${LIBDIR} -name "*.sld"
COMMAND ${EXEC} ${GENMETA} ${VERSION}
OUTPUT_FILE ${OUT}
RESULT_VARIABLE error)
if(error)
message(FATAL_ERROR "${error}")
endif()

View file

@ -0,0 +1,27 @@
#
# chibi-genstatic-helper.cmake
#
# INPUT:
# ROOT=<DIR>
# EXEC=<EXECUTABLE>
# GENSTATIC=<FILE>
# STUBS=<FILE>
# OUT=<FILE>
if(NOT EXEC)
message(FATAL_ERROR "huh?")
endif()
if(NOT OUT)
message(FATAL_ERROR "huh?")
endif()
execute_process(
COMMAND ${EXEC} ${GENSTATIC} --no-inline
INPUT_FILE ${STUBS}
OUTPUT_FILE ${OUT}
RESULT_VARIABLE rr
)
if(rr)
message(FATAL_ERROR "Error: ${rr}")
endif()

View file

@ -0,0 +1,2 @@
include(${CMAKE_CURRENT_LIST_DIR}/chibi-scheme-targets.cmake)

View file

@ -0,0 +1,14 @@
# pkg-config
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_FULL_BINDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
version=@CMAKE_PROJECT_VERSION@
Name: chibi-scheme
URL: http://synthcode.com/scheme/chibi/
Description: Minimal Scheme Implementation for use as an Extension Language
Version: ${version}
Libs: -L${libdir} -lchibi-scheme
Libs.private: -dl -lm
Cflags: -I${includedir}

439
contrib/scheme-keywords.el Normal file
View file

@ -0,0 +1,439 @@
;; scheme-keywords.el
;; Scheme R7RS-small syntax highlighting and keyword completion for GNU Emacs
;; Copyright (c) 2015 Frère Jérôme. Contributed to the `Chibi-Scheme' project
;; under the same BSD-style license: http://synthcode.com/license.txt
;; The *optional* keyword completion is provided by the `company' framework
;; See: https://company-mode.github.io
;; Installation:
;; If necessary, add the location of this file to your Emacs `load-path':
;; (add-to-list 'load-path "FILE LOCATION")
;; Add the following lines to your `.emacs' configuration file:
;; (when (require 'scheme-keywords nil t)
;; (add-to-list 'auto-mode-alist '("\\.sld\\'" . scheme-mode))
;; ;; CUSTOMIZATION HERE
;; )
;; Customization:
;; (scheme-add-keywords 'LIST 'FACE) ;; define additional highlights
;; (setq scheme-keywords-completions 'LIST) ;; define additional completions
(require 'company nil t)
(require 'cl)
(defconst scheme-procedures-list
'("and"
"begin"
"call\/cc"
"call-with-current-continuation"
"call-with-input-file"
"call-with-output-file"
"call-with-port"
"call-with-values"
"case"
"case-lambda"
"cond"
"cond-expand"
"cons"
"define"
"define-library"
"define-record-type"
"define-syntax"
"define-values"
"delay"
"delay-force"
"do"
"dynamic-wind"
"else"
"eof-object"
"export"
"features"
"force"
"for-each"
"if"
"import"
"include"
"include-ci"
"lambda"
"let"
"let\*"
"letrec"
"letrec\*"
"letrec-syntax"
"let-syntax"
"let-values"
"let\*-values"
"library"
"list"
"load"
"not"
"or"
"quasiquote"
"quote"
"scheme-report-environment"
"syntax-error"
"syntax-rules"
"unless"
"unquote"
"unquote-splicing"
"values"
"when"))
(defconst scheme-operators-list
'("\<"
"\<\="
"\="
"\=\>"
"\>"
"\>\="
"\_"
"\-"
"\/"
"\.\.\."
"\*"
"\+"
"caaaar"
"caaadr"
"caaar"
"caadar"
"caaddr"
"caadr"
"caar"
"cadaar"
"cadadr"
"cadar"
"caddar"
"cadddr"
"caddr"
"cadr"
"car"
"cdaaar"
"cdaadr"
"cdaar"
"cdadar"
"cdaddr"
"cdadr"
"cdar"
"cddaar"
"cddadr"
"cddar"
"cdddar"
"cddddr"
"cdddr"
"cddr"
"cdr"
"\#f"
"\#false"
"\#t"
"\#true"))
(defconst scheme-predicates-list
'("binary-port\?"
"boolean\=\?"
"boolean\?"
"bytevector"
"bytevector\?"
"char\<\=\?"
"char\<\?"
"char\=\?"
"char\>\=\?"
"char\>\?"
"char\?"
"char-alphabetic\?"
"char-ci\<\=\?"
"char-ci\<\?"
"char-ci\=\?"
"char-ci\>\=\?"
"char-ci\>\?"
"char-numeric\?"
"char-ready\?"
"char-lower-case\?"
"char-upper-case\?"
"char-whitespace\?"
"complex\?"
"eof-object\?"
"eq\?"
"equal\?"
"eqv\?"
"error-object\?"
"even\?"
"exact\?"
"exact-integer\?"
"file-error\?"
"file-exists\?"
"finite\?"
"inexact\?"
"infinite\?"
"input-port\?"
"input-port-open\?"
"integer\?"
"list\?"
"nan\?"
"negative\?"
"null\?"
"number\?"
"odd\?"
"output-port\?"
"output-port-open\?"
"pair\?"
"port\?"
"positive\?"
"procedure\?"
"promise\?"
"rational\?"
"read-error\?"
"real\?"
"string\<\=\?"
"string\<\?"
"string\=\?"
"string\>\=\?"
"string\>\?"
"string\?"
"string-ci\<\=\?"
"string-ci\<\?"
"string-ci\=\?"
"string-ci\>\=\?"
"string-ci\>\?"
"symbol\=\?"
"symbol\?"
"textual-port\?"
"u8-ready\?"
"vector\?"
"zero\?"))
(defconst scheme-mutations-list
'("bytevector-copy\!"
"bytevector-u8-set\!"
"list-set\!"
"read-bytevector\!"
"set\!"
"set-car\!"
"set-cdr\!"
"string-copy\!"
"string-fill\!"
"string-set\!"
"vector-copy\!"
"vector-fill\!"
"vector-set\!"))
(defconst scheme-exceptions-list
'("emergency-exit"
"error"
"error-object-message"
"error-object-irritants"
"exit"
"guard"
"raise"
"raise-continuable"
"with-exception-handler"))
(defconst scheme-functions-list
'("abs"
"acos"
"angle"
"append"
"apply"
"asin"
"assoc"
"assq"
"assv"
"atan"
"bytevector"
"bytevector-append"
"bytevector-copy"
"bytevector-length"
"bytevector-u8-ref"
"ceiling"
"ceiling\/"
"ceiling-quotient"
"ceiling-remainder"
"centered\/"
"centered-quotient"
"centered-remainder"
"char-downcase"
"char-foldcase"
"char-\>integer"
"char-upcase"
"close-input-port"
"close-output-port"
"close-port"
"command-line"
"cos"
"current-error-port"
"current-input-port"
"current-jiffy"
"current-output-port"
"current-second"
"delete-file"
"denominator"
"digit-value"
"display"
"environment"
"euclidean\/"
"euclidean-quotient"
"euclidean-remainder"
"exact"
"exact-\>inexact"
"exact-integer-sqrt"
"exp"
"expt"
"floor"
"floor\/"
"floor-quotient"
"floor-remainder"
"flush-output-port"
"gcd"
"get-environment-variable"
"get-environment-variables"
"get-output-bytevector"
"get-output-string"
"imag-part"
"inexact"
"inexact-\>exact"
"integer-\>char"
"interaction-environment"
"jiffies-per-second"
"lcm"
"length"
"list-copy"
"list-ref"
"list-\>string"
"list-tail"
"list-\>vector"
"log"
"magnitude"
"make-bytevector"
"make-list"
"make-parameter"
"make-polar"
"make-promise"
"make-rectangular"
"make-string"
"make-vector"
"map"
"max"
"member"
"memq"
"memv"
"min"
"modulo"
"newline"
"null-environment"
"number-\>string"
"numerator"
"open-binary-input-file"
"open-binary-output-file"
"open-input-bytevector"
"open-input-file"
"open-input-string"
"open-output-bytevector"
"open-output-file"
"open-output-string"
"parameterize"
"peek-char"
"peek-u8"
"quotient"
"rationalize"
"read"
"read-bytevector"
"read-char"
"read-line"
"read-string"
"read-u8"
"real-part"
"remainder"
"reverse"
"round"
"round\/"
"round-quotient"
"round-remainder"
"sin"
"sqrt"
"square"
"string"
"string-append"
"string-copy"
"string-downcase"
"string-foldcase"
"string-for-each"
"string-length"
"string-\>list"
"string-map"
"string-\>number"
"string-ref"
"string-\>symbol"
"string-upcase"
"string-\>utf8"
"string-\>vector"
"substring"
"symbol-\>string"
"tan"
"truncate"
"truncate\/"
"truncate-quotient"
"truncate-remainder"
"utf8-\>string"
"vector"
"vector-append"
"vector-copy"
"vector-for-each"
"vector-length"
"vector-\>list"
"vector-map"
"vector-ref"
"vector-\>string"
"with-input-from-file"
"with-output-to-file"
"write"
"write-bytevector"
"write-char"
"write-shared"
"write-simple"
"write-string"
"write-u8"))
(defvar scheme-keywords-completions '())
(defun scheme-add-keywords (keywords face)
"Add keywords to Scheme mode."
(interactive (list 'interactive))
(let ((keyword-list (concat "\\<\\(" (regexp-opt keywords) "\\)\\>")))
(font-lock-add-keywords 'scheme-mode
`((,keyword-list 1 ',face)))))
(scheme-add-keywords scheme-procedures-list
'font-lock-keyword-face)
(scheme-add-keywords scheme-operators-list
'font-lock-builtin-face)
(scheme-add-keywords scheme-predicates-list
'font-lock-type-face)
(scheme-add-keywords scheme-mutations-list
'font-lock-type-face)
(scheme-add-keywords scheme-exceptions-list
'font-lock-warning-face)
(scheme-add-keywords scheme-functions-list
'font-lock-function-name-face)
(defun scheme-keywords-hook ()
(when (featurep 'company)
(defun company-scheme-keywords
(command &optional argument &rest ignored)
(interactive (list 'interactive))
(case command
(interactive (company-begin-backend 'company-scheme-keywords))
(prefix (and (eq major-mode 'scheme-mode) (company-grab-symbol)))
(candidates (remove-if-not
(lambda (candidate)
(string-prefix-p argument candidate))
(append scheme-procedures-list scheme-operators-list
scheme-predicates-list scheme-mutations-list
scheme-exceptions-list scheme-functions-list
scheme-keywords-completions)))))
(add-to-list 'company-backends 'company-scheme-keywords)))
(add-hook 'scheme-mode-hook 'scheme-keywords-hook)
(provide 'scheme-keywords)

View file

@ -52,4 +52,4 @@ Alex Shinn (alexshinn @ gmail . com)
.PP
The chibi-scheme home-page:
.BR
http://code.google.com/p/chibi-scheme/
https://github.com/ashinn/chibi-scheme/

View file

@ -42,4 +42,4 @@ Alex Shinn (alexshinn @ gmail . com)
.PP
The chibi-scheme home-page:
.BR
http://code.google.com/p/chibi-scheme/
https://github.com/ashinn/chibi-scheme/

View file

@ -6,13 +6,16 @@ chibi-scheme \- a tiny Scheme interpreter
.SH SYNOPSIS
.B chibi-scheme
[-qQrRfV]
[-qQrRfTV]
[-I
.I path
]
[-A
.I path
]
[-D
.I feature
]
[-m
.I module
]
@ -76,8 +79,14 @@ module. This can be launched automatically with:
.I chibi-scheme -R
\[char46]
The default language the R7RS
(scheme base) module. To get a mostly R5RS-compatible language, use
For convenience the default language is the
(scheme small) module, which includes every library in the R7RS
small standard, and transitively some other dependencies. All of this
together is actually quite large, so for a more minimal startup
language you'll want to use the
.I -x module
option described below.
To get a mostly R5RS-compatible language, use
.I chibi-scheme -xscheme.r5rs
or to get just the core language used for bootstrapping, use
.I chibi-scheme -xchibi
@ -130,7 +139,7 @@ need not be exported) with a single argument of the list of command-line
arguments as in SRFI-22. The name "main" can be overridden with the -r
option.
.I [module]
may be omitted, in which case it default to chibi.repl. Thus
may be omitted, in which case it defaults to chibi.repl. Thus
.I chibi-scheme -R
is the recommended means to obtain the advanced REPL.
.TP
@ -140,6 +149,11 @@ Strict mode, escalating warnings to fatal errors.
.BI -f
Change the reader to case-fold symbols as in R5RS.
.TP
.BI -T
Disables tail-call optimization. This can be useful for
debugging in some cases, but also makes it very likely to
overflow the stack.
.TP
.BI -h size[/max_size]
Specifies the initial size of the heap, in bytes,
optionally followed by the maximum size the heap can
@ -161,6 +175,12 @@ Appends
.I path
to the load path list.
.TP
.BI -D feature
Adds
.I feature
to the feature list, useful for cond-expanding different
library code.
.TP
.BI -m module
.TP
.BI -x module
@ -205,13 +225,17 @@ Loads the Scheme heap from
.I image-file
instead of compiling the init file on the fly.
This feature is still experimental.
.TP
.BI -b
Makes stdio nonblocking (blocking by default). Only available when
lightweight threads are enabled.
.SH ENVIRONMENT
.TP
.B CHIBI_MODULE_PATH
A colon separated list of directories to search for module
files, inserted before the system default load paths. chibi-scheme
searchs for modules in directories in the following order:
searches for modules in directories in the following order:
.TP
directories included with the -I path option
@ -222,8 +246,14 @@ searchs for modules in directories in the following order:
.TP
directories included with -A path option
If CHIBI_MODULE_PATH is unset, the directoriese "./lib", and "." are
search in order.
If CHIBI_MODULE_PATH is unset, the directories "./lib", and "." are
searched in order. Set to empty to only consider -I, system
directories and -A.
.TP
.B CHIBI_IGNORE_SYSTEM_PATH
If set to anything but "0", system directories (as listed above) are
not included in the search paths.
.SH AUTHORS
.PP
@ -231,9 +261,9 @@ Alex Shinn (alexshinn @ gmail . com)
.SH SEE ALSO
.PP
More detailed information can be found in the manuale included in
More detailed information can be found in the manual included in
doc/chibi.scrbl included in the distribution.
The chibi-scheme home-page:
.br
http://code.google.com/p/chibi-scheme/
https://github.com/ashinn/chibi-scheme/

View file

@ -4,7 +4,7 @@
\author{Alex Shinn}
\centered{\smaller{Minimal Scheme Implementation for use as an Extension Language}}
\centered{\url{http://synthcode.com/wiki/chibi-scheme}}
\centered{\url{https://github.com/ashinn/chibi-scheme}}
\section{Introduction}
@ -28,8 +28,8 @@ standard modules. You can choose whichever layer suits your needs
best and customize the rest. Adding your own primitives or wrappers
around existing C libraries is easy with the C FFI.
Chibi is known to build and run on 32 and 64-bit Linux, FreeBSD,
DragonFly, OS X, iOS, Windows (under Cygwin) and Plan9.
Chibi is known to build and run on 32 and 64-bit Linux, OpenBSD, FreeBSD,
DragonFlyBSD, OS X, iOS, Windows (under Cygwin) and Plan9.
\section{Installation}
@ -69,6 +69,13 @@ To compile a static executable, use
\command{make chibi-scheme-static SEXP_USE_DL=0}
Note this static executable has none of the external binary libraries
included, which means among other things you can't load the
\scheme{(scheme base)} default language. You need to specify the
\scheme{(chibi)} or other Scheme-only language to run:
\command{./chibi-scheme-static -q}
To compile a static executable with all C libraries statically
included, first you need to create a clibs.c file, which can be done
with:
@ -79,7 +86,8 @@ or edited manually. Be sure to run this with a non-static
chibi-scheme. Then you can make the static executable with:
\command{
make -B chibi-scheme-static SEXP_USE_DL=0 CPPFLAGS=-DSEXP_USE_STATIC_LIBS
make -B chibi-scheme-static SEXP_USE_DL=0 \
CPPFLAGS="-DSEXP_USE_STATIC_LIBS -DSEXP_USE_STATIC_LIBS_NO_INCLUDE=0"
}
By default files are installed in /usr/local. You can optionally
@ -112,6 +120,7 @@ are listed below.
\item{\ccode{SEXP_USE_RATIOS} - use exact ratios (enabled by default)}
\item{\ccode{SEXP_USE_COMPLEX} - use complex numbers (enabled by default)}
\item{\ccode{SEXP_USE_UTF8_STRINGS} - Unicode support (enabled by default)}
\item{\ccode{SEXP_USE_STRING_INDEX_TABLE} - precompute offsets for O(1) \scheme{string-ref}}
\item{\ccode{SEXP_USE_NO_FEATURES} - disable almost all features}
]
@ -127,6 +136,8 @@ documentation system described in
build this manual. \ccode{chibi-ffi} is a tool to build wrappers for
C libraries, described in the FFI section below.
See the examples directory for some sample programs.
\section{Default Language}
\subsection{Scheme Standard}
@ -137,9 +148,10 @@ superset of
\hyperlink["http://www.schemers.org/Documents/Standards/R5RS/HTML/"]{R5RS}.
The reader defaults to case-sensitive, like R6RS and R7RS but unlike
R5RS. The default configuration includes the full numeric tower:
fixnums, flonums, bignums, exact rationals and complex numbers, though
this can be customized at compile time.
R5RS. You can specify the -f option on the command-line to enable
case-folding. The default configuration includes the full numeric
tower: fixnums, flonums, bignums, exact rationals and complex numbers,
though this can be customized at compile time.
Full continuations are supported, but currently continuations don't
take C code into account. This means that you can call from Scheme to
@ -153,13 +165,14 @@ currently unspecified.
In R7RS (and R6RS) semantics it is impossible to use two macros from
different modules which both use the same auxiliary keywords (like
\scheme{else} in \scheme{cond} forms) without renaming one of the
keywords. By default Chibi considers all top-level bindings
effectively unbound when matching auxiliary keywords, so this case
will "just work". This decision was made because the chance of
different modules using the same keywords seems more likely than user
code unintentionally matching a top-level keyword with a different
binding, however if you want to use R7RS semantics you can compile
with \ccode{SEXP_USE_STRICT_TOPLEVEL_BINDINGS=1}.
keywords. To minimize conflicts Chibi offers a special module named
\scheme{(auto)} which can export any identifier requested with
\scheme{only}, e.g. \scheme{(import (only (auto) foo))} will import
an auxiliary syntax \scheme{foo} binding. Separate modules can use
this to get the same binding without needing to know about each other
in advance. This is a Chibi-specific extension so is non-portable, but
you can always define a static \scheme{(auto)} module exporting a list
of all known bindings for other implementations.
\scheme{load} is extended to accept an optional environment argument, like
\scheme{eval}. You can also \scheme{load} shared libraries in addition to
@ -179,11 +192,12 @@ other languages.
\subsection{Module System}
Chibi uses the R7RS module system natively, which is a simple static
module system in the style of the
\hyperlink["http://s48.org/"]{Scheme48} module system. As with most
features this is optional, and can be ignored or completely disabled
at compile time.
Chibi supports the R7RS module system natively, which is a simple
static module system. The Chibi implementation is actually a
hierarchy of languages in the style of the
\hyperlink["http://s48.org/"]{Scheme48} module system, allowing easy
extension of the module system itself. As with most features this is
optional, and can be ignored or completely disabled at compile time.
Modules names are hierarchical lists of symbols or numbers. A module
definition uses the following form:
@ -201,7 +215,8 @@ where \var{<library-declarations>} can be any of
(begin <expr> ...) ;; inline Scheme code
(include <file> ...) ;; load one or more files
(include-ci <file> ...) ;; as include, with case-folding
(include-shared <file> ...) ;; dynamic load a library
(include-shared <file> ...) ;; dynamic load a library (non-R7RS)
(alias-for <library>) ;; a library alias (non-R7RS)
}
\var{<import-spec>} can either be a module name or any of
@ -210,13 +225,23 @@ where \var{<library-declarations>} can be any of
(only <import-spec> <id> ...)
(except <import-spec> <id> ...)
(rename <import-spec> (<from-id> <to-id>) ...)
(prefix <prefix-id> <import-spec>)
(prefix <import-spec> <prefix-id>)
(drop-prefix <import-spec> <prefix-id>) ;; non-R7RS
}
These forms perform basic selection and renaming of individual
identifiers from the given module. They may be composed to perform
combined selection and renaming.
Note while the repl provides default bindings as a convenience,
programs have strict semantics as in R7RS and must start with at least
one import, e.g.
\schemeblock{
(import (scheme base))
(write-string "Hello world!\n")
}
Some modules can be statically included in the initial configuration,
and even more may be included in image files, however in general
modules are searched for in a module load path. The definition of the
@ -225,7 +250,7 @@ module \scheme{(foo bar baz)} is searched for in the file
installed directories, \scheme{"."} and \scheme{"./lib"}. Additional
directories can be specified with the command-line options \ccode{-I}
and \ccode{-A} (see the command-line options below) or with the
\scheme{add-modue-directory} procedure at runtime. You can search for
\scheme{add-module-directory} procedure at runtime. You can search for
a module file with \scheme{(find-module-file <file>)}, or load it with
\scheme{(load-module-file <file> <env>)}.
@ -264,8 +289,8 @@ These are just syntactic sugar for the following more primitive type
constructors:
\schemeblock{
(register-simple-type <name-string> <parent> <num-fields>)
=> <type>
(register-simple-type <name-string> <parent> <field-names>)
=> <type> ; parent may be #f, field-names should be a list of symbols
(make-type-predicate <opcode-name-string> <type>)
=> <opcode> ; takes 1 arg, returns #t iff that arg is of the type
@ -278,27 +303,38 @@ constructors:
(make-setter <setter-name-string> <type> <field-index>)
=> <opcode> ; takes 2 args, sets the field located at the index
(type-slot-offset <type> <field-name>)
=> <index> ; returns the index of the field with the given name
}
\subsection{Unicode}
Chibi supports Unicode strings, encoding them as utf8. This provides easy
interoperability with many C libraries, but means that \scheme{string-ref} and
\scheme{string-set!} are O(n), so they should be avoided in
performance-sensitive code.
Chibi supports Unicode strings and I/O natively. Case mappings and
comparisons, character properties, formatting and regular expressions
are all Unicode aware, supporting the latest version 13.0 of the
Unicode standard.
Internally strings are encoded as UTF-8. This provides easy
interoperability with many C libraries, but means that
\scheme{string-ref} and \scheme{string-set!} are O(n), so they should
be avoided in performance-sensitive code (unless you compile Chibi
with SEXP_USE_STRING_INDEX_TABLE).
In general you should use high-level APIs such as \scheme{string-map}
to ensure fast string iteration. String ports also provide a simple
way to efficiently iterate and construct strings, by looping over an
input string or accumulating characters in an output string.
and portable way to efficiently iterate and construct strings, by
looping over an input string or accumulating characters in an output
string.
The \scheme{in-string} and \scheme{in-string-reverse} iterators in the
\scheme{(chibi loop)} module will also iterate over strings
efficiently while hiding the low-level details.
In the event that you do need a low-level interface, such as when
writing your own iterator protocol, you should use the following
string cursor API instead of indexes.
writing your own iterator protocol, you should use string cursors.
\scheme{(srfi 130)} provides a portable API for this, or you can use
\scheme{(chibi string)} which builds on the following core procedures:
\itemlist[
\item{\scheme{(string-cursor-start str)}
@ -334,9 +370,10 @@ To use Chibi-Scheme in a program you need to link against the
\ccode{#include <chibi/eval.h>}
All definitions begin with a "sexp_" prefix, or "SEXP_" for constants.
In addition to the prototypes and utility macros, this includes the
following type definitions:
All definitions begin with a "sexp_" prefix, or "SEXP_" for constants
(deliberately chosen not to conflict with other Scheme implementations
which typically use "scm_"). In addition to the prototypes and
utility macros, this includes the following type definitions:
\itemlist[
\item{\ctype{sexp} - an s-expression, used to represent all Scheme objects}
@ -370,9 +407,10 @@ void dostuff(sexp ctx) {
int main(int argc, char** argv) {
sexp ctx;
sexp_scheme_init();
ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 0);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);
dostuff(ctx);
sexp_destroy_context(ctx);
}
@ -397,7 +435,7 @@ temporary values we may generate, which is what the
\cmacro{sexp_gc_var2}, \cmacro{sexp_gc_preserve2} and
\cmacro{sexp_gc_release2} macros do (there are similar macros for
values 1-6). Precise GCs prevent a class of memory leaks (and
potential attackes based thereon), but if you prefer convenience then
potential attacks based thereon), but if you prefer convenience then
Chibi can be compiled with a conservative GC and you can ignore these.
The interesting part is then the calls to \cfun{sexp_load},
@ -438,6 +476,11 @@ using only the parent.
Otherwise, a new heap is allocated with \var{size} bytes, expandable to a
maximum of \var{max_size} bytes, using the system defaults if either is 0.
Note this context is not a malloced pointer (it resides inside a
malloced heap), and therefore can't be passed to \ccode{free()},
or stored in a C++ smart pointer. It can only be reclaimed with
\ccode{sexp_destroy_context}.
}}
\item{\ccode{sexp_make_eval_context(sexp ctx, sexp stack, sexp env, sexp_uint_t size, sexp_uint_t max_size)}
@ -469,7 +512,8 @@ the default context environment is used. Any of the \ctype{FILE*} may
be \cvar{NULL}, in which case the corresponding port is not set. If
\var{leave_open} is true, then the underlying \ctype{FILE*} is left
open after the Scheme port is closed, otherwise they are both closed
together.
together. If you want to reuse these streams from other vms, or from
C, you should specify leave_open.
}}
\item{\ccode{sexp_load(sexp ctx, sexp file, sexp env)}
@ -513,6 +557,11 @@ Returns the current binding of \var{sym} in \var{env}, or \var{dflt} if there
is no binding.
}}
\item{\ccode{sexp_env_import(sexp ctx, sexp to, sexp from, sexp ls, sexp immutp)}
\p{
Imports the bindings from environment \var{from} into environment \var{to}. \var{ls} is the list of bindings to import - if it is \scheme{#f} then import all bindings. If \var{immutp} is true the imported bindings are immutable and cannot be redefined.
}}
\item{\ccode{sexp_parameter_ref(sexp ctx, sexp param)}
\p{
Returns the current dynamic value of the parameter \var{param} in the
@ -617,13 +666,15 @@ sexp_release_object(ctx, obj)
Decrement the absolute reference count for \var{obj}.
\subsection{API Index}
\subsection{C API Index}
The above sections describe most everything you need for embedding in
a typical application, notably creating environments and evaluating
code from sexps, strings or files. The following sections expand on
additional macros and utilities for inspecting, accessing and creating
different Scheme types, and for performing port and string I/O.
different Scheme types, and for performing port and string I/O. It is
incomplete - see the macros and SEXP_API annotated functions in the
include files (sexp.h, eval.h, bignum.h) for more bindings.
Being able to convert from C string to sexp, evaluate it, and convert
the result back to a C string forms the basis of the C API. Because
@ -651,10 +702,13 @@ need to check manually before applying the predicate.
\item{\ccode{sexp_fixnump(obj)} - \var{obj} is an immediate integer}
\item{\ccode{sexp_flonump(obj)} - \var{obj} is an inexact real}
\item{\ccode{sexp_bignump(obj)} - \var{obj} is a heap-allocated integer}
\item{\ccode{sexp_integerp(obj)} - \var{obj} is an integer}
\item{\ccode{sexp_integerp(obj)} - \var{obj} is an integer (or flonum truncating without loss)}
\item{\ccode{sexp_ratiop(obj)} - \var{obj} is an exact rational (with SEXP_USE_RATIOS)}
\item{\ccode{sexp_complexp(obj)} - \var{obj} is a complex number (with SEXP_USE_COMPLEX)}
\item{\ccode{sexp_numberp(obj)} - \var{obj} is any kind of number}
\item{\ccode{sexp_charp(obj)} - \var{obj} is a character}
\item{\ccode{sexp_stringp(obj)} - \var{obj} is a string}
\item{\ccode{sexp_string_cursorp(obj)} - \var{obj} is a string cursor}
\item{\ccode{sexp_bytesp(obj)} - \var{obj} is a bytevector}
\item{\ccode{sexp_symbolp(obj)} - \var{obj} is a symbol}
\item{\ccode{sexp_idp(obj)} - \var{obj} is a symbol or hygienic identifier}
@ -712,7 +766,7 @@ check. The runtime does not prevent embedded NULLs inside strings,
however data after the NULL may be ignored.
By default (unless you compile with -DSEXP_USE_UTF8_STRING=0), strings
are interpreted as utf8 encoded on the Scheme side, as describe in
are interpreted as UTF-8 encoded on the Scheme side, as describe in
section Unicode above. In many cases you can ignore this on the C
side and just treat the string as an opaque sequence of bytes.
However, if you need to you can use the following macros to safely
@ -730,7 +784,7 @@ compiled with:
\item{\ccode{sexp sexp_substring_cursor(sexp ctx, sexp s, sexp i, sexp j)} - returns the substring between raw offsets \var{i} and \var{j}}
]
When UTF8 support is not compiled in the cursor and non-cursor
When UTF-8 support is not compiled in the cursor and non-cursor
variants are equivalent.
\subsubsection{Accessors}
@ -746,8 +800,12 @@ once.
\item{\ccode{sexp_unbox_boolean(obj)} - 1 if \var{obj} is \scheme{#t}, 0 otherwise}
\item{\ccode{sexp_make_fixnum(n)} - creates a new fixnum representing int \var{n}}
\item{\ccode{sexp_unbox_fixnum(obj)} - converts a fixnum to a C integer}
\item{\ccode{sexp_make_flonum(sexp ctx, float f)} - creates a new floating point value}
\item{\ccode{sexp_flonum_value(obj)} - converts a flonum to a C float}
\item{\ccode{sexp_make_character(ch)} - creates a new character representing char \var{ch}}
\item{\ccode{sexp_unbox_character(obj)} - converts a character to a C char}
\item{\ccode{sexp sexp_make_string_cursor(int offset)} - creates a string cursor for the given byte offset}
\item{\ccode{int sexp_unbox_string_cursor(sexp sc)} - returns the offset for the given string cursor}
\item{\ccode{sexp_car(pair)} - the car of \var{pair}}
\item{\ccode{sexp_cdr(pair)} - the cdr of \var{pair}}
\item{\ccode{sexp_ratio_numerator(q)} - the numerator of the ratio \var{q}}
@ -776,6 +834,7 @@ Any of these may fail and return the OOM exception object.
\item{\ccode{sexp_cons(sexp ctx, sexp obj1, sexp obj2)} - create a new pair whose car is \var{obj1} and whose cdr is \var{obj2}}
\item{\ccode{sexp_list1(sexp ctx, sexp obj)} - alias for sexp_cons(ctx, obj, SEXP_NULL)}
\item{\ccode{sexp_list2(sexp ctx, sexp obj1, sexp obj2)} - create a list of two elements}
\item{\ccode{sexp_list3(sexp ctx, sexp obj1, sexp obj2, sexp obj3)} - create a list of three elements}
\item{\ccode{sexp_make_string(sexp ctx, sexp len, sexp ch)} - create a new Scheme string of \var{len} characters, all initialized to \var{ch}}
\item{\ccode{sexp_c_string(sexp ctx, const char* str, int len)} - create a new Scheme string copying the first \var{len} characters of the C string \var{str}. If \var{len} is -1, uses strlen(\var{str}).}
\item{\ccode{sexp_intern(sexp ctx, const char* str, int len)} - interns a symbol from the first \var{len} characters of the C string \var{str}. If \var{len} is -1, uses strlen(\var{str}).}
@ -791,7 +850,6 @@ Any of these may fail and return the OOM exception object.
\item{\ccode{sexp_read(sexp ctx, sexp in)} - read a single datum from port \var{in}}
\item{\ccode{sexp_write(sexp ctx, sexp obj, sexp out)} - write \var{obj} to port \var{out}}
\item{\ccode{sexp_write_string(sexp ctx, char* str, sexp out)} - write the characters in \var{str} to port \var{out}}
\item{\ccode{sexp_display(sexp ctx, sexp obj, sexp out)} - display \var{obj} to port \var{out}}
\item{\ccode{sexp_newline(sexp ctx, sexp out)} - write a newline to port \var{out}}
\item{\ccode{sexp_print_exception(sexp ctx, sexp exn, sexp out)} - print an error message for \var{exn} to port \var{out}}
\item{\ccode{sexp_current_input_port(sexp ctx)} - the \scheme{current-input-port}}
@ -802,7 +860,7 @@ Any of these may fail and return the OOM exception object.
\item{\ccode{sexp_write_to_string(sexp ctx, sexp obj)} - return a Scheme string representation of \var{obj}}
\item{\ccode{sexp_open_input_string(sexp ctx, sexp str)} - equivalent to \scheme{open-input-string}}
\item{\ccode{sexp_open_output_string(sexp ctx)} - equivalent to \scheme{open-output-string}}
\item{\ccode{sexp_get_output_string(sexp ctx, sexp port)} - equivalent to \scheme{open-output-string}}
\item{\ccode{sexp_get_output_string(sexp ctx, sexp port)} - equivalent to \scheme{get-output-string}}
]
\subsubsection{Utilities}
@ -815,7 +873,7 @@ Any of these may fail and return the OOM exception object.
\item{\ccode{sexp_assq(sexp ctx, sexp x, sexp ls)} - \scheme{assq}}
\item{\ccode{sexp_reverse(sexp ctx, sexp ls)} - \scheme{reverse}}
\item{\ccode{sexp_nreverse(sexp ctx, sexp ls)} - \scheme{reverse!}}
\item{\ccode{sexp_append2(sexp ctx, sexp ls)} - \scheme{append} for two arguments}
\item{\ccode{sexp_append2(sexp ctx, sexp ls1, sexp ls2)} - \scheme{append} for two arguments}
\item{\ccode{sexp_copy_list(sexp ctx, sexp ls)} - return a shallow copy of \var{ls}}
\item{\ccode{sexp_list_to_vector(sexp ctx, sexp ls)} - \scheme{list->vector}}
\item{\ccode{sexp_symbol_to_string(sexp ctx, sexp sym)} - \scheme{symbol->string}}
@ -895,6 +953,39 @@ to any inherited from the parent type \var{parent}. If \var{parent} is false,
inherits from the default \var{object} record type.
}}
\item{\ccode{sexp sexp_register_c_type(sexp ctx, sexp name, sexp finalizer)}
\p{
Shortcut to defines a new type as a wrapper around a C pointer.
Returns the type object, which can be used with sexp_make_cpointer to
wrap instances of the type. The finalizer may be sexp_finalize_c_type
in which case managed pointers are freed as if allocated with malloc,
NULL in which case the pointers are never freed, or otherwise a
procedure of one argument which should release any resources.
}}
\item{\ccode{sexp sexp_make_cpointer(sexp ctx, sexp_uint_t type_tag, void* value, sexp parent, int freep)}
\p{
Creates a new instance of the type indicated by type_tag wrapping
value. If parent is provided, references to the child will also
preserve the parent, important e.g. to preserve an enclosing struct
when wrapped references to nested structs are still in use. If freep
is true, then when reclaimed by the GC the finalizer for this type,
if any, will be called on the instance.
You can retrieve the tag from a type object with sexp_type_tag(type).
}}
\item{\ccode{sexp sexp_lookup_type(sexp ctx, sexp name, sexp tag_or_id)}
\p{
Returns the type whose name matches the string \var{name}. If
\var{tag_or_id} is an integer, it is taken as the tag and requires the
numeric type tag (as from sexp_type_tag) to also match.
}
\p{If \var{tag_or_id} is a string, it is taken as the unique id of the
type, and must match sexp_type_id(type). However, currently
sexp_type_id(type) is never set.
}}
]
See the C FFI for an easy way to automate adding bindings for C
@ -1157,7 +1248,8 @@ A number of SRFIs are provided in the default installation. Note that
SRFIs 0, 6, 23, 46 and 62 are built into the default environment so
there's no need to import them. SRFI 22 is available with the "-r"
command-line option. This list includes popular SRFIs or SRFIs used
in standard Chibi modules
in standard Chibi modules (many other SRFIs are available on
snow-fort):
\itemlist[
@ -1168,6 +1260,7 @@ in standard Chibi modules
\item{\hyperlink["http://srfi.schemers.org/srfi-8/srfi-8.html"]{(srfi 8) - receive}}
\item{\hyperlink["http://srfi.schemers.org/srfi-9/srfi-9.html"]{(srfi 9) - define-record-type}}
\item{\hyperlink["http://srfi.schemers.org/srfi-11/srfi-11.html"]{(srfi 11) - let-values/let*-values}}
\item{\hyperlink["http://srfi.schemers.org/srfi-14/srfi-14.html"]{(srfi 14) - character-set library}}
\item{\hyperlink["http://srfi.schemers.org/srfi-16/srfi-16.html"]{(srfi 16) - case-lambda}}
\item{\hyperlink["http://srfi.schemers.org/srfi-18/srfi-18.html"]{(srfi 18) - multi-threading support}}
\item{\hyperlink["http://srfi.schemers.org/srfi-22/srfi-22.html"]{(srfi 22) - running scheme scripts on Unix}}
@ -1177,13 +1270,53 @@ in standard Chibi modules
\item{\hyperlink["http://srfi.schemers.org/srfi-33/srfi-33.html"]{(srfi 33) - bitwise operators}}
\item{\hyperlink["http://srfi.schemers.org/srfi-38/srfi-38.html"]{(srfi 38) - read/write shared structures}}
\item{\hyperlink["http://srfi.schemers.org/srfi-39/srfi-39.html"]{(srfi 39) - parameter objects}}
\item{\hyperlink["http://srfi.schemers.org/srfi-41/srfi-41.html"]{(srfi 41) - streams}}
\item{\hyperlink["http://srfi.schemers.org/srfi-46/srfi-46.html"]{(srfi 46) - basic syntax-rules extensions}}
\item{\hyperlink["http://srfi.schemers.org/srfi-55/srfi-55.html"]{(srfi 55) - require-extension}}
\item{\hyperlink["http://srfi.schemers.org/srfi-62/srfi-62.html"]{(srfi 62) - s-expression comments}}
\item{\hyperlink["http://srfi.schemers.org/srfi-64/srfi-64.html"]{(srfi 64) - a scheme API for test suites}}
\item{\hyperlink["http://srfi.schemers.org/srfi-69/srfi-69.html"]{(srfi 69) - basic hash tables}}
\item{\hyperlink["http://srfi.schemers.org/srfi-95/srfi-95.html"]{(srfi 95) - sorting and merging}}
\item{\hyperlink["http://srfi.schemers.org/srfi-98/srfi-98.html"]{(srfi 98) - environment access}}
\item{\hyperlink["http://srfi.schemers.org/srfi-99/srfi-99.html"]{(srfi 99) - ERR5RS records}}
\item{\hyperlink["http://srfi.schemers.org/srfi-101/srfi-101.html"]{(srfi 101) - purely functional random-access pairs and lists}}
\item{\hyperlink["http://srfi.schemers.org/srfi-111/srfi-111.html"]{(srfi 111) - boxes}}
\item{\hyperlink["http://srfi.schemers.org/srfi-113/srfi-113.html"]{(srfi 113) - sets and bags}}
\item{\hyperlink["http://srfi.schemers.org/srfi-115/srfi-115.html"]{(srfi 115) - Scheme regular expressions}}
\item{\hyperlink["http://srfi.schemers.org/srfi-116/srfi-116.html"]{(srfi 116) - immutable list library}}
\item{\hyperlink["http://srfi.schemers.org/srfi-117/srfi-117.html"]{(srfi 117) - mutable queues}}
\item{\hyperlink["http://srfi.schemers.org/srfi-121/srfi-121.html"]{(srfi 121) - generators}}
\item{\hyperlink["http://srfi.schemers.org/srfi-124/srfi-124.html"]{(srfi 124) - ephemerons}}
\item{\hyperlink["http://srfi.schemers.org/srfi-125/srfi-125.html"]{(srfi 125) - intermediate hash tables}}
\item{\hyperlink["http://srfi.schemers.org/srfi-127/srfi-127.html"]{(srfi 127) - lazy sequences}}
\item{\hyperlink["http://srfi.schemers.org/srfi-128/srfi-128.html"]{(srfi 128) - comparators (reduced)}}
\item{\hyperlink["http://srfi.schemers.org/srfi-129/srfi-129.html"]{(srfi 129) - titlecase procedures}}
\item{\hyperlink["http://srfi.schemers.org/srfi-130/srfi-130.html"]{(srfi 130) - cursor-based string library}}
\item{\hyperlink["http://srfi.schemers.org/srfi-132/srfi-132.html"]{(srfi 132) - sort libraries}}
\item{\hyperlink["http://srfi.schemers.org/srfi-133/srfi-133.html"]{(srfi 133) - vector library}}
\item{\hyperlink["http://srfi.schemers.org/srfi-134/srfi-134.html"]{(srfi 134) - immutable deques}}
\item{\hyperlink["http://srfi.schemers.org/srfi-135/srfi-135.html"]{(srfi 135) - immutable texts}}
\item{\hyperlink["http://srfi.schemers.org/srfi-139/srfi-139.html"]{(srfi 139) - syntax parameters}}
\item{\hyperlink["http://srfi.schemers.org/srfi-141/srfi-141.html"]{(srfi 141) - integer division}}
\item{\hyperlink["http://srfi.schemers.org/srfi-143/srfi-142.html"]{(srfi 142) - bitwise operations}}
\item{\hyperlink["http://srfi.schemers.org/srfi-143/srfi-143.html"]{(srfi 143) - fixnums}}
\item{\hyperlink["http://srfi.schemers.org/srfi-144/srfi-144.html"]{(srfi 144) - flonums}}
\item{\hyperlink["http://srfi.schemers.org/srfi-145/srfi-145.html"]{(srfi 145) - assumptions}}
\item{\hyperlink["http://srfi.schemers.org/srfi-147/srfi-147.html"]{(srfi 147) - custom macro transformers}}
\item{\hyperlink["http://srfi.schemers.org/srfi-151/srfi-151.html"]{(srfi 151) - bitwise operators}}
\item{\hyperlink["http://srfi.schemers.org/srfi-154/srfi-154.html"]{(srfi 154) - first-class dynamic extents}}
\item{\hyperlink["http://srfi.schemers.org/srfi-158/srfi-158.html"]{(srfi 158) - generators and accumulators}}
\item{\hyperlink["http://srfi.schemers.org/srfi-160/srfi-160.html"]{(srfi 160) - homogeneous numeric vector libraries}}
\item{\hyperlink["http://srfi.schemers.org/srfi-165/srfi-165.html"]{(srfi 165) - the environment Monad}}
\item{\hyperlink["http://srfi.schemers.org/srfi-166/srfi-166.html"]{(srfi 166) - monadic formatting}}
\item{\hyperlink["http://srfi.schemers.org/srfi-179/srfi-179.html"]{(srfi 179) - nonempty intervals and generalized arrays}}
\item{\hyperlink["http://srfi.schemers.org/srfi-188/srfi-188.html"]{(srfi 188) - splicing binding constructs for syntactic keywords}}
\item{\hyperlink["http://srfi.schemers.org/srfi-193/srfi-193.html"]{(srfi 193) - command-line}}
\item{\hyperlink["http://srfi.schemers.org/srfi-211/srfi-211.html"]{(srfi 211) - scheme macro libaries}}
\item{\hyperlink["http://srfi.schemers.org/srfi-219/srfi-219.html"]{(srfi 219) - define higher-order lambda}}
\item{\hyperlink["http://srfi.schemers.org/srfi-227/srfi-227.html"]{(srfi 227) - optional arguments}}
\item{\hyperlink["http://srfi.schemers.org/srfi-229/srfi-229.html"]{(srfi 229) - tagged procedures}}
\item{\hyperlink["http://srfi.schemers.org/srfi-231/srfi-231.html"]{(srfi 231) - intervals and generalized arrays}}
]
@ -1196,10 +1329,30 @@ namespace.
\item{\hyperlink["lib/chibi/ast.html"]{(chibi ast) - Abstract Syntax Tree and other internal data types}}
\item{\hyperlink["lib/chibi/assert.html"]{(chibi assert) - A nicer assert macro}}
\item{\hyperlink["lib/chibi/base64.html"]{(chibi base64) - Base64 encoding and decoding}}
\item{\hyperlink["lib/chibi/binary-record.html"]{(chibi binary-record) - Record types with binary serialization}}
\item{\hyperlink["lib/chibi/bytevector.html"]{(chibi bytevector) - Bytevector Utilities}}
\item{\hyperlink["lib/chibi/config.html"]{(chibi config) - General configuration management}}
\item{\hyperlink["lib/chibi/crypto/md5.html"]{(chibi crypto md5) - MD5 hash}}
\item{\hyperlink["lib/chibi/crypto/rsa.html"]{(chibi crypto rsa) - RSA public key encryption}}
\item{\hyperlink["lib/chibi/crypto/sha2.html"]{(chibi crypto sha2) - SHA-2 hash}}
\item{\hyperlink["lib/chibi/diff.html"]{(chibi diff) - LCS Algorithm and diff utilities}}
\item{\hyperlink["lib/chibi/disasm.html"]{(chibi disasm) - Disassembler for the virtual machine}}
\item{\hyperlink["lib/chibi/doc.html"]{(chibi doc) - Chibi documentation utilities}}
\item{\hyperlink["lib/chibi/edit-distance.html"]{(chibi edit-distance) - A levenshtein distance implementation}}
\item{\hyperlink["lib/chibi/equiv.html"]{(chibi equiv) - A version of \scheme{equal?} which is guaranteed to terminate}}
\item{\hyperlink["lib/chibi/filesystem.html"]{(chibi filesystem) - Interface to the filesystem and file descriptor objects}}
@ -1210,16 +1363,36 @@ namespace.
\item{\hyperlink["lib/chibi/io.html"]{(chibi io) - Various I/O extensions and custom ports}}
\item{\hyperlink["lib/chibi/iset/base.html"]{(chibi iset base) - Compact integer sets}}
\item{\hyperlink["lib/chibi/iset/base.html"]{(chibi iset base) - Compact integer sets}}
\item{\hyperlink["lib/chibi/iset/constructors.html"]{(chibi iset constructors) - Compact integer set construction}}
\item{\hyperlink["lib/chibi/iset/iterators.html"]{(chibi iset iterators) - Iterating over compact integer sets}}
\item{\hyperlink["lib/chibi/json.html"]{(chibi json) - JSON reading and writing}}
\item{\hyperlink["lib/chibi/loop.html"]{(chibi loop) - Fast and extensible loop syntax}}
\item{\hyperlink["lib/chibi/match.html"]{(chibi match) - Intuitive and widely supported pattern matching syntax}}
\item{\hyperlink["lib/chibi/math/prime.html"]{(chibi math prime) - Prime number utilities}}
\item{\hyperlink["lib/chibi/memoize.html"]{(chibi memoize) - Procedure memoization}}
\item{\hyperlink["lib/chibi/mime.html"]{(chibi mime) - Parse MIME files into SXML}}
\item{\hyperlink["lib/chibi/modules.html"]{(chibi modules) - Introspection for the module system itself}}
\item{\hyperlink["lib/chibi/net.html"]{(chibi net) - Simple networking interface}}
\item{\hyperlink["lib/chibi/net/http-server.html"]{(chibi net http-server) - Simple http-server with servlet support}}
\item{\hyperlink["lib/chibi/net/servlet.html"]{(chibi net servlet) - HTTP servlets for http-server or CGI}}
\item{\hyperlink["lib/chibi/optional.html"]{(chibi optional) - Syntax to support optional and named keyword arguments}}
\item{\hyperlink["lib/chibi/parse.html"]{(chibi parse) - Parser combinators with convenient syntax}}
\item{\hyperlink["lib/chibi/pathname.html"]{(chibi pathname) - Utilities to decompose and manipulate pathnames}}
@ -1228,16 +1401,22 @@ namespace.
\item{\hyperlink["lib/chibi/repl.html"]{(chibi repl) - A full-featured Read/Eval/Print Loop}}
\item{\hyperlink["lib/chibi/shell.html"]{(chibi shell) - Process combinators with high-level pipeline syntax in the spirit of SCSH.}}
\item{\hyperlink["lib/chibi/show.html"]{(chibi show) - Monadic formatting.}}
\item{\hyperlink["lib/chibi/scribble.html"]{(chibi scribble) - A parser for the scribble syntax used to write this manual}}
\item{\hyperlink["lib/chibi/show.html"]{(chibi show) - A combinator formatting library}}
\item{\hyperlink["lib/chibi/show/base.scm"]{(chibi show base) - Base combinator formatting}}
\item{\hyperlink["lib/chibi/string.html"]{(chibi string) - Cursor-based string library (predecessor to SRFI 130)}}
\item{\hyperlink["lib/chibi/stty.html"]{(chibi stty) - A high-level interface to ioctl}}
\item{\hyperlink["lib/chibi/sxml.html"]{(chibi sxml) - SXML utilities}}
\item{\hyperlink["lib/chibi/system.html"]{(chibi system) - Access to the host system and current user information}}
\item{\hyperlink["lib/chibi/temp-file.html"]{(chibi temp-file) - Temporary file and directory creation}}
\item{\hyperlink["lib/chibi/test.html"]{(chibi test) - A simple unit testing framework}}
\item{\hyperlink["lib/chibi/time.html"]{(chibi time) - An interface to the current system time}}
@ -1255,17 +1434,23 @@ namespace.
\section{Snow Package Manager}
Beyond the distributed modules, Chibi comes with a package manager
based on \hyperlink["http://trac.sacrideo.us/wg/wiki/Snow"]{Snow2}
based on \hyperlink["https://small.r7rs.org/wiki/Snow/"]{Snow2}
which can be used to share R7RS libraries. Packages are distributed
as tar gzipped files called "snowballs," and may contain multiple
libraries. The program is installed as \scheme{snow-chibi} and takes
the following subcommands:
libraries. The program is installed as \scheme{snow-chibi}. The
"help" subcommand can be used to list all subcommands and options.
Note by default \scheme{snow-chibi} uses an image file to speed-up
loading (since it loads many libraries) - if you have any difficulties
with image files on your platform you can run
\command{snow-chibi --noimage} to disable this feature.
\subsubsection{Querying Packages and Status}
By default \scheme{snow-chibi} looks for packages in the public
repository \hyperlink["http://snow-fort.org/"]{http://snow-fort.org/},
though you can customize this with the \scheme{--repository-uri} option.
though you can customize this with the \scheme{--repository-uri} or
\scheme{--repo} option (e.g. "http://snow-fort.org/s/repo.scm").
Packages can be browsed on the site, but you can also search and query
from the command-line tool.
@ -1297,6 +1482,11 @@ older version, a warning is printed.}}
The basic package management functionality, installing upgrading and
removing packages.
By default the packages will be managed for Chibi. You can specify
what Scheme implementation to install, upgrade... with
\scheme{--implementations} or \scheme{--impls} option. Specify "all"
to manage all supported implementations.
\itemlist[
\item{install names ... - install packages
@ -1305,8 +1495,10 @@ use the dotted shorthand. Explicit names for packages are optional,
as a package can always be referred to by the name of any library it
contains. If multiple packages provide libraries with the same name,
you will be asked to confirm which implementation to install.}
\p{You can also bypass the repository and install a manually downloaded
snowball by giving a path to that file instead of a name.}}
snowball by giving a path to that file instead of a name. No package
dependencies will be checked for install in this case}}
\item{upgrade names ... - upgrade installed packages
\p{Upgrade the packages if new versions are available.
@ -1328,6 +1520,10 @@ update with this command.}}
Creating packages can be done with the \scheme{package} command,
though other commands allow for uploading to public repositories.
By default the public repository is
\hyperlink["http://snow-fort.org/"]{http://snow-fort.org/} but you can
customize this with the \scheme{--host} option.
\itemlist[
\item{package files ... - create a package
@ -1425,10 +1621,12 @@ command tells you which you currently have installed. The following
are currently supported:
\itemlist[
\item{chibi - native support as of version 0.7.3}
\item{chibi - version >= 0.7.3}
\item{chicken - version >= 4.9.0 with the \scheme{r7rs} egg}
\item{cyclone - version >= 0.5.3}
\item{foment - version >= 0.4}
\item{gauche - version >= 0.9.4}
\item{kawa - version >= 2.0; you need to add the install dir to the search path, e.g. \scheme{-Dkawa.import.path=/usr/local/share/kawa}}
\item{larceny - version 0.98; you need to add "lib/Snow" to the paths in startup.sch}
\item{sagittarius - version >= 0.98}
]

575
eval.c

File diff suppressed because it is too large Load diff

3
examples/hello.scm Normal file
View file

@ -0,0 +1,3 @@
(import (scheme base))
(write-string "Hello world!\n")

36
examples/simple-http-client.scm Executable file
View file

@ -0,0 +1,36 @@
#! /usr/bin/env chibi-scheme
; Simple HTTP client
; Retrieves the contents of the URL argument:
; Usage:
; simple-http-client.scm [URL]
;
; Example:
; simple-http-client.scm http://localhost:8000
(import (chibi) (chibi net) (chibi net http) (chibi io))
(if (> (length (command-line)) 1)
(let ((url (car (cdr (command-line)))))
(if (> (string-length url) 0)
(begin
(display (read-string 65536 (http-get url)))
(newline))))
(let ((progname (car (command-line))))
(display "Retrieve the contents of a URL.")
(newline)
(display "Usage:")
(newline)
(newline)
(display progname)
(display " [URL]")
(newline)))

16
examples/simple-http-server.scm Executable file
View file

@ -0,0 +1,16 @@
#! /usr/bin/env chibi-scheme
; Simple HTTP server
; Returns a minimal HTML page with a single number incremented
; every request. Binds to localhost port 8000.
(import (chibi) (chibi net http-server) (chibi net servlet) (chibi sxml))
(let ((count 0))
(run-http-server
8000
(lambda (cfg request next restart)
(set! count (+ 1 count))
(servlet-write request (sxml->xml `(html (body
(p "Count: \n")
(p ,count))))))))

414
gc.c
View file

@ -6,14 +6,12 @@
#include "chibi/sexp.h"
#if SEXP_USE_MMAP_GC
#include <sys/mman.h>
#if SEXP_USE_TIME_GC
#include <sys/resource.h>
#endif
#ifdef __APPLE__
#define SEXP_RTLD_DEFAULT RTLD_SELF
#else
#define SEXP_RTLD_DEFAULT RTLD_DEFAULT
#if SEXP_USE_MMAP_GC
#include <sys/mman.h>
#endif
#define SEXP_BANNER(x) ("**************** GC "x"\n")
@ -39,14 +37,52 @@ static sexp_heap sexp_heap_last (sexp_heap h) {
return h;
}
#if !SEXP_USE_FIXED_CHUNK_SIZE_HEAPS && !SEXP_USE_MALLOC
static size_t sexp_heap_total_size (sexp_heap h) {
size_t total_size = 0;
for (; h; h=h->next)
total_size += h->size;
return total_size;
}
#endif
#if ! SEXP_USE_GLOBAL_HEAP
#if SEXP_USE_DEBUG_GC
void sexp_debug_heap_stats (sexp_heap heap) {
sexp_free_list ls;
size_t available = 0;
for (ls=heap->free_list; ls; ls=ls->next)
available += ls->size;
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
sexp_debug_printf("free heap: %p (chunk size: %lu): %ld / %ld used (%.2f%%)", heap, heap->chunk_size, heap->size - available, heap->size, 100*(heap->size - available) / (float)heap->size);
#else
sexp_debug_printf("free heap: %p: %ld / %ld used (%.2f%%)", heap, heap->size - available, heap->size, 100*(heap->size - available) / (float)heap->size);
#endif
if (heap->next)
sexp_debug_heap_stats(heap->next);
}
#endif
#if SEXP_USE_TRACK_ALLOC_TIMES
void sexp_debug_alloc_times(sexp ctx) {
double mean = (double) sexp_context_alloc_usecs(ctx) / sexp_context_alloc_count(ctx);
double var = (double) sexp_context_alloc_usecs_sq(ctx) / sexp_context_alloc_count(ctx) - mean*mean;
fprintf(stderr, SEXP_BANNER("alloc: mean: %0.3lfμs var: %0.3lfμs (%ld times)"), mean, var, sexp_context_alloc_count(ctx));
}
#endif
#if SEXP_USE_TRACK_ALLOC_SIZES
void sexp_debug_alloc_sizes(sexp ctx) {
int i;
fprintf(stderr, "alloc size histogram: {");
for (i=0; i<SEXP_ALLOC_HISTOGRAM_BUCKETS; ++i) {
if ((i+1)*sexp_heap_align(1)<100 || sexp_context_alloc_histogram(ctx)[i]>0)
fprintf(stderr, " %ld:%ld", (i+1)*sexp_heap_align(1), sexp_context_alloc_histogram(ctx)[i]);
}
fprintf(stderr, "}\n");
}
#endif
void sexp_free_heap (sexp_heap heap) {
#if SEXP_USE_MMAP_GC
munmap(heap, sexp_heap_pad_size(heap->size));
@ -92,7 +128,7 @@ void sexp_release_object(sexp ctx, sexp x) {
}
}
sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) {
SEXP_API sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) {
sexp_uint_t res;
sexp t;
if (!sexp_pointerp(x) || (sexp_pointer_tag(x) >= sexp_context_num_types(ctx)))
@ -101,7 +137,7 @@ sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) {
res = sexp_type_size_of_object(t, x) + SEXP_GC_PAD;
#if SEXP_USE_DEBUG_GC
if (res == 0) {
fprintf(stderr, SEXP_BANNER("%p zero-size object: %p"), ctx, x);
fprintf(stderr, SEXP_BANNER("%p zero-size object: %p (type tag: %d)"), ctx, x, sexp_pointer_tag(x));
return 1;
}
#endif
@ -184,9 +220,40 @@ int sexp_valid_object_p (sexp ctx, sexp x) {
return sexp_in_heap_p(ctx, x) && sexp_valid_object_type_p(ctx, x)
&& sexp_valid_header_magic_p(ctx, x);
}
#define sexp_gc_pass_ctx(x) x,
#else
#define sexp_gc_pass_ctx(x)
#endif
void sexp_mark (sexp ctx, sexp x) {
static void sexp_mark_stack_push (sexp ctx, sexp *start, sexp *end) {
struct sexp_mark_stack_ptr_t *stack = sexp_context_mark_stack(ctx);
struct sexp_mark_stack_ptr_t **ptr = &sexp_context_mark_stack_ptr(ctx);
struct sexp_mark_stack_ptr_t *old = *ptr;
if (old == NULL) {
*ptr = stack;
} else if (old >= stack && old + 1 < stack + SEXP_MARK_STACK_COUNT) {
(*ptr)++;
} else {
*ptr = malloc(sizeof(**ptr));
}
(*ptr)->start = start;
(*ptr)->end = end;
(*ptr)->prev = old;
}
static void sexp_mark_stack_pop (sexp ctx) {
struct sexp_mark_stack_ptr_t *stack = sexp_context_mark_stack(ctx);
struct sexp_mark_stack_ptr_t *old = sexp_context_mark_stack_ptr(ctx);
sexp_context_mark_stack_ptr(ctx) = old->prev;
if (!(old >= stack && old < stack + SEXP_MARK_STACK_COUNT)) {
free(old);
}
}
static void sexp_mark_one (sexp ctx, sexp* types, sexp x) {
sexp_sint_t len;
sexp t, *p, *q;
struct sexp_gc_var_t *saves;
@ -196,24 +263,44 @@ void sexp_mark (sexp ctx, sexp x) {
sexp_markedp(x) = 1;
if (sexp_contextp(x)) {
for (saves=sexp_context_saves(x); saves; saves=saves->next)
if (saves->var) sexp_mark(ctx, *(saves->var));
if (saves->var) sexp_mark_one(ctx, types, *(saves->var));
}
t = sexp_object_type(ctx, x);
t = types[sexp_pointer_tag(x)];
len = sexp_type_num_slots_of_object(t, x) - 1;
if (len >= 0) {
p = (sexp*) (((char*)x) + sexp_type_field_base(t));
q = p + len;
while (p < q && ! (*q && sexp_pointerp(*q)))
while (p < q && (*q && sexp_pointerp(*q) ? sexp_markedp(*q) : 1))
q--; /* skip trailing immediates */
while (p < q && *q == q[-1])
q--; /* skip trailing duplicates */
while (p < q)
sexp_mark(ctx, *p++);
x = *p;
if (p < q) {
sexp_mark_stack_push(ctx, p, q);
}
x = *q;
goto loop;
}
}
static void sexp_mark_one_start (sexp ctx, sexp* types, sexp x) {
struct sexp_mark_stack_ptr_t **ptr = &sexp_context_mark_stack_ptr(ctx);
sexp *p, *q;
sexp_mark_one(ctx, types, x);
while (*ptr) {
p = (*ptr)->start;
q = (*ptr)->end;
sexp_mark_stack_pop(ctx);
while (p < q) {
sexp_mark_one(ctx, types, *p++);
}
}
}
void sexp_mark (sexp ctx, sexp x) {
sexp_mark_one_start(ctx, sexp_vector_data(sexp_global(ctx, SEXP_G_TYPES)), x);
}
#if SEXP_USE_CONSERVATIVE_GC
int stack_references_pointer_p (sexp ctx, sexp x) {
@ -277,12 +364,16 @@ void sexp_conservative_mark (sexp ctx) {
#endif
#if SEXP_USE_WEAK_REFERENCES
void sexp_reset_weak_references(sexp ctx) {
int i, len, all_reset_p;
sexp_heap h = sexp_context_heap(ctx);
int sexp_reset_weak_references(sexp ctx) {
int i, len, broke, all_reset_p;
sexp_heap h;
sexp p, t, end, *v;
sexp_free_list q, r;
for ( ; h; h=h->next) { /* just scan the whole heap */
if (sexp_not(sexp_global(ctx, SEXP_G_WEAK_OBJECTS_PRESENT)))
return 0;
broke = 0;
/* just scan the whole heap */
for (h = sexp_context_heap(ctx) ; h; h=h->next) {
p = sexp_heap_first_block(h);
q = h->free_list;
end = sexp_heap_end(h);
@ -309,6 +400,7 @@ void sexp_reset_weak_references(sexp ctx) {
}
}
if (all_reset_p) { /* ephemerons */
broke++;
len += sexp_type_weak_len_extra(t);
for ( ; i<len; i++) v[i] = SEXP_FALSE;
}
@ -317,11 +409,14 @@ void sexp_reset_weak_references(sexp ctx) {
p = (sexp) (((char*)p)+sexp_heap_align(sexp_allocated_bytes(ctx, p)));
}
}
sexp_debug_printf("%p (broke %d weak references)", ctx, broke);
return broke;
}
#else
#define sexp_reset_weak_references(ctx)
#define sexp_reset_weak_references(ctx) 0
#endif
#if SEXP_USE_FINALIZERS
sexp sexp_finalize (sexp ctx) {
size_t size;
sexp p, t, end;
@ -347,6 +442,9 @@ sexp sexp_finalize (sexp ctx) {
continue;
}
size = sexp_heap_align(sexp_allocated_bytes(ctx, p));
if (size == 0) {
return SEXP_FALSE;
}
if (!sexp_markedp(p)) {
t = sexp_object_type(ctx, p);
finalizer = sexp_type_finalize(t);
@ -368,6 +466,7 @@ sexp sexp_finalize (sexp ctx) {
#endif
return sexp_make_fixnum(finalize_count);
}
#endif
sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
size_t freed, max_freed=0, sum_freed=0, size;
@ -388,7 +487,7 @@ sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
continue;
}
size = sexp_heap_align(sexp_allocated_bytes(ctx, p));
#if SEXP_USE_DEBUG_GC
#if SEXP_USE_DEBUG_GC > 1
if (!sexp_valid_object_p(ctx, p))
fprintf(stderr, SEXP_BANNER("%p sweep: invalid object at %p"), ctx, p);
if ((char*)q + q->size > (char*)p)
@ -453,17 +552,29 @@ void sexp_mark_global_symbols(sexp ctx) {
sexp sexp_gc (sexp ctx, size_t *sum_freed) {
sexp res, finalized SEXP_NO_WARN_UNUSED;
#if SEXP_USE_TIME_GC
sexp_uint_t gc_usecs;
struct rusage start, end;
getrusage(RUSAGE_SELF, &start);
sexp_debug_printf("%p (heap: %p size: %lu)", ctx, sexp_context_heap(ctx),
sexp_heap_total_size(sexp_context_heap(ctx)));
#endif
sexp_mark_global_symbols(ctx);
sexp_mark(ctx, ctx);
sexp_conservative_mark(ctx);
sexp_reset_weak_references(ctx);
finalized = sexp_finalize(ctx);
res = sexp_sweep(ctx, sum_freed);
sexp_debug_printf("%p (freed: %lu max_freed: %lu finalized: %lu)", ctx,
(sum_freed ? *sum_freed : 0), sexp_unbox_fixnum(res),
sexp_unbox_fixnum(finalized));
++sexp_context_gc_count(ctx);
#if SEXP_USE_TIME_GC
getrusage(RUSAGE_SELF, &end);
gc_usecs = (end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000 +
end.ru_utime.tv_usec - start.ru_utime.tv_usec;
sexp_context_gc_usecs(ctx) += gc_usecs;
sexp_debug_printf("%p (freed: %lu max_freed: %lu finalized: %lu time: %luus)",
ctx, (sum_freed ? *sum_freed : 0), sexp_unbox_fixnum(res),
sexp_unbox_fixnum(finalized), gc_usecs);
#endif
return res;
}
@ -471,12 +582,13 @@ sexp_heap sexp_make_heap (size_t size, size_t max_size, size_t chunk_size) {
sexp_free_list free, next;
sexp_heap h;
#if SEXP_USE_MMAP_GC
h = mmap(NULL, sexp_heap_pad_size(size), PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_ANON|MAP_PRIVATE, 0, 0);
h = mmap(NULL, sexp_heap_pad_size(size), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0);
if (h == MAP_FAILED) return NULL;
#else
h = sexp_malloc(sexp_heap_pad_size(size));
#endif
if (! h) return NULL;
#endif
h->size = size;
h->max_size = max_size;
h->chunk_size = chunk_size;
@ -501,24 +613,46 @@ sexp_heap sexp_make_heap (size_t size, size_t max_size, size_t chunk_size) {
int sexp_grow_heap (sexp ctx, size_t size, size_t chunk_size) {
size_t cur_size, new_size;
sexp_heap h = sexp_heap_last(sexp_context_heap(ctx));
sexp_heap tmp, h = sexp_heap_last(sexp_context_heap(ctx));
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
for (tmp=sexp_context_heap(ctx); tmp; tmp=tmp->next)
if (tmp->chunk_size == size) {
while (tmp->next && tmp->next->chunk_size == size)
tmp = tmp->next;
h = tmp;
chunk_size = size;
break;
}
#endif
cur_size = h->size;
new_size = sexp_heap_align(((cur_size > size) ? cur_size : size) * 2);
h->next = sexp_make_heap(new_size, h->max_size, chunk_size);
new_size = (size_t) ceil(SEXP_GROW_HEAP_FACTOR * (double) (sexp_heap_align(((cur_size > size) ? cur_size : size))));
tmp = sexp_make_heap(new_size, h->max_size, chunk_size);
if (tmp) {
tmp->next = h->next;
h->next = tmp;
}
return (h->next != NULL);
}
void* sexp_try_alloc (sexp ctx, size_t size) {
sexp_free_list ls1, ls2, ls3;
sexp_heap h;
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
int found_fixed = 0;
#endif
for (h=sexp_context_heap(ctx); h; h=h->next) {
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
if (h->chunk_size && h->chunk_size != size)
if (h->chunk_size) {
if (h->chunk_size != size)
continue;
found_fixed = 1;
} else if (found_fixed) { /* don't use a non-fixed heap */
return NULL;
}
#endif
for (ls1=h->free_list, ls2=ls1->next; ls2; ls1=ls2, ls2=ls2->next) {
if (ls2->size >= size) {
#if SEXP_USE_DEBUG_GC
#if SEXP_USE_DEBUG_GC > 1
ls3 = (sexp_free_list) sexp_heap_end(h);
if (ls2 >= ls3)
fprintf(stderr, "alloced %lu bytes past end of heap: %p (%lu) >= %p"
@ -541,15 +675,53 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
return NULL;
}
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
int sexp_find_fixed_chunk_heap_usage(sexp ctx, size_t size, size_t* sum_freed, size_t* total_size) {
sexp_heap h;
sexp_free_list ls;
size_t avail=0, total=0;
for (h=sexp_context_heap(ctx); h; h=h->next) {
if (h->chunk_size == size || !h->chunk_size) {
for (; h && (h->chunk_size == size || !h->chunk_size); h=h->next) {
total += h->size;
for (ls=h->free_list; ls; ls=ls->next)
avail += ls->size;
}
*sum_freed = avail;
*total_size = total;
return h && h->chunk_size > 0;
}
}
return 0;
}
#endif
#if ! SEXP_USE_MALLOC
void* sexp_alloc (sexp ctx, size_t size) {
void *res;
size_t max_freed, sum_freed, total_size;
size_t max_freed, sum_freed, total_size=0;
sexp_heap h = sexp_context_heap(ctx);
#if SEXP_USE_TRACK_ALLOC_SIZES
size_t size_bucket;
#endif
#if SEXP_USE_TRACK_ALLOC_TIMES
sexp_uint_t alloc_time;
struct timeval start, end;
gettimeofday(&start, NULL);
#endif
size = sexp_heap_align(size) + SEXP_GC_PAD;
#if SEXP_USE_TRACK_ALLOC_SIZES
size_bucket = (size - SEXP_GC_PAD) / sexp_heap_align(1) - 1;
++sexp_context_alloc_histogram(ctx)[size_bucket >= SEXP_ALLOC_HISTOGRAM_BUCKETS ? SEXP_ALLOC_HISTOGRAM_BUCKETS-1 : size_bucket];
#endif
res = sexp_try_alloc(ctx, size);
if (! res) {
max_freed = sexp_unbox_fixnum(sexp_gc(ctx, &sum_freed));
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
sexp_find_fixed_chunk_heap_usage(ctx, size, &sum_freed, &total_size);
#else
total_size = sexp_heap_total_size(sexp_context_heap(ctx));
#endif
if (((max_freed < size)
|| ((total_size > sum_freed)
&& (total_size - sum_freed) > (total_size*SEXP_GROW_HEAP_RATIO)))
@ -561,177 +733,17 @@ void* sexp_alloc (sexp ctx, size_t size) {
sexp_debug_printf("ran out of memory allocating %lu bytes => %p", size, res);
}
}
#if SEXP_USE_TRACK_ALLOC_TIMES
gettimeofday(&end, NULL);
alloc_time = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
sexp_context_alloc_count(ctx) += 1;
sexp_context_alloc_usecs(ctx) += alloc_time;
sexp_context_alloc_usecs_sq(ctx) += alloc_time*alloc_time;
#endif
return res;
}
#if ! SEXP_USE_GLOBAL_HEAP
void sexp_offset_heap_pointers (sexp_heap heap, sexp_heap from_heap, sexp* types, sexp flags) {
sexp_sint_t i, off, len, freep, loadp;
sexp_free_list q;
sexp p, t, end, *v;
#if SEXP_USE_DL
sexp name;
#endif
freep = sexp_unbox_fixnum(flags) & sexp_unbox_fixnum(SEXP_COPY_FREEP);
loadp = sexp_unbox_fixnum(flags) & sexp_unbox_fixnum(SEXP_COPY_LOADP);
off = (sexp_sint_t)((sexp_sint_t)heap - (sexp_sint_t)from_heap);
heap->data += off;
end = (sexp) (heap->data + heap->size);
/* adjust the free list */
heap->free_list = (sexp_free_list) ((char*)heap->free_list + off);
for (q=heap->free_list; q->next; q=q->next)
q->next = (sexp_free_list) ((char*)q->next + off);
/* adjust data by traversing over the new heap */
p = (sexp) (heap->data + sexp_heap_align(sexp_free_chunk_size));
q = heap->free_list;
while (p < end) {
/* find the next free list pointer */
for ( ; q && ((char*)q < (char*)p); q=q->next)
;
if ((char*)q == (char*)p) { /* this is a free block, skip it */
p = (sexp) (((char*)p) + q->size);
} else {
t = (sexp)((char*)(types[sexp_pointer_tag(p)])
+ ((char*)types > (char*)p ? off : 0));
len = sexp_type_num_slots_of_object(t, p);
v = (sexp*) ((char*)p + sexp_type_field_base(t));
/* offset any pointers in the _destination_ heap */
for (i=0; i<len; i++)
if (v[i] && sexp_pointerp(v[i]))
v[i] = (sexp) ((char*)v[i] + off);
/* don't free unless specified - only the original cleans up */
if (! freep)
sexp_freep(p) = 0;
/* adjust context heaps, don't copy saved sexp_gc_vars */
if (sexp_contextp(p)) {
#if SEXP_USE_GREEN_THREADS
sexp_context_ip(p) += off;
#endif
sexp_context_last_fp(p) += off;
sexp_stack_top(sexp_context_stack(p)) = 0;
sexp_context_saves(p) = NULL;
sexp_context_heap(p) = heap;
} else if (sexp_bytecodep(p) && off != 0) {
for (i=0; i<sexp_bytecode_length(p); ) {
switch (sexp_bytecode_data(p)[i++]) {
case SEXP_OP_FCALL0: case SEXP_OP_FCALL1:
case SEXP_OP_FCALL2: case SEXP_OP_FCALL3:
case SEXP_OP_FCALL4: case SEXP_OP_CALL:
case SEXP_OP_TAIL_CALL: case SEXP_OP_PUSH:
case SEXP_OP_GLOBAL_REF: case SEXP_OP_GLOBAL_KNOWN_REF:
#if SEXP_USE_GREEN_THREADS
case SEXP_OP_PARAMETER_REF:
#endif
#if SEXP_USE_EXTENDED_FCALL
case SEXP_OP_FCALLN:
#endif
v = (sexp*)(&(sexp_bytecode_data(p)[i]));
if (v[0] && sexp_pointerp(v[0])) v[0] = (sexp) (((char*)v[0]) + off);
/* ... FALLTHROUGH ... */
case SEXP_OP_JUMP: case SEXP_OP_JUMP_UNLESS:
case SEXP_OP_STACK_REF: case SEXP_OP_CLOSURE_REF:
case SEXP_OP_LOCAL_REF: case SEXP_OP_LOCAL_SET:
case SEXP_OP_TYPEP:
#if SEXP_USE_RESERVE_OPCODE
case SEXP_OP_RESERVE:
#endif
i += sizeof(sexp); break;
case SEXP_OP_MAKE: case SEXP_OP_SLOT_REF: case SEXP_OP_SLOT_SET:
i += 2*sizeof(sexp); break;
case SEXP_OP_MAKE_PROCEDURE:
v = (sexp*)(&(sexp_bytecode_data(p)[i]));
if (v[2] && sexp_pointerp(v[2])) v[2] = (sexp) (((char*)v[2]) + off);
i += 3*sizeof(sexp); break;
}
}
} else if (sexp_portp(p) && sexp_port_stream(p)) {
sexp_port_stream(p) = 0;
sexp_port_openp(p) = 0;
sexp_freep(p) = 0;
#if SEXP_USE_DL
} else if (loadp && sexp_dlp(p)) {
sexp_dl_handle(p) = NULL;
#endif
}
p = (sexp) (((char*)p)+sexp_heap_align(sexp_type_size_of_object(t, p))+SEXP_GC_PAD);
}
}
/* make a second pass to fix code references */
if (loadp) {
p = (sexp) (heap->data + sexp_heap_align(sexp_free_chunk_size));
q = heap->free_list;
while (p < end) {
/* find the next free list pointer */
for ( ; q && ((char*)q < (char*)p); q=q->next)
;
if ((char*)q == (char*)p) { /* this is a free block, skip it */
p = (sexp) (((char*)p) + q->size);
} else {
#if SEXP_USE_DL
if (sexp_opcodep(p) && sexp_opcode_func(p)) {
name = (sexp_opcode_data2(p) && sexp_stringp(sexp_opcode_data2(p))) ? sexp_opcode_data2(p) : sexp_opcode_name(p);
if (sexp_dlp(sexp_opcode_dl(p))) {
if (!sexp_dl_handle(sexp_opcode_dl(p)))
sexp_dl_handle(sexp_opcode_dl(p)) = dlopen(sexp_string_data(sexp_dl_file(sexp_opcode_dl(p))), RTLD_LAZY);
sexp_opcode_func(p) = dlsym(sexp_dl_handle(sexp_opcode_dl(p)), sexp_string_data(name));
} else {
sexp_opcode_func(p) = dlsym(SEXP_RTLD_DEFAULT, sexp_string_data(name));
}
} else
#endif
if (sexp_typep(p)) {
if (sexp_type_finalize(p)) {
/* TODO: handle arbitrary finalizers in images */
#if SEXP_USE_DL
if (sexp_type_tag(p) == SEXP_DL)
sexp_type_finalize(p) = SEXP_FINALIZE_DL;
else
#endif
sexp_type_finalize(p) = SEXP_FINALIZE_PORT;
}
}
t = types[sexp_pointer_tag(p)];
p = (sexp) (((char*)p)+sexp_heap_align(sexp_type_size_of_object(t, p)+SEXP_GC_PAD));
}
}
}
}
sexp sexp_copy_context (sexp ctx, sexp dst, sexp flags) {
sexp_sint_t off;
sexp_heap to, from = sexp_context_heap(ctx);
/* validate input, creating a new heap if needed */
if (from->next) {
return sexp_user_exception(ctx, NULL, "can't copy a non-contiguous heap", ctx);
} else if (! dst || sexp_not(dst)) {
to = sexp_make_heap(from->size, from->max_size, from->chunk_size);
if (!to) return sexp_global(ctx, SEXP_G_OOM_ERROR);
dst = (sexp) ((char*)ctx + ((char*)to - (char*)from));
} else if (! sexp_contextp(dst)) {
return sexp_type_exception(ctx, NULL, SEXP_CONTEXT, dst);
} else if (sexp_context_heap(dst)->size < from->size) {
return sexp_user_exception(ctx, NULL, "destination context too small", dst);
} else {
to = sexp_context_heap(dst);
}
/* copy the raw data */
off = (char*)to - (char*)from;
memcpy(to, from, sexp_heap_pad_size(from->size));
/* adjust the pointers */
sexp_offset_heap_pointers(to, from, sexp_context_types(ctx) + off, flags);
return dst;
}
#endif
void sexp_gc_init (void) {
#if SEXP_USE_GLOBAL_HEAP || SEXP_USE_CONSERVATIVE_GC
@ -746,4 +758,4 @@ void sexp_gc_init (void) {
#endif
}
#endif
#endif /* ! SEXP_USE_BOEHM && ! SEXP_USE_MALLOC */

789
gc_heap.c Normal file
View file

@ -0,0 +1,789 @@
/* gc_heap.h -- heap packing, run-time image generation */
/* Copyright (c) 2016 Chris Walsh. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
#include "chibi/gc_heap.h"
#if SEXP_USE_IMAGE_LOADING
#define ERR_STR_SIZE 256
static char gc_heap_err_str[ERR_STR_SIZE];
static sexp_uint_t sexp_gc_allocated_bytes (sexp ctx, sexp *types, size_t types_cnt, sexp x) {
sexp_uint_t res = 0;
if (!sexp_pointerp(x) || (sexp_pointer_tag(x) >= types_cnt)) {
res = 1;
} else {
res = sexp_type_size_of_object(types[sexp_pointer_tag(x)], x) + SEXP_GC_PAD;
}
return sexp_heap_align(res);
}
sexp sexp_gc_heap_walk(sexp ctx,
sexp_heap h, /* normally set to sexp_context_heap(ctx) */
sexp *t, /* normally set to sexp_context_types(ctx) */
size_t t_cnt, /* normally set to sexp_context_num_types(ctx) */
void *user,
sexp (*heap_callback)(sexp ctx, sexp_heap h, void *user),
sexp (*free_callback)(sexp ctx, sexp_free_list f, void *user),
sexp (*sexp_callback)(sexp ctx, sexp s, void *user))
{
sexp res = SEXP_FALSE;
size_t size = 0;
while (h) {
sexp p = sexp_heap_first_block(h);
sexp_free_list q = h->free_list;
sexp end = sexp_heap_end(h);
while (p < end) {
/* find the preceding and succeeding free list pointers */
sexp_free_list r = q->next;
while (r && ((unsigned char*)r < (unsigned char*)p)) {
q = r;
r = r->next;
}
if ( (unsigned char*)r == (unsigned char*)p ) {
if (free_callback && (res = free_callback(ctx, r, user)) != SEXP_TRUE) {
return res; }
size = r ? r->size : 0;
} else {
if (sexp_callback && (res = sexp_callback(ctx, p, user)) != SEXP_TRUE) {
return res; }
size = sexp_gc_allocated_bytes(ctx, t, t_cnt, p);
if (size == 0) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "Heap element with a zero size detected");
goto done;
}
}
p = (sexp)(((unsigned char*)p) + size);
}
if (heap_callback && (res = heap_callback(ctx, h, user)) != SEXP_TRUE) {
return res; }
h = h->next;
}
res = SEXP_TRUE;
done:
if (res != SEXP_TRUE) res = sexp_user_exception(ctx, NULL, gc_heap_err_str, SEXP_NULL);
return res;
}
struct sexp_remap {
sexp srcp;
sexp dstp;
};
struct sexp_remap_state {
size_t index, heaps_count, sexps_count, sexps_size;
sexp p, end, ctx_src, ctx_dst;
sexp_heap heap;
int mode;
struct sexp_remap *remap;
};
static sexp heap_callback_count(sexp ctx, sexp_heap h, void *user) {
struct sexp_remap_state* state = user;
state->heaps_count += 1;
return SEXP_TRUE;
}
static sexp sexp_callback_count(sexp ctx, sexp s, void *user) {
struct sexp_remap_state* state = user;
size_t size = sexp_gc_allocated_bytes(ctx, sexp_context_types(ctx),
sexp_context_num_types(ctx), s);
state->sexps_count += 1;
state->sexps_size += size;
return SEXP_TRUE;
}
static sexp heap_callback_remap(sexp ctx, sexp_heap h, void *user) {
return SEXP_NULL;
}
static sexp sexp_callback_remap(sexp ctx, sexp s, void *user) {
struct sexp_remap_state* state = user;
size_t size = sexp_gc_allocated_bytes(ctx, sexp_context_types(ctx),
sexp_context_num_types(ctx), s);
if (state->p >= state->end) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "callback_remap i=%zu p>end internal error", state->index);
return SEXP_FALSE; }
memcpy(state->p, s, size);
state->remap[state->index].srcp = s;
state->remap[state->index].dstp = state->p;
if (ctx == s) state->ctx_dst = state->p;
state->p = (sexp)(((unsigned char*)state->p) + size);
state->index += 1;
return SEXP_TRUE;
}
/* Return a destination (remapped) pointer for a given source pointer */
static sexp sexp_gc_heap_pack_src_to_dst(void* adata, sexp srcp) {
struct sexp_remap_state* state = adata;
sexp_sint_t imin = 0;
sexp_sint_t imax = state->sexps_count - 1;
while (imin <= imax) {
sexp_sint_t imid = ((imax - imin) / 2) + imin;
sexp midp = state->remap[imid].srcp;
if (midp == srcp) {
return state->remap[imid].dstp;
} else if (midp < srcp) {
imin = imid + 1;
} else {
imax = imid - 1;
}
}
snprintf(gc_heap_err_str, ERR_STR_SIZE, "Source SEXP not found in src->dst mapping");
return SEXP_FALSE;
}
static sexp sexp_adjust_fields(sexp dstp, sexp* types, sexp (* adjust_fn)(void *, sexp), void *adata) {
sexp_tag_t tag = sexp_pointer_tag(dstp);
sexp type_spec = types[tag];
size_t type_sexp_cnt = sexp_type_num_slots_of_object(type_spec, dstp);
sexp* vec = (sexp*)((unsigned char*)dstp + sexp_type_field_base(type_spec));
int i;
for (i = 0; i < type_sexp_cnt; i++) {
sexp src = vec[i];
sexp dst = src;
if (src && sexp_pointerp(src)) {
dst = adjust_fn(adata, src);
if (!sexp_pointerp(dst)) {
size_t sz = strlen(gc_heap_err_str);
snprintf(gc_heap_err_str + sz, ERR_STR_SIZE - sz, " from adjust fields, tag=%u i=%d", tag, i);
return SEXP_FALSE; }
}
vec[i] = dst;
}
return SEXP_TRUE;
}
static sexp sexp_adjust_bytecode(sexp dstp, sexp (*adjust_fn)(void *, sexp), void *adata) {
sexp res = SEXP_FALSE;
sexp src, dst;
sexp* vec;
int i;
for (i=0; i < sexp_bytecode_length(dstp); ) {
switch (sexp_bytecode_data(dstp)[i++]) {
case SEXP_OP_FCALL0: case SEXP_OP_FCALL1:
case SEXP_OP_FCALL2: case SEXP_OP_FCALL3:
case SEXP_OP_FCALL4: case SEXP_OP_CALL:
case SEXP_OP_TAIL_CALL: case SEXP_OP_PUSH:
case SEXP_OP_GLOBAL_REF: case SEXP_OP_GLOBAL_KNOWN_REF:
#if SEXP_USE_GREEN_THREADS
case SEXP_OP_PARAMETER_REF:
#endif
#if SEXP_USE_EXTENDED_FCALL
case SEXP_OP_FCALLN:
#endif
vec = (sexp*)(&(sexp_bytecode_data(dstp)[i]));
src = vec[0];
if (src && sexp_pointerp(src)) {
dst = adjust_fn(adata, src);
if (!sexp_pointerp(dst)) {
size_t sz = strlen(gc_heap_err_str);
snprintf(gc_heap_err_str + sz, ERR_STR_SIZE - sz, " from adjust bytecode, FCALLN");
goto done; }
vec[0] = dst;
}
/* ... FALLTHROUGH ... */
case SEXP_OP_JUMP: case SEXP_OP_JUMP_UNLESS:
case SEXP_OP_STACK_REF: case SEXP_OP_CLOSURE_REF:
case SEXP_OP_LOCAL_REF: case SEXP_OP_LOCAL_SET:
case SEXP_OP_TYPEP:
#if SEXP_USE_RESERVE_OPCODE
case SEXP_OP_RESERVE:
#endif
i += sizeof(sexp); break;
case SEXP_OP_MAKE: case SEXP_OP_SLOT_REF: case SEXP_OP_SLOT_SET:
i += 2*sizeof(sexp); break;
case SEXP_OP_MAKE_PROCEDURE:
vec = (sexp*)(&(sexp_bytecode_data(dstp)[i]));
src = vec[2];
if (src && sexp_pointerp(src)) {
dst = adjust_fn(adata, src);
if (!sexp_pointerp(dst)) {
size_t sz = strlen(gc_heap_err_str);
snprintf(gc_heap_err_str + sz, ERR_STR_SIZE - sz, " from adjust bytecode, PROCEDURE");
goto done; }
vec[2] = dst;
}
i += 3*sizeof(sexp); break;
}
}
res = SEXP_TRUE;
done:
return res;
}
static sexp sexp_gc_heap_pack_adjust(sexp dstp, sexp* types, struct sexp_remap_state* state) {
sexp res = SEXP_FALSE;
/* Adjust internal types which contain fields of sexp pointer(s)
within in the heap */
if ((res = sexp_adjust_fields(dstp, types, sexp_gc_heap_pack_src_to_dst, state)) != SEXP_TRUE) {
goto done; }
/* Other adjustments - context heap pointer, bytecode pointers */
if (sexp_contextp(dstp)) {
sexp_context_heap(dstp) = state->heap;
} else if (sexp_bytecodep(dstp)) {
if ((res = sexp_adjust_bytecode(dstp, sexp_gc_heap_pack_src_to_dst, state)) != SEXP_TRUE) {
goto done; }
}
res = SEXP_TRUE;
done:
return res;
}
static sexp_heap sexp_gc_packed_heap_make(size_t packed_size, size_t free_size) {
if (free_size > 0 && free_size < 2*sexp_free_chunk_size) {
free_size = 2*sexp_free_chunk_size;
}
free_size = sexp_heap_align(free_size);
size_t req_size = packed_size + free_size + sexp_free_chunk_size + 128;
sexp_heap heap = sexp_make_heap(sexp_heap_align(req_size), 0, 0);
if (!heap) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "Could not allocate memory for heap");
return NULL;
}
sexp base = sexp_heap_first_block(heap);
size_t pad = (unsigned char *)base - (unsigned char *)heap->data;
heap->size = packed_size + free_size + pad;
heap->free_list->size = 0;
if (free_size == 0) {
heap->free_list->next = NULL;
} else {
heap->free_list->next = (sexp_free_list)((unsigned char *)base + packed_size);
heap->free_list->next->next = NULL;
heap->free_list->next->size = free_size;
}
return heap;
}
static int heaps_compar(const void* v1, const void* v2) {
sexp_heap h1 = *((sexp_heap*)v1);
sexp_heap h2 = *((sexp_heap*)v2);
return
(h1 < h2) ? -1 :
(h1 > h2) ? 1 : 0;
}
/* Pack the heap. Return a new context with a unified, packed heap. No change to original context. */
sexp sexp_gc_heap_pack(sexp ctx_src, sexp_uint_t heap_free_size) {
sexp res = NULL;
sexp_gc(ctx_src, NULL);
sexp_heap* heaps = NULL;
int i = 0;
/* 1. Collect statistics - sexp count, size, heap count */
struct sexp_remap_state state;
memset(&state, 0, sizeof(struct sexp_remap_state));
state.ctx_src = ctx_src;
if ((res = sexp_gc_heap_walk(ctx_src, sexp_context_heap(ctx_src),
sexp_context_types(ctx_src), sexp_context_num_types(ctx_src),
&state, heap_callback_count, NULL, sexp_callback_count)) != SEXP_TRUE) {
goto done; }
/* 2. Make a new heap of the correct size to hold the sexps from the old heap. */
state.heap = sexp_gc_packed_heap_make(state.sexps_size, heap_free_size);
if (!state.heap) {
res = sexp_global(ctx_src, SEXP_G_OOM_ERROR);
goto done; }
/* 3. Create a list of heaps sorted by increasing memory address, for srcp search lookup */
heaps = malloc(sizeof(sexp_heap) * state.heaps_count);
if (!heaps) {
res = sexp_global(ctx_src, SEXP_G_OOM_ERROR);
goto done; }
sexp_heap h = sexp_context_heap(ctx_src);
for (i = 0; h; i++, h=h->next) { heaps[i] = h; }
qsort(heaps, state.heaps_count, sizeof(sexp_heap), heaps_compar);
/* 4. Pack the sexps into the new heap */
state.p = sexp_heap_first_block(state.heap);
state.end = sexp_heap_end(state.heap);
state.index = 0;
state.remap = malloc(sizeof(struct sexp_remap) * state.sexps_count);
if (!state.remap) {
res = sexp_global(ctx_src, SEXP_G_OOM_ERROR);
goto done; }
for (i = 0; i < state.heaps_count; i++) {
res = sexp_gc_heap_walk(ctx_src, heaps[i],
sexp_context_types(ctx_src), sexp_context_num_types(ctx_src),
&state, heap_callback_remap, NULL, sexp_callback_remap);
if (!(res == SEXP_TRUE || res == SEXP_NULL)) {
size_t sz = strlen(gc_heap_err_str);
snprintf(gc_heap_err_str + sz, ERR_STR_SIZE - sz, "; remap heap %d %p walk heap_pack", i, heaps[i]);
goto done; }
}
/* 5. Adjust sexp pointers to new locations inside the new heap */
sexp* types = sexp_context_types(state.ctx_src);
int idx;
for (idx = 0; idx < state.sexps_count; idx++) {
sexp dstp = state.remap[idx].dstp;
res = sexp_gc_heap_pack_adjust(dstp, types, &state);
if (res != SEXP_TRUE) {
size_t sz = strlen(gc_heap_err_str);
snprintf(gc_heap_err_str + sz, ERR_STR_SIZE - sz, "; src->dst idx=%d heap_pack", idx);
goto done; }
}
res = SEXP_TRUE;
done:
/* 6. Clean up. */
if (state.heap && res != SEXP_TRUE) { sexp_free_heap(state.heap); }
if (state.remap) { free(state.remap); }
if (heaps) { free(heaps); }
return (res == SEXP_TRUE) ? state.ctx_dst : res;
}
#define SEXP_IMAGE_MAGIC "\a\achibi\n\0"
#define SEXP_IMAGE_MAJOR_VERSION 1
#define SEXP_IMAGE_MINOR_VERSION 1
struct sexp_image_header_t {
char magic[8];
short major, minor;
sexp_abi_identifier_t abi;
sexp_uint_t size;
sexp base;
sexp context;
};
sexp sexp_save_image (sexp ctx_in, const char* filename) {
sexp_heap heap = NULL;
sexp res = NULL;
FILE *fp = fopen(filename, "wb");
if (!fp) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "Could not open image file for writing: %s", filename);
goto done;
}
/* Save ONLY packed, active SEXPs. No free list structures or padding. */
sexp ctx_out = sexp_gc_heap_pack(ctx_in, 0);
if (!ctx_out || !sexp_contextp(ctx_out)) {
goto done;
}
heap = sexp_context_heap(ctx_out);
sexp base = sexp_heap_first_block(heap);
size_t pad = (size_t)((unsigned char *)base - (unsigned char *)heap->data);
size_t size = heap->size - pad;
struct sexp_image_header_t header;
memcpy(&header.magic, SEXP_IMAGE_MAGIC, sizeof(header.magic));
memcpy(&header.abi, SEXP_ABI_IDENTIFIER, sizeof(header.abi));
header.major = SEXP_IMAGE_MAJOR_VERSION;
header.minor = SEXP_IMAGE_MINOR_VERSION;
header.size = size;
header.base = base;
header.context = ctx_out;
if (! (fwrite(&header, sizeof(header), 1, fp) == 1 &&
fwrite(base, size, 1, fp) == 1)) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "Error writing image file: %s", filename);
goto done;
}
res = SEXP_TRUE;
done:
if (fp) fclose(fp);
if (heap) sexp_free_heap(heap);
if (res != SEXP_TRUE) res = sexp_user_exception(ctx_in, NULL, gc_heap_err_str, SEXP_NULL);
return res;
}
#if SEXP_USE_DL
#ifdef __APPLE__
#define SEXP_RTLD_DEFAULT RTLD_SELF
#else
#define SEXP_RTLD_DEFAULT RTLD_DEFAULT
#endif
struct load_image_state {
sexp_sint_t offset;
sexp_heap heap;
sexp *types;
size_t types_cnt;
};
/* Return a destination (remapped) pointer for a given source pointer */
static sexp load_image_src_to_dst(void* adata, sexp srcp) {
struct load_image_state* state = adata;
return (sexp)((unsigned char *)srcp + state->offset);
}
static sexp load_image_callback_p1 (sexp ctx, sexp p, void *user) {
sexp res = NULL;
struct load_image_state* state = user;
if ((res = sexp_adjust_fields(p, state->types, load_image_src_to_dst, state)) != SEXP_TRUE) {
goto done; }
if (sexp_contextp(p)) {
#if SEXP_USE_GREEN_THREADS
sexp_context_ip(p) += state->offset;
#endif
sexp_context_last_fp(p) += state->offset;
sexp_stack_top(sexp_context_stack(p)) = 0;
sexp_context_saves(p) = NULL;
sexp_context_heap(p) = state->heap;
} else if (sexp_bytecodep(p)) {
if ((res = sexp_adjust_bytecode(p, load_image_src_to_dst, state)) != SEXP_TRUE) {
goto done; }
} else if (sexp_portp(p) && sexp_port_stream(p)) {
sexp_port_stream(p) = 0;
sexp_port_openp(p) = 0;
sexp_freep(p) = 0;
} else if (sexp_dlp(p)) {
sexp_dl_handle(p) = NULL;
}
res = SEXP_TRUE;
done:
return res;
}
#ifdef _WIN32
static void* load_image_fn(sexp ctx, sexp dl, sexp name) {
snprintf(gc_heap_err_str, ERR_STR_SIZE,
"load_image_fn: Needed to be ported to Win32");
return NULL;
}
#else
static void* load_image_fn(sexp ctx, sexp dl, sexp name) {
sexp ls;
void *fn = NULL;
char *file_name, *rel_name=NULL, *new_file_name;
char *handle_name = "<static>";
char *symbol_name = sexp_string_data(name);
if (dl && sexp_dlp(dl)) {
if (!sexp_dl_handle(dl)) {
/* try exact file, then the search path */
file_name = sexp_string_data(sexp_dl_file(dl));
sexp_dl_handle(dl) = dlopen(file_name, RTLD_LAZY);
if (!sexp_dl_handle(dl)) {
for (ls = sexp_global(ctx, SEXP_G_MODULE_PATH); sexp_pairp(ls); ls=sexp_cdr(ls)) {
if (strstr(file_name, sexp_string_data(sexp_car(ls))) == file_name) {
rel_name = file_name + sexp_string_size(sexp_car(ls));
while (*rel_name == '/')
++rel_name;
new_file_name = sexp_find_module_file_raw(ctx, rel_name);
if (new_file_name) {
sexp_dl_handle(dl) = dlopen(new_file_name, RTLD_LAZY);
free(new_file_name);
if (sexp_dl_handle(dl))
break;
}
}
}
if (!sexp_dl_handle(dl)) {
handle_name = sexp_string_data(sexp_dl_file(dl));
snprintf(gc_heap_err_str, ERR_STR_SIZE, "dlopen failure: %s",
handle_name);
return NULL;
}
}
}
fn = dlsym(sexp_dl_handle(dl), symbol_name);
} else {
fn = dlsym(SEXP_RTLD_DEFAULT, symbol_name);
}
if (!fn) {
snprintf(gc_heap_err_str, ERR_STR_SIZE,
"dynamic function lookup failure: %s %s",
handle_name, symbol_name);
}
return fn;
}
#endif
static sexp load_image_callback_p2 (sexp ctx, sexp dstp, void *user) {
sexp res = NULL;
sexp name = NULL;
void *fn = NULL;
if (sexp_opcodep(dstp) && sexp_opcode_func(dstp)) {
if (sexp_opcode_data2(dstp) && sexp_stringp(sexp_opcode_data2(dstp))) {
name = sexp_opcode_data2(dstp);
} else {
name = sexp_opcode_name(dstp);
}
if (!name) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "opcode func field missing function name");
return SEXP_FALSE;
}
fn = load_image_fn(ctx, sexp_opcode_dl(dstp), name);
if (!fn) {
return SEXP_FALSE;
}
sexp_opcode_func(dstp) = fn;
} else if (sexp_typep(dstp) && sexp_type_finalize(dstp)) {
name = sexp_type_finalize_name(dstp);
if (!name) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "type finalize field missing function name");
return SEXP_FALSE;
}
fn = load_image_fn(ctx, sexp_type_dl(dstp), name);
if (!fn) {
return SEXP_FALSE;
}
sexp_type_finalize(dstp) = fn;
}
res = SEXP_TRUE;
return res;
}
static int load_image_header(FILE *fp, struct sexp_image_header_t* header) {
if (!fp || !header) { return 0; }
if (fread(header, sizeof(struct sexp_image_header_t), 1, fp) != 1) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "couldn't read image header");
return 0;
}
if (memcmp(header->magic, SEXP_IMAGE_MAGIC, sizeof(header->magic)) != 0) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "invalid image file magic %s\n", header->magic);
return 0;
} else if (header->major != SEXP_IMAGE_MAJOR_VERSION
|| header->major < SEXP_IMAGE_MINOR_VERSION) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "unsupported image version: %d.%d\n",
header->major, header->minor);
return 0;
} else if (!sexp_abi_compatible(NULL, header->abi, SEXP_ABI_IDENTIFIER)) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "unsupported ABI: %s (expected %s)\n",
header->abi, SEXP_ABI_IDENTIFIER);
return 0;
}
return 1;
}
char* sexp_load_image_err() {
gc_heap_err_str[ERR_STR_SIZE-1] = 0;
return gc_heap_err_str;
}
static const char* all_paths[] = {sexp_default_module_path, sexp_default_user_module_path};
sexp sexp_load_image (const char* filename, off_t offset, sexp_uint_t heap_free_size, sexp_uint_t heap_max_size) {
struct load_image_state state;
struct sexp_image_header_t header;
const char *mod_path, *colon, *end;
char path[512];
FILE *fp;
int i, len;
sexp res = NULL, ctx = NULL, base, *ctx_globals, *ctx_types;
gc_heap_err_str[0] = 0;
memset(&state, 0, sizeof(struct load_image_state));
fp = fopen(filename, "rb");
/* fallback to the default search path (can't use sexp_find_module_file */
/* since there's no context yet) */
for (i=0; !fp && i<sizeof(all_paths)/sizeof(all_paths[0]); ++i) {
for (mod_path=all_paths[i]; *mod_path; mod_path=colon+1) {
colon = strchr(mod_path, ':');
end = colon ? colon : mod_path + strlen(mod_path);
snprintf(path, sizeof(path), "%s", mod_path);
if (end[-1] != '/') path[end-mod_path] = '/';
len = (end-mod_path) + (end[-1] == '/' ? 0 : 1);
snprintf(path + len, sizeof(path) - len, "%s", filename);
fp = fopen(path, "rb");
if (fp || !colon) break;
}
}
if (!fp) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "couldn't open image file for reading: %s\n", filename);
goto done;
}
if (offset > 0 && fseek(fp, offset, SEEK_SET) < 0) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "couldn't seek to image offset: %s -> %"SEXP_PRIdOFF": %s\n", filename, offset, strerror(errno));
goto done;
}
if (!load_image_header(fp, &header)) { goto done; }
state.heap = sexp_gc_packed_heap_make(header.size, heap_free_size);
if (!state.heap) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "couldn't malloc heap\n");
goto done;
}
base = sexp_heap_first_block(state.heap);
if (fread(base, 1, header.size, fp) != header.size) {
snprintf(gc_heap_err_str, ERR_STR_SIZE, "error reading image\n");
goto done;
}
/* Adjust pointers in loaded packed heap. */
state.offset = (sexp_sint_t)((sexp_sint_t)base - (sexp_sint_t)header.base);
ctx = (sexp)((unsigned char *)header.context + state.offset);
sexp_context_heap(ctx) = state.heap;
/* Type information (specifically, how big types are) is stored as sexps in the
heap. This information is needed to sucessfully walk an arbitrary heap. A
copy of the type array pointers with correct offsets is applied is created outside
of the new heap to be used with the pointer adjustment process.
*/
ctx_globals = sexp_vector_data((sexp)((unsigned char*)sexp_context_globals(ctx) + state.offset));
ctx_types = sexp_vector_data((sexp)((unsigned char*)(ctx_globals[SEXP_G_TYPES]) + state.offset));
state.types_cnt = sexp_unbox_fixnum(ctx_globals[SEXP_G_NUM_TYPES]);
state.types = malloc(sizeof(sexp) * state.types_cnt);
if (!state.types) goto done;
for (i = 0; i < state.types_cnt; i++) {
state.types[i] = (sexp)((unsigned char *)ctx_types[i] + state.offset);
}
if (sexp_gc_heap_walk(ctx, sexp_context_heap(ctx), state.types, state.types_cnt,
&state, NULL, NULL, load_image_callback_p1) != SEXP_TRUE)
goto done;
/* Second pass to fix code references */
if (sexp_gc_heap_walk(ctx, sexp_context_heap(ctx), state.types, state.types_cnt,
&state, NULL, NULL, load_image_callback_p2) != SEXP_TRUE)
goto done;
if (heap_max_size > SEXP_INITIAL_HEAP_SIZE) {
sexp_context_heap(ctx)->max_size = heap_max_size;
}
res = ctx;
done:
if (fp) fclose(fp);
if (state.heap && !ctx) free(state.heap);
if (state.types) free(state.types);
return res;
}
#else
sexp sexp_load_image (const char* filename, sexp_uint_t heap_free_size, sexp_uint_t heap_max_size) {
return NULL;
}
#endif
/****************** Debugging ************************/
/* you can use (chibi heap-stats) without debug enabled */
#if SEXP_USE_DEBUG_GC
#define SEXP_CORE_TYPES_MAX 255
struct sexp_stats_entry {
size_t count;
size_t size_all;
size_t size_min;
size_t size_max;
};
struct sexp_stats {
struct sexp_stats_entry sexps[SEXP_CORE_TYPES_MAX+1];
struct sexp_stats_entry heaps;
struct sexp_stats_entry frees;
size_t sexp_count;
};
static void sexp_stats_entry_set(struct sexp_stats_entry *entry, size_t value) {
entry->count += 1;
entry->size_all += value;
if (entry->size_min == 0 || value < entry->size_min) entry->size_min = value;
if (value > entry->size_max) entry->size_max = value;
}
static sexp heap_stats_callback(sexp ctx, sexp_heap h, void *user) {
struct sexp_stats *stats = user;
sexp_stats_entry_set(&(stats->heaps), h->size);
return SEXP_TRUE;
}
static sexp free_stats_callback(sexp ctx, sexp_free_list f, void *user) {
struct sexp_stats *stats = user;
sexp_stats_entry_set(&(stats->frees), f->size);
return SEXP_TRUE;
}
static sexp sexp_stats_callback(sexp ctx, sexp s, void *user) {
struct sexp_stats *stats = user;
int tag = sexp_pointer_tag(s);
size_t size = sexp_gc_allocated_bytes(ctx, sexp_context_types(ctx),
sexp_context_num_types(ctx), s);
if (tag > SEXP_CORE_TYPES_MAX) tag = SEXP_CORE_TYPES_MAX;
sexp_stats_entry_set(&(stats->sexps[tag]), size);
stats->sexp_count += 1;
return SEXP_TRUE;
}
void sexp_gc_heap_stats_print(sexp ctx)
{
if (!ctx || !sexp_contextp(ctx)) return;
struct sexp_stats stats;
memset(&stats, 0, sizeof(struct sexp_stats));
sexp_gc_heap_walk(ctx, sexp_context_heap(ctx), sexp_context_types(ctx), sexp_context_num_types(ctx),
&stats, heap_stats_callback, free_stats_callback, sexp_stats_callback);
printf("Heap Stats\n %6zu %7zu\n",
stats.heaps.count, stats.heaps.size_all);
printf("Free Stats\n %6zu %7zu %5zu %5zu\n",
stats.frees.count, stats.frees.size_all, stats.frees.size_min, stats.frees.size_max);
printf("Sexp Stats\n");
size_t total_count = 0;
size_t total_size = 0;
int i;
for (i = 0; i <= SEXP_CORE_TYPES_MAX; i++) {
if (stats.sexps[i].count == 0) continue;
printf("%3d %6zu %7zu %5zu %5zu\n", i,
stats.sexps[i].count, stats.sexps[i].size_all, stats.sexps[i].size_min, stats.sexps[i].size_max);
total_count += stats.sexps[i].count;
total_size += stats.sexps[i].size_all;
}
printf(" ========================================\n");
printf(" %6zu %7zu\n", total_count, total_size);
}
#endif
#endif /* SEXP_USE_IMAGE_LOADING */

View file

@ -1,5 +1,5 @@
/* bignum.h -- header for bignum utilities */
/* Copyright (c) 2009-2015 Alex Shinn. All rights reserved. */
/* Copyright (c) 2009-2020 Alex Shinn. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
#ifndef SEXP_BIGNUM_H
@ -7,7 +7,23 @@
#include "chibi/eval.h"
#if (SEXP_64_BIT) && defined(__GNUC__)
#if SEXP_USE_CUSTOM_LONG_LONGS
#ifdef PLAN9
#include <ape/stdint.h>
#else
#include <stdint.h>
#endif
typedef struct
{
uint64_t hi;
uint64_t lo;
} sexp_luint_t;
typedef struct
{
int64_t hi;
uint64_t lo;
} sexp_lsint_t;
#elif SEXP_64_BIT
typedef unsigned int uint128_t __attribute__((mode(TI)));
typedef int sint128_t __attribute__((mode(TI)));
typedef uint128_t sexp_luint_t;
@ -17,6 +33,364 @@ typedef unsigned long long sexp_luint_t;
typedef long long sexp_lsint_t;
#endif
#if !SEXP_USE_CUSTOM_LONG_LONGS
#define sexp_lsint_fits_sint(x) ((sexp_sint_t)x == x)
#define sexp_luint_fits_uint(x) ((sexp_uint_t)x == x)
#define lsint_from_sint(v) ((sexp_lsint_t)v)
#define luint_from_uint(v) ((sexp_luint_t)v)
#define lsint_to_sint(v) ((sexp_sint_t)v)
#define luint_to_uint(v) ((sexp_uint_t)v)
#define lsint_to_sint_hi(v) ((sexp_sint_t) ((v) >> (8*sizeof(sexp_sint_t))))
#define luint_to_uint_hi(v) ((sexp_uint_t) ((v) >> (8*sizeof(sexp_uint_t))))
#define lsint_negate(v) (-((sexp_lsint_t)v))
#define luint_eq(a, b) (((sexp_luint_t)a)==((sexp_luint_t)b))
#define luint_lt(a, b) (((sexp_luint_t)a)<((sexp_luint_t)b))
#define lsint_lt_0(a) (((sexp_lsint_t)a)<0)
#define luint_shl(a, shift) (((sexp_luint_t)a)<<(shift))
#define luint_shr(a, shift) (((sexp_luint_t)a)>>(shift))
#define luint_add(a, b) (((sexp_luint_t)a)+((sexp_luint_t)b))
#define luint_add_uint(a, b) (((sexp_luint_t)a)+((sexp_uint_t)b))
#define luint_sub(a, b) (((sexp_luint_t)a)-((sexp_luint_t)b))
#define luint_mul_uint(a, b) (((sexp_luint_t)a)*((sexp_uint_t)b))
#define lsint_mul_sint(a, b) (((sexp_lsint_t)a)*((sexp_sint_t)b))
#define luint_div(a, b) (((sexp_luint_t)a)/((sexp_luint_t)b))
#define luint_div_uint(a, b) (((sexp_luint_t)a)/((sexp_luint_t)b))
#define luint_and(a, b) (((sexp_luint_t)a)&((sexp_luint_t)b))
#define luint_is_fixnum(x) (((sexp_luint_t)x)<=SEXP_MAX_FIXNUM)
#define lsint_is_fixnum(x) ((SEXP_MIN_FIXNUM <= ((sexp_lsint_t)x)) && (((sexp_lsint_t)x) <= SEXP_MAX_FIXNUM))
#else
static inline int lsint_lt_0(sexp_lsint_t a) {
return a.hi < 0;
}
static inline int sexp_lsint_fits_sint(sexp_lsint_t x) {
return x.hi == (((int64_t)x.lo)>>63) && ((sexp_sint_t)x.lo == x.lo);
}
static inline int sexp_luint_fits_uint(sexp_luint_t x) {
return x.hi == 0 && ((sexp_uint_t)x.lo == x.lo);
}
static inline sexp_luint_t luint_from_lsint(sexp_lsint_t v) {
sexp_luint_t result;
result.hi = v.hi;
result.lo = v.lo;
return result;
}
static inline sexp_lsint_t lsint_from_luint(sexp_luint_t v) {
sexp_lsint_t result;
result.hi = v.hi;
result.lo = v.lo;
return result;
}
static inline sexp_lsint_t lsint_from_sint(sexp_sint_t v) {
sexp_lsint_t result;
result.hi = v >> 63;
result.lo = v;
return result;
}
static inline sexp_luint_t luint_from_uint(sexp_uint_t v) {
sexp_luint_t result;
result.hi = 0;
result.lo = v;
return result;
}
static inline sexp_sint_t lsint_to_sint(sexp_lsint_t v) {
return v.lo;
}
static inline sexp_uint_t luint_to_uint(sexp_luint_t v) {
return v.lo;
}
static inline sexp_sint_t lsint_to_sint_hi(sexp_lsint_t v) {
#if SEXP_64_BIT
return v.hi;
#else
return v.lo >> 32;
#endif
}
static inline sexp_uint_t luint_to_uint_hi(sexp_luint_t v) {
#if SEXP_64_BIT
return v.hi;
#else
return v.lo >> 32;
#endif
}
static inline sexp_lsint_t lsint_negate(sexp_lsint_t v) {
sexp_luint_t a;
a.hi = ~v.hi;
a.lo = ~v.lo;
uint64_t aLoLo = a.lo & 0xFFFFFFFF;
uint64_t aLoHi = a.lo >> 32;
uint64_t aHiLo = a.hi & 0xFFFFFFFF;
uint64_t aHiHi = a.hi >> 32;
uint64_t carry;
uint64_t sumLoLo = aLoLo + 1;
carry = sumLoLo >> 32;
uint64_t resultLoLo = sumLoLo & 0xFFFFFFFF;
uint64_t sumLoHi = aLoHi + carry;
uint64_t resultLoHi = sumLoHi & 0xFFFFFFFF;
carry = sumLoHi >> 32;
uint64_t sumHiLo = aHiLo + carry;
uint64_t resultHiLo = sumHiLo & 0xFFFFFFFF;
carry = sumHiLo >> 32;
uint64_t sumHiHi = aHiHi + carry;
uint64_t resultHiHi = sumHiHi & 0xFFFFFFFF;
/* carry = sumHiHi >> 32; */
sexp_lsint_t result;
result.hi = (resultHiHi << 32) | resultHiLo;
result.lo = (resultLoHi << 32) | resultLoLo;
return result;
}
static inline int luint_eq(sexp_luint_t a, sexp_luint_t b) {
return (a.hi == b.hi) && (a.lo == b.lo);
}
static inline int luint_lt(sexp_luint_t a, sexp_luint_t b) {
if (a.hi < b.hi)
return 1;
else if (a.hi > b.hi)
return 0;
else
return a.lo < b.lo;
}
static inline sexp_luint_t luint_shl(sexp_luint_t v, size_t shift) {
if (shift == 0)
return v;
sexp_luint_t result;
if (shift >= 64) {
result.hi = v.lo << (shift - 64);
result.lo = 0;
} else {
result.hi = (v.hi << shift) | (v.lo >> (64-shift));
result.lo = v.lo << shift;
}
return result;
}
static inline sexp_luint_t luint_shr(sexp_luint_t v, size_t shift) {
if (shift == 0)
return v;
sexp_luint_t result;
if (shift >= 64) {
result.hi = 0;
result.lo = v.hi >> (shift - 64);
} else {
result.hi = v.hi >> shift;
result.lo = (v.lo >> shift) | (v.hi << (64-shift));
}
return result;
}
static inline sexp_luint_t luint_add(sexp_luint_t a, sexp_luint_t b) {
uint64_t aLoLo = a.lo & 0xFFFFFFFF;
uint64_t aLoHi = a.lo >> 32;
uint64_t aHiLo = a.hi & 0xFFFFFFFF;
uint64_t aHiHi = a.hi >> 32;
uint64_t bLoLo = b.lo & 0xFFFFFFFF;
uint64_t bLoHi = b.lo >> 32;
uint64_t bHiLo = b.hi & 0xFFFFFFFF;
uint64_t bHiHi = b.hi >> 32;
uint64_t carry;
uint64_t sumLoLo = (aLoLo + bLoLo);
carry = sumLoLo >> 32;
uint64_t resultLoLo = sumLoLo & 0xFFFFFFFF;
uint64_t sumLoHi = (aLoHi + bLoHi) + carry;
uint64_t resultLoHi = sumLoHi & 0xFFFFFFFF;
carry = sumLoHi >> 32;
uint64_t sumHiLo = (aHiLo + bHiLo) + carry;
uint64_t resultHiLo = sumHiLo & 0xFFFFFFFF;
carry = sumHiLo >> 32;
uint64_t sumHiHi = (aHiHi + bHiHi) + carry;
uint64_t resultHiHi = sumHiHi & 0xFFFFFFFF;
/* carry = sumHiHi >> 32; */
sexp_luint_t result;
result.hi = (resultHiHi << 32) | resultHiLo;
result.lo = (resultLoHi << 32) | resultLoLo;
return result;
}
static inline sexp_luint_t luint_add_uint(sexp_luint_t a, sexp_uint_t b) {
uint64_t aLoLo = a.lo & 0xFFFFFFFF;
uint64_t aLoHi = a.lo >> 32;
uint64_t aHiLo = a.hi & 0xFFFFFFFF;
uint64_t aHiHi = a.hi >> 32;
uint64_t bLoLo = b & 0xFFFFFFFF;
uint64_t bLoHi = b >> 32;
uint64_t carry;
uint64_t sumLoLo = (aLoLo + bLoLo);
carry = sumLoLo >> 32;
uint64_t resultLoLo = sumLoLo & 0xFFFFFFFF;
uint64_t sumLoHi = (aLoHi + bLoHi) + carry;
uint64_t resultLoHi = sumLoHi & 0xFFFFFFFF;
carry = sumLoHi >> 32;
uint64_t sumHiLo = aHiLo + carry;
uint64_t resultHiLo = sumHiLo & 0xFFFFFFFF;
carry = sumHiLo >> 32;
uint64_t sumHiHi = aHiHi + carry;
uint64_t resultHiHi = sumHiHi & 0xFFFFFFFF;
/* carry = sumHiHi >> 32; */
sexp_luint_t result;
result.hi = (resultHiHi << 32) | resultHiLo;
result.lo = (resultLoHi << 32) | resultLoLo;
return result;
}
static inline sexp_luint_t luint_sub(sexp_luint_t a, sexp_luint_t b) {
sexp_luint_t negB;
negB.hi = ~b.hi;
negB.lo = ~b.lo;
return luint_add(a, luint_add_uint(negB, 1));
}
static inline sexp_luint_t luint_mul_uint(sexp_luint_t a, sexp_uint_t b) {
uint64_t aLoLo = a.lo & 0xFFFFFFFF;
uint64_t aLoHi = a.lo >> 32;
uint64_t aHiLo = a.hi & 0xFFFFFFFF;
uint64_t aHiHi = a.hi >> 32;
uint64_t bLo = b & 0xFFFFFFFF;
uint64_t bHi = b >> 32;
sexp_luint_t resultBLo, resultBHi;
{
sexp_luint_t prodLoLo;
prodLoLo.hi = 0;
prodLoLo.lo = aLoLo * bLo;
sexp_luint_t prodLoHi;
prodLoHi.hi = (aLoHi * bLo) >> 32;
prodLoHi.lo = (aLoHi * bLo) << 32;
sexp_luint_t prodHiLo;
prodHiLo.hi = aHiLo * bLo;
prodHiLo.lo = 0;
sexp_luint_t prodHiHi;
prodHiHi.hi = (aHiHi * bLo) << 32;
prodHiHi.lo = 0;
resultBLo = luint_add(luint_add(luint_add(prodLoLo, prodLoHi), prodHiLo), prodHiHi);
}
{
sexp_luint_t prodLoLo;
prodLoLo.hi = 0;
prodLoLo.lo = aLoLo * bHi;
sexp_luint_t prodLoHi;
prodLoHi.hi = (aLoHi * bHi) >> 32;
prodLoHi.lo = (aLoHi * bHi) << 32;
sexp_luint_t prodHiLo;
prodHiLo.hi = aHiLo * bHi;
prodHiLo.lo = 0;
sexp_luint_t prodHiHi;
prodHiHi.hi = (aHiHi * bHi) << 32;
prodHiHi.lo = 0;
resultBHi = luint_add(luint_add(luint_add(prodLoLo, prodLoHi), prodHiLo), prodHiHi);
}
sexp_luint_t result = luint_add(resultBLo, luint_shl(resultBHi, 32));
return result;
}
static inline sexp_lsint_t lsint_mul_sint(sexp_lsint_t a, sexp_sint_t b) {
if (lsint_lt_0(a)) {
sexp_luint_t minusA = luint_from_lsint(lsint_negate(a));
if (b < 0)
return lsint_from_luint(luint_mul_uint(minusA, (sexp_uint_t)-b));
else
return lsint_negate(lsint_from_luint(luint_mul_uint(minusA, (sexp_uint_t)b)));
} else {
if (b < 0)
return lsint_negate(lsint_from_luint(luint_mul_uint(luint_from_lsint(a), (sexp_uint_t)-b)));
else
return lsint_from_luint(luint_mul_uint(luint_from_lsint(a), (sexp_uint_t)b));
}
}
static inline sexp_luint_t luint_div(sexp_luint_t a, sexp_luint_t b) {
if (luint_lt(a, b))
return luint_from_uint(0);
else if (luint_eq(a, b))
return luint_from_uint(1);
sexp_luint_t quotient = luint_from_uint(0);
sexp_luint_t remainder = luint_from_uint(0);
for (int i = 0; i < 128; i++) {
quotient = luint_shl(quotient, 1);
remainder = luint_shl(remainder, 1);
remainder.lo |= (a.hi >> 63) & 1;
a = luint_shl(a, 1);
if (!(luint_lt(remainder, b))) {
remainder = luint_sub(remainder, b);
quotient.lo |= 1;
}
}
return quotient;
}
static inline sexp_luint_t luint_div_uint(sexp_luint_t a, sexp_uint_t b) {
return luint_div(a, luint_from_uint(b));
}
static inline sexp_luint_t luint_and(sexp_luint_t a, sexp_luint_t b) {
sexp_luint_t result;
result.hi = a.hi & b.hi;
result.lo = a.lo & b.lo;
return result;
}
static inline int luint_is_fixnum(sexp_luint_t x) {
return (x.hi == 0) && (x.lo <= SEXP_MAX_FIXNUM);
}
static inline int lsint_is_fixnum(sexp_lsint_t x) {
if (x.hi > 0)
return 0;
else if (x.hi == 0)
return x.lo <= SEXP_MAX_FIXNUM;
else if (x.hi == -1)
return SEXP_MIN_FIXNUM <= x.lo;
else return 0;
}
#endif
SEXP_API sexp_sint_t sexp_bignum_compare (sexp a, sexp b);
SEXP_API sexp sexp_compare (sexp ctx, sexp a, sexp b);
SEXP_API sexp sexp_make_bignum (sexp ctx, sexp_uint_t len);
@ -26,7 +400,9 @@ SEXP_API sexp_uint_t sexp_bignum_hi (sexp a);
SEXP_API sexp sexp_fixnum_to_bignum (sexp ctx, sexp a);
SEXP_API double sexp_bignum_to_double (sexp a);
SEXP_API sexp sexp_double_to_bignum (sexp ctx, double f);
SEXP_API double sexp_to_double (sexp ctx, sexp x);
SEXP_API sexp sexp_bignum_fxadd (sexp ctx, sexp a, sexp_uint_t b);
SEXP_API sexp sexp_bignum_fxsub (sexp ctx, sexp a, sexp_uint_t b);
SEXP_API sexp sexp_bignum_fxmul (sexp ctx, sexp d, sexp a, sexp_uint_t b, int offset);
SEXP_API sexp_uint_t sexp_bignum_fxdiv (sexp ctx, sexp a, sexp_uint_t b, int offset);
SEXP_API sexp sexp_bignum_add (sexp ctx, sexp dst, sexp a, sexp b);
@ -43,7 +419,8 @@ SEXP_API sexp sexp_quotient (sexp ctx, sexp a, sexp b);
SEXP_API sexp sexp_remainder (sexp ctx, sexp a, sexp b);
#if SEXP_USE_RATIOS
SEXP_API sexp sexp_double_to_ratio (sexp ctx, double f);
SEXP_API double sexp_ratio_to_double (sexp rat);
SEXP_API sexp sexp_double_to_ratio_2 (sexp ctx, double f);
SEXP_API double sexp_ratio_to_double (sexp ctx, sexp rat);
SEXP_API sexp sexp_make_ratio (sexp ctx, sexp num, sexp den);
SEXP_API sexp sexp_ratio_normalize (sexp ctx, sexp rat, sexp in);
SEXP_API sexp sexp_ratio_round (sexp ctx, sexp a);

View file

@ -46,8 +46,6 @@ enum sexp_opcode_classes {
SEXP_OPC_NUM_OP_CLASSES
};
SEXP_API struct sexp_opcode_struct* sexp_primitive_opcodes;
#if SEXP_USE_DEBUG_VM || SEXP_USE_PROFILE_VM || SEXP_USE_STATIC_LIBS
SEXP_API const char** sexp_opcode_names;
#endif
@ -76,7 +74,7 @@ SEXP_API void sexp_bless_bytecode (sexp ctx, sexp bc);
#endif
SEXP_API sexp sexp_complete_bytecode (sexp ctx);
SEXP_API void sexp_shrink_bcode (sexp ctx, sexp_uint_t i);
SEXP_API void sexp_expand_bcode (sexp ctx, sexp_uint_t size);
SEXP_API void sexp_expand_bcode (sexp ctx, sexp_sint_t size);
SEXP_API void sexp_stack_trace (sexp ctx, sexp out);
SEXP_API sexp sexp_free_vars (sexp context, sexp x, sexp fv);
SEXP_API int sexp_param_index (sexp ctx, sexp lambda, sexp name);
@ -94,6 +92,7 @@ SEXP_API sexp sexp_make_standard_env_op (sexp context, sexp self, sexp_sint_t n,
SEXP_API void sexp_set_parameter (sexp ctx, sexp env, sexp name, sexp value);
SEXP_API sexp sexp_load_standard_ports (sexp context, sexp env, FILE* in, FILE* out, FILE* err, int no_close);
SEXP_API sexp sexp_load_standard_env (sexp context, sexp env, sexp version);
SEXP_API char* sexp_find_module_file_raw (sexp ctx, const char *file);
SEXP_API sexp sexp_find_module_file (sexp ctx, const char *file);
SEXP_API sexp sexp_load_module_file (sexp ctx, const char *file, sexp env);
SEXP_API sexp sexp_current_module_path_op (sexp ctx, sexp self, sexp_sint_t n, sexp x);
@ -129,13 +128,15 @@ SEXP_API sexp sexp_warn_undefs_op (sexp ctx, sexp self, sexp_sint_t n, sexp from
SEXP_API sexp sexp_make_lit (sexp ctx, sexp value);
SEXP_API sexp sexp_make_opcode (sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp, sexp_proc1);
SEXP_API sexp sexp_make_procedure_op (sexp ctx, sexp self, sexp_sint_t n, sexp flags, sexp num_args, sexp bc, sexp vars);
SEXP_API sexp sexp_define_foreign_aux (sexp ctx, sexp env, const char *name, int num_args, int flags, sexp_proc1 f, sexp data);
SEXP_API sexp sexp_define_foreign_aux (sexp ctx, sexp env, const char *name, int num_args, int flags, const char *fname, sexp_proc1 f, sexp data);
SEXP_API sexp sexp_define_foreign_proc_aux (sexp ctx, sexp env, const char *name, int num_args, int flags, const char *fname, sexp_proc1 f, sexp data);
SEXP_API sexp sexp_register_optimization(sexp ctx, sexp self, sexp_sint_t n, sexp f, sexp i);
#if SEXP_USE_AUTO_FORCE
SEXP_API sexp sexp_make_promise (sexp ctx, sexp self, sexp_sint_t n, sexp done, sexp val);
#endif
#if SEXP_USE_UTF8_STRINGS
SEXP_API sexp sexp_read_utf8_char (sexp ctx, sexp port, int i);
SEXP_API void sexp_push_utf8_char (sexp ctx, int i, sexp port);
SEXP_API void sexp_string_utf8_set (sexp ctx, sexp str, sexp index, sexp ch);
SEXP_API sexp sexp_string_utf8_index_ref (sexp ctx, sexp self, sexp_sint_t n, sexp str, sexp i);
SEXP_API sexp sexp_string_utf8_index_set (sexp ctx, sexp self, sexp_sint_t n, sexp str, sexp i, sexp ch);
@ -189,10 +190,13 @@ SEXP_API sexp sexp_char_upcase(sexp ctx, sexp self, sexp_sint_t n, sexp ch);
SEXP_API sexp sexp_char_downcase(sexp ctx, sexp self, sexp_sint_t n, sexp ch);
#endif
#define sexp_define_foreign(c,e,s,n,f) sexp_define_foreign_aux(c,e,s,n,0,(sexp_proc1)f,NULL)
#define sexp_define_foreign_opt(c,e,s,n,f,d) sexp_define_foreign_aux(c,e,s,n,1,(sexp_proc1)f,d)
SEXP_API sexp sexp_define_foreign_param_aux(sexp ctx, sexp env, const char *name, int num_args, const char *fname, sexp_proc1 f, const char *param);
SEXP_API sexp sexp_define_foreign_param (sexp ctx, sexp env, const char *name, int num_args, sexp_proc1 f, const char *param);
#define sexp_define_foreign(c,e,s,n,f) sexp_define_foreign_aux(c,e,s,n,0,(const char*)#f,(sexp_proc1)f,NULL)
#define sexp_define_foreign_param(c,e,s,n,f,p) sexp_define_foreign_param_aux(c,e,s,n,(const char*)#f,(sexp_proc1)f,p)
#define sexp_define_foreign_opt(c,e,s,n,f,p) sexp_define_foreign_aux(c,e,s,n,1,(const char*)#f,(sexp_proc1)f,p)
#define sexp_define_foreign_proc(c,e,s,n,f) sexp_define_foreign_proc_aux(c,e,s,n,SEXP_PROC_NONE,(const char*)#f,(sexp_proc1)f,NULL)
#define sexp_define_foreign_proc_rest(c,e,s,n,f) sexp_define_foreign_proc_aux(c,e,s,n,SEXP_PROC_VARIADIC,(const char*)#f,(sexp_proc1)f,NULL)
#define sexp_env_key(x) sexp_car(x)
#define sexp_env_value(x) sexp_cdr(x)
@ -236,6 +240,7 @@ SEXP_API sexp sexp_9p_respond (sexp ctx, sexp self, sexp_sint_t n, sexp req, sex
SEXP_API sexp sexp_9p_responderror (sexp ctx, sexp self, sexp_sint_t n, sexp req);
#else
SEXP_API sexp sexp_get_port_fileno (sexp ctx, sexp self, sexp_sint_t n, sexp port);
SEXP_API sexp sexp_stream_portp_op (sexp ctx, sexp self, sexp_sint_t n, sexp port);
#endif
#if SEXP_USE_SIMPLIFY

View file

@ -1,5 +1,5 @@
/* features.h -- general feature configuration */
/* Copyright (c) 2009-2015 Alex Shinn. All rights reserved. */
/* Copyright (c) 2009-2021 Alex Shinn. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
/* uncomment this to disable most features */
@ -23,16 +23,27 @@
/* sexp_init_library(ctx, env) function provided. */
/* #define SEXP_USE_DL 0 */
/* uncomment this to statically compile all C libs */
/* If set, this will statically include the clibs.c file */
/* into the standard environment, so that you can have */
/* access to a predefined set of C libraries without */
/* needing dynamic loading. The clibs.c file is generated */
/* automatically by searching the lib directory for */
/* modules with include-shared, but can be hand-tailored */
/* to your needs. */
/* uncomment this to support statically compiled C libs */
/* Unless SEXP_USE_STATIC_LIBS_EMPTY is set (see below), this */
/* will statically include the clibs.c file into the standard */
/* environment, so that you can have access to a predefined set */
/* of C libraries without needing dynamic loading. The clibs.c */
/* file is generated automatically by searching the lib directory */
/* for modules with include-shared, but can be hand-tailored to */
/* your needs. You can also register your own C libraries using */
/* sexp_add_static_libraries (see below). */
/* #define SEXP_USE_STATIC_LIBS 1 */
/* uncomment this to enable user exported C libs */
/* You can register your own C libraries using */
/* sexp_add_static_libraries. Each entry in the supplied table, */
/* is a name/entry point pair. These work as if they were */
/* dynamically loaded libraries, so naming follows the same */
/* conventions. An entry {"foo", init_foo} will register a */
/* library that can be loaded with (load "foo"), or */
/* (include-shared "foo"), both of which will call init_foo. */
/* #define SEXP_USE_STATIC_LIBS_EMPTY 1 */
/* uncomment this to disable detailed source info for debugging */
/* By default Chibi will associate source info with every */
/* bytecode offset. By disabling this only lambda-level source */
@ -64,6 +75,15 @@
/* if you suspect a bug in the native GC. */
/* #define SEXP_USE_BOEHM 1 */
/* uncomment this to enable automatic file descriptor unification */
/* File descriptors as returned by C functions are raw integers, */
/* which are convereted to GC'ed first-class objects on the Scheme */
/* side. By default we assume that each fd is new, however if this */
/* option is enabled and an fd is returned which matches an existing */
/* open fd, they are assumed to refer to the same descriptor and */
/* unified. */
/* #define SEXP_USE_UNIFY_FILENOS_BY_NUMBER 1 */
/* uncomment this to disable weak references */
/* #define SEXP_USE_WEAK_REFERENCES 0 */
@ -84,6 +104,11 @@
/* go away and you're not working on your own C extension. */
/* #define SEXP_USE_CONSERVATIVE_GC 1 */
/* uncomment this to disable automatic running of finalizers */
/* You will need to close ports and file descriptors manually */
/* (as you should anyway) and some C extensions may break. */
/* #define SEXP_USE_FINALIZERS 0 */
/* uncomment this to add additional native checks to only mark objects in the heap */
/* #define SEXP_USE_SAFE_GC_MARK 1 */
@ -100,6 +125,9 @@
/* uncomment this to add very verbose debugging stats to the native GC */
/* #define SEXP_USE_DEBUG_GC 1 */
/* uncomment this to add instrumentation to the native GC */
/* #define SEXP_USE_TIME_GC 1 */
/* uncomment this to enable "safe" field accessors for primitive types */
/* The sexp union type fields are abstracted away with macros of the */
/* form sexp_<type>_<field>(<obj>), however these are just convenience */
@ -160,11 +188,27 @@
/* uncomment this if you don't want 1## style approximate digits */
/* #define SEXP_USE_PLACEHOLDER_DIGITS 0 */
/* uncomment this to disable a workaround for numeric formatting, */
/* to fix numbers in locales which don't use the '.' decimal sep */
/* #define SEXP_USE_PATCH_NON_DECIMAL_NUMERIC_FORMATS 0 */
/* uncomment this if you don't need extended math operations */
/* This includes the trigonometric and expt functions. */
/* Automatically disabled if you've disabled flonums. */
/* #define SEXP_USE_MATH 0 */
/* uncomment this to enable lenient matching of top-level bindings */
/* Historically, to match behavior with some other Schemes and in */
/* hopes of making it easier to use macros and modules, Chibi allowed */
/* top-level bindings with the same underlying symbol name to match */
/* with identifier=?. In particular, there still isn't a good way */
/* to handle the case where auxiliary syntax conflicts with some other */
/* binding without renaming one or the other (though SRFI 206 helps). */
/* However, if people make use of this you can write Chibi programs */
/* which don't work portably in other implementations, which has been */
/* a source of confusion, so the default has reverted to strict R7RS. */
/* #define SEXP_USE_STRICT_TOPLEVEL_BINDINGS 0 */
/* uncomment this to disable warning about references to undefined variables */
/* This is something of a hack, but can be quite useful. */
/* It's very fast and doesn't involve any separate analysis */
@ -187,6 +231,11 @@
/* uncomment this to disable extended char names as defined in R7RS */
/* #define SEXP_USE_EXTENDED_CHAR_NAMES 0 */
/* uncomment this to disable R7RS #<n>= and #<n># reader labels in source */
/* The (scheme read) and (scheme write) libraries always support */
/* this regardless. */
/* #define SEXP_USE_READER_LABELS 0 */
/* uncomment this to disable UTF-8 string support */
/* The default settings store strings in memory as UTF-8, */
/* and assumes strings passed to/from the C FFI are UTF-8. */
@ -197,10 +246,32 @@
/* Making them immutable allows for packed UTF-8 strings. */
/* #define SEXP_USE_MUTABLE_STRINGS 0 */
/* uncomment this to base string ports on C streams */
/* This historic option enables string and custom ports backed */
/* by FILE* objects using memstreams and funopen/fopencookie. */
/* #define SEXP_USE_STRING_STREAMS 1 */
/* uncomment this to enable precomputed index->cursor tables for strings */
/* This makes string-ref faster at the expensive of making string */
/* construction (including string-append and I/O) slower. */
/* You can configure with SEXP_STRING_INDEX_TABLE_CHUNK_SIZE below, */
/* the default is caching every 64th index (<=12.5% string overhead). */
/* With a minimum of 1 you'd have up to 8x string overhead, and */
/* string-ref would still be slightly slower than string-cursors, */
/* and string-append would be marginally slower as well. */
/* */
/* In practice, the overhead of iterating over a string with */
/* string-ref isn't noticeable until about 10k chars. Times */
/* for iteration using the different approaches: */
/* */
/* impl\len 1000 10000 100000 1000000 */
/* string-ref (utf8) 1 97 9622 x */
/* string-ref (fast) 0 2 19 216 */
/* cursor-ref (srfi 130) 0 4 18 150 */
/* text-ref (srfi 135) 2 27 211 2006 */
/* */
/* #define SEXP_USE_STRING_INDEX_TABLE 1 */
/* uncomment this to cache a string cursor for string-ref calls */
/* The default is not to use a cache. The goal of caching is to */
/* soften the performance impact of repeated O(n) string-ref */
/* operations on the same string. */
/* #define SEXP_USE_STRING_REF_CACHE 1 */
/* uncomment this to disable automatic closing of ports */
/* If enabled, the underlying FILE* for file ports will be */
@ -230,7 +301,7 @@
/* uncomment this to make the VM adhere to alignment rules */
/* This is required on some platforms, e.g. ARM */
/* #define SEXP_USE_ALIGNED_BYTECODE */
/* #define SEXP_USE_ALIGNED_BYTECODE 1 */
/************************************************************************/
/* These settings are configurable but only recommended for */
@ -256,6 +327,15 @@
#define SEXP_GROW_HEAP_RATIO 0.75
#endif
/* how much to expand the heap size by */
#ifndef SEXP_GROW_HEAP_FACTOR
#define SEXP_GROW_HEAP_FACTOR 2 /* 1.6180339887498948482 */
#endif
/* size of per-context stack that is used during gc cycles
* increase if you can affort extra unused memory */
#define SEXP_MARK_STACK_COUNT 1024
/* the default number of opcodes to run each thread for */
#ifndef SEXP_DEFAULT_QUANTUM
#define SEXP_DEFAULT_QUANTUM 500
@ -265,12 +345,21 @@
#define SEXP_MAX_ANALYZE_DEPTH 8192
#endif
/* The size of flexible arrays (empty arrays at the end of a struct */
/* representing the trailing data), when compiled with C++. Technically */
/* 0 is an illegal value here, and the C++ idiom is to use 1, but this */
/* breaks compatibility with C when computing the size of structs, and */
/* in practice all of the major C++ compilers support 0. */
#ifndef SEXP_FLEXIBLE_ARRAY_SIZE
#define SEXP_FLEXIBLE_ARRAY_SIZE 0
#endif
/************************************************************************/
/* DEFAULTS - DO NOT MODIFY ANYTHING BELOW THIS LINE */
/************************************************************************/
#ifndef SEXP_64_BIT
#if defined(__amd64) || defined(__x86_64) || defined(_WIN64) || defined(_Wp64) || defined(__LP64__) || defined(__PPC64__)
#if defined(__amd64) || defined(__x86_64) || defined(_WIN64) || defined(_Wp64) || defined(__LP64__) || defined(__PPC64__) || defined(__mips64__) || defined(__sparc64__) || defined(__arm64)
#define SEXP_64_BIT 1
#else
#define SEXP_64_BIT 0
@ -286,6 +375,51 @@
#endif
#endif
/* Detect specific BSD */
#if SEXP_BSD
#if defined(__APPLE__)
#define SEXP_DARWIN 1
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__FreeBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 1
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__NetBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 1
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__DragonFly__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 1
#define SEXP_OPENBSD 0
#elif defined(__OpenBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 1
#endif
#endif
/* for bignum support, need a double long to store long*long */
/* gcc supports uint128_t, otherwise we need a custom struct */
#ifndef SEXP_USE_CUSTOM_LONG_LONGS
#if SEXP_64_BIT && !defined(__GNUC__)
#define SEXP_USE_CUSTOM_LONG_LONGS 1
#else
#define SEXP_USE_CUSTOM_LONG_LONGS 0
#endif
#endif
#ifndef SEXP_USE_NO_FEATURES
#define SEXP_USE_NO_FEATURES 0
#endif
@ -294,9 +428,19 @@
#define SEXP_USE_PEDANTIC 0
#endif
/* this ensures public structs and enums are unchanged by feature toggles. */
/* should generally be left at 1. */
#ifndef SEXP_USE_STABLE_ABI
#define SEXP_USE_STABLE_ABI 1
#endif
#ifndef SEXP_USE_GREEN_THREADS
#if defined(_WIN32)
#define SEXP_USE_GREEN_THREADS 0
#else
#define SEXP_USE_GREEN_THREADS ! SEXP_USE_NO_FEATURES
#endif
#endif
#ifndef SEXP_USE_DEBUG_THREADS
#define SEXP_USE_DEBUG_THREADS 0
@ -327,20 +471,28 @@
#endif
#ifndef SEXP_USE_DL
#if defined(PLAN9) || defined(_WIN32)
#if defined(PLAN9)
#define SEXP_USE_DL 0
#else
#define SEXP_USE_DL ! SEXP_USE_NO_FEATURES
#endif
#endif
#ifndef SEXP_USE_STATIC_LIBS_EMPTY
#define SEXP_USE_STATIC_LIBS_EMPTY 0
#endif
#ifndef SEXP_USE_STATIC_LIBS
#define SEXP_USE_STATIC_LIBS 0
#define SEXP_USE_STATIC_LIBS SEXP_USE_STATIC_LIBS_EMPTY
#endif
/* don't include clibs.c - include separately or link */
#ifndef SEXP_USE_STATIC_LIBS_NO_INCLUDE
#define SEXP_USE_STATIC_LIBS_NO_INCLUDE defined(PLAN9)
#if defined(PLAN9) || SEXP_USE_STATIC_LIBS_EMPTY
#define SEXP_USE_STATIC_LIBS_NO_INCLUDE 0
#else
#define SEXP_USE_STATIC_LIBS_NO_INCLUDE 1
#endif
#endif
#ifndef SEXP_USE_FULL_SOURCE_INFO
@ -355,9 +507,17 @@
#define SEXP_USE_BOEHM 0
#endif
#ifdef SEXP_USE_UNIFY_FILENOS_BY_NUMBER
#define SEXP_USE_UNIFY_FILENOS_BY_NUMBER 0
#endif
#ifndef SEXP_USE_WEAK_REFERENCES
#if SEXP_USE_UNIFY_FILENOS_BY_NUMBER
#define SEXP_USE_WEAK_REFERENCES 1
#else
#define SEXP_USE_WEAK_REFERENCES ! SEXP_USE_NO_FEATURES
#endif
#endif
#ifndef SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
#define SEXP_USE_FIXED_CHUNK_SIZE_HEAPS 0
@ -379,6 +539,14 @@
#define SEXP_USE_DEBUG_GC 0
#endif
#ifndef SEXP_USE_TIME_GC
#if SEXP_USE_DEBUG_GC > 0 || defined(__linux) || SEXP_BSD
#define SEXP_USE_TIME_GC 1
#else
#define SEXP_USE_TIME_GC 0
#endif
#endif
#ifndef SEXP_USE_SAFE_GC_MARK
#define SEXP_USE_SAFE_GC_MARK SEXP_USE_DEBUG_GC > 1
#endif
@ -387,6 +555,10 @@
#define SEXP_USE_CONSERVATIVE_GC 0
#endif
#ifndef SEXP_USE_FINALIZERS
#define SEXP_USE_FINALIZERS 1
#endif
#ifndef SEXP_USE_TRACK_ALLOC_SOURCE
#define SEXP_USE_TRACK_ALLOC_SOURCE SEXP_USE_DEBUG_GC > 2
#endif
@ -395,6 +567,18 @@
#define SEXP_USE_TRACK_ALLOC_BACKTRACE SEXP_USE_TRACK_ALLOC_SOURCE
#endif
#ifndef SEXP_USE_TRACK_ALLOC_TIMES
#define SEXP_USE_TRACK_ALLOC_TIMES 0
#endif
#ifndef SEXP_USE_TRACK_ALLOC_SIZES
#define SEXP_USE_TRACK_ALLOC_SIZES 0
#endif
#ifndef SEXP_ALLOC_HISTOGRAM_BUCKETS
#define SEXP_ALLOC_HISTOGRAM_BUCKETS 32
#endif
#ifndef SEXP_BACKTRACE_SIZE
#define SEXP_BACKTRACE_SIZE 3
#endif
@ -432,7 +616,7 @@
#endif
#ifndef SEXP_USE_STRICT_TOPLEVEL_BINDINGS
#define SEXP_USE_STRICT_TOPLEVEL_BINDINGS 0
#define SEXP_USE_STRICT_TOPLEVEL_BINDINGS 1
#endif
#if SEXP_USE_STRICT_TOPLEVEL_BINDINGS
@ -506,6 +690,10 @@
#define SEXP_PLACEHOLDER_DIGIT '#'
#endif
#ifndef SEXP_USE_PATCH_NON_DECIMAL_NUMERIC_FORMATS
#define SEXP_USE_PATCH_NON_DECIMAL_NUMERIC_FORMATS 1
#endif
#ifndef SEXP_USE_MATH
#define SEXP_USE_MATH SEXP_USE_FLONUMS && ! SEXP_USE_NO_FEATURES
#endif
@ -522,15 +710,27 @@
#define SEXP_USE_OBJECT_BRACE_LITERALS (SEXP_USE_TYPE_DEFS && !SEXP_USE_NO_FEATURES)
#endif
/* Dangerous without shared object detection. */
#ifndef SEXP_USE_TYPE_PRINTERS
#define SEXP_USE_TYPE_PRINTERS 0
#define SEXP_USE_TYPE_PRINTERS SEXP_USE_OBJECT_BRACE_LITERALS
#endif
#ifndef SEXP_USE_UNIFORM_VECTOR_LITERALS
#define SEXP_USE_UNIFORM_VECTOR_LITERALS ! SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_MINI_FLOAT_UNIFORM_VECTORS
#define SEXP_USE_MINI_FLOAT_UNIFORM_VECTORS ! SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_BYTEVECTOR_LITERALS
#define SEXP_USE_BYTEVECTOR_LITERALS ! SEXP_USE_NO_FEATURES
#define SEXP_USE_BYTEVECTOR_LITERALS SEXP_USE_UNIFORM_VECTOR_LITERALS
#endif
#ifndef SEXP_BYTEVECTOR_HEX_LITERALS
#define SEXP_BYTEVECTOR_HEX_LITERALS SEXP_USE_BYTEVECTOR_LITERALS
#endif
#ifndef SEXP_USE_SELF_PARAMETER
#define SEXP_USE_SELF_PARAMETER 1
#endif
@ -583,6 +783,10 @@
#define SEXP_USE_EXTENDED_CHAR_NAMES ! SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_READER_LABELS
#define SEXP_USE_READER_LABELS ! SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_UTF8_STRINGS
#define SEXP_USE_UTF8_STRINGS ! SEXP_USE_NO_FEATURES
#endif
@ -598,8 +802,20 @@
#define SEXP_USE_PACKED_STRINGS 1
#endif
#ifndef SEXP_USE_STRING_STREAMS
#define SEXP_USE_STRING_STREAMS 0
#if SEXP_USE_PACKED_STRINGS
#define SEXP_USE_STRING_INDEX_TABLE 0
#endif
#ifndef SEXP_USE_STRING_INDEX_TABLE
#define SEXP_USE_STRING_INDEX_TABLE 0
#endif
/* for every chunk_size indexes store the precomputed offset */
#ifndef SEXP_STRING_INDEX_TABLE_CHUNK_SIZE
#define SEXP_STRING_INDEX_TABLE_CHUNK_SIZE 64
#endif
#ifndef SEXP_USE_DISJOINT_STRING_CURSORS
#define SEXP_USE_DISJOINT_STRING_CURSORS SEXP_USE_UTF8_STRINGS
#endif
#ifndef SEXP_USE_AUTOCLOSE_PORTS
@ -607,7 +823,11 @@
#endif
#ifndef SEXP_USE_GC_FILE_DESCRIPTORS
#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM && !defined(PLAN9))
#ifdef PLAN9
#define SEXP_USE_GC_FILE_DESCRIPTORS 0
#else
#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM)
#endif
#endif
#ifndef SEXP_USE_BIDIRECTIONAL_PORTS
@ -660,6 +880,10 @@
#define SEXP_MAX_STACK_SIZE SEXP_INIT_STACK_SIZE*1000
#endif
#ifndef SEXP_MAX_VECTOR_LENGTH
#define SEXP_MAX_VECTOR_LENGTH (SEXP_MAX_FIXNUM >> 1)
#endif
#ifndef SEXP_DEFAULT_EQUAL_DEPTH
#define SEXP_DEFAULT_EQUAL_DEPTH 10000
#endif
@ -668,8 +892,21 @@
#define SEXP_DEFAULT_EQUAL_BOUND 100000000
#endif
#ifndef SEXP_DEFAULT_WRITE_BOUND
#define SEXP_DEFAULT_WRITE_BOUND 10000
#endif
#ifndef SEXP_STRIP_SYNCLOS_BOUND
#define SEXP_STRIP_SYNCLOS_BOUND 10000
#endif
#ifndef SEXP_POLL_SLEEP_TIME
#define SEXP_POLL_SLEEP_TIME 5000
#define SEXP_POLL_SLEEP_TIME_MS 5
#endif
#ifndef SEXP_USE_IMAGE_LOADING
#define SEXP_USE_IMAGE_LOADING SEXP_USE_DL && !SEXP_USE_GLOBAL_HEAP && !SEXP_USE_BOEHM && !SEXP_USE_NO_FEATURES
#define SEXP_USE_IMAGE_LOADING SEXP_USE_DL && SEXP_64_BIT && !SEXP_USE_GLOBAL_HEAP && !SEXP_USE_BOEHM && !SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_UNSAFE_PUSH
@ -707,13 +944,17 @@
#endif
#ifndef SEXP_USE_ALIGNED_BYTECODE
#if defined(__arm__)
#if defined(__arm__) || defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)
#define SEXP_USE_ALIGNED_BYTECODE 1
#else
#define SEXP_USE_ALIGNED_BYTECODE 0
#endif
#endif
#ifndef SEXP_USE_SIGNED_SHIFTS
#define SEXP_USE_SIGNED_SHIFTS 0
#endif
#ifdef PLAN9
#define strcasecmp cistrcmp
#define strncasecmp cistrncmp
@ -723,6 +964,17 @@
#define isinf(x) (isInf(x,1) || isInf(x,-1))
#define isnan(x) isNaN(x)
#elif defined(_WIN32)
#define SHUT_RD 0 /* SD_RECEIVE */
#define SHUT_WR 1 /* SD_SEND */
#define SHUT_RDWR 2 /* SD_BOTH */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#define _USE_MATH_DEFINES /* For M_LN10 */
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#pragma warning(disable:4146) /* unary minus operator to unsigned type */
#if _MSC_VER < 1900
#define snprintf(buf, len, fmt, val) sprintf(buf, fmt, val)
#define strcasecmp lstrcmpi
#define strncasecmp(s1, s2, n) lstrcmpi(s1, s2)
@ -731,6 +983,10 @@
#define isnan(x) (x!=x)
#define isinf(x) (x > DBL_MAX || x < -DBL_MAX)
#endif
#elif !defined(__MINGW32__)
#error Unknown Win32 compiler!
#endif
#endif
#ifdef _WIN32
#define sexp_pos_infinity (DBL_MAX*DBL_MAX)
@ -746,12 +1002,16 @@
#define sexp_nan (0.0/0.0)
#endif
#ifdef __MINGW32__
#ifdef _WIN32
#ifdef SEXP_STATIC_LIBRARY
#define SEXP_API extern
#else
#ifdef BUILDING_DLL
#define SEXP_API __declspec(dllexport)
#else
#define SEXP_API __declspec(dllimport)
#endif
#endif
#else
#define SEXP_API extern
#endif

105
include/chibi/gc_heap.h Normal file
View file

@ -0,0 +1,105 @@
/* gc_heap.h -- heap packing, run-time image generation */
/* Copyright (c) 2016 Chris Walsh. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
#ifndef SEXP_GC_HEAP_H
#define SEXP_GC_HEAP_H
#include "chibi/sexp.h"
#if SEXP_USE_IMAGE_LOADING
#ifdef __cplusplus
extern "C" {
#endif
/* Iterate the heap associated with the context argument 'ctx',
calling user provided callbacks for the individual heap elements.
For each heap found, heap_callback is called.
For each free segment found, free_callback is called.
For each valid sexp found, sexp_callback is called.
Callbacks are skipped if the associated function
pointer argument is NULL.
A callback return value of SEXP_TRUE allows the heap walk to
continue normally. Any other value terminates the heap walk
with the callback result being returned.
The sexp_gc_heap_walk return value of SEXP_TRUE indicates all
elements of the heap were walked normally. Any other return
value indicates an abnormal return condition.
*/
SEXP_API sexp sexp_gc_heap_walk(
sexp ctx, /* a possibly incomplete context */
sexp_heap h, /* normally set to sexp_context_heap(ctx) */
sexp *types, /* normally set to sexp_context_types(ctx) */
size_t types_cnt, /* normally set to sexp_context_num_types(ctx) */
void *user, /* arbitrary data passed to callbacks */
sexp (*heap_callback)(sexp ctx, sexp_heap h, void *user),
sexp (*free_callback)(sexp ctx, sexp_free_list f, void *user),
sexp (*sexp_callback)(sexp ctx, sexp s, void *user));
/* Returns a new context which contains a single, packed heap.
The original ctx or heap are not altered, leaving two copies
of all sexps. For runtime use where you are packing the heap
to make accesses more efficient, the old heap and context should
be discarded after a sucessful call to heap pack; finalizers do
not need to be called since all active objects are in the new heap.
The input heap_size specifies the amount of free space to allocate
at the end of the packed heap. A heap_size of zero will produce a
single packed heap just large enough to hold all sexps from the
original heap.
*/
SEXP_API sexp sexp_gc_heap_pack(sexp ctx, sexp_uint_t heap_free_size);
/* Creates a new packed heap from the provided context, and saves
the contents of the packed heap to the file named filename.
If sucessful, SEXP_TRUE is returned. If a problem was encountered
in either creating the packed heap or saving to a file, then either
SEXP_FALSE or an exception is returned. Because of shared code with
sexp_load_image, sexp_load_image_err() can also be used to return the
error condition.
In all cases, upon completion the temporary packed context is deleted
and the context provided as an argument is not changed.
*/
SEXP_API sexp sexp_save_image (sexp ctx, const char* filename);
/* Loads a previously saved image, and returns the context associated with
that image. If the context could not be loaded, either NULL or an exception
are returned instead.
A new context is created with the contents of filename loaded into the
heap. The heap_free_size parameter specifies the size of the heap to be
created in addition to the heap image on disk. A size of zero will
result in an initial heap exactly the size of the disk image which will
be expanded with an additional heap when the system requests storage space.
The return value is either the context of the loaded image, or NULL. In
the case of a NULL context, the function sexp_load_image_err() can be called
to provide a description of the error encountered. An sexp exception cannot be
returned because there is not a valid context in which to put the exception.
*/
SEXP_API sexp sexp_load_image (const char* filename, off_t offset, sexp_uint_t heap_free_size, sexp_uint_t heap_max_size);
/* In the case that sexp_load_image() returns NULL, this function will return
a string containing a description of the error condition.
*/
SEXP_API char* sexp_load_image_err();
#ifdef __cplusplus
}
#endif
#endif /* SEXP_USE_IMAGE_LOADING */
#endif /* ! SEXP_GC_HEAP_H */

View file

@ -0,0 +1,6 @@
#define sexp_so_extension "@CMAKE_SHARED_LIBRARY_SUFFIX@"
#define sexp_default_module_path "@default_module_path@"
#define sexp_platform "@platform@"
#define sexp_architecture "@CMAKE_SYSTEM_PROCESSOR@"
#define sexp_version "@CMAKE_PROJECT_VERSION@"
#define sexp_release_name "@release@"

View file

@ -1,3 +1,4 @@
static struct sexp_huff_entry huff_table[] = {
{12, 0x0C00}, /* '\x00' */
{15, 0x0000}, /* '\x01' */
{15, 0x4000}, /* '\x02' */
@ -125,4 +126,5 @@
{14, 0x0E00}, /* '|' */
{14, 0x2E00}, /* '}' */
{14, 0x1E00}, /* '~' */
{14, 0x3E00}, /* '\x7f' */
{14, 0x3E00} /* '\x7f' */
};

View file

@ -1,5 +1,5 @@
char _huff_tab1[8], _huff_tab2[8], _huff_tab3[2], _huff_tab4[2],
extern char _huff_tab1[8], _huff_tab2[8], _huff_tab3[2], _huff_tab4[2],
_huff_tab5[4], _huff_tab6[2], _huff_tab7[4], _huff_tab8[4],
_huff_tab9[4], _huff_tab10[4], _huff_tab11[4], _huff_tab12[2],
_huff_tab13[8], _huff_tab14[2], _huff_tab15[8], _huff_tab16[8],

820
include/chibi/sexp.h Executable file → Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
[
"_main",
"_sexp_resume"
]

116
js/index.html Normal file
View file

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chibi-Scheme</title>
<style>
body {
font-family: sans-serif;
height: 100vh;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
}
main {
flex: 1;
display: flex;
flex-direction: column;
}
#program {
flex: 1 1 0;
padding: 0.5em;
}
#start {
font-size: inherit;
padding: 0.5em;
}
#output {
font-family: monospace;
padding: 0.5em;
white-space: pre;
background-color: #000;
color: #fff;
overflow: auto;
flex: 1 1 0;
}
</style>
</head>
<body>
<main>
<textarea id="program" spellcheck="false">;
; This is Chibi-Scheme compiled with Emscripten to run in the browser.
;
(import (scheme base))
(write-string "Hello, world!\n")
;
; You can also run arbitrary JavaScript code from scheme and yield control back and forth between Scheme and the browser
;
(import (chibi emscripten)) ; exports: eval-script!, integer-eval-script, string-eval-script, wait-on-event!
(write-string (number->string (integer-eval-script "6 * 7")))
(newline)
(eval-script! "window.addEventListener('click', function () {
Module['resume'](); // give control back to the Scheme process
})")
(let loop ()
(wait-on-event!) ; yields control back to the browser
(write-string "You have clicked me!\n")
(loop))
(write-string "Control never reaches this point\n")
</textarea>
<button type="button" id="start" disabled>Start Program</button>
<div id="output"></div>
</main>
<script src="chibi.js"></script>
<script>
function start(program, args, onOutput, onError) {
var firstError = true;
Chibi({
print: onOutput,
printErr: function (text) {
if (firstError) {
firstError = false;
return;
}
if (onError !== undefined) {
onError(text);
} else {
onOutput(text);
}
},
program: program,
arguments: args
});
}
</script>
<script>
(function () {
var programField = document.querySelector('#program');
var startButton = document.querySelector('#start');
var program = sessionStorage.getItem('program');
if (program) {
programField.value = program;
}
programField.addEventListener('input', function() {
sessionStorage.setItem('program', programField.value);
});
startButton.addEventListener('click', function() {
var program = programField.value;
startButton.disabled = true;
start(program, [],
function(text) {
output.textContent = output.textContent + text + '\n'
});
});
startButton.disabled = false;
})();
</script>
</body>
</html>

2
js/post.js Normal file
View file

@ -0,0 +1,2 @@
Module['resume'] = Module.cwrap('sexp_resume', 'void', []);

6
js/pre.js Normal file
View file

@ -0,0 +1,6 @@
Module['preRun'].push(function () {
FS.writeFile('program.scm', Module['program']);
});
Module['arguments'] = Module['arguments'] || [];
Module['arguments'].unshift('program.scm');

View file

@ -92,19 +92,19 @@ sexp sexp_listen (sexp ctx, sexp self, sexp fileno, sexp backlog) {
/* Additional utilities. */
sexp sexp_sockaddr_name (sexp ctx, sexp self, struct sockaddr* addr) {
char buf[24];
char buf[INET6_ADDRSTRLEN];
/* struct sockaddr_in *sa = (struct sockaddr_in *)addr; */
/* unsigned char *ptr = (unsigned char *)&(sa->sin_addr); */
/* sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); */
/* snprintf(buf, sizeof(buf), "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); */
inet_ntop(addr->sa_family,
(addr->sa_family == AF_INET6 ?
(void*)(&(((struct sockaddr_in6 *)addr)->sin6_addr)) :
(void*)(&(((struct sockaddr_in *)addr)->sin_addr))),
buf, 24);
buf, INET6_ADDRSTRLEN);
return sexp_c_string(ctx, buf, -1);
}
int sexp_sockaddr_port (sexp ctx, sexp self, struct sockaddr* addr) {
struct sockaddr_in *sa = (struct sockaddr_in *)addr;
return sa->sin_port;
return ntohs(sa->sin_port);
}

49
lib/chibi/app-test.sld Normal file
View file

@ -0,0 +1,49 @@
(define-library (chibi app-test)
(import (scheme base) (chibi app) (chibi config) (chibi test))
(export run-tests)
(begin
(define (feed cfg spec . args)
(let ((animals (conf-get-list cfg 'animals '())))
(cons (if (conf-get cfg 'lions) (cons 'lions animals) animals) args)))
(define (wash cfg spec . args)
(let ((animals (conf-get-list cfg 'animals '())))
(cons (cons 'soap (conf-get cfg '(command wash soap))) animals)))
(define zoo-app-spec
`(zoo
"Zookeeper Application"
(@
(animals (list symbol) "list of animals to act on (default all)")
(lions boolean (#\l) "also apply the action to lions"))
(or
(feed "feed the animals" (,feed animals ...))
(wash "wash the animals" (@ (soap boolean)) (,wash animals ...))
(help "print help" (,app-help-command)))
))
(define (run-tests)
(test-begin "app")
(test '((camel elephant) "today")
(run-application
zoo-app-spec
'("zoo" "--animals" "camel,elephant" "feed" "today")))
(test '((lions camel elephant) "tomorrow")
(run-application
zoo-app-spec
'("zoo" "--animals" "camel,elephant" "--lions" "feed" "tomorrow")))
(test '((soap . #f) rhino)
(run-application zoo-app-spec '("zoo" "--animals" "rhino" "wash")))
(test '((soap . #t) rhino)
(run-application zoo-app-spec
'("zoo" "--animals" "rhino" "wash" "--soap")))
(test '((soap . #t) rhino)
(run-application zoo-app-spec
'("zoo" "wash" "--soap" "--animals" "rhino")))
(test 'error
(guard (exn (else 'error))
(run-application zoo-app-spec
'("zoo" "--soap" "wash" "--animals" "rhino"))))
(let ((out (open-output-string)))
(parameterize ((current-output-port out))
(run-application zoo-app-spec '("zoo" "help"))
(test "Usage: zoo [options] <command>\nCommands:\n feed animals ... - feed the animals\n wash animals ... - wash the animals\n help - print help\nOptions:\n --animals - list of animals to act on (default all)\n -l, --lions - also apply the action to lions\n"
(get-output-string out))))
(test-end))))

View file

@ -1,12 +1,19 @@
;; app.scm -- unified option parsing and config
;; Copyright (c) 2012-2015 Alex Shinn. All rights reserved.
;; Copyright (c) 2012-2024 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
;;> The high-level interface. Given an application spec \var{spec},
;;> parses the given command-line arguments \var{args} into a config
;;> object, prepended to the existing object \var{config} if given.
;;> Then runs the corresponding command (or sub-command) procedure
;;> from \var{spec}.
;;> The high-level interface. Parses a command-line with optional
;;> and/or positional arguments, with arbitrarily nested subcommands
;;> (optionally having their own arguments), and calls the
;;> corresponding main procedure on the parsed config.
;;>
;;> Given an application spec \var{spec}, parses the given
;;> command-line arguments \var{args} into a config object (from
;;> \scheme{(chibi config)}), prepended to the existing object
;;> \var{config} if given. Then runs the corresponding command (or
;;> sub-command) procedure from \var{spec} on the following arguments:
;;>
;;> \scheme{(<proc> <config> <spec> <positional args> ...)}
;;>
;;> The app spec should be a list of the form:
;;>
@ -15,12 +22,13 @@
;;> where clauses can be any of:
;;>
;;> \itemlist[
;;> \item[\scheme{(@ <opt-spec>)} - option spec, described below]
;;> \item[\scheme{(begin: <begin-proc>)} - procedure to run before main]
;;> \item[\scheme{(end: <end-proc>)} - procedure to run after main]
;;> \item[\scheme{(<proc> args ...)} - main procedure (args only for documentation)]
;;> \item[\scheme{<app-spec>} - a subcommand described by the nested spec]
;;> \item[\scheme{(or <app-spec> ...)} - an alternate list of subcommands]
;;> \item{\scheme{(@ <opt-spec>)} - option spec, described below}
;;> \item{\scheme{(begin: <begin-proc>)} - procedure to run before main}
;;> \item{\scheme{(end: <end-proc>)} - procedure to run after main}
;;> \item{\scheme{(types: (<type-name> <parser>) ...)} - additional types that can be used in argument parsing}
;;> \item{\scheme{(<proc> args ...)} - main procedure (args only for documentation)}
;;> \item{\scheme{<app-spec>} - a subcommand described by the nested spec}
;;> \item{\scheme{(or <app-spec> ...)} - an alternate list of subcommands}
;;> ]
;;>
;;> For subcommands the symbolic command name must match, though it is
@ -40,7 +48,7 @@
;;>
;;> \itemlist[
;;> \item{\scheme{boolean} - boolean, associated value optional, allowing \scheme{--noname} to indicate \scheme{#false}}
;;> \item{[\scheme{char} - a single character}
;;> \item{\scheme{char} - a single character}
;;> \item{\scheme{integer} - an exact integer}
;;> \item{\scheme{real} - any real number}
;;> \item{\scheme{number} - any real or complex number}
@ -55,7 +63,43 @@
;;> files, whereas the app specs include embedded procedure objects so
;;> are typically written with \scheme{quasiquote}.
;;>
;;> Complete Example:
;;> Complete Example - stripped down ls(1):
;;>
;;> \schemeblock{
;;> (import (scheme base)
;;> (scheme process-context)
;;> (scheme write)
;;> (srfi 130)
;;> (chibi app)
;;> (chibi config)
;;> (chibi filesystem))
;;>
;;> (define (ls cfg spec . files)
;;> (for-each
;;> (lambda (x)
;;> (for-each
;;> (lambda (file)
;;> (unless (and (string-prefix? "." file)
;;> (not (conf-get cfg 'all)))
;;> (write-string file)
;;> (when (conf-get cfg 'long)
;;> (write-string " ")
;;> (write (file-modification-time file)))
;;> (newline)))
;;> (if (file-directory? x) (directory-files x) (list x))))
;;> files))
;;>
;;> (run-application
;;> `(ls
;;> "list directory contents"
;;> (@
;;> (long boolean (#\\l) "use a long listing format")
;;> (all boolean (#\\a) "do not ignore entries starting with ."))
;;> (,ls files ...))
;;> (command-line))
;;> }
;;>
;;> Subcommand Skeleton Example:
;;>
;;> \schemeblock{
;;> (run-application
@ -63,11 +107,11 @@
;;> "Zookeeper Application"
;;> (@
;;> (animals (list symbol) "list of animals to act on (default all)")
;;> (lions boolean (#\l) "also apply the action to lions"))
;;> (lions boolean (#\\l) "also apply the action to lions"))
;;> (or
;;> (feed "feed the animals" () (,feed animals ...))
;;> (wash "wash the animals" (@ (soap boolean)) (,wash animals ...))
;;> (help "print help" (,app-help-command)))
;;> (help "print help" (,app-help-command))))
;;> (command-line)
;;> (conf-load (string-append (get-environment-variable "HOME") "/.zoo")))
;;> }
@ -125,7 +169,7 @@
(let ((args (or (and (pair? o) (car o)) (command-line)))
(config (and (pair? o) (pair? (cdr o)) (cadr o))))
(cond
((parse-app '() (cdr spec) '() (cdr args) config #f #f)
((parse-app '() (cdr spec) '() (cdr args) config #f #f '())
=> (lambda (v)
(let ((proc (vector-ref v 0))
(cfg (vector-ref v 1))
@ -133,13 +177,14 @@
(init (vector-ref v 3))
(end (vector-ref v 4)))
(if init (init cfg))
(apply proc cfg spec args)
(if end (end cfg)))))
(let ((res (apply proc cfg spec args)))
(if end (end cfg))
res))))
((null? (cdr args))
(app-help spec args)
(error "Expected a command"))
(else
(error "Unknown command" (cdr args))))))
(error "Unknown command" args)))))
;;> Parse a single command-line argument from \var{args} according to
;;> \var{conf-spec}, and returns a list of two values: the
@ -149,7 +194,7 @@
;;> \var{fail} with a single string argument describing the error,
;;> returning that result.
(define (parse-option prefix conf-spec args fail)
(define (parse-option prefix conf-spec args types fail)
(define (parse-value type str)
(cond
((not (string? str))
@ -186,7 +231,10 @@
res))
#f))
(else
(list str #f))))))
(cond
((assq type types)
=> (lambda (cell) (list ((cadr cell) str) #f)))
(else (list str #f))))))))
(define (lookup-conf-spec conf-spec syms strs)
(let ((sym (car syms))
(str (car strs)))
@ -301,7 +349,7 @@
;;> is the list of remaining non-option arguments. Calls fail on
;;> error and tries to continue processing from the result.
(define (parse-options prefix conf-spec orig-args fail)
(define (parse-options prefix conf-spec orig-args types fail)
(let lp ((args orig-args)
(opts (make-conf '() #f (cons 'options orig-args) #f)))
(cond
@ -311,7 +359,7 @@
(not (eqv? #\- (string-ref (car args) 0))))
(cons opts (if (equal? (car args) "--") (cdr args) args)))
(else
(let ((val+args (parse-option prefix conf-spec args fail)))
(let ((val+args (parse-option prefix conf-spec args types fail)))
(lp (cdr val+args)
(conf-set opts (caar val+args) (cdar val+args))))))))
@ -331,59 +379,92 @@
;;> all prefixed by \var{prefix}. The original \var{spec} is used for
;;> \scheme{app-help}.
(define (parse-app prefix spec opt-spec args config init end . o)
(define (parse-app prefix spec opt-spec args config init end types . o)
(define (next-prefix prefix name)
(append (if (null? prefix) '(command) prefix) (list name)))
(define (prev-prefix prefix)
(cond ((and (= 2 (length prefix))))
(cond ((and (= 2 (length prefix))) '())
((null? prefix) '())
(else (reverse (cdr (reverse prefix))))))
(define (all-opt-names opt-spec)
;; TODO: nested options
(let lp ((ls opt-spec) (res '()))
(if (null? ls)
(map (lambda (x) (if (symbol? x) (symbol->string x) x))
(remove char? (reverse res)))
(let ((o (car ls)))
(lp (cdr ls)
(append (if (and (pair? (cddr o)) (pair? (third o)))
(third o)
'())
(cons (car o) res)))))))
(let ((fail (if (pair? o)
(car o)
(lambda (prefix spec opt args reason)
;; TODO: search for closest option in "unknown" case
(error reason opt)))))
(cond
((and (string=? reason "unknown option")
(find-nearest-edits opt (all-opt-names spec)))
=> (lambda (similar)
(if (pair? similar)
(error reason opt "Did you mean: " similar)
(error reason opt))))
(else
(error reason opt)))))))
(cond
((null? spec)
(error "no procedure in application spec"))
((or (null? (car spec)) (equal? '(@) (car spec)))
(parse-app prefix (cdr spec) opt-spec args config init end types fail))
((pair? (car spec))
(case (caar spec)
((@)
(let* ((new-opt-spec (cadr (car spec)))
(let* ((tail (cdar spec))
(new-opt-spec
(cond
((not (pair? tail))
'())
((or (pair? (cdr tail))
(and (pair? (car tail)) (symbol? (caar tail))))
tail)
(else
(car tail))))
(new-fail
(lambda (new-prefix new-spec new-opt new-args reason)
(parse-options (prev-prefix prefix) opt-spec new-args fail)))
(cfg+args (parse-options prefix new-opt-spec args new-fail))
(parse-option (prev-prefix prefix) opt-spec new-args types fail)))
(cfg+args (parse-options prefix new-opt-spec args types new-fail))
(config (conf-append (car cfg+args) config))
(args (cdr cfg+args)))
(parse-app prefix (cdr spec) new-opt-spec args config
init end new-fail)))
init end types new-fail)))
((or)
(any (lambda (x) (parse-app prefix x opt-spec args config init end))
(any (lambda (x) (parse-app prefix x opt-spec args config init end types))
(cdar spec)))
((begin:)
(parse-app prefix (cdr spec) opt-spec args config
(cadr (car spec)) end fail))
(cadr (car spec)) end types fail))
((end:)
(parse-app prefix (cdr spec) opt-spec args config
init (cadr (car spec)) fail))
init (cadr (car spec)) types fail))
((types:)
(parse-app prefix (cdr spec) opt-spec args config
init end (cdr (car spec)) fail))
(else
(if (procedure? (caar spec))
(vector (caar spec) config args init end) ; TODO: verify
(parse-app prefix (car spec) opt-spec args config
init end fail)))))
init end types fail)))))
((symbol? (car spec))
(and (pair? args)
(eq? (car spec) (string->symbol (car args)))
(let ((prefix (next-prefix prefix (car spec))))
(parse-app prefix (cdr spec) opt-spec (cdr args) config
init end fail))))
init end types fail))))
((procedure? (car spec))
(vector (car spec) config args init end))
(else
(if (not (string? (car spec)))
(error "unknown application spec" (car spec)))
(parse-app prefix (cdr spec) opt-spec args config init end fail)))))
(parse-app prefix (cdr spec) opt-spec args config init end types fail)))))
(define (print-command-help command out)
(cond
@ -457,7 +538,7 @@
(and (pair? (car ls)) (memq (caar ls) '(begin: end:) )))
(lp (cdr ls) (car ls) commands options))
((and (pair? (car ls)) (eq? '@ (caar ls)))
(lp (cdr ls) docs commands (append options (cadr (car ls)))))
(lp (cdr ls) docs commands (append options (cdar ls))))
((and (pair? (car ls)) (symbol? (caar ls)))
;; don't print nested commands
(if (pair? commands)

View file

@ -9,5 +9,6 @@
(scheme process-context)
(srfi 1)
(chibi config)
(chibi edit-distance)
(chibi string))
(include "app.scm"))

33
lib/chibi/apropos.scm Normal file
View file

@ -0,0 +1,33 @@
(define (list-bindings env)
(let parents ((env env) (binds '()))
(if (not env) binds
(let symbols ((syms (env-exports env)) (binds binds))
(if (null? syms) (parents (env-parent env) binds)
(symbols (cdr syms) (if (assv (car syms) binds) binds
(cons (cons (car syms) env)
binds))))))))
(define (apropos-list-bindings query)
(cond ((symbol? query) (set! query (symbol->string query)))
((not (string? query))
(error "Apropos query must be a symbol or a string")))
(sort (filter (lambda (binding)
(string-contains (symbol->string (car binding)) query))
(list-bindings (interaction-environment)))
(lambda (a b) (string<? (symbol->string (car a))
(symbol->string (car b))))))
(define (apropos-list query) (map car (apropos-list-bindings query)))
(define (apropos-prefix sym env)
(let ((p "procedure ")
(s "syntax ")
(v "variable "))
(guard (_ (else s)) (if (procedure? (eval sym env)) p v))))
(define (apropos query)
(for-each (lambda (bind)
(display (apropos-prefix (car bind) (cdr bind)))
(write (car bind))
(newline))
(apropos-list-bindings query)))

4
lib/chibi/apropos.sld Normal file
View file

@ -0,0 +1,4 @@
(define-library (chibi apropos)
(export apropos apropos-list)
(import (scheme base) (chibi) (chibi string) (srfi 1) (srfi 95))
(include "apropos.scm"))

30
lib/chibi/assert-test.sld Normal file
View file

@ -0,0 +1,30 @@
(define-library (chibi assert-test)
(import (chibi) (chibi assert) (chibi test))
(export run-tests)
(begin
(define-syntax test-assert
(syntax-rules ()
((test-assert irritants expr)
(protect (exn
(else
(test irritants (exception-irritants exn))))
expr
(error "assertion not triggered")))))
(define (run-tests)
(test-begin "assert")
(test-assert '((= x (+ x 1))
(x 3))
(let ((x 3)) (assert (= x (+ x 1)))))
(test-assert '((= x (+ y 1))
(x 3)
(y 42))
(let ((x 3) (y 42)) (assert (= x (+ y 1)))))
(test-assert '((eq? x 'three)
(x 3))
(let ((x 3)) (assert (eq? x 'three))))
(test-assert '((eq? x 'three)
"expected three: "
3)
(let ((x 3)) (assert (eq? x 'three) "expected three: " x)))
(test-end))))

115
lib/chibi/assert.sld Normal file
View file

@ -0,0 +1,115 @@
;;> A nice assert macro.
;;>
;;> Assert macros are common in Scheme, in particular being helpful
;;> for domain checks at the beginning of a procedure to catch errors
;;> as early as possible. Compared to statically typed languages this
;;> has the advantages that the assertions are optional, and that they
;;> are not limited by the type system. SRFI 145 provides the related
;;> notion of assumptions, but the motivation there is to provide
;;> hints to optimizing compilers, and these are not required to
;;> actually signal an error.
;;>
;;> \macro{(assert expr [msg ...])}
;;>
;;> Equivalent to SRFI 145 \code{assume} except that an error is
;;> guaranteed to be raised if \var{expr} is false. Conceptually
;;> shorthand for
;;>
;;> \code{(or \var{expr}
;;> (error "assertion failed" \var{msg} ...))}
;;>
;;> that is, evaluates \var{expr} and returns it if true, but raises
;;> an exception otherwise. The error is augmented to include the
;;> text of the failed \var{expr}. If no additional \var{msg}
;;> arguments are provided then \var{expr} is scanned for free
;;> variables in non-operator positions to report values from, e.g. in
;;>
;;> \code{(let ((x 3))
;;> (assert (= x (+ x 1))))}
;;>
;;> the error would also report the bound value of \code{x}. This
;;> uses the technique from Oleg Kiselyov's \hyperlink[http://okmij.org/ftp/Scheme/assert-syntax-rule.txt]{good assert macro},
;;> which is convenient but fallible. It is thus best to keep the
;;> body of the assertion simple, moving any predicates you need to
;;> external utilities, or provide an explicit \var{msg}.
(define-library (chibi assert)
(export assert)
(cond-expand
(chibi
(import (chibi))
(begin
(define-syntax syntax-identifier?
(er-macro-transformer
(lambda (expr rename compare)
(if (identifier? (cadr expr))
(car (cddr expr))
(cadr (cddr expr))))))
(define-syntax syntax-id-memq?
(er-macro-transformer
(lambda (expr rename compare)
(let ((expr (cdr expr)))
(if (any (lambda (x) (compare x (car expr))) (cadr expr))
(car (cddr expr))
(cadr (cddr expr)))))))))
(else
(import (scheme base))
(begin
;; from match.scm
(define-syntax syntax-identifier?
(syntax-rules ()
((_ (x . y) success-k failure-k) failure-k)
((_ #(x ...) success-k failure-k) failure-k)
((_ x success-k failure-k)
(let-syntax
((sym?
(syntax-rules ()
((sym? x sk fk) sk)
((sym? y sk fk) fk))))
(sym? abracadabra success-k failure-k)))))
(define-syntax syntax-id-memq?
(syntax-rules ()
((syntax-memq? id (ids ...) sk fk)
(let-syntax
((memq?
(syntax-rules (ids ...)
((memq? id sk2 fk2) fk2)
((memq? any-other sk2 fk2) sk2))))
(memq? random-symbol-to-match sk fk))))))))
(begin
(define-syntax extract-vars
(syntax-rules ()
((report-vars (op arg0 arg1 ...) (next ...) res)
(syntax-id-memq? op (quote quasiquote lambda let let* letrec letrec*
let-syntax letrec-syntax let-values let*-values
receive match case define define-syntax do)
(next ... res)
(extract-vars arg0
(extract-vars (op arg1 ...) (next ...))
res)))
((report-vars (op . x) (next ...) res)
(next ... res))
((report-vars x (next ...) (res ...))
(syntax-identifier? x
(syntax-id-memq? x (res ...)
(next ... (res ...))
(next ... (res ... x)))
(next ... (res ...))))))
(define-syntax qq-vars
(syntax-rules ()
((qq-vars (next ...) (var ...))
(next ... `(var ,var) ...))))
(define-syntax report-final
(syntax-rules ()
((report-final expr msg ...)
(error "assertion failed" 'expr msg ...))))
(define-syntax assert
(syntax-rules ()
((assert test)
(or test
(extract-vars test (qq-vars (report-final test)) ())))
((assert test msg ...)
(or test
(report-final test msg ...)))
((assert) #t)))))

View file

@ -1,13 +1,35 @@
/* ast.c -- interface to the Abstract Syntax Tree */
/* Copyright (c) 2009-2012 Alex Shinn. All rights reserved. */
/* Copyright (c) 2009-2015 Alex Shinn. All rights reserved. */
/* BSD-style license: http://synthcode.com/license.txt */
#include <chibi/eval.h>
#ifndef PLAN9
#include <stdlib.h>
#include <errno.h>
#endif
#ifdef _WIN32
#if defined(__MINGW32__) || defined(__MINGW64__)
/* Workaround MinGW header implementation */
errno_t getenv_s(size_t*, char*, size_t, const char*);
#endif
int setenv(const char *name, const char *value, int overwrite)
{
int errcode = 0;
if (!overwrite) {
size_t envsize = 0;
errcode = getenv_s(&envsize, NULL, 0, name);
if (errcode || envsize) return errcode;
}
return _putenv_s(name, value);
}
int unsetenv(const char *name)
{
return setenv(name, "", 1);
}
#endif
#if ! SEXP_USE_BOEHM
extern sexp sexp_gc (sexp ctx, size_t *sum_freed);
#endif
@ -40,7 +62,7 @@ static void sexp_define_accessors (sexp ctx, sexp env, sexp_uint_t ctype,
sexp_gc_release2(ctx);
}
static sexp sexp_get_env_cell (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp id, sexp createp) {
sexp sexp_get_env_cell (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp id, sexp createp) {
sexp cell;
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, env);
cell = sexp_env_cell(ctx, env, id, 0);
@ -50,33 +72,55 @@ static sexp sexp_get_env_cell (sexp ctx, sexp self, sexp_sint_t n, sexp env, sex
id = sexp_synclo_expr(id);
}
cell = sexp_env_cell(ctx, env, id, 0);
if (!cell && createp)
if (!cell && sexp_truep(createp))
cell = sexp_env_cell_define(ctx, env, id, SEXP_UNDEF, NULL);
}
return cell ? cell : SEXP_FALSE;
}
static sexp sexp_get_procedure_code (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp sexp_get_procedure_code (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return sexp_procedure_code(proc);
}
static sexp sexp_get_procedure_vars (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp sexp_get_procedure_vars (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return sexp_procedure_vars(proc);
}
static sexp sexp_get_procedure_arity (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp sexp_get_procedure_arity (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return sexp_make_fixnum(sexp_procedure_num_args(proc));
}
static sexp sexp_get_procedure_variadic_p (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp sexp_get_procedure_variadic_p (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return sexp_make_boolean(sexp_procedure_variadic_p(proc));
}
static sexp sexp_get_opcode_name (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_procedure_variable_transformer_p (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return sexp_make_boolean(sexp_procedure_variable_transformer_p(proc));
}
sexp sexp_get_procedure_flags (sexp ctx, sexp self, sexp_sint_t n, sexp proc) {
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, proc);
return (sexp) (sexp_uint_t) sexp_procedure_flags(proc);
}
sexp sexp_make_variable_transformer_op (sexp ctx, sexp self, sexp_sint_t n, sexp base_proc) {
sexp flags;
sexp_assert_type(ctx, sexp_procedurep, SEXP_PROCEDURE, base_proc);
if (sexp_procedure_variable_transformer_p(base_proc))
return base_proc;
flags = sexp_make_fixnum(sexp_unbox_fixnum(sexp_procedure_flags(base_proc)) | SEXP_PROC_VARIABLE_TRANSFORMER);
return sexp_make_procedure(ctx, flags,
sexp_make_fixnum(sexp_procedure_num_args(base_proc)),
sexp_procedure_code(base_proc),
sexp_procedure_vars(base_proc));
}
sexp sexp_get_opcode_name (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
if (! sexp_opcodep(op))
return sexp_type_exception(ctx, self, SEXP_OPCODE, op);
else if (! sexp_opcode_name(op))
@ -103,7 +147,7 @@ static sexp sexp_translate_opcode_type (sexp ctx, sexp type) {
return res;
}
static sexp sexp_get_opcode_ret_type (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_ret_type (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp res;
if (!op)
return sexp_type_by_index(ctx, SEXP_OBJECT);
@ -117,7 +161,7 @@ static sexp sexp_get_opcode_ret_type (sexp ctx, sexp self, sexp_sint_t n, sexp o
return sexp_translate_opcode_type(ctx, res);
}
static sexp sexp_get_opcode_param_type (sexp ctx, sexp self, sexp_sint_t n, sexp op, sexp k) {
sexp sexp_get_opcode_param_type (sexp ctx, sexp self, sexp_sint_t n, sexp op, sexp k) {
sexp res;
int p = sexp_unbox_fixnum(k);
if (! sexp_opcodep(op))
@ -136,7 +180,7 @@ static sexp sexp_get_opcode_param_type (sexp ctx, sexp self, sexp_sint_t n, sexp
default:
res = sexp_opcode_arg3_type(op);
if (res && sexp_vectorp(res)) {
if (sexp_vector_length(res) > (sexp_unbox_fixnum(k)-2))
if (sexp_vector_length(res) > (unsigned)(sexp_unbox_fixnum(k)-2))
res = sexp_vector_ref(res, sexp_fx_sub(k, SEXP_TWO));
else
res = sexp_type_by_index(ctx, SEXP_OBJECT);
@ -146,17 +190,17 @@ static sexp sexp_get_opcode_param_type (sexp ctx, sexp self, sexp_sint_t n, sexp
return sexp_translate_opcode_type(ctx, res);
}
static sexp sexp_get_opcode_class (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_class (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp_assert_type(ctx, sexp_opcodep, SEXP_OPCODE, op);
return sexp_make_fixnum(sexp_opcode_class(op));
}
static sexp sexp_get_opcode_code (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_code (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp_assert_type(ctx, sexp_opcodep, SEXP_OPCODE, op);
return sexp_make_fixnum(sexp_opcode_code(op));
}
static sexp sexp_get_opcode_data (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_data (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp data;
sexp_assert_type(ctx, sexp_opcodep, SEXP_OPCODE, op);
data = sexp_opcode_data(op);
@ -167,29 +211,41 @@ static sexp sexp_get_opcode_data (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp_type_by_index(ctx, sexp_unbox_fixnum(data)) : data;
}
static sexp sexp_get_opcode_num_params (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_num_params (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp_assert_type(ctx, sexp_opcodep, SEXP_OPCODE, op);
return sexp_make_fixnum(sexp_opcode_num_args(op));
}
static sexp sexp_get_opcode_variadic_p (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp sexp_get_opcode_variadic_p (sexp ctx, sexp self, sexp_sint_t n, sexp op) {
sexp_assert_type(ctx, sexp_opcodep, SEXP_OPCODE, op);
return sexp_make_boolean(sexp_opcode_variadic_p(op));
}
static sexp sexp_get_port_line (sexp ctx, sexp self, sexp_sint_t n, sexp p) {
sexp sexp_get_port_line (sexp ctx, sexp self, sexp_sint_t n, sexp p) {
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, p);
return sexp_make_fixnum(sexp_port_line(p));
}
static sexp sexp_set_port_line (sexp ctx, sexp self, sexp_sint_t n, sexp p, sexp i) {
sexp sexp_set_port_line (sexp ctx, sexp self, sexp_sint_t n, sexp p, sexp i) {
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, p);
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, i);
sexp_port_line(p) = sexp_unbox_fixnum(i);
return SEXP_VOID;
}
static sexp sexp_type_of (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp sexp_get_port_sourcep (sexp ctx, sexp self, sexp_sint_t n, sexp p) {
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, p);
return sexp_make_boolean(sexp_port_sourcep(p));
}
sexp sexp_set_port_sourcep (sexp ctx, sexp self, sexp_sint_t n, sexp p, sexp b) {
sexp_assert_type(ctx, sexp_portp, SEXP_IPORT, p);
sexp_assert_type(ctx, sexp_booleanp, SEXP_BOOLEAN, b);
sexp_port_sourcep(p) = sexp_truep(b);
return SEXP_VOID;
}
sexp sexp_type_of (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
if (!x)
return sexp_type_by_index(ctx, SEXP_OBJECT);
if (sexp_pointerp(x))
@ -212,41 +268,43 @@ static sexp sexp_type_of (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return sexp_type_by_index(ctx, SEXP_OBJECT);
}
static sexp sexp_env_parent_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e);
return sexp_env_parent(e) ? sexp_env_parent(e) : SEXP_FALSE;
sexp sexp_env_parent_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e1, sexp e2) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e1);
if (sexp_truep(e2)) sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e2);
sexp_env_parent(e1) = e2;
return SEXP_VOID;
}
static sexp sexp_env_lambda_op (sexp ctx, sexp self, sexp_sint_t n, sexp e) {
sexp sexp_env_lambda_op (sexp ctx, sexp self, sexp_sint_t n, sexp e) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e);
return sexp_env_lambda(e) ? sexp_env_lambda(e) : SEXP_FALSE;
}
static sexp sexp_env_lambda_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e, sexp lam) {
sexp sexp_env_lambda_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e, sexp lam) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e);
sexp_assert_type(ctx, sexp_lambdap, SEXP_LAMBDA, lam);
sexp_env_lambda(e) = lam;
return SEXP_VOID;
}
static sexp sexp_env_syntactic_op (sexp ctx, sexp self, sexp_sint_t n, sexp e) {
sexp sexp_env_syntactic_op (sexp ctx, sexp self, sexp_sint_t n, sexp e) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e);
return sexp_make_boolean(sexp_env_syntactic_p(e));
}
static sexp sexp_env_syntactic_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e, sexp synp) {
sexp sexp_env_syntactic_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp e, sexp synp) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, e);
sexp_env_syntactic_p(e) = sexp_truep(synp);
return SEXP_VOID;
}
static sexp sexp_env_define_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp name, sexp value) {
sexp sexp_env_define_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp name, sexp value) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, env);
sexp_assert_type(ctx, sexp_idp, SEXP_SYMBOL, name);
return sexp_env_cell_define(ctx, env, name, value, NULL);
}
static sexp sexp_env_push_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp name, sexp value) {
sexp sexp_env_push_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp name, sexp value) {
sexp_gc_var1(tmp);
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, env);
sexp_assert_type(ctx, sexp_idp, SEXP_SYMBOL, name);
@ -256,38 +314,45 @@ static sexp sexp_env_push_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp
return SEXP_VOID;
}
static sexp sexp_core_code_op (sexp ctx, sexp self, sexp_sint_t n, sexp c) {
sexp sexp_core_code_op (sexp ctx, sexp self, sexp_sint_t n, sexp c) {
sexp_assert_type(ctx, sexp_corep, SEXP_CORE, c);
return sexp_make_fixnum(sexp_core_code(c));
}
static sexp sexp_type_name_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp sexp_type_name_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
return sexp_type_name(t);
}
static sexp sexp_type_cpl_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp sexp_type_cpl_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
return sexp_type_cpl(t);
}
static sexp sexp_type_slots_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp sexp_type_slots_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
return sexp_type_slots(t);
}
static sexp sexp_type_num_slots_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp sexp_type_num_slots_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
return sexp_truep(sexp_type_slots(t)) ? sexp_length(ctx, sexp_type_slots(t))
: sexp_make_fixnum(sexp_type_field_eq_len_base(t));
}
static sexp sexp_type_printer_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp sexp_type_printer_op (sexp ctx, sexp self, sexp_sint_t n, sexp t) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
return sexp_type_print(t) ? sexp_type_print(t) : SEXP_FALSE;
}
static sexp sexp_object_size (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp sexp_type_printer_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp t, sexp p) {
sexp_assert_type(ctx, sexp_typep, SEXP_TYPE, t);
sexp_assert_type(ctx, sexp_applicablep, SEXP_PROCEDURE, p);
sexp_type_print(t) = p;
return SEXP_VOID;
}
sexp sexp_object_size (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp t;
if ((! sexp_pointerp(x)) || (sexp_pointer_tag(x) >= sexp_context_num_types(ctx)))
return SEXP_ZERO;
@ -295,15 +360,40 @@ static sexp sexp_object_size (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return sexp_make_fixnum(sexp_type_size_of_object(t, x));
}
static sexp sexp_integer_to_immediate (sexp ctx, sexp self, sexp_sint_t n, sexp i, sexp dflt) {
sexp sexp_immutablep_op (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return sexp_pointerp(x) ? sexp_make_boolean(sexp_immutablep(x)) : SEXP_TRUE;
}
sexp sexp_immutable_string_op (sexp ctx, sexp self, sexp_sint_t n, sexp s) {
sexp res;
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, s);
#if SEXP_USE_PACKED_STRINGS
/* no sharing with packed strings */
res = sexp_c_string(ctx, sexp_string_data(s), sexp_string_size(s));
#else
res = sexp_alloc_type(ctx, string, SEXP_STRING);
sexp_string_bytes(res) = sexp_string_bytes(s);
sexp_string_offset(res) = sexp_string_offset(s);
sexp_string_size(res) = sexp_string_size(s);
sexp_copy_on_writep(s) = 1;
#endif
sexp_immutablep(res) = 1;
return res;
}
sexp sexp_integer_to_immediate (sexp ctx, sexp self, sexp_sint_t n, sexp i, sexp dflt) {
sexp x = (sexp)sexp_unbox_fixnum(i);
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, i);
if (sexp_pointerp(x))
if (!x || sexp_pointerp(x))
return dflt;
return x;
}
static sexp sexp_make_lambda_op (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp params, sexp body, sexp locals) {
sexp sexp_object_to_integer (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return sexp_make_integer(ctx, (sexp_uint_t)x);
}
sexp sexp_make_lambda_op (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp params, sexp body, sexp locals) {
sexp res = sexp_alloc_type(ctx, lambda, SEXP_LAMBDA);
sexp_lambda_name(res) = name;
sexp_lambda_params(res) = params;
@ -317,7 +407,7 @@ static sexp sexp_make_lambda_op (sexp ctx, sexp self, sexp_sint_t n, sexp name,
return res;
}
static sexp sexp_copy_lambda (sexp ctx, sexp self, sexp_sint_t n, sexp lambda) {
sexp sexp_copy_lambda (sexp ctx, sexp self, sexp_sint_t n, sexp lambda) {
sexp res = sexp_alloc_type(ctx, lambda, SEXP_LAMBDA);
sexp_lambda_name(res) = sexp_lambda_name(lambda);
sexp_lambda_params(res) = sexp_lambda_params(lambda);
@ -331,21 +421,21 @@ static sexp sexp_copy_lambda (sexp ctx, sexp self, sexp_sint_t n, sexp lambda) {
return res;
}
static sexp sexp_make_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp var, sexp value) {
sexp sexp_make_set_op (sexp ctx, sexp self, sexp_sint_t n, sexp var, sexp value) {
sexp res = sexp_alloc_type(ctx, set, SEXP_SET);
sexp_set_var(res) = var;
sexp_set_value(res) = value;
return res;
}
static sexp sexp_make_ref_op (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp cell) {
sexp sexp_make_ref_op (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp cell) {
sexp res = sexp_alloc_type(ctx, ref, SEXP_REF);
sexp_ref_name(res) = name;
sexp_ref_cell(res) = cell;
return res;
}
static sexp sexp_make_cnd_op (sexp ctx, sexp self, sexp_sint_t n, sexp test, sexp pass, sexp fail) {
sexp sexp_make_cnd_op (sexp ctx, sexp self, sexp_sint_t n, sexp test, sexp pass, sexp fail) {
sexp res = sexp_alloc_type(ctx, cnd, SEXP_CND);
sexp_cnd_test(res) = test;
sexp_cnd_pass(res) = pass;
@ -353,26 +443,26 @@ static sexp sexp_make_cnd_op (sexp ctx, sexp self, sexp_sint_t n, sexp test, sex
return res;
}
static sexp sexp_make_seq (sexp ctx, sexp self, sexp_sint_t n, sexp ls) {
sexp sexp_make_seq (sexp ctx, sexp self, sexp_sint_t n, sexp ls) {
sexp res = sexp_alloc_type(ctx, seq, SEXP_SEQ);
sexp_seq_ls(res) = ls;
return res;
}
static sexp sexp_make_lit_op (sexp ctx, sexp self, sexp_sint_t n, sexp value) {
sexp sexp_make_lit_op (sexp ctx, sexp self, sexp_sint_t n, sexp value) {
sexp res = sexp_alloc_type(ctx, lit, SEXP_LIT);
sexp_lit_value(res) = value;
return res;
}
static sexp sexp_make_macro_op (sexp ctx, sexp self, sexp_sint_t n, sexp proc, sexp env) {
sexp sexp_make_macro_op (sexp ctx, sexp self, sexp_sint_t n, sexp proc, sexp env) {
sexp res = sexp_alloc_type(ctx, macro, SEXP_MACRO);
sexp_macro_proc(res) = proc;
sexp_macro_env(res) = env;
return res;
}
static sexp sexp_analyze_op (sexp ctx, sexp self, sexp_sint_t n, sexp x, sexp e) {
sexp sexp_analyze_op (sexp ctx, sexp self, sexp_sint_t n, sexp x, sexp e) {
sexp ctx2 = ctx;
if (sexp_envp(e)) {
ctx2 = sexp_make_child_context(ctx, NULL);
@ -381,12 +471,12 @@ static sexp sexp_analyze_op (sexp ctx, sexp self, sexp_sint_t n, sexp x, sexp e)
return sexp_analyze(ctx2, x);
}
static sexp sexp_extend_env_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp vars, sexp value) {
sexp sexp_extend_env_op (sexp ctx, sexp self, sexp_sint_t n, sexp env, sexp vars, sexp value) {
sexp_assert_type(ctx, sexp_envp, SEXP_ENV, env);
return sexp_extend_env(ctx, env, vars, value);
}
static sexp sexp_optimize (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp sexp_optimize (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp_gc_var2(ls, res);
sexp_gc_preserve2(ctx, ls, res);
res = x;
@ -398,7 +488,7 @@ static sexp sexp_optimize (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return res;
}
static sexp sexp_gc_op (sexp ctx, sexp self, sexp_sint_t n) {
sexp sexp_gc_op (sexp ctx, sexp self, sexp_sint_t n) {
size_t sum_freed=0;
#if SEXP_USE_BOEHM
GC_gcollect();
@ -408,20 +498,34 @@ static sexp sexp_gc_op (sexp ctx, sexp self, sexp_sint_t n) {
return sexp_make_unsigned_integer(ctx, sum_freed);
}
sexp sexp_gc_count_op (sexp ctx, sexp self, sexp_sint_t n) {
return sexp_make_unsigned_integer(ctx, sexp_context_gc_count(ctx));
}
sexp sexp_gc_usecs_op (sexp ctx, sexp self, sexp_sint_t n) {
return sexp_make_unsigned_integer(ctx, sexp_context_gc_usecs(ctx));
}
#if SEXP_USE_GREEN_THREADS
static sexp sexp_set_atomic (sexp ctx, sexp self, sexp_sint_t n, sexp new_val) {
sexp sexp_set_atomic (sexp ctx, sexp self, sexp_sint_t n, sexp new_val) {
sexp res = sexp_global(ctx, SEXP_G_ATOMIC_P);
sexp_global(ctx, SEXP_G_ATOMIC_P) = new_val;
return res;
}
#endif
sexp sexp_thread_interrupt (sexp ctx, sexp self, sexp_sint_t n, sexp thread) {
sexp_assert_type(ctx, sexp_contextp, SEXP_CONTEXT, thread);
sexp_context_interruptp(thread) = 1;
return sexp_make_boolean(ctx == thread);
}
sexp sexp_thread_list (sexp ctx, sexp self, sexp_sint_t n) {
sexp ls;
sexp_gc_var1(res);
sexp_gc_preserve1(ctx, res);
res = SEXP_NULL;
#if SEXP_USE_GREEN_THREADS
sexp ls;
for (ls=sexp_global(ctx, SEXP_G_THREADS_FRONT); sexp_pairp(ls); ls=sexp_cdr(ls))
sexp_push(ctx, res, sexp_car(ls));
for (ls=sexp_global(ctx, SEXP_G_THREADS_PAUSED); sexp_pairp(ls); ls=sexp_cdr(ls))
@ -432,15 +536,18 @@ sexp sexp_thread_list (sexp ctx, sexp self, sexp_sint_t n) {
return res;
}
static sexp sexp_string_contains (sexp ctx, sexp self, sexp_sint_t n, sexp x, sexp y) {
sexp sexp_string_contains (sexp ctx, sexp self, sexp_sint_t n, sexp x, sexp y, sexp start) {
const char *res;
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, x);
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, y);
res = strstr(sexp_string_data(x), sexp_string_data(y));
return res ? sexp_make_fixnum(res-sexp_string_data(x)) : SEXP_FALSE;
sexp_assert_type(ctx, sexp_string_cursorp, SEXP_STRING_CURSOR, start);
if (sexp_unbox_string_cursor(start) > sexp_string_size(x))
return sexp_user_exception(ctx, self, "string-contains: start out of range", start);
res = strstr(sexp_string_data(x) + sexp_unbox_string_cursor(start), sexp_string_data(y));
return res ? sexp_make_string_cursor(res-sexp_string_data(x)) : SEXP_FALSE;
}
static sexp sexp_string_cursor_copy (sexp ctx, sexp self, sexp_sint_t n, sexp dst, sexp sfrom, sexp src, sexp sstart, sexp send) {
sexp sexp_string_cursor_copy (sexp ctx, sexp self, sexp_sint_t n, sexp dst, sexp sfrom, sexp src, sexp sstart, sexp send) {
unsigned char *pfrom, *pto, *pstart, *pend, *prev, *p;
sexp_sint_t from = sexp_unbox_fixnum(sfrom), to = sexp_string_size(dst),
start = sexp_unbox_fixnum(sstart), end = sexp_unbox_fixnum(send);
@ -451,9 +558,9 @@ static sexp sexp_string_cursor_copy (sexp ctx, sexp self, sexp_sint_t n, sexp ds
sexp_assert_type(ctx, sexp_fixnump, SEXP_FIXNUM, send);
if (from < 0 || from > to)
return sexp_user_exception(ctx, self, "string-cursor-copy!: from out of range", sfrom);
if (start < 0 || start > sexp_string_size(src))
if (start < 0 || start > (sexp_sint_t)sexp_string_size(src))
return sexp_user_exception(ctx, self, "string-cursor-copy!: start out of range", sstart);
if (end < start || end > sexp_string_size(src))
if (end < start || end > (sexp_sint_t)sexp_string_size(src))
return sexp_user_exception(ctx, self, "string-cursor-copy!: end out of range", send);
pfrom = (unsigned char*)sexp_string_data(dst) + from;
pto = (unsigned char*)sexp_string_data(dst) + to;
@ -471,7 +578,7 @@ static sexp sexp_string_cursor_copy (sexp ctx, sexp self, sexp_sint_t n, sexp ds
return sexp_make_fixnum(pstart - (unsigned char*)sexp_string_data(src));
}
static sexp sexp_errno (sexp ctx, sexp self, sexp_sint_t n) {
sexp sexp_errno (sexp ctx, sexp self, sexp_sint_t n) {
#ifdef PLAN9
return SEXP_FALSE;
#else
@ -479,7 +586,7 @@ static sexp sexp_errno (sexp ctx, sexp self, sexp_sint_t n) {
#endif
}
static sexp sexp_error_string (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp sexp_error_string (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
#ifdef PLAN9
return SEXP_FALSE;
#else
@ -494,22 +601,22 @@ static sexp sexp_error_string (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
#endif
}
static sexp sexp_update_free_vars (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
sexp sexp_update_free_vars (sexp ctx, sexp self, sexp_sint_t n, sexp x) {
return sexp_free_vars(ctx, x, SEXP_NULL);
}
static sexp sexp_setenv (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp value) {
sexp sexp_setenv (sexp ctx, sexp self, sexp_sint_t n, sexp name, sexp value) {
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, name);
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, value);
return sexp_make_boolean(setenv(sexp_string_data(name), sexp_string_data(value), 1));
}
static sexp sexp_unsetenv (sexp ctx, sexp self, sexp_sint_t n, sexp name) {
sexp sexp_unsetenv (sexp ctx, sexp self, sexp_sint_t n, sexp name) {
sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, name);
return sexp_make_boolean(unsetenv(sexp_string_data(name)));
}
static sexp sexp_abort (sexp ctx, sexp self, sexp_sint_t n, sexp value) {
sexp sexp_abort (sexp ctx, sexp self, sexp_sint_t n, sexp value) {
sexp res = sexp_make_trampoline(ctx, SEXP_FALSE, value);
sexp_exception_message(res) = SEXP_TRAMPOLINE;
return res;
@ -519,6 +626,7 @@ static sexp sexp_abort (sexp ctx, sexp self, sexp_sint_t n, sexp value) {
sexp_env_define(ctx, env, sexp_intern(ctx, name, -1), sexp_type_by_index(ctx, tag));
sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char* version, const sexp_abi_identifier_t abi) {
sexp_gc_var2(sym, str);
if (!(sexp_version_compatible(ctx, version, sexp_version)
&& sexp_abi_compatible(ctx, abi, SEXP_ABI_IDENTIFIER)))
return SEXP_ABI_ERROR;
@ -551,6 +659,7 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_type(ctx, "Lam", SEXP_LAMBDA);
sexp_define_type(ctx, "Cnd", SEXP_CND);
sexp_define_type(ctx, "Set", SEXP_SET);
sexp_define_type(ctx, "Set-Syn", SEXP_SET_SYN);
sexp_define_type(ctx, "Ref", SEXP_REF);
sexp_define_type(ctx, "Seq", SEXP_SEQ);
sexp_define_type(ctx, "Lit", SEXP_LIT);
@ -568,7 +677,6 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_type_predicate(ctx, env, "ref?", SEXP_REF);
sexp_define_type_predicate(ctx, env, "seq?", SEXP_SEQ);
sexp_define_type_predicate(ctx, env, "lit?", SEXP_LIT);
sexp_define_type_predicate(ctx, env, "opcode?", SEXP_OPCODE);
sexp_define_type_predicate(ctx, env, "type?", SEXP_TYPE);
sexp_define_type_predicate(ctx, env, "core?", SEXP_CORE);
sexp_define_type_predicate(ctx, env, "context?", SEXP_CONTEXT);
@ -592,22 +700,28 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_accessors(ctx, env, SEXP_CND, 2, "cnd-fail", "cnd-fail-set!");
sexp_define_accessors(ctx, env, SEXP_SET, 0, "set-var", "set-var-set!");
sexp_define_accessors(ctx, env, SEXP_SET, 1, "set-value", "set-value-set!");
sexp_define_accessors(ctx, env, SEXP_SET, 2, "set-source", "set-source-set!");
sexp_define_accessors(ctx, env, SEXP_REF, 0, "ref-name", "ref-name-set!");
sexp_define_accessors(ctx, env, SEXP_REF, 1, "ref-cell", "ref-cell-set!");
sexp_define_accessors(ctx, env, SEXP_SEQ, 0, "seq-ls", "seq-ls-set!");
sexp_define_accessors(ctx, env, SEXP_LIT, 0, "lit-value", "lit-value-set!");
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 2, "bytecode-name", "bytecode-name-set!");
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 3, "bytecode-literals", NULL);
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 4, "bytecode-source", NULL);
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 0, "bytecode-name", "bytecode-name-set!");
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 1, "bytecode-literals", NULL);
sexp_define_accessors(ctx, env, SEXP_BYTECODE, 2, "bytecode-source", NULL);
sexp_define_accessors(ctx, env, SEXP_EXCEPTION, 1, "exception-message", NULL);
sexp_define_accessors(ctx, env, SEXP_EXCEPTION, 4, "exception-source", NULL);
sexp_define_accessors(ctx, env, SEXP_MACRO, 0, "macro-procedure", NULL);
sexp_define_accessors(ctx, env, SEXP_MACRO, 1, "macro-env", NULL);
sexp_define_accessors(ctx, env, SEXP_MACRO, 2, "macro-source", NULL);
sexp_define_accessors(ctx, env, SEXP_MACRO, 3, "macro-aux", "macro-aux-set!");
sexp_define_foreign(ctx, env, "make-procedure", 4, sexp_make_procedure_op);
sexp_define_foreign(ctx, env, "procedure-code", 1, sexp_get_procedure_code);
sexp_define_foreign(ctx, env, "procedure-vars", 1, sexp_get_procedure_vars);
sexp_define_foreign(ctx, env, "procedure-arity", 1, sexp_get_procedure_arity);
sexp_define_foreign(ctx, env, "procedure-variadic?", 1, sexp_get_procedure_variadic_p);
sexp_define_foreign(ctx, env, "procedure-variable-transformer?", 1, sexp_get_procedure_variable_transformer_p);
sexp_define_foreign(ctx, env, "procedure-flags", 1, sexp_get_procedure_flags);
sexp_define_foreign(ctx, env, "make-variable-transformer", 1, sexp_make_variable_transformer_op);
sexp_define_foreign(ctx, env, "copy-lambda", 1, sexp_copy_lambda);
sexp_define_foreign_opt(ctx, env, "make-lambda", 4, sexp_make_lambda_op, SEXP_NULL);
sexp_define_foreign_opt(ctx, env, "make-cnd", 3, sexp_make_cnd_op, SEXP_VOID);
@ -630,12 +744,15 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_foreign(ctx, env, "opcode-param-type", 2, sexp_get_opcode_param_type);
sexp_define_foreign(ctx, env, "port-line", 1, sexp_get_port_line);
sexp_define_foreign(ctx, env, "port-line-set!", 2, sexp_set_port_line);
sexp_define_foreign(ctx, env, "port-source?", 1, sexp_get_port_sourcep);
sexp_define_foreign(ctx, env, "port-source?-set!", 2, sexp_set_port_sourcep);
sexp_define_foreign(ctx, env, "type-of", 1, sexp_type_of);
sexp_define_foreign(ctx, env, "type-name", 1, sexp_type_name_op);
sexp_define_foreign(ctx, env, "type-cpl", 1, sexp_type_cpl_op);
sexp_define_foreign(ctx, env, "type-slots", 1, sexp_type_slots_op);
sexp_define_foreign(ctx, env, "type-num-slots", 1, sexp_type_num_slots_op);
sexp_define_foreign(ctx, env, "type-printer", 1, sexp_type_printer_op);
sexp_define_foreign(ctx, env, "type-printer-set!", 2, sexp_type_printer_set_op);
sexp_define_foreign(ctx, env, "env-parent-set!", 2, sexp_env_parent_set_op);
sexp_define_foreign(ctx, env, "env-lambda", 1, sexp_env_lambda_op);
sexp_define_foreign(ctx, env, "env-lambda-set!", 2, sexp_env_lambda_set_op);
@ -645,13 +762,19 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_foreign(ctx, env, "env-push!", 3, sexp_env_push_op);
sexp_define_foreign(ctx, env, "core-code", 1, sexp_core_code_op);
sexp_define_foreign(ctx, env, "object-size", 1, sexp_object_size);
sexp_define_foreign(ctx, env, "immutable?", 1, sexp_immutablep_op);
sexp_define_foreign(ctx, env, "immutable-string", 1, sexp_immutable_string_op);
sexp_define_foreign_opt(ctx, env, "integer->immediate", 2, sexp_integer_to_immediate, SEXP_FALSE);
sexp_define_foreign_opt(ctx, env, "object->integer", 1, sexp_object_to_integer, SEXP_FALSE);
sexp_define_foreign(ctx, env, "gc", 0, sexp_gc_op);
sexp_define_foreign(ctx, env, "gc-count", 0, sexp_gc_count_op);
sexp_define_foreign(ctx, env, "gc-usecs", 0, sexp_gc_usecs_op);
#if SEXP_USE_GREEN_THREADS
sexp_define_foreign(ctx, env, "%set-atomic!", 1, sexp_set_atomic);
#endif
sexp_define_foreign(ctx, env, "%thread-interrupt!", 1, sexp_thread_interrupt);
sexp_define_foreign(ctx, env, "thread-list", 0, sexp_thread_list);
sexp_define_foreign(ctx, env, "string-contains", 2, sexp_string_contains);
sexp_define_foreign_opt(ctx, env, "string-contains", 3, sexp_string_contains, sexp_make_string_cursor(0));
sexp_define_foreign(ctx, env, "string-cursor-copy!", 5, sexp_string_cursor_copy);
sexp_define_foreign(ctx, env, "errno", 0, sexp_errno);
sexp_define_foreign_opt(ctx, env, "integer->error-string", 1, sexp_error_string, SEXP_FALSE);
@ -659,5 +782,11 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char
sexp_define_foreign(ctx, env, "setenv", 2, sexp_setenv);
sexp_define_foreign(ctx, env, "unsetenv", 1, sexp_unsetenv);
sexp_define_foreign(ctx, env, "abort", 1, sexp_abort);
sexp_gc_preserve2(ctx, sym, str);
sym = sexp_intern(ctx, "chibi-version", -1);
str = sexp_c_string(ctx, sexp_version, -1);
sexp_immutablep(str) = 1;
sexp_env_define(ctx, env, sym, str);
sexp_gc_release2(ctx);
return SEXP_VOID;
}

View file

@ -109,6 +109,34 @@
((opcode? x) (cond ((opcode-name x) => string->symbol) (else x)))
(else x)))))
;;> \section{Identifier Macros}
;;> \procedure{(make-variable-transformer proc)}
;;> Returns a new procedure wrapping the input procedure \var{proc}.
;;> The returned procedure, if used as a macro transformer procedure,
;;> can expand an instance of \scheme{set!} with its keyword on the
;;> left hand side.
;;> \macro{(identifier-syntax clauses ...)}
;;> A high-level form for creating identifier macros. See
;;> \hyperlink["http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_idx_796"]{the R6RS specification.}
(define-syntax identifier-syntax
(syntax-rules (set!)
((_ template)
(syntax-rules ()
((_ xs (... ...))
(template xs (... ...)))
(x template)))
((_ (id_1 template_1) ((set! id_2 pattern) template_2))
(make-variable-transformer
(syntax-rules (set!)
((set! id_2 pattern) template_2)
((id_1 xs (... ...)) (template_1 xs (... ...)))
(id_1 template_1))))))
;;> \section{Types}
;;> All objects have an associated type, and types may have parent
@ -121,32 +149,32 @@
;;> used in the \scheme{match} \scheme{($ ...)} syntax.
;;> \itemlist[
;;> \item{\scheme{<object>} - the parent of all types}
;;> \item{\scheme{<number>} - abstract numeric type}
;;> \item{\scheme{<bignum>} - arbitrary precision exact integers}
;;> \item{\scheme{<flonum>} - inexact real numbers}
;;> \item{\scheme{<integer>} - abstract integer type}
;;> \item{\scheme{<symbol>} - symbols}
;;> \item{\scheme{<char>} - character}
;;> \item{\scheme{<boolean>} - \scheme{#t} or \scheme{#f}}
;;> \item{\scheme{<string>} - strings of characters}
;;> \item{\scheme{<byte-vector>} - uniform vector of octets}
;;> \item{\scheme{<pair>} - a \var{car} and \var{cdr}, the basis for lists}
;;> \item{\scheme{<vector>} - vectors}
;;> \item{\scheme{<opcode>} - a primitive opcode or C function}
;;> \item{\scheme{<procedure>} - a closure}
;;> \item{\scheme{<bytecode>} - the compiled code for a closure}
;;> \item{\scheme{<env>} - an environment structure}
;;> \item{\scheme{<macro>} - a macro object, usually not first-class}
;;> \item{\scheme{<lam>} - a lambda AST type}
;;> \item{\scheme{<cnd>} - an conditional AST type (i.e. \scheme{if})}
;;> \item{\scheme{<ref>} - a reference AST type}
;;> \item{\scheme{<set>} - a mutation AST type (i.e. \scheme{set!})}
;;> \item{\scheme{<seq>} - a sequence AST type}
;;> \item{\scheme{<lit>} - a literal AST type}
;;> \item{\scheme{<sc>} - a syntactic closure}
;;> \item{\scheme{<context>} - a context object (including threads)}
;;> \item{\scheme{<exception>} - an exception object}
;;> \item{\scheme{Object} - the parent of all types}
;;> \item{\scheme{Number} - abstract numeric type}
;;> \item{\scheme{Bignum} - arbitrary precision exact integers}
;;> \item{\scheme{Flonum} - inexact real numbers}
;;> \item{\scheme{Integer} - abstract integer type}
;;> \item{\scheme{Symbol} - symbols}
;;> \item{\scheme{Char} - character}
;;> \item{\scheme{Boolean} - \scheme{#t} or \scheme{#f}}
;;> \item{\scheme{String} - strings of characters}
;;> \item{\scheme{Byte-Vector} - uniform vector of octets}
;;> \item{\scheme{Pair} - a \var{car} and \var{cdr}, the basis for lists}
;;> \item{\scheme{Vector} - vectors}
;;> \item{\scheme{Opcode} - a primitive opcode or C function}
;;> \item{\scheme{Procedure} - a closure}
;;> \item{\scheme{Bytecode} - the compiled code for a closure}
;;> \item{\scheme{Env} - an environment structure}
;;> \item{\scheme{Macro} - a macro object, usually not first-class}
;;> \item{\scheme{Lam} - a lambda AST type}
;;> \item{\scheme{Cnd} - an conditional AST type (i.e. \scheme{if})}
;;> \item{\scheme{Ref} - a reference AST type}
;;> \item{\scheme{Set} - a mutation AST type (i.e. \scheme{set!})}
;;> \item{\scheme{Seq} - a sequence AST type}
;;> \item{\scheme{Lit} - a literal AST type}
;;> \item{\scheme{Sc} - a syntactic closure}
;;> \item{\scheme{Context} - a context object (including threads)}
;;> \item{\scheme{Exception} - an exception object}
;;> ]
;;> The following extended type predicates may also be used to test
@ -222,6 +250,8 @@
;;> \item{\scheme{(macro-procedure f)} - the macro procedure}
;;> \item{\scheme{(macro-env f)} - the environment the macro was defined in}
;;> \item{\scheme{(macro-source f)} - the source location the macro was defined in}
;;> \item{\scheme{(macro-aux f)} - custom auxiliary data stored with the macro}
;;> \item{\scheme{(macro-aux-set! f x)}}
;;> ]
;;> \subsection{Bytecode Objects}
@ -351,11 +381,29 @@
;;> Returns the interpretation of the integer \var{n} as
;;> an immediate object, useful for debugging.
;;> \procedure{(string-contains str pat)}
;;> \procedure{(string-contains str pat [start])}
;;> Returns the first string cursor of \var{pat} in \var{str},
;;> of \scheme{#f} if it's not found.
(cond-expand
(safe-string-cursors
(define orig-string-contains string-contains)
(set! string-contains
(lambda (str pat . o)
(let ((res
(if (pair? o)
(orig-string-contains str pat (string-cursor-where (car o)))
(orig-string-contains str pat))))
(and res (make-string-cursor str res (string-size str)))))))
(else
))
;;> \procedure{(string-cursor-copy! dst src from start end)}
;;> Copies the characters from \var{src}[\var{start}..\var{end}]
;;> to \var{dst} starting at \var{from}.
;;> \procedure{(safe-setenv name value)}
;;> Equivalent to \scheme{setenv} but does nothing and returns
@ -388,3 +436,7 @@
(else
(define-syntax atomically
(syntax-rules () ((atomically . body) (begin . body))))))
(define (thread-interrupt! thread)
(if (%thread-interrupt! thread)
(yield!)))

View file

@ -1,11 +1,12 @@
(define-library (chibi ast)
(export
analyze optimize env-cell ast->sexp macroexpand type-of
analyze optimize env-cell ast->sexp macroexpand identifier-syntax
type-of
Object Input-Port Output-Port Opcode Procedure Bytecode Macro Env
Number Bignum Flonum Integer Complex Char Boolean
Symbol String Byte-Vector Vector Pair File-Descriptor
Context Lam Cnd Set Ref Seq Lit Sc Exception Core
Context Lam Cnd Set Set-Syn Ref Seq Lit Sc Exception Core
syntactic-closure? lambda? cnd? set? ref? seq? lit? type? core?
environment? bytecode? exception? macro? context? file-descriptor?
syntactic-closure-expr syntactic-closure-env syntactic-closure-vars
@ -20,23 +21,29 @@
lambda-source-set!
cnd-test cnd-pass cnd-fail
cnd-test-set! cnd-pass-set! cnd-fail-set!
set-var set-value set-var-set! set-value-set!
set-var set-value set-var-set! set-value-set! set-source set-source-set!
ref-name ref-cell ref-name-set! ref-cell-set!
seq-ls seq-ls-set! lit-value lit-value-set!
exception-kind exception-message exception-irritants exception-source
opcode-name opcode-num-params opcode-return-type opcode-param-type
opcode-class opcode-code opcode-data opcode-variadic?
macro-procedure macro-env macro-source
opcode-class opcode-code opcode-data opcode-variadic? opcode?
macro-procedure macro-env macro-source macro-aux macro-aux-set!
procedure-code procedure-vars procedure-name procedure-name-set!
procedure-arity procedure-variadic?
procedure-arity procedure-variadic? procedure-variable-transformer?
procedure-flags make-variable-transformer make-procedure procedure?
bytecode-name bytecode-literals bytecode-source
port-line port-line-set!
port-line port-line-set! port-source? port-source?-set!
extend-env env-parent env-parent-set! env-lambda env-lambda-set!
env-define! env-push! env-syntactic? env-syntactic?-set! core-code
type-name type-cpl type-parent type-slots type-num-slots type-printer
object-size integer->immediate gc atomically thread-list abort
type-name type-cpl type-parent type-slots type-num-slots
type-printer type-printer-set!
object-size object->integer integer->immediate gc gc-usecs gc-count
atomically thread-list abort
string-contains string-cursor-copy! errno integer->error-string
flatten-dot update-free-vars! setenv unsetenv safe-setenv)
flatten-dot update-free-vars! setenv unsetenv safe-setenv
immutable? immutable-string make-immutable!
thread-interrupt!
chibi-version)
(import (chibi))
(include-shared "ast")
(include "ast.scm"))

View file

@ -1,6 +1,6 @@
(define-library (chibi base64-test)
(export run-tests)
(import (chibi) (chibi base64) (chibi test))
(import (scheme base) (chibi base64) (chibi string) (chibi test))
(begin
(define (run-tests)
(test-begin "base64")

View file

@ -141,18 +141,18 @@
dst
j
(bitwise-ior (arithmetic-shift b1 2)
(extract-bit-field 2 4 b2)))
(bit-field b2 4 6)))
(bytevector-u8-set!
dst
(+ j 1)
(bitwise-ior
(arithmetic-shift (extract-bit-field 4 0 b2) 4)
(extract-bit-field 4 2 b3)))
(arithmetic-shift (bit-field b2 0 4) 4)
(bit-field b3 2 6)))
(bytevector-u8-set!
dst
(+ j 2)
(bitwise-ior
(arithmetic-shift (extract-bit-field 2 0 b3) 6)
(arithmetic-shift (bit-field b3 0 2) 6)
c))
(lp (+ i 1) (+ j 3)
*outside-char* *outside-char* *outside-char*)))))))
@ -172,7 +172,7 @@
(bytevector-u8-set! dst
j
(bitwise-ior (arithmetic-shift b1 2)
(extract-bit-field 2 4 b2)))
(bit-field b2 4 6)))
(cond
((eqv? b3 *outside-char*)
(+ j 1))
@ -180,8 +180,8 @@
(bytevector-u8-set! dst
(+ j 1)
(bitwise-ior
(arithmetic-shift (extract-bit-field 4 0 b2) 4)
(extract-bit-field 4 2 b3)))
(arithmetic-shift (bit-field b2 0 4) 4)
(bit-field b3 2 6)))
(+ j 2))))))
;;> Variation of the above to read and write to ports.
@ -193,14 +193,15 @@
(current-output-port))))
(cond
((not (binary-port? in))
(write-string (base64-decode-string (port->string in)) out))
(let ((str (port->string in)))
(write-string (base64-decode-string str) out)))
(else
(let ((src (make-bytevector decode-src-length))
(dst (make-bytevector decode-dst-length)))
(let lp ((offset 0))
(let ((src-len
(+ offset
(read-bytevector! decode-src-length src in offset))))
(read-bytevector! src in offset decode-src-length))))
(cond
((= src-len decode-src-length)
;; read a full chunk: decode, write and loop
@ -209,12 +210,12 @@
(lambda (src-offset dst-len b1 b2 b3)
(cond
((and (< src-offset src-len)
(eqv? #\= (string-ref src src-offset)))
(eqv? #x3D (bytevector-u8-ref src src-offset)))
;; done
(let ((dst-len (base64-decode-finish dst dst-len b1 b2 b3)))
(write-bytevector dst out 0 dst-len)))
((eqv? b1 *outside-char*)
(write-string dst out 0 dst-len)
(write-bytevector dst out 0 dst-len)
(lp 0))
(else
(write-bytevector dst out 0 dst-len)
@ -237,7 +238,7 @@
src 0 src-len dst
(lambda (src-offset dst-len b1 b2 b3)
(let ((dst-len (base64-decode-finish dst dst-len b1 b2 b3)))
(write-string dst out 0 dst-len)))))))))))))
(write-bytevector dst out 0 dst-len)))))))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; encoding
@ -258,8 +259,7 @@
res))
(define (base64-encode-bytevector! bv start end res)
(let* ((res-len (bytevector-length res))
(limit (- end 2)))
(let ((limit (- end 2)))
(let lp ((i start) (j 0))
(if (>= i limit)
(case (- end i)
@ -271,7 +271,8 @@
(+ j 1)
(enc (arithmetic-shift (bitwise-and #b11 b1) 4)))
(bytevector-u8-set! res (+ j 2) (char->integer #\=))
(bytevector-u8-set! res (+ j 3) (char->integer #\=))))
(bytevector-u8-set! res (+ j 3) (char->integer #\=))
(+ j 4)))
((2)
(let ((b1 (bytevector-u8-ref bv i))
(b2 (bytevector-u8-ref bv (+ i 1))))
@ -281,13 +282,15 @@
(+ j 1)
(enc (bitwise-ior
(arithmetic-shift (bitwise-and #b11 b1) 4)
(extract-bit-field 4 4 b2))))
(bit-field b2 4 8))))
(bytevector-u8-set!
res
(+ j 2)
(enc (arithmetic-shift (extract-bit-field 4 0 b2)
2)))
(bytevector-u8-set! res (+ j 3) (char->integer #\=)))))
(enc (arithmetic-shift (bit-field b2 0 4) 2)))
(bytevector-u8-set! res (+ j 3) (char->integer #\=))
(+ j 4)))
(else
j))
(let ((b1 (bytevector-u8-ref bv i))
(b2 (bytevector-u8-ref bv (+ i 1)))
(b3 (bytevector-u8-ref bv (+ i 2))))
@ -297,13 +300,13 @@
(+ j 1)
(enc (bitwise-ior
(arithmetic-shift (bitwise-and #b11 b1) 4)
(extract-bit-field 4 4 b2))))
(bit-field b2 4 8))))
(bytevector-u8-set!
res
(+ j 2)
(enc (bitwise-ior
(arithmetic-shift (extract-bit-field 4 0 b2) 2)
(extract-bit-field 2 6 b3))))
(arithmetic-shift (bit-field b2 0 4) 2)
(bit-field b3 6 8))))
(bytevector-u8-set! res (+ j 3) (enc (bitwise-and #b111111 b3)))
(lp (+ i 3) (+ j 4)))))))
@ -316,17 +319,19 @@
(current-output-port))))
(cond
((not (binary-port? in))
(write-string (base64-encode-string (port->string in)) out))
(let ((str (port->string in)))
(write-string (base64-encode-string str) out)))
(else
(let ((src (make-string encode-src-length))
(dst (make-string
(let ((src (make-bytevector encode-src-length))
(dst (make-bytevector
(arithmetic-shift (quotient encode-src-length 3) 2))))
(let lp ()
(let ((n (read-bytevector! src in 0 2048)))
(base64-encode-bytevector! src 0 n dst)
(write-bytevector dst out 0 (* 3 (quotient (+ n 3) 4)))
(write-bytevector dst out 0 (* 4 (quotient (+ n 2) 3)))
(if (= n 2048)
(lp)))))))))
(lp)
(flush-output-port out)))))))))
;;> Return a base64 encoded representation of the string \var{str} as
;;> above, wrapped in =?ENC?B?...?= as per RFC1522, split across
@ -359,7 +364,7 @@
(string-append
prefix (substring str 0 first-max-col) "?=" nl "\t" prefix)
"")
(string-concatenate (string-chop (substring str first-max-col len)
(string-join (string-chop (substring str first-max-col len)
effective-max-col)
(string-append "?=" nl "\t" prefix))
"?=")))))

View file

@ -3,6 +3,35 @@
(export base64-encode base64-encode-string base64-encode-bytevector
base64-decode base64-decode-string base64-decode-bytevector
base64-encode-header)
(import (scheme base) (srfi 33) (chibi io)
(only (chibi) string-concatenate))
(import (scheme base)
(chibi string))
(cond-expand
((library (srfi 151))
(import (srfi 151)))
((library (srfi 33))
(import (srfi 33))
(begin
(define (%mask size) (bitwise-not (arithmetic-shift -1 size)))
(define (bit-field n start end)
(bitwise-and (arithmetic-shift n (- start)) (mask (- end start))))))
(else
(import (srfi 60))
(begin
(define (%mask size) (bitwise-not (arithmetic-shift -1 size)))
(define (bit-field n start end)
(bitwise-and (arithmetic-shift n (- start)) (mask (- end start)))))))
(cond-expand
(chibi (import (chibi io)))
(else
(begin
(define (port->string in)
(let ((out (open-output-string)))
(let lp ()
(let ((ch (read-char in)))
(cond
((eof-object? ch)
(get-output-string out))
(else
(write-char ch out)
(lp))))))))))
(include "base64.scm"))

View file

@ -0,0 +1,52 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; binary records, simpler version with type-checking on set! removed
(define-syntax defrec
(syntax-rules (make: pred: read: write: block:)
((defrec () n m p r w
((field-tmp field-read field-read-expr field-write field-write-expr field-get) ...)
((field getter . s) ...))
(begin
(define-record-type n (m field ...) p
(field getter . s) ...)
(define n 'n) ; chicken define-record-type doesn't define the rtd
(define r
(let ((field-read field-read-expr) ...)
(lambda (in)
(let* ((field-tmp (field-read in)) ...)
(m field ...)))))
(define w
(let ((field-write field-write-expr) ...)
(lambda (x out)
(field-write (field-get x) out) ...)))))
((defrec ((make: x) . rest) n m p r w b f)
(defrec rest n x p r w b f))
((defrec ((pred: x) . rest) n m p r w b f)
(defrec rest n m x r w b f))
((defrec ((read: x) . rest) n m p r w b f)
(defrec rest n m p x w b f))
((defrec ((write: x) . rest) n m p r w b f)
(defrec rest n m p r x b f))
((defrec ((block: (field (type . args) getter . s) . fields) . rest) n m p r w
(b ...) (f ...))
(defrec ((block: . fields) . rest) n m p r w
(b ...
(field read-tmp (type read: args) write-tmp (type write: args) getter))
(f ...
(field getter . s))))
((defrec ((block: (field . x)) . rest) n m p r w b f)
(syntax-error "invalid field in block" (field . x)))
((defrec ((block: data . fields) . rest) n m p r w (b ...) f)
(defrec ((block: . fields) . rest) n m p r w
(b ...
(tmp-data read-tmp (read-literal 'data) write-tmp (write-literal 'data) (lambda (x) x)))
f))
((defrec ((block:) . rest) n m p r w b f)
(defrec rest n m p r w b f))
))
(define-syntax define-binary-record-type
(syntax-rules ()
((define-binary-record-type name x ...)
(defrec (x ...) name hidden-make hidden-pred hidden-read hidden-write
() ()))))

View file

@ -0,0 +1,31 @@
(define-library (chibi binary-record-test)
(export run-tests)
(import (scheme base) (chibi binary-record) (chibi test))
(begin
(define-binary-record-type gif-header
(make: make-gif-header)
(pred: gif-header?)
(read: read-gif-header)
(write: write-gif-header)
(block:
"GIF89a"
(width (u16/le) gif-header-width)
(height (u16/le) gif-header-height)
(gct (u8) gif-header-gct)
(bgcolor (u8) gif-header-gbcolor)
(aspect-ratio (u8) gif-header-aspect-ratio)
))
(define (gif->bytevector gif)
(let ((out (open-output-bytevector)))
(write-gif-header gif out)
(get-output-bytevector out)))
(define (bytevector->gif bv)
(read-gif-header (open-input-bytevector bv)))
(define (run-tests)
(test-begin "(chibi binary-record)")
(let ((gif (make-gif-header 4096 2160 #xF7 1 2)))
(test #u8(#x47 #x49 #x46 #x38 #x39 #x61 0 #x10 #x70 #x08 #xF7 #x01 #x02)
(gif->bytevector gif))
(test gif (bytevector->gif (gif->bytevector gif))))
(test-end))))

View file

@ -1,300 +1,160 @@
(define (read-u16/be in)
(let* ((i (read-u8 in))
(j (read-u8 in)))
(if (eof-object? j)
(error "end of input")
(+ (arithmetic-shift i 8) j))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Binary Records
(define (read-u16/le in)
(let* ((i (read-u8 in))
(j (read-u8 in)))
(if (eof-object? j)
(error "end of input")
(+ (arithmetic-shift j 8) i))))
;; Record types with user-specified binary formats.
;; A work in progress, but sufficient for tar files.
(define (assert-read-u8 in i)
(let ((i2 (read-u8 in)))
(if (not (eqv? i i2))
(error "unexpected value: " i i2)
i2)))
(define (assert-read-char in ch)
(let ((ch2 (read-char in)))
(if (not (eqv? ch ch2))
(error "unexpected value: " ch ch2)
ch2)))
(define (assert-read-string in s)
(let ((s2 (read-string (string-length s) in)))
(if (not (equal? s s2))
(error "unexpected value: " s s2)
s2)))
(define (assert-read-bytevector in bv)
(let ((bv2 (read-bytevector (bytevector-length bv) in)))
(if (not (equal? bv bv2))
(error "unexpected value: " bv bv2)
bv2)))
(define (assert-read-integer in len radix)
(let* ((s (string-trim (read-string len in)
(lambda (ch) (or (eqv? ch #\space) (eqv? ch #\null)))))
(n (if (equal? s "") 0 (string->number s radix))))
(or n (error "invalid number syntax: " s))))
(define (read-padded-string in len pad)
(string-trim-right (read-string len in) pad))
(define (expand-read rename in spec)
(case (car spec)
((literal)
(let ((val (cadr spec)))
(cond ((integer? val) `(,(rename 'assert-read-u8) ,in ,val))
((char? val) `(,(rename 'assert-read-char) ,in ,val))
((string? val) `(,(rename 'assert-read-string) ,in ,val))
((bytevector? val) `(,(rename 'assert-read-bytevector) ,in ,val))
(else (error "unknown binary literal: " val)))))
((u8)
`(,(rename 'read-u8) ,in))
((u16/be)
`(,(rename 'read-u16/be) ,in))
((u16/le)
`(,(rename 'read-u16/le) ,in))
((octal)
`(,(rename 'assert-read-integer) ,in ,(cadr spec) 8))
((decimal)
`(,(rename 'assert-read-integer) ,in ,(cadr spec) 10))
((hexadecimal)
`(,(rename 'assert-read-integer) ,in ,(cadr spec) 16))
((fixed-string)
(let ((len (cadr spec)))
`(,(rename 'read-string) ,len ,in)))
((padded-string)
(let ((len (cadr spec))
(pad (if (pair? (cddr spec)) (car (cddr spec)) #\null)))
`(,(rename 'read-padded-string) ,in ,len ,pad)))
(else
(error "unknown binary format: " spec))))
(define (string-pad-left str len . o)
(let ((diff (- len (string-length str)))
(pad-ch (if (pair? o) (car o) #\space)))
(if (positive? diff)
(string-append (make-string diff pad-ch) str)
str)))
(define (string-pad-right str len . o)
(let ((diff (- len (string-length str)))
(pad-ch (if (pair? o) (car o) #\space)))
(if (positive? diff)
(string-append str (make-string diff pad-ch))
str)))
(define (write-padded-integer out n radix len left-pad-ch right-pad-ch)
(let ((s (string-pad-left (number->string n radix) (- len 1) left-pad-ch)))
(cond
((>= (string-length s) len)
(error "number too large for width" n radix len))
(else
(write-string s out)
(write-char right-pad-ch out)))))
(define (write-u16/be n out)
(write-u8 (arithmetic-shift n -8) out)
(write-u8 (bitwise-and n #xFF) out))
(define (write-u16/le n out)
(write-u8 (bitwise-and n #xFF) out)
(write-u8 (arithmetic-shift n -8) out))
(define (expand-write rename out val spec)
(let ((_if (rename 'if))
(_not (rename 'not))
(_let (rename 'let))
(_string-length (rename 'string-length))
(_write-string (rename 'write-string))
(_write-bytevector (rename 'write-bytevector))
(_error (rename 'error))
(_> (rename '>))
(_= (rename '=)))
(case (car spec)
((literal)
(let ((val (cadr spec)))
(cond ((integer? val) `(,(rename 'write-u8) ,val ,out))
((char? val) `(,(rename 'write-char) ,val ,out))
((string? val) `(,_write-string ,val ,out))
((bytevector? val) `(,_write-bytevector ,val ,out))
(else (error "unknown binary literal: " val)))))
((u8)
`(,(rename 'write-u8) ,val ,out))
((u16/be)
`(,(rename 'write-u16/be) ,val ,out))
((u16/le)
`(,(rename 'write-u16/le) ,val ,out))
((octal)
`(,(rename 'write-padded-integer) ,out ,val 8 ,(cadr spec) #\0 #\null))
((decimal)
`(,(rename 'write-padded-integer) ,out ,val 10 ,(cadr spec) #\0 #\null))
((hexadecimal)
`(,(rename 'write-padded-integer) ,out ,val 16 ,(cadr spec) #\0 #\null))
((fixed-string)
(let ((len (cadr spec)))
`(,_if (,_not (,_= ,len (,_string-length ,val)))
(,_error "wrong field length: " ,val ,len)
(,_write-string ,val ,out))))
((padded-string)
(let ((len (cadr spec))
(pad (if (pair? (cddr spec)) (car (cddr spec)) #\null)))
`(,_let ((l (,_string-length ,val)))
(,_if (,_> l ,len)
(,_error "field too large: " ,val ,len)
(,_write-string (,(rename 'string-pad-right) ,val ,len ,pad)
,out)))))
(else
(error "unknown binary format: " spec)))))
(define (expand-assert rename spec x v)
(let ((_if (rename 'if))
(_not (rename 'not))
(_error (rename 'error))
(_integer? (rename 'integer?))
(_string? (rename 'string?))
(_string-length (rename 'string-length))
(_> (rename '>)))
(case (car spec)
((literal) #t)
((u8 u16/be u16/le octal decimal hexadecimal)
`(,_if (,_not (,_integer? ,v))
(,_error "expected an integer" ,v)))
((fixed-string padded-string)
(let ((len (cadr spec)))
`(,_if (,_not (,_string? ,v))
(,_error "expected a string" ,v)
(,_if (,_> (,_string-length ,v) ,len)
(,_error "string too long" ,v ,len)))))
(else (error "unknown binary format: " spec)))))
(define (expand-default rename spec)
(case (car spec)
((literal) (cadr spec))
((u8 u16/be u16/le octal decimal hexadecimal) 0)
((fixed-string) (make-string (cadr spec) #\space))
((padded-string) "")
(else (error "unknown binary format: " spec))))
(define (param-ref ls key . o)
(cond ((assq key ls) => cadr) ((pair? o) (car o)) (else #f)))
(define (symbol-append a b)
(string->symbol (string-append (symbol->string a) (symbol->string b))))
(define-record-type Field
(make-field name get set raw-set spec)
field?
(name field-name)
(get field-get)
(set field-set)
(raw-set field-raw-set)
(spec field-spec))
(define (extract-fields type ls)
(let lp ((ls ls) (res '()))
(cond
((null? ls)
(reverse res))
((not (pair? (car ls)))
(lp (cdr ls) (cons (make-field '_ #f #f #f `(literal ,(car ls))) res)))
(else
(let* ((name (caar ls))
(get (or (param-ref (car ls) 'getter)
(and (not (eq? name '_))
(symbol-append type (symbol-append '- name)))))
(set (or (param-ref (car ls) 'setter)
(and (not (eq? name '_))
(symbol-append (symbol-append type '-)
(symbol-append name '-set!)))))
(raw-set (and set (symbol-append '% set)))
(spec0 (cadr (car ls)))
(spec (if (pair? spec0) spec0 (list spec0))))
(lp (cdr ls) (cons (make-field name get set raw-set spec) res)))))))
;;> \macro{(define-binary-record-type <name> [<bindings> ...] (block: <fields> ...))}
;;>
;;> Defines a new record type that supports serializing to and from
;;> binary ports. The generated procedures accept keyword-style
;;> arguments:
;;>
;;> \itemlist[
;;> \item{\scheme{(make: <constructor-name>)}}
;;> \item{\scheme{(pred: <predicate-name>)}}
;;> \item{\scheme{(read: <reader-name>)}}
;;> \item{\scheme{(write: <writer-name>)}}
;;> \item{\scheme{(block: <fields> ...)}}
;;> ]
;;>
;;> The fields are also similar to \scheme{define-record-type} but
;;> with an additional type:
;;>
;;> \scheme{(field (type args ...) getter setter)}
;;>
;;> Built-in types include:
;;>
;;> \itemlist[
;;> \item{\scheme{(u8)} - a single byte in [0, 255]}
;;> \item{\scheme{(u16/le)} - a little-endian short integer}
;;> \item{\scheme{(u16/be)} - a big-endian short integer}
;;> \item{\scheme{(fixed-string <length>)} - a fixed-length utf-8 string}
;;> \item{\scheme{(padded-string <length> (pad <pad-char>))} - a utf-8 string padded to a given length}
;;> \item{\scheme{(octal <length>)} - an integer in octal string format}
;;> \item{\scheme{(decimal <length>)} - an integer in decimal string format}
;;> \item{\scheme{(hexadecimal <length>)} - an integer in hexadecimal string format}
;;> ]
;;>
;;> In addition, the field can be a literal (char, string or
;;> bytevector), for instance as a file magic sequence or fixed
;;> separator. The fields (and any constants) are serialized in the
;;> order they appear in the block. For example, the header of a GIF
;;> file could be defined as:
;;>
;;> \example{
;;> (define-binary-record-type gif-header
;;> (make: make-gif-header)
;;> (pred: gif-header?)
;;> (read: read-gif-header)
;;> (write: write-gif-header)
;;> (block:
;;> "GIF89a"
;;> (width (u16/le) gif-header-width)
;;> (height (u16/le) gif-header-height)
;;> (gct (u8) gif-header-gct)
;;> (bgcolor (u8) gif-header-gbcolor)
;;> (aspect-ratio (u8) gif-header-aspect-ratio)
;;> ))
;;> }
;;>
;;> For a more complex example see the \scheme{(chibi tar)}
;;> implementation.
;;>
;;> The binary type itself is a macro used to expand to a predicate
;;> and reader/writer procedures, which can be defined with
;;> \scheme{define-binary-type}. For example,
;;>
;;> \example{
;;> (define-binary-type (u8)
;;> (lambda (x) (and (exact-integer? x) (<= 0 x 255)))
;;> read-u8
;;> write-u8)
;;> }
(define-syntax define-binary-record-type
(er-macro-transformer
(lambda (expr rename compare)
(let ((name (cadr expr))
(ls (cddr expr)))
(if (not (and (identifier? name) (every list? ls)))
(error "invalid syntax: " expr))
(let* ((type (or (param-ref ls 'type) (symbol-append 'type- name)))
(pred (or (param-ref ls 'predicate) (symbol-append name '?)))
(make (or (param-ref ls 'make) (symbol-append 'make- name)))
(make-spec (if (pair? make) make (list make)))
(%make (rename (symbol-append '% (car make-spec))))
(%%make (rename (symbol-append '%% (car make-spec))))
(reader (or (param-ref ls 'read) (symbol-append 'read- name)))
(writer (or (param-ref ls 'write) (symbol-append 'write- name)))
(block (assq 'block ls))
(_begin (rename 'begin))
(_define (rename 'define))
(_define-record-type (rename 'define-record-type))
(_let (rename 'let)))
(if (not block)
(error "missing binary record block: " expr))
(let* ((fields (extract-fields name (cdr block)))
(named-fields (filter (lambda (f) (not (eq? '_ (field-name f))))
fields)))
`(,_begin
(,_define ,name ',ls)
(,_define-record-type
,type (,%%make) ,pred
,@(map
(lambda (f)
`(,(field-name f) ,(field-get f) ,(field-raw-set f)))
named-fields))
,@(map
(lambda (f)
`(,_define (,(field-set f) x v)
,(expand-assert rename (field-spec f) 'x 'v)
(,(field-raw-set f) x v)))
named-fields)
(,_define (,%make)
(let ((res (,%%make)))
,@(map
(lambda (f)
`(,(field-raw-set f)
res
,(expand-default rename (field-spec f))))
named-fields)
res))
(,_define ,make-spec
(,_let ((res (,%make)))
,@(map
(lambda (x)
(let ((field (find (lambda (f) (eq? x (field-name f)))
fields)))
`(,(field-set field) res ,x)))
(cdr make-spec))
res))
(,_define (,reader in)
(,_let ((res (,%make)))
,@(map
(lambda (f)
(if (eq? '_ (field-name f))
(expand-read rename 'in (field-spec f))
`(,(field-set f)
res
,(expand-read rename 'in (field-spec f)))))
fields)
res))
(,_define (,writer x out)
,@(map
(lambda (f)
(expand-write rename
'out
`(,(field-get f) x)
(field-spec f)))
fields)))))))))
(syntax-rules ()
((define-binary-record-type name x ...)
(defrec (x ...) name hidden-make hidden-pred hidden-read hidden-write
() () ()))))
(define-syntax defrec
(syntax-rules (make: pred: read: write: block:)
((defrec () n m p r w
((field-tmp field-read field-read-expr field-write field-write-expr field-get) ...)
((field getter . s) ...)
(def-setter ...))
(begin
(define-record-type n (m field ...) p
(field getter . s) ...)
(define r
(let ((field-read field-read-expr) ...)
(lambda (in)
(let* ((field-tmp (field-read in)) ...)
(m field ...)))))
(define w
(let ((field-write field-write-expr) ...)
(lambda (x out)
(field-write (field-get x) out) ...)))
def-setter ...)
;; workaround for impls which strip hygiene from top-level defs
;; for some reason, works in chicken but not across libraries
;;
;; (begin
;; (define-values (n m p getter ... setter ...)
;; (let ()
;; (define-record-type n (m field ...) p
;; (field getter . s) ...)
;; (def setter val) ...
;; (values (record-rtd n) m p getter ... setter ...)))
;; (define r
;; (let ((field-read field-read-expr) ...)
;; (lambda (in)
;; (let* ((field-tmp (field-read in)) ...)
;; (m field ...)))))
;; (define w
;; (let ((field-write field-write-expr) ...)
;; (lambda (x out)
;; (field-write (field-get x) out) ...))))
)
((defrec ((make: x) . rest) n m p r w b f s)
(defrec rest n x p r w b f s))
((defrec ((pred: x) . rest) n m p r w b f s)
(defrec rest n m x r w b f s))
((defrec ((read: x) . rest) n m p r w b f s)
(defrec rest n m p x w b f s))
((defrec ((write: x) . rest) n m p r w b f s)
(defrec rest n m p r x b f s))
((defrec ((block: (field (type . args) getter setter) . fields) . rest) n m p r w b f s)
(defrec ((block: (field (type . args) getter setter tmp-setter) . fields) . rest) n m p r w b f s))
((defrec ((block: (field (type . args) getter setter tmp-setter) . fields) . rest) n m p r w
(b ...) (f ...) (s ...))
(defrec ((block: . fields) . rest) n m p r w
(b ...
(field read-tmp (type read: args) write-tmp (type write: args) getter))
(f ...
(field getter tmp-setter))
(s ...
(define setter
(let ((pred? (type pred: args)))
(lambda (x val)
(if (not (pred? val))
(error "invalid val for" 'field val))
(tmp-setter x val)))))))
((defrec ((block: (field (type . args) getter) . fields) . rest) n m p r w
(b ...) (f ...) s)
(defrec ((block: . fields) . rest) n m p r w
(b ...
(field read-tmp (type read: args) write-tmp (type write: args) getter))
(f ...
(field getter))
s))
((defrec ((block: (field . x)) . rest) n m p r w b f s)
(syntax-error "invalid field in block" (field . x)))
((defrec ((block: data . fields) . rest) n m p r w (b ...) f s)
(defrec ((block: . fields) . rest) n m p r w
(b ...
(tmp-data read-tmp (read-literal 'data) write-tmp (write-literal 'data) (lambda (x) x)))
f
s))
((defrec ((block:) . rest) n m p r w b f s)
(defrec rest n m p r w b f s))
))

View file

@ -1,11 +1,46 @@
(define-library (chibi binary-record)
(import (scheme base)
(srfi 1) (srfi 9)
(chibi io) (chibi string)
(only (chibi) identifier? er-macro-transformer))
(import (scheme base) (srfi 1))
(cond-expand
((library (srfi 60)) (import (srfi 60)))
(else (import (srfi 33))))
(export define-binary-record-type)
(include "binary-record.scm"))
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(cond-expand
((library (srfi 130)) (import (srfi 130)))
(else (import (srfi 13))))
(cond-expand
;; ((library (auto))
;; (import (only (auto) make: pred: read: write: block:)))
(else
;; indirect exports for chicken
(export defrec define-auxiliary-syntax syntax-let-optionals*)
(begin
(define-syntax define-auxiliary-syntax
(syntax-rules ()
((define-auxiliary-syntax name)
(define-syntax name
(syntax-rules ()
((name . x)
(syntax-error "invalid use of auxiliary syntax"
(name . x))))))))
(define-auxiliary-syntax make:)
(define-auxiliary-syntax pred:)
(define-auxiliary-syntax read:)
(define-auxiliary-syntax write:)
(define-auxiliary-syntax block:))))
(export
;; interface
define-binary-record-type
;; binary types
u8 u16/le u16/be padded-string fixed-string
octal decimal hexadecimal
;; auxiliary syntax
make: pred: read: write: block:
;; new types
define-binary-type)
(include "binary-types.scm")
(cond-expand
(chicken
(include "binary-record-chicken.scm"))
(else
(include "binary-record.scm"))))

160
lib/chibi/binary-types.scm Normal file
View file

@ -0,0 +1,160 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; utilities
(define (read-u16/be in)
(let* ((i (read-u8 in))
(j (read-u8 in)))
(if (eof-object? j)
(error "end of input")
(+ (arithmetic-shift i 8) j))))
(define (read-u16/le in)
(let* ((i (read-u8 in))
(j (read-u8 in)))
(if (eof-object? j)
(error "end of input")
(+ (arithmetic-shift j 8) i))))
(define (assert-read-u8 in i)
(let ((i2 (read-u8 in)))
(if (not (eqv? i i2))
(error "unmatched value, expected: " i " but got: " i2)
i2)))
(define (assert-read-char in ch)
(let ((ch2 (read-char in)))
(if (not (eqv? ch ch2))
(error "unmatched value, expected: " ch " but got: " ch2)
ch2)))
(define (assert-read-string in s)
(let ((s2 (read-string (string-length s) in)))
(if (not (equal? s s2))
(error "unmatched value, expected: " s " but got: " s2)
s2)))
(define (assert-read-bytevector in bv)
(let ((bv2 (read-bytevector (bytevector-length bv) in)))
(if (not (equal? bv bv2))
(error "unmatched value, expected: " bv " but got: " bv2)
bv2)))
(define (assert-read-integer in len radix)
(let* ((s (string-trim-both (read-string len in)
(lambda (ch) (or (eqv? ch #\space) (eqv? ch #\null)))))
(n (if (equal? s "") 0 (string->number s radix))))
(or n (error "invalid number syntax: " s))))
(define (read-padded-string in len pad)
(string-trim-right (read-string len in) pad))
(define (read-literal val)
(cond
((integer? val) (lambda (in) (assert-read-u8 in val)))
((char? val) (lambda (in) (assert-read-char in val)))
((string? val) (lambda (in) (assert-read-string in val)))
((bytevector? val) (lambda (in) (assert-read-bytevector in val)))
(else (error "unknown binary literal: " val))))
(define (write-literal val)
(cond
((integer? val) (lambda (x out) (write-u8 val out)))
((char? val) (lambda (x out) (write-char val out)))
((string? val) (lambda (x out) (write-string val out)))
((bytevector? val) (lambda (x out) (write-bytevector val out)))
(else (error "unknown binary literal: " val))))
(define (write-padded-integer out n radix len left-pad-ch right-pad-ch)
(let ((s (string-pad (number->string n radix) (- len 1) left-pad-ch)))
(cond
((>= (string-length s) len)
(error "number too large for width" n radix len))
(else
(write-string s out)
(write-char right-pad-ch out)))))
(define (write-u16/be n out)
(write-u8 (arithmetic-shift n -8) out)
(write-u8 (bitwise-and n #xFF) out))
(define (write-u16/le n out)
(write-u8 (bitwise-and n #xFF) out)
(write-u8 (arithmetic-shift n -8) out))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; syntax
(define-syntax syntax-let-optionals*
(syntax-rules ()
((syntax-let-optionals* () type-args expr)
expr)
((syntax-let-optionals* ((param default) . rest) (arg0 . args) expr)
(let ((param arg0))
(syntax-let-optionals* rest args expr)))
((syntax-let-optionals* ((param default) . rest) () expr)
(let ((param default))
(syntax-let-optionals* rest () expr)))
((syntax-let-optionals* (param . rest) (arg0 . args) expr)
(let ((param arg0))
(syntax-let-optionals* rest args expr)))
((syntax-let-optionals* (param . rest) () expr)
(syntax-error "missing required parameter" param expr))))
(define-syntax define-binary-type
(syntax-rules ()
((define-binary-type (name params ...) gen-pred gen-read gen-write)
(define-syntax name
(syntax-rules (pred: read: write:)
((name pred: type-args)
(syntax-let-optionals* (params ...) type-args gen-pred))
((name read: type-args)
(syntax-let-optionals* (params ...) type-args gen-read))
((name write: type-args)
(syntax-let-optionals* (params ...) type-args gen-write)))))))
(define-binary-type (u8)
(lambda (x) (and (exact-integer? x) (<= 0 x 255)))
read-u8
write-u8)
(define-binary-type (u16/le)
(lambda (x) (and (exact-integer? x) (<= 0 x 65536)))
read-u16/le
write-u16/le)
(define-binary-type (u16/be)
(lambda (x) (and (exact-integer? x) (<= 0 x 65536)))
read-u16/be
write-u16/be)
(define-binary-type (padded-string len (pad #\null))
(lambda (x) (and (string? x) (<= (string-length x) len)))
(lambda (in) (read-padded-string in len pad))
(lambda (str out)
(write-string (string-pad-right str len pad) out)))
(define-binary-type (fixed-string len)
(lambda (x) (and (string? x) (= (string-length x) len)))
(lambda (in)
(read-string len in))
(lambda (str out)
(write-string str out)))
(define-binary-type (octal len)
exact-integer?
(lambda (in) (assert-read-integer in len 8))
(lambda (n out)
(write-padded-integer out n 8 len #\0 #\null)))
(define-binary-type (decimal len)
exact-integer?
(lambda (in) (assert-read-integer in len 10))
(lambda (n out)
(write-padded-integer out n 10 len #\0 #\null)))
(define-binary-type (hexadecimal len)
exact-integer?
(lambda (in) (assert-read-integer in len 16))
(lambda (n out)
(write-padded-integer out n 16 len #\0 #\null)))

View file

@ -0,0 +1,81 @@
(define-library (chibi bytevector-test)
(export run-tests)
(import (scheme base) (chibi bytevector) (chibi test))
(begin
(define floats
`(0.0 -1.0 #i1/3 1.192092896E-07 ,(+ 1 1.192092896E-07)
1e-23 -1e-23
3.40282346638528860e+38 -3.40282346638528860e+38
1.40129846432481707e-45 -1.40129846432481707e-45
3.14159265358979323846))
(define f32-le
'#u8(#x00 #x00 #x00 #x00 #x00 #x00 #x80 #xbf
#xab #xaa #xaa #x3e #x00 #x00 #x00 #x34
#x01 #x00 #x80 #x3f #x9a #x6d #x41 #x19
#x9a #x6d #x41 #x99 #xff #xff #x7f #x7f
#xff #xff #x7f #xff #x01 #x00 #x00 #x00
#x01 #x00 #x00 #x80 #xdb #x0f #x49 #x40))
(define f64-le
'#u8(#x00 #x00 #x00 #x00 #x00 #x00 #x00 #x00
#x00 #x00 #x00 #x00 #x00 #x00 #xf0 #xbf
#x55 #x55 #x55 #x55 #x55 #x55 #xd5 #x3f
#x68 #x5f #x1c #x00 #x00 #x00 #x80 #x3e
#x00 #x00 #x00 #x20 #x00 #x00 #xf0 #x3f
#x51 #xb2 #x12 #x40 #xb3 #x2d #x28 #x3b
#x51 #xb2 #x12 #x40 #xb3 #x2d #x28 #xbb
#x00 #x00 #x00 #xe0 #xff #xff #xef #x47
#x00 #x00 #x00 #xe0 #xff #xff #xef #xc7
#x00 #x00 #x00 #x00 #x00 #x00 #xa0 #x36
#x00 #x00 #x00 #x00 #x00 #x00 #xa0 #xb6
#x18 #x2d #x44 #x54 #xfb #x21 #x09 #x40))
(define (run-tests)
(test-begin "bytevector")
(test-group "reading ieee"
(do ((ls floats (cdr ls))
(i 0 (+ i 4)))
((null? ls))
(test (car ls) (bytevector-ieee-single-native-ref f32-le i)))
(do ((ls floats (cdr ls))
(i 0 (+ i 8)))
((null? ls))
(test (car ls) (bytevector-ieee-double-native-ref f64-le i))))
(test-group "writing ieee"
(do ((ls floats (cdr ls))
(i 0 (+ i 4)))
((null? ls))
(let ((bv (make-bytevector 4 0)))
(bytevector-ieee-single-native-set! bv 0 (car ls))
(test (bytevector-copy f32-le i (+ i 4)) (values bv))))
(do ((ls floats (cdr ls))
(i 0 (+ i 8)))
((null? ls))
(let ((bv (make-bytevector 8 0)))
(bytevector-ieee-double-native-set! bv 0 (car ls))
;;(test (bytevector-copy f64-le i (+ i 8)) (values bv))
(test (car ls)
(bytevector-ieee-double-native-ref bv 0)))))
(test-group "ber integers"
(do ((ls '(0 1 128 16383 32767
18446744073709551615
340282366920938463463374607431768211456)
(cdr ls)))
((null? ls))
(let ((bv (make-bytevector 256)))
(do ((offsets '(0 1 27) (cdr offsets)))
((null? offsets))
(bytevector-ber-set! bv (car ls) (car offsets))
(test (car ls) (bytevector-ber-ref bv (car offsets)))))))
(test-end))))

View file

@ -33,6 +33,46 @@
(arithmetic-shift (bytevector-u8-ref bv (+ i 2)) 8)
(bytevector-u8-ref bv (+ i 3))))
;;> \section{Bignum encodings}
;;> A BER compressed integer (X.209) is an unsigned integer in base 128,
;;> most significant digit first, where the high bit is set on all but the
;;> final (least significant) byte. Thus any size integer can be
;;> encoded, but the encoding is efficient and small integers don't take
;;> up any more space than they would in normal char/short/int encodings.
(define (bytevector-ber-ref bv . o)
(let ((end (if (and (pair? o) (pair? (cdr o)))
(cadr o)
(bytevector-length bv))))
(let lp ((acc 0) (i (if (pair? o) (car o) 0)))
(if (>= i end)
(error "unterminated ber integer in bytevector" bv)
(let ((b (bytevector-u8-ref bv i)))
(if (< b 128)
(+ acc b)
(lp (arithmetic-shift (+ acc (bitwise-and b 127)) 7)
(+ i 1))))))))
(define (bytevector-ber-set! bv n . o)
;;(assert (integer? number) (not (negative? number)))
(let ((start (if (pair? o) (car o) 0))
(end (if (and (pair? o) (pair? (cdr o)))
(cadr o)
(bytevector-length bv))))
(let lp ((n (arithmetic-shift n -7))
(ls (list (bitwise-and n 127))))
(if (zero? n)
(do ((i start (+ i 1))
(ls ls (cdr ls)))
((null? ls))
(if (>= i end)
(error "integer doesn't fit in bytevector as ber"
bv n start end)
(bytevector-u8-set! bv i (car ls))))
(lp (arithmetic-shift n -7)
(cons (+ 128 (bitwise-and n 127)) ls))))))
;;> \section{Integer conversion}
;;> Convert an unsigned integer \var{n} to a bytevector representing

View file

@ -5,12 +5,37 @@
(export
bytevector-u16-ref-le bytevector-u16-ref-be
bytevector-u32-ref-le bytevector-u32-ref-be
bytevector-ber-ref bytevector-ber-set!
bytevector-pad-left
integer->bytevector bytevector->integer
integer->hex-string hex-string->integer
bytevector->hex-string hex-string->bytevector)
(import (scheme base))
bytevector->hex-string hex-string->bytevector
bytevector-ieee-single-ref
bytevector-ieee-single-native-ref
bytevector-ieee-single-set!
bytevector-ieee-single-native-set!
bytevector-ieee-double-ref
bytevector-ieee-double-native-ref
bytevector-ieee-double-set!
bytevector-ieee-double-native-set!
)
(import (scheme base) (scheme inexact))
(cond-expand
((library (srfi 60)) (import (srfi 60)))
(else (import (srfi 33))))
(include "bytevector.scm"))
(big-endian
(begin
(define-syntax native-endianness
(syntax-rules () ((_) 'big)))))
(else
(begin
(define-syntax native-endianness
(syntax-rules () ((_) 'little))))))
(cond-expand
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(include "bytevector.scm")
(cond-expand
(chibi
(import (except (scheme bytevector) bytevector-copy!)))
(else
(include "ieee-754.scm"))))

View file

@ -1,42 +1,42 @@
;; char-set:lower-case
(define char-set:lower-case (immutable-char-set (%make-iset 97 122 #f #f #f)))
(define char-set:lower-case (immutable-char-set (%make-iset 97 127 67108863 #f #f)))
;; char-set:upper-case
(define char-set:upper-case (immutable-char-set (%make-iset 65 90 #f #f #f)))
(define char-set:upper-case (immutable-char-set (%make-iset 65 127 67108863 #f #f)))
;; char-set:title-case
(define char-set:title-case (immutable-char-set (%make-iset 0 0 0 #f #f)))
;; char-set:letter
(define char-set:letter (immutable-char-set (%make-iset 97 122 #f (%make-iset 65 90 #f #f #f) #f)))
(define char-set:letter (immutable-char-set (%make-iset 65 127 288230371923853311 #f #f)))
;; char-set:punctuation
(define char-set:punctuation (immutable-char-set (%make-iset 63 64 #f (%make-iset 44 47 #f (%make-iset 37 42 #f (%make-iset 33 35 #f #f #f) #f) (%make-iset 58 59 #f #f #f)) (%make-iset 123 123 #f (%make-iset 95 95 #f (%make-iset 91 93 #f #f #f) #f) (%make-iset 125 125 #f #f #f)))))
(define char-set:punctuation (immutable-char-set (%make-iset 33 127 6189700203056200029306911735 #f #f)))
;; char-set:symbol
(define char-set:symbol (immutable-char-set (%make-iset 94 94 #f (%make-iset 43 43 #f (%make-iset 36 36 #f #f #f) (%make-iset 60 62 #f #f #f)) (%make-iset 124 124 #f (%make-iset 96 96 #f #f #f) (%make-iset 126 126 #f #f #f)))))
(define char-set:symbol (immutable-char-set (%make-iset 36 127 1547425050547877224499904641 #f #f)))
;; char-set:blank
(define char-set:blank (immutable-char-set (%make-iset 32 32 #f (%make-iset 9 9 #f #f #f) #f)))
(define char-set:blank (immutable-char-set (%make-iset 9 32 8388609 #f #f)))
;; char-set:whitespace
(define char-set:whitespace (immutable-char-set (%make-iset 32 32 #f (%make-iset 9 13 #f #f #f) #f)))
(define char-set:whitespace (immutable-char-set (%make-iset 9 127 8388639 #f #f)))
;; char-set:digit
(define char-set:digit (immutable-char-set (%make-iset 48 57 #f #f #f)))
;; char-set:letter+digit
(define char-set:letter+digit (immutable-char-set (%make-iset 65 90 #f (%make-iset 48 57 #f #f #f) (%make-iset 97 122 #f #f #f))))
(define char-set:letter+digit (immutable-char-set (%make-iset 48 127 37778931308803301180415 #f #f)))
;; char-set:hex-digit
(define char-set:hex-digit (immutable-char-set (%make-iset 65 70 #f (%make-iset 48 57 #f #f #f) (%make-iset 97 102 #f #f #f))))
(define char-set:hex-digit (immutable-char-set (%make-iset 48 102 35465847073801215 #f #f)))
;; char-set:iso-control
(define char-set:iso-control (immutable-char-set (%make-iset 127 127 #f (%make-iset 0 31 #f #f #f) #f)))
(define char-set:iso-control (immutable-char-set (%make-iset 0 127 170141183460469231731687303720179073023 #f #f)))
;; char-set:graphic
(define char-set:graphic (immutable-char-set (%make-iset 33 126 #f #f #f)))
(define char-set:graphic (immutable-char-set (%make-iset 33 127 19807040628566084398385987583 #f #f)))
;; char-set:printing
(define char-set:printing (immutable-char-set (%make-iset 32 126 #f (%make-iset 9 13 #f #f #f) #f)))
(define char-set:printing (immutable-char-set (%make-iset 9 127 332306998946228968225951765061697567 #f #f)))

View file

@ -2,9 +2,11 @@
(define (char-set . args)
(list->char-set args))
;; This is a mistake in the SRFI-14 design - end should be inclusive.
(define (ucs-range->char-set start end)
(make-iset start (- end 1)))
(define (ucs-range->char-set start end . o)
(let ((res (make-iset start (- end 1))))
(if (and (pair? o) (pair? (cdr o)))
(iset-union res (cadr o))
res)))
(define char-set-copy iset-copy)
@ -16,8 +18,8 @@
(define (char-set-for-each proc cset)
(iset-for-each (lambda (i) (proc (integer->char i))) cset))
(define (list->char-set ls)
(list->iset (map char->integer ls)))
(define (list->char-set ls . o)
(apply list->iset (map char->integer ls) o))
(define (char-set->list cset)
(map integer->char (iset->list cset)))
@ -26,10 +28,10 @@
(define (char-set->string cset)
(list->string (char-set->list cset)))
(define (char-set-adjoin! cset ch)
(iset-adjoin! cset (char->integer ch)))
(define (char-set-adjoin cset ch)
(iset-adjoin cset (char->integer ch)))
(define (char-set-adjoin! cset . o)
(apply iset-adjoin! cset (map char->integer o)))
(define (char-set-adjoin cset . o)
(apply iset-adjoin cset (map char->integer o)))
(define char-set-union iset-union)
(define char-set-union! iset-union!)

File diff suppressed because one or more lines are too long

View file

@ -76,13 +76,18 @@
;;> Returns true iff \var{x} is a config object.
(define-record-type Config
(make-conf alist parent source timestamp)
(%make-conf alist parent source timestamp)
conf?
(alist conf-alist conf-alist-set!)
(parent conf-parent conf-parent-set!)
(source conf-source conf-source-set!)
(timestamp conf-timestamp conf-timestamp-set!))
(define (make-conf alist parent source timestamp)
(if (not (alist? alist))
(error "config requires an alist" alist)
(%make-conf alist parent source timestamp)))
(define (assq-tail key alist)
(let lp ((ls alist))
(and (pair? ls)
@ -106,7 +111,12 @@
(else (lp (cdr ls) (cons (car ls) rev))))))
(define (read-from-file file . opt)
(guard (exn (else (and (pair? opt) (car opt))))
(guard (exn
(else
(warn "couldn't load config:" file)
(print-exception exn)
(print-stack-trace exn)
(and (pair? opt) (car opt))))
(call-with-input-file file read)))
(define (alist? x)
@ -451,7 +461,7 @@
(every* (lambda (x)
(and (pair? x)
(conf-verify-match key-def (car x) warn)
(conf-verify-match val-def (cell-value x) warn)))
(conf-verify-match val-def (cell-value) warn)))
(cell-list)))))
((conf)
(and (alist? (cell-list))

View file

@ -10,6 +10,18 @@
;; This is only used for config verification, it's acceptable to
;; substitute file existence for the stronger directory check.
(cond-expand
(chibi (import (only (chibi filesystem) file-directory?)))
(else (begin (define file-directory? file-exists?))))
(chibi
(import (only (meta) warn))
(import (only (chibi) print-exception print-stack-trace))
(import (only (chibi filesystem) file-directory?)))
(else
(begin
(define file-directory? file-exists?)
(define (print-exception exn) (write exn))
(define (print-stack-trace . o) #f)
(define (warn msg . args)
(let ((err (current-error-port)))
(display msg err)
(for-each (lambda (x) (display " " err) (write x err)) args)
(newline err))))))
(include "config.scm"))

View file

@ -1,6 +1,6 @@
(define-library (chibi crypto md5-test)
(export run-tests)
(import (chibi) (chibi crypto md5) (chibi test))
(import (scheme base) (chibi crypto md5) (chibi test))
(begin
(define (run-tests)
(test-begin "md5")

View file

@ -5,7 +5,8 @@
(define-library (chibi crypto md5)
(import (scheme base) (chibi bytevector))
(cond-expand
((library (srfi 60)) (import (srfi 60)))
(else (import (srfi 33))))
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(export md5)
(include "md5.scm"))

View file

@ -6,23 +6,28 @@
(chibi test))
(begin
(define (run-tests)
(define (test-key key)
(test #t (rsa-key? key))
(test #t (positive? (rsa-key-n key)))
(test #t (positive? (rsa-key-e key)))
(test #t (positive? (rsa-key-d key)))
(test 5 (rsa-decrypt key (rsa-encrypt (rsa-pub-key key) 5))))
(test-begin "rsa")
;; Verify an explicit key.
;; p = 61, q = 53
(define priv-key (rsa-key-gen-from-primes 8 61 53))
(define pub-key (rsa-pub-key priv-key))
(let* ((priv-key (rsa-key-gen-from-primes 8 61 53))
(pub-key (rsa-pub-key priv-key)))
(test 439 (rsa-sign priv-key 42))
(test #t (rsa-verify? pub-key 42 (rsa-sign priv-key 42)))
(let ((msg 42))
(test msg (rsa-decrypt priv-key (rsa-encrypt pub-key msg))))
(define priv-key2 (rsa-key-gen-from-primes 32 2936546443 3213384203))
(define pub-key2 (rsa-pub-key priv-key2))
(test msg (rsa-decrypt priv-key (rsa-encrypt pub-key msg)))))
(let* ((priv-key2 (rsa-key-gen-from-primes 32 2936546443 3213384203))
(pub-key2 (rsa-pub-key priv-key2)))
(let ((msg 42))
(test msg (rsa-decrypt priv-key2 (rsa-encrypt pub-key2 msg))))
@ -36,17 +41,10 @@
(test #t (rsa-verify? pub-key2 msg (rsa-sign priv-key2 msg))))
(let ((msg #u8(42)))
(test #t (rsa-verify? pub-key2 msg (rsa-sign priv-key2 msg))))
(test #t (rsa-verify? pub-key2 msg (rsa-sign priv-key2 msg)))))
;; Key generation.
(define (test-key key)
(test #t (rsa-key? key))
(test #t (positive? (rsa-key-n key)))
(test #t (positive? (rsa-key-e key)))
(test #t (positive? (rsa-key-d key)))
(test 5 (rsa-decrypt key (rsa-encrypt (rsa-pub-key key) 5))))
(test-key (rsa-key-gen 8))
(test-key (rsa-key-gen 16))
(test-key (rsa-key-gen 32))

View file

@ -5,8 +5,9 @@
(import (scheme base) (srfi 27)
(chibi bytevector) (chibi math prime))
(cond-expand
((library (srfi 60)) (import (srfi 60)))
(else (import (srfi 33))))
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(export make-rsa-key rsa-key-gen rsa-key-gen-from-primes rsa-pub-key
rsa-encrypt rsa-decrypt rsa-sign rsa-verify rsa-verify?
rsa-key? rsa-key-bits rsa-key-n rsa-key-e rsa-key-d

View file

@ -1,6 +1,6 @@
(define-library (chibi crypto sha2-test)
(export run-tests)
(import (chibi) (chibi io) (chibi crypto sha2) (chibi test))
(import (scheme base) (chibi crypto sha2) (chibi test))
(begin
(define (run-tests)
(test-begin "sha2")

View file

@ -11,8 +11,9 @@
(include-shared "crypto"))
(else
(cond-expand
((library (srfi 60)) (import (srfi 60)))
(else (import (srfi 33))))
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(import (chibi bytevector))
(include "sha2.scm"))))

98
lib/chibi/csv-test.sld Normal file
View file

@ -0,0 +1,98 @@
(define-library (chibi csv-test)
(import (scheme base)
(srfi 227)
(chibi csv)
(chibi test))
(export run-tests)
(begin
(define string->csv
(opt-lambda (str (reader (csv-read->list)))
(reader (open-input-string str))))
(define csv->string
(opt-lambda (row (writer (csv-writer)))
(let ((out (open-output-string)))
(writer row out)
(get-output-string out))))
(define (run-tests)
(test-begin "(chibi csv)")
(test-assert (eof-object? (string->csv "")))
(test '("1997" "Ford" "E350")
(string->csv "1997,Ford,E350"))
(test '("1997" "Ford" "E350")
(string->csv "\n1997,Ford,E350"))
(test '(" ")
(string->csv " \n1997,Ford,E350"))
(test '("" "")
(string->csv ",\n1997,Ford,E350"))
(test '("1997" "Ford" "E350")
(string->csv "\"1997\",\"Ford\",\"E350\""))
(test '("1997" "Ford" "E350" "Super, luxurious truck")
(string->csv "1997,Ford,E350,\"Super, luxurious truck\""))
(test '("1997" "Ford" "E350" "Super, \"luxurious\" truck")
(string->csv "1997,Ford,E350,\"Super, \"\"luxurious\"\" truck\""))
(test '("1997" "Ford" "E350" "Go get one now\nthey are going fast")
(string->csv "1997,Ford,E350,\"Go get one now
they are going fast\""))
(test '("1997" "Ford" "E350")
(string->csv
"# this is a comment\n1997,Ford,E350"
(csv-read->list
(csv-parser (csv-grammar '((comment-chars #\#)))))))
(let ((parser (csv-parser (csv-grammar '((quote-non-numeric? . #t))))))
(test-error (string->csv "1997,\"Ford\",E350" (csv-read->list parser)))
(test '(1997 "Ford" "E350")
(string->csv "1997,\"Ford\",\"E350\"" (csv-read->list parser))))
(test '("1997" "Fo\"rd" "E3\"50")
(string->csv "1997\tFo\"rd\tE3\"50"
(csv-read->list (csv-parser default-tsv-grammar))))
(test '#("1997" "Ford" "E350")
(string->csv "1997,Ford,E350" (csv-read->vector)))
(test '#("1997" "Ford" "E350")
(string->csv "1997,Ford,E350" (csv-read->fixed-vector 3)))
(test-error
(string->csv "1997,Ford,E350" (csv-read->fixed-vector 2)))
(let ((city-csv "Los Angeles,34°03N,118°15W
New York City,40°4246″N,74°0021″W
Paris,48°5124″N,2°2103″E"))
(test '(*TOP*
(row (col-0 "Los Angeles")
(col-1 "34°03N")
(col-2 "118°15W"))
(row (col-0 "New York City")
(col-1 "40°4246″N")
(col-2 "74°0021″W"))
(row (col-0 "Paris")
(col-1 "48°5124″N")
(col-2 "2°2103″E")))
((csv->sxml) (open-input-string city-csv)))
(test '(*TOP*
(city (name "Los Angeles")
(latitude "34°03N")
(longitude "118°15W"))
(city (name "New York City")
(latitude "40°4246″N")
(longitude "74°0021″W"))
(city (name "Paris")
(latitude "48°5124″N")
(longitude "2°2103″E")))
((csv->sxml 'city '(name latitude longitude))
(open-input-string city-csv)))
(test 3 (csv-num-rows default-csv-grammar (open-input-string city-csv)))
(test 0 (csv-num-rows default-csv-grammar (open-input-string "")))
(test 1 (csv-num-rows default-csv-grammar (open-input-string "x"))))
(test "1997,Ford,E350\n"
(csv->string '("1997" "Ford" "E350")))
(test "1997,Ford,E350,\"Super, luxurious truck\"\n"
(csv->string '("1997" "Ford" "E350" "Super, luxurious truck")))
(test "1997,Ford,E350,\"Super, \"\"luxurious\"\" truck\"\n"
(csv->string '("1997" "Ford" "E350" "Super, \"luxurious\" truck")))
(test "1997,Ford,E350,\"Go get one now\nthey are going fast\"\n"
(csv->string
'("1997" "Ford" "E350" "Go get one now\nthey are going fast")))
(test "1997,Ford,E350\n"
(csv->string '(1997 "Ford" E350)))
(test "1997,\"Ford\",\"E350\"\n"
(csv->string '(1997 "Ford" E350)
(csv-writer (csv-grammar '((quote-non-numeric? . #t))))))
(test-end))))

498
lib/chibi/csv.scm Normal file
View file

@ -0,0 +1,498 @@
;;> \section{CSV Grammars}
;;> CSV is a simple and compact format for tabular data, which has
;;> made it popular for a variety of tasks since the early days of
;;> computing. Unfortunately, there are many incompatible dialects
;;> requiring a grammar to specify all of the different options.
(define-record-type Csv-Grammar
(make-csv-grammar separator-chars quote-char quote-doubling-escapes? escape-char record-separator comment-chars quote-non-numeric?)
csv-grammar?
(separator-chars csv-grammar-separator-chars csv-grammar-separator-chars-set!)
(quote-char csv-grammar-quote-char csv-grammar-quote-char-set!)
(quote-doubling-escapes? csv-grammar-quote-doubling-escapes? csv-grammar-quote-doubling-escapes?-set!)
(escape-char csv-grammar-escape-char csv-grammar-escape-char-set!)
(record-separator csv-grammar-record-separator csv-grammar-record-separator-set!)
(comment-chars csv-grammar-comment-chars csv-grammar-comment-chars-set!)
(quote-non-numeric? csv-grammar-quote-non-numeric? csv-grammar-quote-non-numeric?-set!))
;; TODO: Other options to consider:
;; - strip-leading/trailing-whitespace?
;; - newlines-in-quotes?
;;> Creates a new CSV grammar from the given spec, an alist of symbols
;;> to values. The following options are supported:
;;>
;;> \itemlist[
;;> \item{\scheme{'separator-chars} - A non-empty list of characters used to delimit fields, by default \scheme{'(#\\,)} (comma-separated).}
;;> \item{\scheme{'quote-char} - A single character used to quote fields containing special characters, or \scheme{#f} to disable quoting, by default \scheme{#\\"} (a double-quote).}
;;> \item{\scheme{'quote-doubling-escapes?} - If true, two successive \scheme{quote-char}s within quotes are treated as a single escaped \scheme{quote-char} (default true).}
;;> \item{\scheme{'escape-char} - A single character used to escape characters within quoted fields, or \scheme{#f} to disable escapes, by default \scheme{#f} (no explicit escape, use quote doubling).}
;;> \item{\scheme{'record-separator} - A single character used to delimit the record (row), or one of the symbols \scheme{'cr}, \scheme{'crlf}, \scheme{'lf} or \scheme{'lax}. These correspond to sequences of carriage return and line feed, or in the case of \scheme{'lax} any of the other three sequences. Defaults to \scheme{'lax}.}
;;> \item{\scheme{'comment-chars} - A list of characters which if found at the start of a record indicate it is a comment, discarding all characters through to the next record-separator. Defaults to the empty list (no comments).}
;;> ]
;;>
;;> Example Gecos grammar:
;;>
;;> \example{
;;> (csv-grammar
;;> '((separator-chars #\\:)
;;> (quote-char . #f)))
;;> }
(define (csv-grammar spec)
(let ((grammar (make-csv-grammar '(#\,) #\" #t #f 'lax '() #f)))
(for-each
(lambda (x)
(case (car x)
((separator-chars delimiter)
(csv-grammar-separator-chars-set! grammar (cdr x)))
((quote-char)
(csv-grammar-quote-char-set! grammar (cdr x)))
((quote-doubling-escapes?)
(csv-grammar-quote-doubling-escapes?-set! grammar (cdr x)))
((escape-char)
(csv-grammar-escape-char-set! grammar (cdr x)))
((record-separator newline-type)
(let ((rec-sep
(case (cdr x)
((crlf lax) (cdr x))
((cr) #\return)
((lf) #\newline)
(else
(if (char? (cdr x))
(cdr x)
(error "invalid record-separator, expected a char or one of 'lax or 'crlf" (cdr x)))))))
(csv-grammar-escape-char-set! grammar (cdr x))))
((comment-chars)
(csv-grammar-comment-chars-set! grammar (cdr x)))
((quote-non-numeric?)
(csv-grammar-quote-non-numeric?-set! grammar (cdr x)))
(else
(error "unknown csv-grammar spec" x))))
spec)
grammar))
;;> The default CSV grammar for convenience, with all of the defaults
;;> from \scheme{csv-grammar}, i.e. comma-delimited with \scheme{#\"}
;;> for quoting, doubled to escape.
(define default-csv-grammar
(csv-grammar '()))
;;> The default TSV grammar for convenience, splitting fields only on
;;> tabs, with no quoting or escaping.
(define default-tsv-grammar
(csv-grammar '((separator-chars #\tab) (quote-char . #f))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \section{CSV Parsers}
;;> Parsers are low-level utilities to perform operations on records a
;;> field at a time. You generally want to work with readers, which
;;> build on this to build records into familiar data structures.
;;> Parsers follow the rules of a grammar to parse a single CSV
;;> record, possible comprised of multiple fields. A parser is a
;;> procedure of three arguments which performs a fold operation over
;;> the fields of the record. The parser signature is:
;;> \scheme{(parser kons knil in)}, where \scheme{kons} itself is
;;> a procedure of three arguments: \scheme{(proc acc index field)}.
;;> \scheme{proc} is called on each field of the record, in order,
;;> along with its zero-based \scheme{index} and the accumulated
;;> result of the last call, starting with \scheme{knil}.
;;> Returns a new CSV parser for the given \var{grammar}. The parser
;;> by itself can be used to parse a record at a time.
;;>
;;> \example{
;;> (let ((parse (csv-parser)))
;;> (parse (lambda (vec i field) (vector-set! vec i (string->number field)) vec)
;;> (make-vector 3)
;;> (open-input-string "1,2,3")))
;;> }
(define csv-parser
(opt-lambda ((grammar default-csv-grammar))
(lambda (kons knil in)
(when (pair? (csv-grammar-comment-chars grammar))
(let lp ()
(when (memv (peek-char in) (csv-grammar-comment-chars grammar))
(csv-skip-line in grammar)
(lp))))
(let lp ((acc knil)
(index 0)
(quoted? #f)
(out (open-output-string)))
(define (get-field)
(let ((field (get-output-string out)))
(cond
((and (zero? index) (equal? field "")) field)
((and (csv-grammar-quote-non-numeric? grammar) (not quoted?))
(or (string->number field)
(error "unquoted field is not numeric" field)))
(else field))))
(define (finish-row)
(let ((field (get-field)))
(if (and (zero? index) (equal? field ""))
;; empty row, read again
(lp acc index #f out)
(kons acc index field))))
(let ((ch (read-char in)))
(cond
((eof-object? ch)
(let ((field (get-field)))
(if (and (zero? index) (equal? field ""))
;; no data
ch
(kons acc index field))))
((memv ch (csv-grammar-separator-chars grammar))
(lp (kons acc index (get-field))
(+ index 1)
#f
(open-output-string)))
((eqv? ch (csv-grammar-quote-char grammar))
;; TODO: Consider a strict mode to enforce no text
;; before/after the quoted text.
(csv-read-quoted in out grammar)
(lp acc index #t out))
((eqv? ch (csv-grammar-record-separator grammar))
(finish-row))
((and (eqv? ch #\return)
(memq (csv-grammar-record-separator grammar) '(crlf lax)))
(cond
((eqv? (peek-char in) #\newline)
(read-char in)
(finish-row))
((eq? (csv-grammar-record-separator grammar) 'lax)
(finish-row))
(else
(write-char ch out)
(lp acc (+ index 1) quoted? out))))
((and (eqv? ch #\newline)
(eq? (csv-grammar-record-separator grammar) 'lax))
(finish-row))
(else
(write-char ch out)
(lp acc index quoted? out))))))))
(define (csv-skip-line in grammar)
(let lp ()
(let ((ch (read-char in)))
(cond
((eof-object? ch))
((eqv? ch (csv-grammar-record-separator grammar)))
((and (eqv? ch #\newline)
(eq? (csv-grammar-record-separator grammar) 'lax)))
((and (eqv? ch #\return)
(memq (csv-grammar-record-separator grammar) '(crlf lax)))
(cond
((eqv? (peek-char in) #\newline) (read-char in))
((eq? (csv-grammar-record-separator grammar) 'lax))
(else (lp))))
(else (lp))))))
(define (csv-read-quoted in out grammar)
(let lp ()
(let ((ch (read-char in)))
(cond
((eof-object? ch)
(error "unterminated csv quote" (get-output-string out)))
((eqv? ch (csv-grammar-quote-char grammar))
(when (and (csv-grammar-quote-doubling-escapes? grammar)
(eqv? ch (peek-char in)))
(write-char (read-char in) out)
(lp)))
((eqv? ch (csv-grammar-escape-char grammar))
(write-char (read-char in) out)
(lp))
(else
;; TODO: Consider an option to disable newlines in quotes.
(write-char ch out)
(lp))))))
(define (csv-skip-quoted in grammar)
(let lp ()
(let ((ch (read-char in)))
(cond
((eof-object? ch)
(error "unterminated csv quote"))
((eqv? ch (csv-grammar-quote-char grammar))
(when (and (csv-grammar-quote-doubling-escapes? grammar)
(eqv? ch (peek-char in)))
(read-char in)
(lp)))
((eqv? ch (csv-grammar-escape-char grammar))
(read-char in)
(lp))
(else
(lp))))))
;;> Returns the number of rows in the input.
(define csv-num-rows
(opt-lambda ((grammar default-csv-grammar)
(in (current-input-port)))
(let lp ((num-rows 0) (start? #t))
(let ((ch (read-char in)))
(cond
((eof-object? ch) (if start? num-rows (+ num-rows 1)))
((eqv? ch (csv-grammar-quote-char grammar))
(csv-skip-quoted in grammar)
(lp num-rows #f))
((eqv? ch (csv-grammar-record-separator grammar))
(lp (+ num-rows 1) #f))
((and (eqv? ch #\return)
(memq (csv-grammar-record-separator grammar) '(crlf lax)))
(cond
((eqv? (peek-char in) #\newline)
(read-char in)
(lp (+ num-rows 1) #t))
((eq? (csv-grammar-record-separator grammar) 'lax)
(lp (+ num-rows 1) #t))
(else
(lp num-rows #f))))
((and (eqv? ch #\newline)
(eq? (csv-grammar-record-separator grammar) 'lax))
(lp (+ num-rows 1) #t))
(else
(lp num-rows #f)))))))
;;> \section{CSV Readers}
;;> A CSV reader reads a single record, returning some representation
;;> of it. You can either loop manually with these or pass them to
;;> one of the high-level utilities to operate on a whole CSV file at
;;> a time.
;;> The simplest reader, simply returns the field string values in
;;> order as a list.
;;>
;;> \example{
;;> ((csv-read->list) (open-input-string "foo,bar,baz"))
;;> }
(define csv-read->list
(opt-lambda ((parser (csv-parser)))
(opt-lambda ((in (current-input-port)))
(let ((res (parser (lambda (ls i field) (cons field ls)) '() in)))
(if (pair? res)
(reverse res)
res)))))
;;> The equivalent of \scheme{csv-read->list} but returns a vector.
;;>
;;> \example{
;;> ((csv-read->vector) (open-input-string "foo,bar,baz"))
;;> }
(define csv-read->vector
(opt-lambda ((parser (csv-parser)))
(let ((reader (csv-read->list parser)))
(opt-lambda ((in (current-input-port)))
(let ((res (reader in)))
(if (pair? res)
(list->vector res)
res))))))
;;> The same as \scheme{csv-read->vector} but requires the vector to
;;> be of a fixed size, and may be more efficient.
;;>
;;> \example{
;;> ((csv-read->fixed-vector 3) (open-input-string "foo,bar,baz"))
;;> }
(define csv-read->fixed-vector
(opt-lambda (size (parser (csv-parser)))
(opt-lambda ((in (current-input-port)))
(let ((res (make-vector size)))
(let ((len (parser (lambda (prev-i i field) (vector-set! res i field) i)
0
in)))
(if (zero? len)
(eof-object)
res))))))
;;> Returns an SXML representation of the record, as a row with
;;> multiple named columns.
;;>
;;> \example{
;;> ((csv-read->sxml 'city '(name latitude longitude))
;;> (open-input-string "Tokyo,35°4123″N,139°4132″E"))
;;> }
(define csv-read->sxml
(opt-lambda ((row-name 'row)
(column-names
(lambda (i)
(string->symbol (string-append "col-" (number->string i)))))
(parser (csv-parser)))
(define (get-column-name i)
(if (procedure? column-names)
(column-names i)
(list-ref column-names i)))
(opt-lambda ((in (current-input-port)))
(let ((res (parser (lambda (ls i field)
`((,(get-column-name i) ,field) ,@ls))
(list row-name)
in)))
(if (pair? res)
(reverse res)
res)))))
;;> \section{CSV Utilities}
;;> A folding operation on records. \var{proc} is called successively
;;> on each row and the accumulated result.
;;>
;;> \example{
;;> (csv-fold
;;> (lambda (row acc) (cons (cadr (assq 'name (cdr row))) acc))
;;> '()
;;> (csv-read->sxml 'city '(name latitude longitude))
;;> (open-input-string
;;> "Tokyo,35°4123″N,139°4132″E
;;> Paris,48°5124″N,2°2103″E"))
;;> }
(define csv-fold
(opt-lambda (proc
knil
(reader (csv-read->list))
(in (current-input-port)))
(let lp ((acc knil))
(let ((row (reader in)))
(cond
((eof-object? row) acc)
(else (lp (proc row acc))))))))
;;> An iterator which simply calls \var{proc} on each record in the
;;> input in order.
;;>
;;> \example{
;;> (let ((count 0))
;;> (csv-for-each
;;> (lambda (row) (if (string->number (car row)) (set! count (+ 1 count))))
;;> (csv-read->list)
;;> (open-input-string
;;> "1,foo\\n2,bar\\nthree,baz\\n4,qux"))
;;> count)
;;> }
(define csv-for-each
(opt-lambda (proc
(reader (csv-read->list))
(in (current-input-port)))
(csv-fold (lambda (row acc) (proc row)) #f reader in)))
;;> Returns a list containing the result of calling \var{proc} on each
;;> element in the input.
;;>
;;> \example{
;;> (csv-map
;;> (lambda (row) (string->symbol (cadr row)))
;;> (csv-read->list)
;;> (open-input-string
;;> "1,foo\\n2,bar\\nthree,baz\\n4,qux"))
;;> }
(define csv-map
(opt-lambda (proc
(reader (csv-read->list))
(in (current-input-port)))
(reverse (csv-fold (lambda (row acc) (cons (proc row) acc)) '() reader in))))
;;> Returns a list of all of the read records in the input.
;;>
;;> \example{
;;> (csv->list
;;> (csv-read->list)
;;> (open-input-string
;;> "1,foo\\n2,bar\\nthree,baz\\n4,qux"))
;;> }
(define csv->list
(opt-lambda ((reader (csv-read->list))
(in (current-input-port)))
(csv-map (lambda (row) row) reader in)))
;;> Returns an SXML representation of the CSV.
;;>
;;> \example{
;;> ((csv->sxml 'city '(name latitude longitude))
;;> (open-input-string
;;> "Tokyo,35°4123″N,139°4132″E
;;> Paris,48°5124″N,2°2103″E"))
;;> }
(define csv->sxml
(opt-lambda ((row-name 'row)
(column-names
(lambda (i)
(string->symbol (string-append "col-" (number->string i)))))
(parser (csv-parser)))
(opt-lambda ((in (current-input-port)))
(cons '*TOP*
(csv->list (csv-read->sxml row-name column-names parser) in)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \section{CSV Writers}
(define (write->string obj)
(let ((out (open-output-string)))
(write obj out)
(get-output-string out)))
(define (csv-grammar-char-needs-quoting? grammar ch)
(or (eqv? ch (csv-grammar-quote-char grammar))
(eqv? ch (csv-grammar-escape-char grammar))
(memv ch (csv-grammar-separator-chars grammar))
(eqv? ch (csv-grammar-record-separator grammar))
(memv ch '(#\newline #\return))))
(define (csv-write-quoted obj out grammar)
(let ((in (open-input-string (if (string? obj) obj (write->string obj)))))
(write-char (csv-grammar-quote-char grammar) out)
(let lp ()
(let ((ch (read-char in)))
(cond
((eof-object? ch))
((or (eqv? ch (csv-grammar-quote-char grammar))
(eqv? ch (csv-grammar-escape-char grammar)))
(cond
((and (csv-grammar-quote-doubling-escapes? grammar)
(eqv? ch (csv-grammar-quote-char grammar)))
(write-char ch out))
((csv-grammar-escape-char grammar)
=> (lambda (esc) (write-char esc out)))
(else (error "no quote defined for" ch grammar)))
(write-char ch out)
(lp))
(else
(write-char ch out)
(lp)))))
(write-char (csv-grammar-quote-char grammar) out)))
(define csv-writer
(opt-lambda ((grammar default-csv-grammar))
(opt-lambda (row (out (current-output-port)))
(let lp ((ls row) (first? #t))
(when (pair? ls)
(unless first?
(write-char (car (csv-grammar-separator-chars grammar)) out))
(if (or (and (csv-grammar-quote-non-numeric? grammar)
(not (number? (car ls))))
(and (string? (car ls))
(string-any
(lambda (ch) (csv-grammar-char-needs-quoting? grammar ch))
(car ls)))
(and (not (string? (car ls)))
(not (number? (car ls)))
(not (symbol? (car ls)))))
(csv-write-quoted (car ls) out grammar)
(display (car ls) out))
(lp (cdr ls) #f)))
(write-string
(case (csv-grammar-record-separator grammar)
((crlf) "\r\n")
((lf lax) "\n")
((cr) "\r")
(else (string (csv-grammar-record-separator grammar))))
out))))
(define csv-write
(opt-lambda ((writer (csv-writer)))
(opt-lambda (rows (out (current-output-port)))
(for-each
(lambda (row) (writer row out))
rows))))

11
lib/chibi/csv.sld Normal file
View file

@ -0,0 +1,11 @@
(define-library (chibi csv)
(import (scheme base) (scheme write) (srfi 130) (srfi 227))
(export csv-grammar csv-parser csv-grammar?
default-csv-grammar default-tsv-grammar
csv-read->list csv-read->vector csv-read->fixed-vector
csv-read->sxml csv-num-rows
csv-fold csv-map csv->list csv-for-each csv->sxml
csv-writer csv-write
csv-skip-line)
(include "csv.scm"))

63
lib/chibi/diff-test.sld Normal file
View file

@ -0,0 +1,63 @@
(define-library (chibi diff-test)
(import (scheme base) (chibi diff))
(export run-tests)
(cond-expand
(chibi (import (chibi test)))
(else
(import (scheme write))
;; inline (chibi test) to avoid circular dependencies in snow
;; installations
(begin
(define-syntax test
(syntax-rules ()
((test expect expr)
(test 'expr expect expr))
((test name expect expr)
(guard (exn (else (display "!\nERROR: ") (write name) (newline)
(write exn) (newline)))
(let* ((res expr)
(pass? (equal? expect expr)))
(display (if pass? "." "x"))
(cond
((not pass?)
(display "\nFAIL: ") (write name) (newline))))))))
(define (test-begin name)
(display name))
(define (test-end)
(newline)))))
(begin
(define (run-tests)
(test-begin "diff")
(test '((#\A 1 0) (#\C 2 2))
(lcs-with-positions '(#\G #\A #\C) '(#\A #\G #\C #\A #\T)))
(test '(#\A #\C)
(lcs '(#\G #\A #\C) '(#\A #\G #\C #\A #\T)))
(test '((#\G #\A #\C) (#\A #\G #\C #\A #\T) ((#\A 1 0) (#\C 2 2)))
(diff "GAC" "AGCAT" read-char))
(test '((#\A #\G #\C #\A #\T) (#\A #\G #\C #\A #\T)
((#\A 0 0) (#\G 1 1) (#\C 2 2) (#\A 3 3) (#\T 4 4)))
(diff "AGCAT" "AGCAT" read-char))
(test '((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\.
#\G #\A #\C #\. #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\.
#\A #\G #\C #\A #\T #\. #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
((#\0 0 0) (#\1 1 1) (#\2 2 2) (#\3 3 3) (#\4 4 4) (#\5 5 5)
(#\6 6 6) (#\7 7 7) (#\8 8 8) (#\9 9 9) (#\. 10 10)
(#\A 12 11) (#\C 13 13)
(#\. 14 16) (#\0 15 17) (#\1 16 18) (#\2 17 19) (#\3 18 20)
(#\4 19 21) (#\5 20 22) (#\6 21 23) (#\7 22 24) (#\8 23 25)
(#\9 24 26)))
(diff "0123456789.GAC.0123456789"
"0123456789.AGCAT.0123456789"
read-char))
(let ((d (diff "GAC" "AGCAT" read-char)))
(test " »G« AC"
(edits->string (car d) (car (cddr d)) 1))
(test "A «G» C «AT» "
(edits->string (cadr d) (car (cddr d)) 2))
(test "\x1b;[31mG\x1b;[39mAC"
(edits->string/color (car d) (car (cddr d)) 1))
(test "A\x1b;[32mG\x1b;[39mC\x1b;[32mAT\x1b;[39m"
(edits->string/color (cadr d) (car (cddr d)) 2)))
(test-end))))

279
lib/chibi/diff.scm Normal file
View file

@ -0,0 +1,279 @@
;; utility for lcs-with-positions
(define (max-seq . o)
(if (null? o)
(list 0 '())
(let loop ((a (car o)) (ls (cdr o)))
(if (null? ls)
a
(let ((b (car ls)))
(if (>= (car a) (car b))
(loop a (cdr ls))
(loop b (cdr ls))))))))
;;> Finds the Longest Common Subsequence between \var{a-ls} and
;;> \var{b-ls}, comparing elements with \var{eq} (default
;;> \scheme{equal?}. Returns this sequence as a list, using the
;;> elements from \var{a-ls}. Uses quadratic time and space.
(define (lcs a-ls b-ls . o)
(let ((eq (if (pair? o) (car o) equal?)))
(map car (lcs-with-positions a-ls b-ls eq))))
;;> Variant of \scheme{lcs} which returns the annotated sequence. The
;;> result is a list of the common elements, each represented as a
;;> list of 3 values: the element, the zero-indexed position in
;;> \var{a-ls} where the element occurred, and the position in
;;> \var{b-ls}.
(define (lcs-with-positions a-ls b-ls . o)
(let* ((eq (if (pair? o) (car o) equal?))
(a-len (+ 1 (length a-ls)))
(b-len (+ 1 (length b-ls)))
(results (make-vector (* a-len b-len) #f)))
(let loop ((a a-ls) (a-pos 0) (b b-ls) (b-pos 0))
;; cache this step if not already done
(let ((i (+ (* a-pos b-len) b-pos)))
(or (vector-ref results i)
(let ((res
(if (or (null? a) (null? b))
(list 0 '()) ;; base case
(let ((a1 (car a))
(b1 (car b))
(a-tail (loop (cdr a) (+ a-pos 1) b b-pos))
(b-tail (loop a a-pos (cdr b) (+ b-pos 1))))
(cond
((eq a1 b1)
;; match found, we either use it or we don't
(let* ((a-b-tail (loop (cdr a) (+ a-pos 1)
(cdr b) (+ b-pos 1)))
(a-b-res (list (+ 1 (car a-b-tail))
(cons (list a1 a-pos b-pos)
(cadr a-b-tail)))))
(max-seq a-b-res a-tail b-tail)))
(else
;; not a match
(max-seq a-tail b-tail)))))))
(vector-set! results i res)
res))))
(cadr (vector-ref results 0))))
(define (source->list x reader)
(port->list
reader
(cond ((port? x) x)
((string? x) (open-input-string x))
(else (error "don't know how to diff from:" x)))))
;;> Utility to run lcs on text. \var{a} and \var{b} can be strings or
;;> ports, which are tokenized into a sequence by calling \var{reader}
;;> until \var{eof-object} is found. Returns a list of three values,
;;> the sequences read from \var{a} and \var{b}, and the \scheme{lcs}
;;> result. Unless \var{minimal?} is set, we trim common
;;> prefixes/suffixes before computing the lcs.
(define (diff a b . o)
(let-optionals o ((reader read-line)
(eq equal?)
(optimal? #f))
(let ((a-ls (source->list a reader))
(b-ls (source->list b reader)))
(if optimal?
(list a-ls b-ls (lcs-with-positions a-ls b-ls eq))
(let lp1 ((i 0) (a a-ls) (b b-ls))
(cond
((or (null? a) (null? b)) ;; prefix or equal
(if (and (null? a) (null? b))
(let ((n-ls (iota (length a-ls)))) ;; equal
(list a-ls b-ls (map list a-ls n-ls n-ls)))
(list a-ls b-ls (lcs-with-positions a-ls b-ls eq))))
((eq (car a) (car b))
(lp1 (+ i 1) (cdr a) (cdr b)))
(else
(let lp2 ((j 0) (ra (reverse a)) (rb (reverse b)))
(cond
((or (null? ra) (null? rb)) ;; can't happen
(list a-ls b-ls (lcs-with-positions a-ls b-ls eq)))
((eq (car ra) (car rb))
(lp2 (+ j 1) (cdr ra) (cdr rb)))
(else
(let* ((a-ls2 (reverse ra))
(b-ls2 (reverse rb))
(a-left-len (+ i (length a-ls2)))
(b-left-len (+ i (length b-ls2))))
(list a-ls
b-ls
(append
(map (lambda (x i) (list x i i))
(take a-ls i)
(iota i))
(map (lambda (x)
(list (car x)
(+ i (cadr x))
(+ i (car (cddr x)))))
(lcs-with-positions a-ls2 b-ls2 eq))
(map (lambda (x i)
(list x (+ i a-left-len) (+ i b-left-len)))
(take-right a j)
(iota j))))))
)))))))))
;;> Utility to format the result of a \var{diff} to output port
;;> \var{out} (default \scheme{(current-output-port)}). Applies
;;> \var{writer} to successive diff chunks. \var{writer} should be a
;;> procedure of three arguments: \scheme{(writer subsequence type
;;> out). \var{subsequence} is a subsequence from the original input,
;;> \var{type} is a symbol indicating the type of diff: \scheme{'same}
;;> if this is part of the lcs, \scheme{'add} if it is unique to the
;;> second input, or \scheme{'remove} if it is unique to the first
;;> input. \var{writer} defaults to \scheme{write-line-diffs},
;;> assuming the default line diffs.
(define (write-diff diff . o)
(let-optionals o ((writer write-line-diffs)
(out (current-output-port)))
(let* ((a-ls (car diff))
(b-ls (cadr diff))
(d-ls (car (cddr diff))))
;; context diff
(let lp ((d d-ls) (a a-ls) (a-pos 0) (b b-ls) (b-pos 0))
(unless (null? d)
(let* ((d1 (car d))
(a-off (cadr d1))
(a-skip (- a-off a-pos))
(b-off (car (cddr d1)))
(b-skip (- b-off b-pos)))
(let-values (((a-head a-tail) (split-at a a-skip))
((b-head b-tail) (split-at b b-skip)))
;; elements only in a have been removed
(if (pair? a-head)
(writer (cdr a-head) 'remove out))
;; elements only in b have been added
(if (pair? b-head)
(writer (cdr b-head) 'add out))
;; reprint this common element
(writer (list (car d1)) 'same out)
;; recurse
(lp (cdr d) a-tail a-off b-tail b-off))))))))
;;> Equivalent to \scheme{write-diff} but collects the output to a string.
(define (diff->string diff . o)
(let ((out (open-output-string)))
(write-diff diff (if (pair? o) (car o) write-line-diffs) out)
(get-output-string out)))
;;> The default writer for \scheme{write-diff}, annotates simple +/-
;;> prefixes for added/removed lines.
(define (write-line-diffs lines type out)
(for-each
(lambda (line)
(case type
((add)
(write-char #\+ out))
((remove)
(write-char #\- out))
((same)
(write-char #\space out))
(else (error "unknown diff type:" type)))
(write-string line out)
(newline out))
lines))
;;> A variant of \scheme{write-line-diffs} which adds red/green ANSI
;;> coloring to the +/- prefix.
(define (write-line-diffs/color lines type out)
(for-each
(lambda (line)
(case type
((add)
(write-string (green "+") out)
(write-string (green line) out))
((remove)
(write-string (red "-") out)
(write-string (red line) out))
((same)
(write-char #\space out)
(write-string line out))
(else (error "unknown diff type:" type)))
(newline out))
lines))
;;> A diff writer for sequences of characters (when a diff was
;;> generated with \scheme{read-char}), enclosing added characters in
;;> «...» brackets and removed characters in »...«.
(define (write-char-diffs chars type out)
(case type
((add)
(write-string " «" out)
(write-string (list->string chars) out)
(write-string "» " out))
((remove)
(write-string " »" out)
(write-string (list->string chars) out)
(write-string "« " out))
((same)
(write-string (list->string chars) out))
(else (error "unknown diff type:" type))))
;;> A diff writer for sequences of characters (when a diff was
;;> generated with \scheme{read-char}), formatting added characters in
;;> green and removed characters in red.
(define (write-char-diffs/color chars type out)
(case type
((add)
(write-string (green (list->string chars)) out))
((remove)
(write-string (red (list->string chars)) out))
((same)
(write-string (list->string chars) out))
(else (error "unknown diff type:" type))))
;;> Utility to format the result of a \scheme{diff} with respect to a
;;> single input sequence \var{ls}. \var{lcs} is the annotated common
;;> sequence from \scheme{diff} or \scheme{lcs-with-positions}, and
;;> \var{index} is the index (0 or 1, default 1) of \var{ls} in the
;;> original call. Since we have no information about the other
;;> input, we can only format what is the same and what is different,
;;> formatting the differences as either added (if \var{index} is 0)
;;> or removed (if \var{index} is 1).
(define (write-edits ls lcs . o)
(let-optionals o ((index 1)
(writer write-line-diffs)
(out (current-output-port)))
(let ((type (if (eq? index 1) 'remove 'add)))
(let lp ((ls ls) (lcs lcs) (buf '(#f)) (i 0))
(define (output ch type)
(cond
((eq? type (car buf))
(cons type (cons ch (cdr buf))))
(else
(if (car buf)
(writer (reverse (cdr buf)) (car buf) out))
(list type ch))))
(cond
((null? ls) (output #f 'done))
((null? lcs)
(lp (cdr ls) lcs (output (car ls) type) (+ i 1)))
((= i (list-ref (car lcs) index))
(lp (cdr ls) (cdr lcs) (output (car ls) 'same) (+ i 1)))
(else
(lp (cdr ls) lcs (output (car ls) type) (+ i 1))))))))
;;> Equivalent to \scheme{write-edits} but collects the output to a string.
(define (edits->string ls lcs . o)
(let-optionals o ((type 'add)
(writer (if (and (pair? ls) (char? (car ls)))
write-char-diffs
write-line-diffs)))
(let ((out (open-output-string)))
(write-edits ls lcs type writer out)
(get-output-string out))))
;;> Equivalent to \scheme{write-edits} but collects the output to a
;;> string and uses a color-aware writer by default. Note with a
;;> character diff this returns the original input string as-is, with
;;> only ANSI escapes indicating what changed.
(define (edits->string/color ls lcs . o)
(let-optionals o ((type 'add)
(writer (if (and (pair? ls) (char? (car ls)))
write-char-diffs/color
write-line-diffs/color)))
(let ((out (open-output-string)))
(write-edits ls lcs type writer out)
(get-output-string out))))

21
lib/chibi/diff.sld Normal file
View file

@ -0,0 +1,21 @@
(define-library (chibi diff)
(import (scheme base) (srfi 1) (chibi optional) (chibi term ansi))
(export lcs lcs-with-positions
diff write-diff diff->string
write-edits edits->string edits->string/color
write-line-diffs
write-line-diffs/color
write-char-diffs
write-char-diffs/color)
(cond-expand
(chibi (import (only (chibi io) port->list)))
(else
(begin
(define (port->list reader port)
(let lp ((res '()))
(let ((x (reader port)))
(if (eof-object? x)
(reverse res)
(lp (cons x res)))))))))
(include "diff.scm"))

View file

@ -11,20 +11,24 @@
#define SEXP_DISASM_PAD_WIDTH 4
#if SEXP_64_BIT
#ifdef _WIN32
#define SEXP_PRId "%I64d"
#else
#define SEXP_PRId "%ld"
#endif
#else
#define SEXP_PRId "%d"
#endif
static void sexp_write_pointer (sexp ctx, void *p, sexp out) {
char buf[32];
sprintf(buf, "%p", p);
snprintf(buf, sizeof(buf), "%p", p);
sexp_write_string(ctx, buf, out);
}
static void sexp_write_integer (sexp ctx, sexp_sint_t n, sexp out) {
char buf[32];
sprintf(buf, SEXP_PRId, n);
snprintf(buf, sizeof(buf), SEXP_PRId, n);
sexp_write_string(ctx, buf, out);
}
@ -37,6 +41,10 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
sexp_sint_t src_off=0;
#endif
if (sexp_idp(bc))
bc = sexp_env_ref(ctx, sexp_context_env(ctx), bc, SEXP_FALSE);
if (sexp_macrop(bc))
bc = sexp_macro_proc(bc);
if (sexp_procedurep(bc)) {
bc = sexp_procedure_code(bc);
} else if (sexp_opcodep(bc)) {
@ -76,14 +84,20 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
/* build a table of labels that are jumped to */
labels = (sexp_sint_t*)calloc(sexp_bytecode_length(bc), sizeof(sexp_sint_t));
ip = sexp_bytecode_data(bc);
while (ip - sexp_bytecode_data(bc) < sexp_bytecode_length(bc)) {
while (ip - sexp_bytecode_data(bc) < (int)sexp_bytecode_length(bc)) {
switch (*ip++) {
case SEXP_OP_JUMP:
case SEXP_OP_JUMP_UNLESS:
off = ip - sexp_bytecode_data(bc) + ((sexp_sint_t*)ip)[0];
if (off >= 0 && off < sexp_bytecode_length(bc) && labels[off] == 0)
if (off >= 0 && off < (int)sexp_bytecode_length(bc) && labels[off] == 0)
labels[off] = label++;
case SEXP_OP_CALL:
case SEXP_OP_FCALL0:
case SEXP_OP_FCALL1:
case SEXP_OP_FCALL2:
case SEXP_OP_FCALL3:
case SEXP_OP_FCALL4:
case SEXP_OP_FCALLN:
case SEXP_OP_CLOSURE_REF:
case SEXP_OP_GLOBAL_KNOWN_REF:
case SEXP_OP_GLOBAL_REF:
@ -130,7 +144,7 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
== sexp_unbox_fixnum(
sexp_car(sexp_vector_ref(src, sexp_make_fixnum(src_off)))))) {
src_here = sexp_cdr(sexp_vector_ref(src, sexp_make_fixnum(src_off)));
src_off = src_off < sexp_vector_length(src)-1 ? src_off + 1 : -1;
src_off = src_off < (sexp_sint_t)sexp_vector_length(src)-1 ? src_off + 1 : -1;
} else {
src_here = NULL;
}
@ -159,7 +173,7 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
case SEXP_OP_JUMP_UNLESS:
sexp_write_integer(ctx, ((sexp_sint_t*)ip)[0], out);
off = ip - sexp_bytecode_data(bc) + ((sexp_sint_t*)ip)[0];
if (off >= 0 && off < sexp_bytecode_length(bc) && labels[off] > 0) {
if (off >= 0 && off < (sexp_sint_t)sexp_bytecode_length(bc) && labels[off] > 0) {
sexp_write_string(ctx, " L", out);
sexp_write_integer(ctx, labels[off], out);
}
@ -170,6 +184,7 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
case SEXP_OP_FCALL2:
case SEXP_OP_FCALL3:
case SEXP_OP_FCALL4:
case SEXP_OP_FCALLN:
sexp_write_pointer(ctx, ((sexp*)ip)[0], out);
sexp_write_char(ctx, ' ', out);
sexp_write(ctx, sexp_opcode_name(((sexp*)ip)[0]), out);
@ -220,7 +235,7 @@ static sexp disasm (sexp ctx, sexp self, sexp bc, sexp out, int depth) {
&& (depth < SEXP_DISASM_MAX_DEPTH)
&& tmp && (sexp_bytecodep(tmp) || sexp_procedurep(tmp)))
disasm(ctx, self, tmp, out, depth+1);
if (ip - sexp_bytecode_data(bc) < sexp_bytecode_length(bc))
if (ip - sexp_bytecode_data(bc) < (int)sexp_bytecode_length(bc))
goto loop;
free(labels);

View file

@ -25,4 +25,25 @@
(index (if (pair? o) (car o) 0))
(acc knil))
(f p index fk)))))
(test "hello" (ansi->sxml "hello"))
(test '(span "[ " (span (@ (style . "color:red")) "FAIL") "]")
(ansi->sxml "[ \x1B;[31mFAIL\x1B;[39m]"))
(test '(span (u "under " (span (@ (style . "color:red")) "red") " line"))
(ansi->sxml "\x1B;[4munder \x1B;[31mred\x1B;[39m line\x1B;[24m"))
(test '(span "plain "
(u "under "
(span (@ (style . "color:red")) "red")
" line"))
(ansi->sxml
"plain \x1B;[4munder \x1B;[31mred\x1B;[39m line\x1B;[24m"))
(test '(code "(" "string?" " "
(span (@ (class . "string")) "\"hello\"")
")")
(expand-docs '(scheme "(string? \"hello\")")
(make-default-doc-env)))
(test '(code "(" "string?" " "
(span (@ (class . "string")) "\"<hello>\"")
")")
(expand-docs '(scheme "(string? \"<hello>\")")
(make-default-doc-env)))
(test-end))))

View file

@ -79,6 +79,95 @@
(define (sxml->sexp-list x)
(call-with-input-string (sxml-strip x) port->sexp-list))
;;> Replace ansi escape sequences in a \var{str} with the corresponding sxml.
(define (ansi->sxml str)
;; TODO: ick
(let ((start (string-cursor-start str))
(end (string-cursor-end str)))
(let lp1 ((from start)
(to start)
(res '()))
(define (lookup str)
(case (string->number str)
((0) '/) ((1) 'b) ((3) 'i) ((4) 'u) ((9) 's)
((22) '/b) ((23) '/i) ((24) '/u) ((29) '/s)
((30) 'black) ((31) 'red) ((32) 'green) ((33) 'yellow)
((34) 'blue) ((35) 'magenta) ((36) 'cyan) ((37) 'white)
((39) '/color)
(else #f)))
(define (collect from to res)
(if (string-cursor<? from to)
(cons (substring-cursor str from to) res)
res))
(define (finish)
(let ((ls (reverse (collect from to res))))
(if (and (= 1 (length ls)) (string? (car ls)))
(car ls)
(let lp1 ((ls ls) (cur '()) (res '()))
(define (close to)
(let lp2 ((ls cur) (tmp '()))
(cond
((null? ls)
(list '() `(,@(reverse tmp) ,@res)))
((eq? to (car ls))
(list (cdr ls) `((,to ,@tmp) ,@res)))
((and (eq? to 'color) (memq (car ls) '(b i u s)))
;; color close came to an open non-color
;; back off and leave this open
(let ((s `(,(car ls) ,@(take-while string? tmp)))
(tmp (drop-while string? tmp)))
(list `(,@(reverse tmp) ,@(reverse s)) res)))
((symbol? (car ls))
(lp2 (cdr ls) `((,(car ls) ,@(reverse tmp)))))
((and (pair? (car ls)) (eq? 'color to))
(lp2 (cdr ls) `((,@(car ls) ,@(reverse tmp)))))
((pair? (car ls))
(lp2 (cdr ls) `(,(car ls) ,@(reverse tmp))))
(else
(lp2 (cdr ls) `(,(car ls) ,@tmp))))))
(cond
((null? ls)
`(span ,@(reverse (cadr (close #f)))))
((and (string? (car ls)) (pair? cur))
(lp1 (cdr ls) (cons (car ls) cur) res))
((string? (car ls))
(lp1 (cdr ls) cur (cons (car ls) res)))
(else
(case (car ls)
((b i u s) (lp1 (cdr ls) (cons (car ls) cur) res))
((/b) (apply lp1 (cdr ls) (close 'b)))
((/i) (apply lp1 (cdr ls) (close 'i)))
((/u) (apply lp1 (cdr ls) (close 'u)))
((/s) (apply lp1 (cdr ls) (close 's)))
((/) (apply lp1 (cdr ls) (close 'all)))
((/color) (apply lp1 (cdr ls) (close 'color)))
(else
(let ((style (string-append "color:"
(symbol->string (car ls)))))
(lp1 (cdr ls)
(cons `(span (@ (style . ,style))) cur)
res))))))))))
(if (string-cursor>=? to end)
(finish)
(let ((c (string-cursor-ref str to))
(sc2 (string-cursor-next str to)))
(if (and (= 27 (char->integer c))
(string-cursor<? sc2 end)
(eqv? #\[ (string-cursor-ref str sc2)))
(let ((sc3 (string-cursor-next str sc2)))
(let lp2 ((sc4 sc3))
(if (string-cursor>=? sc4 end)
(finish)
(let ((c2 (string-cursor-ref str sc4))
(sc5 (string-cursor-next str sc4)))
(if (eqv? #\m c2)
(let ((code (lookup
(substring-cursor str sc3 sc4)))
(res (collect from to res)))
(lp1 sc5 sc5 (if code (cons code res) res)))
(lp2 sc5))))))
(lp1 from sc2 res)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> Extract the literate Scribble docs for module \var{mod-name} and
@ -88,9 +177,11 @@
(define (print-module-docs mod-name . o)
(let ((out (if (pair? o) (car o) (current-output-port)))
(render (or (and (pair? o) (pair? (cdr o)) (cadr o))
sxml-display-as-text)))
sxml-display-as-text))
(unexpanded?
(and (pair? o) (pair? (cdr o)) (pair? (cddr o)) (car (cddr o)))))
(render
(generate-docs
((if unexpanded? (lambda (sxml env) (fixup-docs sxml)) generate-docs)
`((title ,(write-to-string mod-name))
,@(extract-module-docs mod-name #f))
(make-module-doc-env mod-name))
@ -176,6 +267,8 @@
(url . ,expand-url)
(hyperlink . ,expand-hyperlink)
(rawcode . code)
(pre . pre)
(bibitem . ,(lambda (x env) '())) ;; TODO: bibtex
(code . ,expand-code)
(codeblock . ,expand-codeblock)
(ccode
@ -195,6 +288,7 @@
(margin-note . ,expand-note)
(example . ,expand-example)
(example-import . ,expand-example-import)
(example-import-only . ,expand-example-import-only)
)))
;;> Return a new document environment as in
@ -206,9 +300,9 @@
(define (make-module-doc-env mod-name)
(env-extend (make-default-doc-env)
'(example-env)
(list (environment '(scheme small)
(list (delay (environment '(scheme small)
'(only (chibi) import)
mod-name))))
mod-name)))))
(define (section-name tag name)
(string-strip
@ -269,21 +363,41 @@
(define (expand-example x env)
(let ((expr `(begin ,@(sxml->sexp-list x)))
(example-env (or (env-ref env 'example-env) (current-environment))))
(example-env
(force (or (env-ref env 'example-env) (current-environment)))))
`(div
,(expand-codeblock `(,(car x) language: scheme ,@(cdr x)) env)
(code
(div (@ (class . "result"))
,(call-with-output-string
(lambda (out)
(protect (exn (#t (print-exception exn out)))
(let ((res (eval expr example-env)))
(display "=> " out)
(write res out))))))))))
,(let* ((res-out (open-output-string))
(tmp-out (open-output-string))
(tmp-err (open-output-string))
(res (parameterize ((current-output-port tmp-out)
(current-error-port tmp-err))
(protect (exn (#t (print-exception exn tmp-err)))
(eval expr example-env)))))
(display "=> " res-out)
(write res res-out)
(let ((res-str (get-output-string res-out))
(out-str (get-output-string tmp-out))
(err-str (get-output-string tmp-err)))
`(,@(if (string-null? out-str)
'()
`((div (@ (class . "output")) (pre ,(ansi->sxml out-str)))))
,@(if (string-null? err-str)
'()
`((div (@ (class . "error")) (pre ,(ansi->sxml err-str)))))
,@(if (and (or (not (string-null? err-str))
(not (string-null? out-str)))
(eq? res (if #f #f)))
'()
`((div (@ (class . "result")) (code ,res-str))))))))))
(define (expand-example-import x env)
(eval `(import ,@(cdr x))
(or (env-ref env 'example-env) (current-environment)))
(force (or (env-ref env 'example-env) (current-environment))))
"")
(define (expand-example-import-only x env)
(env-set! env 'example-env (apply environment (cdr x)))
"")
(define (expand-command sxml env)
@ -315,7 +429,7 @@
sxml)))
(define (expand-procedure sxml env)
((expand-section 'h3) `(,(car sxml) (rawcode ,@(cdr sxml))) env))
((expand-section 'h4) `(,(car sxml) (rawcode ,@(cdr sxml))) env))
(define (expand-macro sxml env)
(expand-procedure sxml env))
@ -354,31 +468,45 @@
(define (get-contents x)
(if (null? x)
'()
(let ((d (caar x)))
(let lp ((ls (cdr x)) (parent (car (cdar x))) (kids '()) (res '()))
(let lp ((ls (cdr x))
(depth (caar x))
(parent (cadr (car x)))
(kids '())
(res '()))
(define (collect)
(cons `(li ,parent ,(get-contents (reverse kids))) res))
;; take a span of all sub-headers, recurse and repeat on next span
(cond
((null? ls)
`(ol ,@(reverse (collect))))
((> (caar ls) d)
(lp (cdr ls) parent (cons (car ls) kids) res))
((> (caar ls) depth)
(lp (cdr ls) depth parent (cons (car ls) kids) res))
(else
(lp (cdr ls) (car (cdar ls)) '() (collect))))))))
(lp (cdr ls) (caar ls) (cadr (car ls)) '() (collect)))))))
(define (fix-header x)
`(html (head ,@(cond ((assq 'title x) => (lambda (x) (list x)))
`((!DOCTYPE html)
(html (head ,@(cond ((assq 'title x) => (lambda (x) (list x)))
(else '()))
"\n"
(meta (@ (charset . "UTF-8")))
(style (@ (type . "text/css"))
"
body {color: #000; background-color: #FFF}
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 190px; height: 100%}
div#main {position: absolute; top: 0; left: 200px; width: 540px; height: 100%}
div#notes {position: relative; top: 2em; left: 570px; max-width: 200px; height: 0px; font-size: smaller;}
body {color: #000; background-color: #FFFFF8;}
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 250px; height: 100%}
div#menu a:link {text-decoration: none}
div#main {font-size: large; position: absolute; top: 0; left: 260px; max-width: 590px; height: 100%}
div#notes {position: relative; top: 2em; left: 620px; width: 200px; height: 0px; font-size: smaller;}
div#footer {padding-bottom: 50px}
div#menu ol {list-style-position:inside; padding-left: 5px; margin-left: 5px}
div#menu ol ol {list-style: lower-alpha; padding-left: 15px; margin-left: 15px}
div#menu ol ol ol {list-style: decimal; padding-left: 5px; margin-left: 5px}
h2 { color: #888888; border-top: 3px solid #4588ba; }
h3 { color: #666666; border-top: 2px solid #4588ba; }
h4 { color: #222288; border-top: 1px solid #4588ba; }
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
.output { color: #000; background-color: beige; width: 100%; padding: 3px}
.error { color: #000; background-color: #F0B0B0; width: 100%; padding: 3px}
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
"
,(highlight-style))
@ -397,7 +525,7 @@ div#footer {padding-bottom: 50px}
(cons 'h1 (cdr x))
x))
x)
(div (@ (id . "footer")))))))
(div (@ (id . "footer"))))))))
(define (fix-paragraphs x)
(let lp ((ls x) (p '()) (res '()))
@ -513,10 +641,14 @@ div#footer {padding-bottom: 50px}
((v ('if ('and ('pair? (? o?)) ('pair? ('cdr (? o?))))
('cadr (? o?))
default))
(lp (cdr ls) (cons (cons v (if ordered? j i)) vars) j))
(lp (cdr ls)
(cons (cons v (+ 1 (if ordered? j i))) vars)
j))
((v ('and ('pair? (? o?)) ('pair? ('cdr (? o?)))
('cadr (? o?))))
(lp (cdr ls) (cons (cons v (if ordered? j i)) vars) j))
(lp (cdr ls)
(cons (cons v (+ 1 (if ordered? j i))) vars)
j))
(else
(lp (cdr ls) vars j))))
(else
@ -528,14 +660,13 @@ div#footer {padding-bottom: 50px}
(let lp ((ls var) (vars vars) (i i))
(cond
((pair? ls)
(lp (cdr ls) (cons (cons (caar ls) i) vars) (+ i 1)))
(lp (cdr ls) (cons (cons (car ls) i) vars) (+ i 1)))
(else
(extract body vars i)))))
(else
(let ((opts (map car (sort vars < cdr)))
(rest-var? (contains? x o)))
(append (reverse pre)
(cond
(_
(let* ((opts (map car (sort vars < cdr)))
(rest-var? (contains? x o))
(tail (cond
((and (pair? opts) rest-var?)
(list (append opts o)))
(rest-var?
@ -543,17 +674,19 @@ div#footer {padding-bottom: 50px}
((pair? opts)
(list opts))
(else
'()))))))))))))
o))))
(append (reverse pre) tail))))))))))
(define (get-procedure-signature mod id proc)
(protect (exn (else '()))
(cond ((and mod (procedure? proc) (procedure-signature id mod))
=> (lambda (sig)
(list (cons (or id (procedure-name proc)) (cdr sig)))))
(else '())))
(else '()))))
(define (get-value-signature mod id proc name value)
(match value
(('(or let let* letrec letrec*) vars body0 ... body)
(((or 'let 'let* 'letrec 'letrec*) vars body0 ... body)
(get-value-signature mod id proc name body))
(('lambda args . body)
(list (cons name (get-optionals-signature args body))))
@ -562,8 +695,6 @@ div#footer {padding-bottom: 50px}
(('begin body0 ... body) (get-value-signature mod id proc name body))
(else (get-procedure-signature mod id proc))))
;; TODO: analyze and match on AST instead of making assumptions about
;; bindings
(define (get-signature mod id proc source form)
(match form
(('define (name args ...) . body)
@ -577,7 +708,11 @@ div#footer {padding-bottom: 50px}
(map (lambda (x) (cons name (cdr x)))
(filter external-clause? clause)))
(else
(get-procedure-signature mod id proc))))
(cond
((procedure-analysis proc mod)
=> (lambda (lam) (list (cons (lambda-name lam) (lambda-params lam)))))
(else
(get-procedure-signature mod id proc))))))
(define (get-ffi-signatures form)
(match form
@ -590,6 +725,8 @@ div#footer {padding-bottom: 50px}
args)))))
(('define-c-const type (or (name _) name))
(list (list 'const: type name)))
(('cond-expand (test . clauses) . rest)
(append-map get-ffi-signatures clauses))
(((or 'define-c-struct 'define-c-class 'define-c-type) name . rest)
(let lp ((ls rest) (res '()))
(cond
@ -618,7 +755,7 @@ div#footer {padding-bottom: 50px}
(let ((sections '(section subsection subsubsection subsubsubsection)))
(lambda (x)
(cond ((memq x sections) => length)
((memq x '(procedure macro)) (section-number 'subsection))
((memq x '(procedure macro)) (section-number 'subsubsection))
(else 0)))))
(define (section>=? x n)
@ -676,9 +813,10 @@ div#footer {padding-bottom: 50px}
(write-to-string sig)))
(define (insert-signature orig-ls name sig)
(let ((sig (if (pair? sig) sig (and name (list name)))))
(cond
((not (pair? sig))
orig-ls)
'())
(else
(let ((name
(cond
@ -689,15 +827,16 @@ div#footer {padding-bottom: 50px}
(let lp ((ls orig-ls) (rev-pre '()))
(cond
((or (null? ls)
(section>=? (car ls) (section-number 'subsection)))
(section>=? (car ls) (section-number 'subsubsection)))
`(,@(reverse rev-pre)
,@(if (and (pair? ls)
(section-describes?
(extract-sxml '(subsection procedure macro)
(extract-sxml
'(subsubsection procedure macro)
(car ls))
name))
'()
`((subsection
`((subsubsection
tag: ,(write-to-string name)
(rawcode
,@(if (and (pair? (car sig)) (eq? 'const: (caar sig)))
@ -706,7 +845,7 @@ div#footer {padding-bottom: 50px}
(intersperse (map write-signature sig) '(br)))))))
,@ls))
(else
(lp (cdr ls) (cons (car ls) rev-pre)))))))))
(lp (cdr ls) (cons (car ls) rev-pre))))))))))
;;> Extract inline Scribble documentation (with the ;;> prefix) from
;;> the source file \var{file}, associating any signatures from the
@ -714,17 +853,22 @@ div#footer {padding-bottom: 50px}
(define (extract-file-docs mod file all-defs strict? . o)
;; extract (<file> . <line>) macro source or
;; (<offset> <file . <line>>) procedure source
;; (<offset> <file . <line>) procedure source or
;; ((<offset> <file . <line>) ...) bytecode sources
(define (source-line source)
(and (pair? source)
(if (string? (car source))
(cond
((string? (car source))
(and (equal? file (car source))
(number? (cdr source))
(cdr source))
(cdr source)))
((pair? (car source))
(source-line (car source)))
(else
(and (number? (car source))
(pair? (cdr source))
(equal? file (cadr source))
(cddr source)))))
(cddr source))))))
(define (read-to-paren in)
(let lp1 ((res '()))
(let ((ch (peek-char in)))
@ -894,21 +1038,28 @@ div#footer {padding-bottom: 50px}
(else #f)))
;; helper for below functions
(define (extract-module-docs-from-files mod srcs includes stubs strict? exports)
(let ((defs (map (lambda (x)
(let ((val (and mod (module-ref mod x))))
(define (extract-module-docs-from-files mod srcs includes stubs strict? exports . o)
(let ((dir (or (and (pair? o) (car o)) (module-dir mod)))
(defs (map (lambda (x)
(let ((val (and mod (protect (exn (else #f))
(module-ref mod x)))))
`(,x ,val ,(object-source val))))
exports)))
(define (resolve-file file)
(let ((res (make-path dir file)))
(if (file-exists? res)
res
file)))
(append
(reverse
(append-map (lambda (x)
(extract-file-docs mod x defs strict? 'module))
(extract-file-docs mod (resolve-file x) defs strict? 'module))
srcs))
(reverse
(append-map (lambda (x) (extract-file-docs mod x defs strict?))
(append-map (lambda (x) (extract-file-docs mod (resolve-file x) defs strict?))
includes))
(reverse
(append-map (lambda (x) (extract-file-docs mod x defs strict? 'ffi))
(append-map (lambda (x) (extract-file-docs mod (resolve-file x) defs strict? 'ffi))
stubs)))))
;;> Extract the literate Scribble docs from module \var{mod-name} and
@ -939,30 +1090,55 @@ div#footer {padding-bottom: 50px}
(memq (caar forms) '(define-library library))))
(error "file doesn't define a library" file))
(let* ((mod-form (car forms))
(mod-name (cadr mod-form)))
(load file (vector-ref (find-module '(meta)) 1))
(let* ((mod (protect (exn (else #f)) (load-module mod-name)))
(dir (path-directory file))
(resolve (lambda (f) (make-path dir f))))
(define (get-forms name)
(mod-name (cadr mod-form))
(lib-dir (module-lib-dir file mod-name))
(orig-mod-path (current-module-path))
(new-mod-path (cons lib-dir orig-mod-path))
(mod (protect (exn (else #f))
(dynamic-wind
(lambda () (current-module-path new-mod-path))
(lambda ()
(let ((mod (load-module mod-name)))
(protect (exn (else #f)) (analyze-module mod-name))
mod))
(lambda () (current-module-path orig-mod-path)))))
(dir (path-directory file)))
(define (get-forms ls names dir . o)
(let ((resolve? (and (pair? o) (car o))))
(let lp ((ls ls) (res '()))
(if (null? ls)
(reverse res)
(let ((x (car ls)))
(lp (cdr ls)
(append
(if (and (pair? x) (memq (car x) names))
(map (lambda (y)
(if (and resolve? (string? y))
(make-path dir y)
y))
(reverse (cdr x)))
'())
(if (and (pair? x)
(eq? 'include-library-declarations (car x)))
(append-map
(lambda (x) (if (and (pair? x) (eq? name (car x))) (cdr x) '()))
(cddr mod-form)))
(lambda (inc)
(let* ((file (make-path dir inc))
(sexps (file->sexp-list file))
(dir (path-directory file)))
(get-forms sexps names dir resolve?)))
(cdr x))
'())
res)))))))
(define (get-exports)
(if mod (module-exports mod) (get-forms 'exports)))
(if mod (module-exports mod) (get-forms (cddr mod-form) '(exports) dir)))
(define (get-decls)
(if mod
(module-include-library-declarations mod)
(map resolve (get-forms 'include-library-declarations))))
(get-forms (cddr mod-form) '(include-library-declarations) dir #t))
(define (get-includes)
(if mod
(module-includes mod)
(map resolve (get-forms 'include))))
(get-forms (cddr mod-form) '(include include-ci) dir #t))
(define (get-shared-includes)
(if mod
(module-shared-includes mod)
(map resolve (get-forms 'shared-include))))
(map (lambda (f) (string-append f ".stub"))
(get-forms (cddr mod-form) '(include-shared) dir #t)))
(let* ((exports (if (pair? o) (car o) (get-exports)))
(srcs (cons file (get-decls))))
(extract-module-docs-from-files
mod srcs (get-includes) (get-shared-includes) strict? exports))))))
mod srcs (get-includes) (get-shared-includes) strict? exports)))))

View file

@ -1,7 +1,7 @@
(define-library (chibi doc)
(import
(except (chibi) eval) (scheme eval) (srfi 1) (srfi 95)
(except (chibi) eval) (scheme eval) (srfi 1) (srfi 39) (srfi 95)
(chibi modules) (chibi ast) (chibi io) (chibi match)
(chibi time) (chibi filesystem) (chibi process) (chibi pathname)
(chibi string) (chibi scribble) (chibi sxml) (chibi highlight)
@ -11,5 +11,6 @@
generate-docs expand-docs fixup-docs
extract-module-docs extract-module-file-docs extract-file-docs
make-default-doc-env make-module-doc-env
get-optionals-signature)
get-optionals-signature
ansi->sxml)
(include "doc.scm"))

View file

@ -0,0 +1,14 @@
(define-library (chibi edit-distance-test)
(export run-tests)
(import (scheme base) (chibi edit-distance) (chibi test))
(begin
(define (run-tests)
(test-begin "(chibi edit-distance)")
(test 0 (edit-distance "" ""))
(test 0 (edit-distance "same" "same"))
(test 1 (edit-distance "same" "game"))
(test 2 (edit-distance "same" "sand"))
(test 3 (edit-distance "kitten" "sitting"))
(test 3 (edit-distance "Saturday" "Sunday"))
(test-end))))

View file

@ -0,0 +1,52 @@
(define-library (chibi edit-distance)
(export edit-distance find-nearest-edits)
(import (scheme base) (srfi 130))
(begin
;;> Returns the levenshtein distance between s1 and s2 - a cost of
;;> 1 per character insertion, deletion or update. Runs in
;;> quadratic time and linear memory.
;;>
;;> \example{(edit-distance "same" "same")}
;;> \example{(edit-distance "same" "sand")}
;;> \example{(edit-distance "Saturday" "Sunday")}
(define (edit-distance s1 s2)
(let* ((len1 (string-length s1))
(len2 (string-length s2))
(vec (make-vector (+ len1 1) 0)))
(do ((i 0 (+ i 1)))
((> i len1))
(vector-set! vec i i))
(do ((i 1 (+ i 1))
(sc2 (string-cursor-start s2) (string-cursor-next s2 sc2)))
((> i len2)
(vector-ref vec len1))
(vector-set! vec 0 i)
(let ((ch2 (string-ref/cursor s2 sc2)))
(let lp ((j 1)
(sc1 (string-cursor-start s1))
(last-diag (- i 1)))
(when (<= j len1)
(let ((old-diag (vector-ref vec j))
(ch1 (string-ref/cursor s1 sc1)))
(vector-set! vec j (min (+ (vector-ref vec j) 1)
(+ (vector-ref vec (- j 1)) 1)
(+ last-diag
(if (eqv? ch1 ch2) 0 1))))
(lp (+ j 1)
(string-cursor-next s1 sc1)
old-diag))))))))
;;> Returns a list of strings in \var{str-ls} with the smallest
;;> edit distance to \var{str}, preserving order. If
;;> \var{max-distance} is provided and positive, only return if
;;> the edits are less or equal to that distance.
(define (find-nearest-edits str str-ls . o)
(let ((max-distance (if (pair? o) (car o) 1e100)))
(let lp ((ls str-ls) (dist (+ max-distance 1)) (res '()))
(if (null? ls)
(reverse res)
(let ((ed (edit-distance str (car ls))))
(cond
((= ed dist) (lp (cdr ls) dist (cons (car ls) res)))
((< ed dist) (lp (cdr ls) ed (list (car ls))))
(else (lp (cdr ls) dist res))))))))))

View file

@ -45,5 +45,5 @@
(lp (- i 1))))))))))
(else
(equal? a b))))
(let ((res (equal?/bounded a b 100000 100000)))
(let ((res (equal?/bounded a b 10000 10000)))
(and res (or (> res 0) (equiv? a b)) #t))))

View file

@ -1,7 +1,14 @@
(define-library (chibi filesystem-test)
(export run-tests)
(import (chibi) (chibi io) (chibi filesystem) (chibi test) (srfi 33))
(import (scheme base) (scheme file) (scheme write)
(chibi filesystem) (chibi test))
(cond-expand
((library (srfi 151)) (import (srfi 151)))
((library (srfi 33)) (import (srfi 33)))
(else (import (srfi 60))))
(begin
(define (port->string in)
(read-string 1024 in))
(define (run-tests)
(define tmp-file "/tmp/chibi-fs-test-0123456789")
(define tmp-file2 "/tmp/chibi-fs-test-0123456789-2")

View file

@ -10,10 +10,11 @@
(let ((mode (if (pair? o) (car o) #o755)))
(or (file-directory? dir)
(create-directory dir mode)
(let ((slash
(string-find-right dir #\/ 0 (string-skip-right dir #\/))))
(and (> slash 0)
(let ((parent (substring-cursor dir 0 slash)))
(let* ((start (string-cursor-start dir))
(slash
(string-find-right dir #\/ start (string-skip-right dir #\/))))
(and (string-cursor>? slash start)
(let ((parent (substring-cursor dir start slash)))
(and (not (equal? parent dir))
(not (file-exists? parent))
(create-directory* parent mode)
@ -77,7 +78,7 @@
(define (delete-file file)
(if (not (%delete-file file))
(raise-continuable
(make-exception 'file "couldn't delete file" file delete-file #f))))
(make-exception 'file "couldn't delete file" (list file) delete-file #f))))
;;> Recursively delete all files and directories under \var{dir}.
;;> Unless optional arg \var{ignore-errors?} is true, raises an error
@ -103,7 +104,9 @@
(define (with-directory dir thunk)
(let ((pwd (current-directory)))
(dynamic-wind
(lambda () (change-directory dir))
(lambda ()
(if (not (change-directory dir))
(error "couldn't change directory" dir)))
thunk
(lambda () (change-directory pwd)))))
@ -122,10 +125,18 @@
(define (file-group x) (stat-gid (if (stat? x) x (file-status x))))
(define (file-represented-device x) (stat-rdev (if (stat? x) x (file-status x))))
(define (file-size x) (stat-size (if (stat? x) x (file-status x))))
(define (file-block-size x) (stat-blksize (if (stat? x) x (file-status x))))
(define (file-num-blocks x) (stat-blocks (if (stat? x) x (file-status x))))
(cond-expand
(windows
(define (file-block-size x) 1)
(define (file-num-blocks x) (file-size x)))
(else
(define (file-block-size x) (stat-blksize (if (stat? x) x (file-status x))))
(define (file-num-blocks x) (stat-blocks (if (stat? x) x (file-status x))))))
(define (file-access-time x) (stat-atime (if (stat? x) x (file-status x))))
(define (file-modification-time x) (stat-mtime (if (stat? x) x (file-status x))))
(define (file-modification-time/safe x)
(let ((status (if (stat? x) x (file-status x))))
(and status (stat-mtime status))))
(define (file-change-time x) (stat-ctime (if (stat? x) x (file-status x))))
;;> File status accessors. \var{x} should be a string indicating
@ -145,9 +156,13 @@
(define (file-character? x) (file-test-mode S_ISCHR x))
(define (file-block? x) (file-test-mode S_ISBLK x))
(define (file-fifo? x) (file-test-mode S_ISFIFO x))
(define (file-link? x)
(cond-expand
(windows
(define (file-link? x) #f))
(else
(define (file-link? x)
(let ((st (if (stat? x) x (file-link-status x))))
(and st (S_ISLNK (stat-mode st)))))
(and st (S_ISLNK (stat-mode st)))))))
(define (file-socket? x) (file-test-mode S_ISSOCK x))
(define (file-exists? x) (and (if (stat? x) #t (file-status x)) #t))
@ -176,8 +191,12 @@
;;> Returns the path the symbolic link \var{file} points to, or
;;> \scheme{#f} on error.
(define (read-link file)
(cond-expand
(windows
(define (read-link file) #f))
(else
(define (read-link file)
(let* ((buf (make-string 512))
(res (readlink file buf 512)))
(and (positive? res)
(substring buf 0 res))))
(substring buf 0 res))))))

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