git.iko.soy/rowtype-yoga/purescm
on bytevector help sign in
151 files changed+17208−975
since splitsnapshots
unifiedsplit
.envrc+1 .github/workflows/ci.yml+23−12 .gitignore+1−2 CONTRIBUTORS.md+3−1 README.md+80−4 flake.lock+104 flake.nix+57 index.dev.js+9 index.js+9 lib/purescm/bytevector.ss+244 lib/purescm/finalizers.ss+28 lib/purescm/pstring-buffer.ss+105 lib/purescm/pstring.ss+1433 lib/purescm/runtime.ss+149 lib/purescm/stack-trace.ss+29 lib/purescm/test/bytevector-test.ss+307 lib/purescm/test/pstring-test.ss+539 lib/srfi/:0.sls+11 lib/srfi/:0/cond-expand.guile.sls+9 lib/srfi/:0/cond-expand.sls+44 lib/srfi/:1.sls+34 lib/srfi/:1/lists.sls+1594 lib/srfi/:126.sls+23 lib/srfi/:128.sls+19 lib/srfi/:133.sls+17 lib/srfi/:133/vectors.sls+885 lib/srfi/:133/vectors.sls3a132.sls+6 lib/srfi/:152.sls+28 lib/srfi/:152/strings.sls+1015 lib/srfi/:158.sls+25 lib/srfi/:158/generators-and-accumulators.sls+457 lib/srfi/:19.sls+39 lib/srfi/:19/time.sls+1533 lib/srfi/:19/time/compat.chezscheme.sls+34 lib/srfi/:19/time/compat.ikarus.sls+20 lib/srfi/:19/time/compat.ironscheme.sls+39 lib/srfi/:19/time/compat.larceny.sls+28 lib/srfi/:19/time/compat.loko.sls+24 lib/srfi/:19/time/compat.mzscheme.sls+37 lib/srfi/:19/time/compat.ypsilon.sls+26 lib/srfi/:19/time/not-implemented.sls+24 lib/srfi/:214.sls+35 lib/srfi/:214/impl.sls+546 lib/srfi/:214/parameters.sls+39 lib/srfi/:23.sls+11 lib/srfi/:23/error.sls+13 lib/srfi/:23/error/tricks.sls+43 lib/srfi/:26.sls+11 lib/srfi/:26/cut.sls+102 lib/srfi/:27.sls+15 lib/srfi/:27/random-bits.sls+299 lib/srfi/:39.sls+11 lib/srfi/:39/parameters.chezscheme.sls+24 lib/srfi/:39/parameters.ikarus.sls+12 lib/srfi/:39/parameters.ironscheme.sls+14 lib/srfi/:39/parameters.mzscheme.sls+12 lib/srfi/:39/parameters.sls+35 lib/srfi/:39/parameters.ypsilon.sls+12 lib/srfi/:6.sls+14 lib/srfi/:6/basic-string-ports.mzscheme.sls+45 lib/srfi/:6/basic-string-ports.sls+17 lib/srfi/:6/basic-string-ports/compat.chezscheme.sls+24 lib/srfi/:6/basic-string-ports/compat.ikarus.sls+13 lib/srfi/:6/basic-string-ports/compat.ironscheme.sls+15 lib/srfi/:6/basic-string-ports/compat.larceny.sls+12 lib/srfi/:6/basic-string-ports/compat.loko.sls+12 lib/srfi/:6/basic-string-ports/compat.ypsilon.sls+19 lib/srfi/:8.sls+11 lib/srfi/:8/receive.sls+18 lib/srfi/:99.sls+14 lib/srfi/:99/records.sls+35 lib/srfi/:99/records/helper.sls+30 lib/srfi/:99/records/inspection.larceny.sls+10 lib/srfi/:99/records/inspection.sls+60 lib/srfi/:99/records/procedural.larceny.sls+10 lib/srfi/:99/records/procedural.sls+108 lib/srfi/:99/records/syntactic.larceny.sls+9 lib/srfi/:99/records/syntactic.sls+208 lib/srfi/private/OS-id-features.sls+22 lib/srfi/private/check-arg.sls+23 lib/srfi/private/define-values.chezscheme.sls+3 lib/srfi/private/include.chezscheme.sls+3 lib/srfi/private/platform-features.chezscheme.sls+34 lib/srfi/private/registry-names.sls+66 lib/srfi/private/registry.sls+48 lib/srfi/private/vanish.sls+35 package-lock.json+14 package-sets/1.0.0.json+175 package.json+15−2 publish-release.sh+42 shell.nix+12−29 spago.lock+2001 spago.yaml+76−16 src/Main.purs+304−6 src/PureScript/Backend/Chez/Builder.purs+118 src/PureScript/Backend/Chez/Convert.purs+283−117 src/PureScript/Backend/Chez/Printer.purs+371 src/PureScript/Backend/Chez/Runtime.purs−69 src/PureScript/Backend/Chez/Syntax.purs+92−386 test-runtime.js+6 test-runtime.ss+12 test-snapshots/.gitignore+1 test-snapshots/spago.lock+922 test-snapshots/spago.yaml+51−21 test-snapshots/src/snapshots-input/Snapshot.Constructor.purs+9 test-snapshots/src/snapshots-input/Snapshot.ConstructorAccessor.purs+16−7 test-snapshots/src/snapshots-input/Snapshot.Effect.purs+13−5 test-snapshots/src/snapshots-input/Snapshot.EffectRef.purs+53 test-snapshots/src/snapshots-input/Snapshot.Failing.RecursiveBindingGroupLet.purs+23 test-snapshots/src/snapshots-input/Snapshot.Failing.RecursiveBindingGroupTopLevel.purs+23 test-snapshots/src/snapshots-input/Snapshot.Import.Constructor.purs+3 test-snapshots/src/snapshots-input/Snapshot.Import.Impl.purs+2 test-snapshots/src/snapshots-input/Snapshot.Import.Product.purs+3 test-snapshots/src/snapshots-input/Snapshot.Import.purs+8 test-snapshots/src/snapshots-input/Snapshot.Let.purs+16 test-snapshots/src/snapshots-input/Snapshot.List.purs+34 test-snapshots/src/snapshots-input/Snapshot.Literals.Char.purs+33 test-snapshots/src/snapshots-input/Snapshot.Literals.Number.purs+12 test-snapshots/src/snapshots-input/Snapshot.Literals.Record.purs+41 test-snapshots/src/snapshots-input/Snapshot.Literals.Record.ss+13 test-snapshots/src/snapshots-input/Snapshot.PrimUndefined.purs+15 test-snapshots/src/snapshots-input/Snapshot.Prime.purs+76 test-snapshots/src/snapshots-input/Snapshot.RecursiveDefinition.purs+26 test-snapshots/src/snapshots-input/Snapshot.UncurriedFunction.purs+36−2 test-snapshots/src/snapshots-output/Snapshot.ArrayIndex.ss+4−2 test-snapshots/src/snapshots-output/Snapshot.Branch.ss+21−5 test-snapshots/src/snapshots-output/Snapshot.Comparison.ss+6−6 test-snapshots/src/snapshots-output/Snapshot.Constructor.ss+32−2 test-snapshots/src/snapshots-output/Snapshot.ConstructorAccessor.ss+29−7 test-snapshots/src/snapshots-output/Snapshot.Effect.ss+24−3 test-snapshots/src/snapshots-output/Snapshot.EffectRef.ss+72 test-snapshots/src/snapshots-output/Snapshot.Failing.RecursiveBindingGroupLet.ss+25 test-snapshots/src/snapshots-output/Snapshot.Failing.RecursiveBindingGroupTopLevel.ss+35 test-snapshots/src/snapshots-output/Snapshot.Function.ss+2−2 test-snapshots/src/snapshots-output/Snapshot.Import.Constructor.ss+17 test-snapshots/src/snapshots-output/Snapshot.Import.Impl.ss+14−1 test-snapshots/src/snapshots-output/Snapshot.Import.Product.ss+21 test-snapshots/src/snapshots-output/Snapshot.Import.ss+15−4 test-snapshots/src/snapshots-output/Snapshot.Let.ss+33−3 test-snapshots/src/snapshots-output/Snapshot.List.ss+76 test-snapshots/src/snapshots-output/Snapshot.Literals.Char.ss+96 test-snapshots/src/snapshots-output/Snapshot.Literals.Number.ss+20 test-snapshots/src/snapshots-output/Snapshot.Literals.Record.ss+52 test-snapshots/src/snapshots-output/Snapshot.Literals.String.ss+21−21 test-snapshots/src/snapshots-output/Snapshot.Literals.ss+6−6 test-snapshots/src/snapshots-output/Snapshot.PrimUndefined.ss+19 test-snapshots/src/snapshots-output/Snapshot.Prime.ss+151 test-snapshots/src/snapshots-output/Snapshot.RecursiveDefinition.ss+51 test-snapshots/src/snapshots-output/Snapshot.UncurriedFunction.ss+35−6 test/Main.purs+90−137 test/Utils.purs+47−91
.envrcnew file+1
@@ -0,0 +1 @@
1+use flake
.github/workflows/ci.yml+23−12
@@ -8,34 +8,45 @@ on:
88
99jobs:
1010 build:
11− runs-on: ubuntu-latest
11+ runs-on: ${{ matrix.os }}
12+ strategy:
13+ matrix:
14+ include:
15+ - os: ubuntu-latest
16+ - os: macos-latest
1217 steps:
13− - uses: actions/checkout@v2
18+ - uses: actions/checkout@v3
19+
20+ - name: Install current Bash on macOS
21+ if: runner.os == 'macOS'
22+ run: brew install bash
1423
1524 - name: Cache PureScript dependencies
1625 uses: actions/cache@v2
1726 with:
18− key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }}
27+ key: ${{ runner.os }}-spago-${{ hashFiles('**/spago.yaml') }}
1928 path: |
2029 .spago
2130 output
2231
23− - name: Set up Node toolchain
24− uses: actions/setup-node@v2
25− with:
26− node-version: "16"
27−
2832 - name: Install Nix
29− uses: cachix/install-nix-action@v16
33+ uses: cachix/install-nix-action@v22
34+
35+ - name: Nix cache
36+ uses: DeterminateSystems/magic-nix-cache-action@main
3037
3138 - name: Build the project
3239 run: |
33− nix-shell --command "spago build"
40+ nix develop -c bash -c "spago build"
41+
42+ - name: Bundle
43+ run: |
44+ nix develop -c bash -c "npm run build"
3445
3546 - name: Run tests
3647 run: |
37− nix-shell --command "spago test"
48+ nix develop -c bash -c "npm run test"
3849
3950 - name: Check Formatting
4051 run: |
41− nix-shell --command "purs-tidy check src test"
52+ nix develop -c bash -c "purs-tidy check src test"
.gitignore+1−2
@@ -1,5 +1,3 @@
1−/bower_components/
2−/node_modules/
31/.pulp-cache/
42/output/
53/output-es/
@@ -21,3 +19,4 @@
2119/test-snapshots/**/.psc*
2220/test-snapshots/generated-docs
2321/test-snapshots/test-out/
22+/.direnv
CONTRIBUTORS.md+3−1
@@ -1,6 +1,6 @@
11## Contributors
22
3−This file lists the contributors to the `purs-backend-chez` project, and the terms under which their code is licensed.
3+This file lists the contributors to the `purescm` project, and the terms under which their code is licensed.
44
55### Contributors using Standard Terms
66
@@ -18,6 +18,8 @@ If you would prefer to use different terms, please use the section below instead
1818| [@jordanmartinez](https://github.com/jordanmartinez) | Jordan Martinez | [Apache-2.0] |
1919| [@PureFunctor](https://github.com/PureFunctor), [@sjpgarcia](https://github.com/sjpgarcia) | Justin Garcia | [Apache-2.0] |
2020| [@turlando](https://github.com/turlando) | Tancredi Orlando | [Apache-2.0] |
21+| [@anttih](https://github.com/anttih) | Antti Holvikari | [Apache-2.0] |
22+| toastal | toastal | [Apache-2.0] |
2123
2224### Contributors using Modified Terms
2325
README.md+80−4
@@ -1,8 +1,84 @@
1−# purs-backend-chez
1+# purescm - Chez Scheme backend for PureScript
22
3−## Snapshots
3+## Installation
4+
5+Install requisites:
6+
7+* [`chezscheme`](https://cisco.github.io/ChezScheme/) - you should have the `scheme` command available in your `$PATH`.
8+* [`libpcre2`](https://pcre2project.github.io/pcre2/) - `purescm` has a runtime dependency on the 16-bit variant of pcre2. Check your package manager for `pcre2` or `pcre2-16` or similar.
9+* [`icu`](https://icu.unicode.org/) - `libicu` is used for locale-aware case conversions.
10+
11+You can install purescm with npm:
12+
13+```
14+npm i --global purescm
15+```
16+
17+## Usage
18+
19+The best way to use `purescm` is to use the [spago](https://github.com/purescript/spago) integration for alternative PureScript backends. In `spago.yaml` use the `backend` config like so:
20+
21+```
22+workspace:
23+ backend:
24+ cmd: purescm
25+ args:
26+ - "build"
27+```
28+
29+Then to compile your `purescm` project you can run:
30+
31+```
32+spago build
33+```
34+
35+This will produce output under `output/`. You can run the compiled program with:
36+
37+```
38+purescm run
39+```
40+
41+### Bundling
42+
43+Scheme files can be precompiled to a single Chez program:
44+
45+```
46+purescm bundle-app
47+```
48+
49+which generates a single file `output/main` which can be run with `scheme` or `petite`:
50+
51+```
52+scheme --program output/main
53+```
54+
55+## Development
56+
57+### Running the tests
58+
59+To run all tests, run `npm run test`. This will run both the scheme runtime unit tests and the snapshot tests.
460
5−To run snapshots, run `npm run test`.
661To overwrite old snapshots with the latest output, run `npm run test -- -a "--accept"`.
762To add a new snapshot, create a file called `Snapshot.X.purs` where `X` indicates what is being tested.
8−If a snapshot needs a dependency, install it by running `spago -x test-snapshots/spago.dhall install <packages...>`. The snapshots have their own `spago.dhall` file so as not to pollute the `purs-backend-chez` binary with unneeded dependencies.
63+If a snapshot needs a dependency, install it by running `cd test-snapshots && spago install <packages...>`.
64+
65+### Vendored Dependencies
66+
67+In order to represent `Array` and record types in `purescm`, the backend has a runtime dependency on implementation of SRFI 214 (Flexvectors). This is due in part to how [vectors](https://cisco.github.io/ChezScheme/csug9.5/objects.html#./objects:h5) are more like "arrays" than "array lists".
68+
69+We vendor [chez-srfi](https://github.com/arcfide/chez-srfi) using the following steps:
70+
71+1. Clone `chez-srfi` at the project root.
72+
73+2. Navigate to `chez-srfi` and run `./install.chezscheme.sps ../lib`.
74+
75+3. To verify, simply invoke the Scheme REPL:
76+```scheme
77+$ scheme --libdirs ./lib:
78+Chez Scheme Version 9.5.8
79+Copyright 1984-2022 Cisco Systems, Inc.
80+
81+> (import (srfi :125))
82+>
83+```
84+
flake.locknew file+104
@@ -0,0 +1,104 @@
1+{
2+ "nodes": {
3+ "flake-compat": {
4+ "flake": false,
5+ "locked": {
6+ "lastModified": 1696426674,
7+ "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
8+ "owner": "edolstra",
9+ "repo": "flake-compat",
10+ "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
11+ "type": "github"
12+ },
13+ "original": {
14+ "owner": "edolstra",
15+ "repo": "flake-compat",
16+ "type": "github"
17+ }
18+ },
19+ "flake-compat_2": {
20+ "flake": false,
21+ "locked": {
22+ "lastModified": 1696426674,
23+ "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
24+ "owner": "edolstra",
25+ "repo": "flake-compat",
26+ "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
27+ "type": "github"
28+ },
29+ "original": {
30+ "owner": "edolstra",
31+ "repo": "flake-compat",
32+ "type": "github"
33+ }
34+ },
35+ "nixpkgs": {
36+ "locked": {
37+ "lastModified": 1728217273,
38+ "narHash": "sha256-p/gvyVf24WFs0bted3c71uSQk++ZOYRWbg3bjRoePu4=",
39+ "owner": "nixos",
40+ "repo": "nixpkgs",
41+ "rev": "50b3bd3fed0442bcbf7f58355e990da84af1749d",
42+ "type": "github"
43+ },
44+ "original": {
45+ "owner": "nixos",
46+ "ref": "nixpkgs-unstable",
47+ "repo": "nixpkgs",
48+ "type": "github"
49+ }
50+ },
51+ "purescript-overlay": {
52+ "inputs": {
53+ "flake-compat": "flake-compat_2",
54+ "nixpkgs": [
55+ "nixpkgs"
56+ ],
57+ "slimlock": "slimlock"
58+ },
59+ "locked": {
60+ "lastModified": 1728216350,
61+ "narHash": "sha256-inQ9vxjD+otzVnaXNgHyxFqdjjiok9rGAbs+N+xHIxA=",
62+ "owner": "thomashoneyman",
63+ "repo": "purescript-overlay",
64+ "rev": "cb3032aec53900bd1b90e018b4cfa347a4a57770",
65+ "type": "github"
66+ },
67+ "original": {
68+ "owner": "thomashoneyman",
69+ "repo": "purescript-overlay",
70+ "type": "github"
71+ }
72+ },
73+ "root": {
74+ "inputs": {
75+ "flake-compat": "flake-compat",
76+ "nixpkgs": "nixpkgs",
77+ "purescript-overlay": "purescript-overlay"
78+ }
79+ },
80+ "slimlock": {
81+ "inputs": {
82+ "nixpkgs": [
83+ "purescript-overlay",
84+ "nixpkgs"
85+ ]
86+ },
87+ "locked": {
88+ "lastModified": 1688756706,
89+ "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=",
90+ "owner": "thomashoneyman",
91+ "repo": "slimlock",
92+ "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c",
93+ "type": "github"
94+ },
95+ "original": {
96+ "owner": "thomashoneyman",
97+ "repo": "slimlock",
98+ "type": "github"
99+ }
100+ }
101+ },
102+ "root": "root",
103+ "version": 7
104+}
flake.nixnew file+57
@@ -0,0 +1,57 @@
1+{
2+ description = "Chez Scheme backend for PureScript";
3+
4+ inputs = {
5+ nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
6+
7+ flake-compat = {
8+ url = "github:edolstra/flake-compat";
9+ flake = false;
10+ };
11+
12+ purescript-overlay.url = "github:thomashoneyman/purescript-overlay";
13+ purescript-overlay.inputs.nixpkgs.follows = "nixpkgs";
14+ };
15+
16+ outputs = { self, nixpkgs, ... }@inputs:
17+ let
18+ supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
19+
20+ forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
21+
22+ nixpkgsFor = forAllSystems (system: import nixpkgs {
23+ inherit system;
24+ overlays = builtins.attrValues self.overlays;
25+ });
26+ in
27+ {
28+ overlays = {
29+ purescript = inputs.purescript-overlay.overlays.default;
30+ };
31+
32+ devShells = forAllSystems (system:
33+ let pkgs = nixpkgsFor.${system};
34+ in {
35+ default = pkgs.mkShell {
36+ name = "purescm";
37+ packages = [
38+ pkgs.purescript-language-server
39+ pkgs.purs-backend-es
40+ pkgs.purs-bin.purs-0_15_10
41+ pkgs.purs-tidy
42+ pkgs.spago-unstable
43+ pkgs.nodejs-slim
44+ pkgs.esbuild
45+ pkgs.pkg-config
46+ pkgs.icu
47+ pkgs.chez
48+ ];
49+
50+ CHEZ_DYLD_LIBRARY_PATH="${pkgs.pcre2.out}/lib:${pkgs.icu.out}/lib";
51+ LD_LIBRARY_PATH = "${pkgs.pcre2.out}/lib:${pkgs.icu.out}/lib";
52+ };
53+ });
54+
55+ formatter = forAllSystems (system: nixpkgsFor.${system}.nixpkgs-fmt);
56+ };
57+}
index.dev.jsnew file+9
@@ -0,0 +1,9 @@
1+#!/usr/bin/env node
2+import { dirname } from 'path';
3+import { fileURLToPath } from 'url';
4+
5+import { main } from "./output/Main/index.js";
6+
7+const __dirname = dirname(fileURLToPath(import.meta.url));
8+
9+main(__dirname)();
index.jsnew file+9
@@ -0,0 +1,9 @@
1+#!/usr/bin/env node
2+import { dirname } from 'path';
3+import { fileURLToPath } from 'url';
4+
5+import { main } from "./bundle/index.js";
6+
7+const __dirname = dirname(fileURLToPath(import.meta.url));
8+
9+main(__dirname)();
lib/purescm/bytevector.ssnew file+244
@@ -0,0 +1,244 @@
1+#!chezscheme
2+(library (purescm bytevector)
3+ (export
4+ ;; Construction
5+ bytevector-make
6+
7+ ;; Pure accessors (curried for PureScript calling convention)
8+ bv-length
9+ bv-ref
10+ bv-set
11+
12+ ;; Slicing / concatenation
13+ bv-slice
14+ bv-concat
15+
16+ ;; Equality / comparison
17+ bv-eq?
18+ bv-compare
19+
20+ ;; Conversion: flexvector <-> bytevector
21+ bv-from-flexvector
22+ bv-to-flexvector
23+
24+ ;; Conversion: native Chez string <-> bytevector (UTF-8)
25+ ;; NOTE: These work with native Chez strings, NOT pstrings.
26+ ;; In PureScript FFI .ss files, wrap with rt:pstring->string / rt:string->pstring
27+ bv-from-utf8
28+ bv-to-utf8
29+
30+ ;; Hex encoding (native Chez strings — same wrapping needed at FFI boundary)
31+ bv-to-hex
32+ bv-from-hex
33+
34+ ;; Mutation primitives (for Effect-based APIs)
35+ bv-copy-into!
36+ bv-xor-into!
37+ bv-fill!)
38+
39+ (import
40+ (chezscheme)
41+ (prefix (srfi :214) fv:))
42+
43+ ;; ------------------------------------------------------------------
44+ ;; Construction
45+ ;; ------------------------------------------------------------------
46+
47+ (define bytevector-make
48+ (lambda (n) (make-bytevector n 0)))
49+
50+ ;; ------------------------------------------------------------------
51+ ;; Pure accessors (curried for PureScript calling convention)
52+ ;; ------------------------------------------------------------------
53+
54+ (define bv-length bytevector-length)
55+
56+ ;; ByteArray -> Int -> Int
57+ (define bv-ref
58+ (lambda (bv)
59+ (lambda (i)
60+ (bytevector-u8-ref bv i))))
61+
62+ ;; Pure set: returns a fresh copy with one byte changed.
63+ ;; ByteArray -> Int -> Int -> ByteArray
64+ (define bv-set
65+ (lambda (bv)
66+ (lambda (i)
67+ (lambda (val)
68+ (let ([out (bytevector-copy bv)])
69+ (bytevector-u8-set! out i val)
70+ out)))))
71+
72+ ;; ------------------------------------------------------------------
73+ ;; Slicing / concatenation
74+ ;; ------------------------------------------------------------------
75+
76+ ;; Int -> Int -> ByteArray -> ByteArray
77+ (define bv-slice
78+ (lambda (start)
79+ (lambda (end)
80+ (lambda (bv)
81+ (let* ([len (fx- end start)]
82+ [out (make-bytevector len)])
83+ (bytevector-copy! bv start out 0 len)
84+ out)))))
85+
86+ ;; ByteArray -> ByteArray -> ByteArray
87+ (define bv-concat
88+ (lambda (a)
89+ (lambda (b)
90+ (let* ([la (bytevector-length a)]
91+ [lb (bytevector-length b)]
92+ [out (make-bytevector (fx+ la lb))])
93+ (bytevector-copy! a 0 out 0 la)
94+ (bytevector-copy! b 0 out la lb)
95+ out))))
96+
97+ ;; ------------------------------------------------------------------
98+ ;; Equality / comparison
99+ ;; ------------------------------------------------------------------
100+
101+ ;; ByteArray -> ByteArray -> Boolean
102+ (define bv-eq?
103+ (lambda (a)
104+ (lambda (b)
105+ (bytevector=? a b))))
106+
107+ ;; Lexicographic comparison, returns -1 / 0 / 1.
108+ ;; ByteArray -> ByteArray -> Int
109+ (define bv-compare
110+ (lambda (a)
111+ (lambda (b)
112+ (let ([la (bytevector-length a)]
113+ [lb (bytevector-length b)])
114+ (let loop ([i 0])
115+ (cond
116+ [(and (fx= i la) (fx= i lb)) 0]
117+ [(fx= i la) -1]
118+ [(fx= i lb) 1]
119+ [else
120+ (let ([ba (bytevector-u8-ref a i)]
121+ [bb (bytevector-u8-ref b i)])
122+ (cond
123+ [(fx<? ba bb) -1]
124+ [(fx>? ba bb) 1]
125+ [else (loop (fx+ i 1))]))]))))))
126+
127+ ;; ------------------------------------------------------------------
128+ ;; Conversion: flexvector (PureScript Array Int) <-> bytevector
129+ ;; ------------------------------------------------------------------
130+
131+ ;; Array Int -> ByteArray
132+ (define bv-from-flexvector
133+ (lambda (fv)
134+ (let* ([n (fv:flexvector-length fv)]
135+ [bv (make-bytevector n)])
136+ (do ([i 0 (fx+ i 1)])
137+ ((fx= i n) bv)
138+ (bytevector-u8-set! bv i
139+ (fxlogand (fv:flexvector-ref fv i) #xFF))))))
140+
141+ ;; ByteArray -> Array Int
142+ (define bv-to-flexvector
143+ (lambda (bv)
144+ (let* ([n (bytevector-length bv)]
145+ [fv (fv:make-flexvector n 0)])
146+ (do ([i 0 (fx+ i 1)])
147+ ((fx= i n) fv)
148+ (fv:flexvector-set! fv i (bytevector-u8-ref bv i))))))
149+
150+ ;; ------------------------------------------------------------------
151+ ;; Conversion: native Chez string <-> bytevector (UTF-8)
152+ ;; ------------------------------------------------------------------
153+
154+ ;; Native Chez String -> ByteArray
155+ (define bv-from-utf8
156+ (lambda (s)
157+ (string->utf8 s)))
158+
159+ ;; ByteArray -> Native Chez String
160+ (define bv-to-utf8
161+ (lambda (bv)
162+ (utf8->string bv)))
163+
164+ ;; ------------------------------------------------------------------
165+ ;; Hex encoding (native Chez strings)
166+ ;; ------------------------------------------------------------------
167+
168+ (define hex-chars "0123456789abcdef")
169+
170+ ;; ByteArray -> Native Chez String
171+ (define bv-to-hex
172+ (lambda (bv)
173+ (let* ([n (bytevector-length bv)]
174+ [out (make-string (fx* n 2))])
175+ (do ([i 0 (fx+ i 1)])
176+ ((fx= i n) out)
177+ (let ([b (bytevector-u8-ref bv i)])
178+ (string-set! out (fx* i 2)
179+ (string-ref hex-chars (fxsrl b 4)))
180+ (string-set! out (fx+ (fx* i 2) 1)
181+ (string-ref hex-chars (fxlogand b #xF))))))))
182+
183+ (define hex-val
184+ (lambda (c)
185+ (let ([cp (char->integer c)])
186+ (cond
187+ [(fx<=? 48 cp 57) (fx- cp 48)] ;; 0-9
188+ [(fx<=? 97 cp 102) (fx- cp 87)] ;; a-f
189+ [(fx<=? 65 cp 70) (fx- cp 55)] ;; A-F
190+ [else (error 'hex-val "invalid hex digit" c)]))))
191+
192+ ;; Native Chez String -> ByteArray
193+ (define bv-from-hex
194+ (lambda (s)
195+ (let* ([slen (string-length s)]
196+ [n (fxsrl slen 1)]
197+ [bv (make-bytevector n)])
198+ (do ([i 0 (fx+ i 1)])
199+ ((fx= i n) bv)
200+ (let ([hi (hex-val (string-ref s (fx* i 2)))]
201+ [lo (hex-val (string-ref s (fx+ (fx* i 2) 1)))])
202+ (bytevector-u8-set! bv i
203+ (fxlogor (fxsll hi 4) lo)))))))
204+
205+ ;; ------------------------------------------------------------------
206+ ;; Mutation primitives (for Effect-based PureScript APIs)
207+ ;; ------------------------------------------------------------------
208+
209+ ;; ByteArray -> Int -> ByteArray -> Int -> Int -> Unit
210+ (define bv-copy-into!
211+ (lambda (src)
212+ (lambda (src-off)
213+ (lambda (dst)
214+ (lambda (dst-off)
215+ (lambda (len)
216+ (bytevector-copy! src src-off dst dst-off len)))))))
217+
218+ ;; ByteArray -> Int -> ByteArray -> Int -> Int -> Unit
219+ (define bv-xor-into!
220+ (lambda (dst)
221+ (lambda (dst-off)
222+ (lambda (src)
223+ (lambda (src-off)
224+ (lambda (len)
225+ (do ([i 0 (fx+ i 1)])
226+ ((fx= i len))
227+ (let ([di (fx+ dst-off i)]
228+ [si (fx+ src-off i)])
229+ (bytevector-u8-set! dst di
230+ (fxlogxor
231+ (bytevector-u8-ref dst di)
232+ (bytevector-u8-ref src si)))))))))))
233+
234+ ;; ByteArray -> Int -> Int -> Int -> Unit
235+ (define bv-fill!
236+ (lambda (bv)
237+ (lambda (off)
238+ (lambda (len)
239+ (lambda (val)
240+ (do ([i 0 (fx+ i 1)])
241+ ((fx= i len))
242+ (bytevector-u8-set! bv (fx+ off i) val)))))))
243+
244+) ;; end library
lib/purescm/finalizers.ssnew file+28
@@ -0,0 +1,28 @@
1+#!r6rs
2+#!chezscheme
3+; Finalizers can be used to free memory allocated outisde the Chez heap. A
4+; finalizer is a callback registered using `finalizer` that will free the
5+; memory. The finalizer callbacks are called automatically by the `purescm`
6+; runtime, so there is no need to call `run-finalizers` by the user. Finalizers
7+; are implemented using Chez's guardians, documented here:
8+; <https://cisco.github.io/ChezScheme/csug10.0/smgmt.html#./smgmt:h2>
9+(library (purescm finalizers)
10+ (export finalizer
11+ run-finalizers)
12+ (import (chezscheme))
13+
14+ (define finalizer-guardian (make-guardian))
15+
16+ (define (finalizer o proc)
17+ (finalizer-guardian o (cons o proc))
18+ o)
19+
20+ (define run-finalizers
21+ (lambda ()
22+ (let recur ()
23+ (let ([o (finalizer-guardian)])
24+ (when o
25+ ((cdr o) (car o))
26+ (recur))))))
27+
28+ )
lib/purescm/pstring-buffer.ssnew file+105
@@ -0,0 +1,105 @@
1+#!chezscheme
2+; An immobile UTF-16 encoded bytevector used for the pstring buffer.
3+; Offsets are handled as code units unlike with a raw bytevector.
4+(library (purescm pstring-buffer)
5+ (export code-unit-length
6+ pstring-buffer-alloc
7+ pstring-buffer-ref
8+ pstring-buffer-set!
9+ pstring-buffer-&ref
10+ pstring-buffer-copy!
11+ string->utf16-immobile
12+ utf16-immobile->string)
13+ (import (chezscheme))
14+
15+ (define code-unit-length 2)
16+
17+ (define (pstring-buffer-alloc n)
18+ (make-immobile-bytevector (fx* n code-unit-length)))
19+
20+ ; Access the nth code unit of the buffer
21+ (define (pstring-buffer-ref bv n)
22+ (bytevector-u16-native-ref bv (fx* n code-unit-length)))
23+
24+ (define (pstring-buffer-set! bv i val)
25+ (bytevector-u16-native-set! bv (fx* i code-unit-length) val))
26+
27+ (define (pstring-buffer-&ref bv i)
28+ (ftype-&ref
29+ unsigned-16
30+ ()
31+ (make-ftype-pointer unsigned-16 (object->reference-address bv))
32+ i))
33+
34+ ; Copies `n` code units to dst
35+ (define (pstring-buffer-copy! src-buf src-offset dst dst-offset n)
36+ (let loop ([i 0])
37+ (when (fx<? i n)
38+ (begin
39+ (pstring-buffer-set!
40+ dst
41+ (fx+ dst-offset i)
42+ (pstring-buffer-ref src-buf (fx+ src-offset i)))
43+ (loop (fx1+ i))))))
44+
45+ ; Encode a scheme string as an immobile UTF-16 bytevector
46+ (define (string->utf16-immobile s)
47+ (let* ([sn (string-length s)]
48+ [buf-size (do ([si 0 (fx+ si 1)]
49+ [n 0 (+ n (if (char<=? (string-ref s si) #\xffff) 1 2))])
50+ ((fx= si sn) n))]
51+ [buf (make-immobile-bytevector (fx* buf-size 2))])
52+ (let loop ([ci 0] [i 0])
53+ (if (fx<? ci sn)
54+ (let ([point (char->integer (string-ref s ci))])
55+ (if (fx>? point #x10FFFF)
56+ (raise-continuable
57+ (make-message-condition
58+ (format "Value ~d is too large to encode as UTF-16 code point" point))))
59+ (if (fx<=? #x10000 point)
60+ (let* ([code (fx- point #x10000)]
61+ [w1 (fxlogor #xD800 (fxsrl code 10))]
62+ [w2 (fxlogor #xDC00 (fxlogand code #x3FF))])
63+ (bytevector-u16-native-set! buf (fx* i 2) w1)
64+ (bytevector-u16-native-set! buf (fx* (fx1+ i) 2) w2)
65+ (loop (fx1+ ci) (fx+ i 2)))
66+ (begin
67+ (bytevector-u16-native-set! buf (fx* i 2) point)
68+ (loop (fx1+ ci) (fx1+ i)))))))
69+ buf))
70+
71+ (define (utf16-immobile->string vec offset len)
72+ ; First allocate a string based on the code unit size
73+ ; and then truncate at the end.
74+ (let* ([out (make-string len)])
75+ (let loop ([i 0] [char-i 0])
76+ (if (fx<? i len)
77+ (let* ([w1 (pstring-buffer-ref vec (fx+ offset i))])
78+ (cond
79+ ;; Two-word encoding? Check for high surrogate
80+ [(and (fx<= #xD800 w1 #xDBFF) (fx>=? (fx- len i) 2))
81+ (let ([w2 (pstring-buffer-ref vec (fx+ offset i 1))])
82+ (if (fx<= #xDC00 w2 #xDFFF)
83+ (begin
84+ (string-set! out
85+ char-i
86+ (integer->char
87+ (fx+
88+ (fxlogor
89+ (fxsll (fx- w1 #xD800) 10)
90+ (fx- w2 #xDC00))
91+ #x10000)))
92+ (loop (fx+ i 2) (fx1+ char-i)))
93+ (begin
94+ (string-set! out char-i #\xfffd)
95+ (loop (fx+ i 1) (fx1+ char-i)))))]
96+ ;; misplaced continuation word?
97+ [(fx<= #xDC00 w1 #xDFFF)
98+ (begin
99+ (string-set! out char-i #\xfffd)
100+ (loop (fx+ i 1) (fx1+ char-i)))]
101+ ;; one-word encoding
102+ [else (begin (string-set! out char-i (integer->char w1)) (loop (fx+ i 1) (fx1+ char-i)))]))
103+ (begin (string-truncate! out char-i) out)))))
104+ )
105+
lib/purescm/pstring.ssnew file+1433
@@ -0,0 +1,1433 @@
1+#!chezscheme
2+(library (purescm pstring)
3+ (export char-flexvector->pstring
4+ code-points->pstring
5+ number->pstring
6+ (rename (list->pstring pstring))
7+ pstring-compact?
8+ pstring<=?
9+ pstring<?
10+ pstring=?
11+ pstring>=?
12+ pstring>?
13+ pstring?
14+ pstring->char-flexvector
15+ pstring->code-point-flexvector
16+ pstring-concat
17+ pstring-downcase
18+ pstring-drop
19+ pstring-empty?
20+ pstring-index-of
21+ pstring-join-with
22+ pstring-last-index-of
23+ pstring-length
24+ pstring-length-code-points
25+ pstring->list
26+ pstring-make-regex
27+ pstring->number
28+ pstring-ref
29+ pstring-ref-code-point
30+ pstring-regex-match
31+ pstring-regex-replace
32+ pstring-regex-replace-by
33+ pstring-regex-search
34+ pstring-regex-split
35+ pstring-replace
36+ pstring-replace-all
37+ pstring-singleton
38+ pstring-slice
39+ pstring-split
40+ pstring->string
41+ pstring->symbol
42+ symbol->pstring
43+ pstring-take
44+ pstring-take-code-points
45+ pstring-trim
46+ pstring-uncons-char
47+ pstring-upcase
48+ regex-flags
49+ regex-source
50+ (rename (make-pstring-of-length make-pstring))
51+ string->pstring
52+ pstring->cursor
53+ cursor->pstring
54+ pstring-cursor-read-char
55+ pstring-cursor-peek-char
56+ pstring-cursor-read-code-unit
57+ pstring-cursor-peek-code-unit
58+ pstring-cursor-read-code-point
59+ pstring-cursor-peek-code-point)
60+ (import (chezscheme)
61+ (prefix (srfi :214) srfi:214:)
62+ (only (purescm finalizers) finalizer)
63+ (purescm pstring-buffer))
64+
65+ ;
66+ ; Internals
67+ ;
68+
69+ ; Persistent string with support for constant-time `concat` using a rope data structure.
70+ ;
71+ ; * When the string is a `Slice`, then slicing by code unit offsets is a constant-time
72+ ; operation.
73+ ; * Concatenating two strings is always constant-time because no new string buffer is
74+ ; allocated until a single continuous buffer is required by a read.
75+ ; * When a single continuous buffer is required and the string is a `Concat`,
76+ ; then a new string buffer is allocated and the chunks are copied in linear
77+ ; time to that new buffer. This new buffer is memoized so that the expensive
78+ ; copy will only be computed once.
79+ ; * All chunks in the tree (rope) are non-empty.
80+ ; * Getting the length of the string in code units is always constant-time.
81+ ; * If the string is a `Concat` (after concatenation) then slicing is
82+ ; constant-time if the offsets are reachable in the first or last slice of
83+ ; the tree. If the slice cannot be reached in the prefix or suffix, then
84+ ; slicing is a linear-time operation because the tree needs to be compacted
85+ ; to a continuous slice first.
86+ ;
87+ ; Rough sketch of the type:
88+ ;
89+ ; type pstring
90+ ; = Slice { buffer :: pstring-buffer, offset :: fixnum, length :: fixnum }
91+ ; | Concat { length :: fixnum, str :: MutableRef (ConcatTree | Slice) }
92+ ;
93+ (define-record pstring ())
94+ (define-record Slice pstring
95+ ((immutable buffer)
96+ (immutable offset)
97+ (immutable length)))
98+ (define-record Concat pstring
99+ ((immutable length)
100+ (mutable str)))
101+
102+ (define (pstring-length str)
103+ (cond
104+ [(Slice? str) (Slice-length str)]
105+ [else (Concat-length str)]))
106+
107+ ; A concatenation of two slices with constant-time access to the first and last slice
108+ ;
109+ ; type Rope = Slice | pair Rope Rope
110+ ; type ConcatTree = ConcatTree { prefix :: Slice, deep :: Rope | null, suffix :: Slice }
111+ ;
112+ (define-record ConcatTree
113+ ((immutable prefix)
114+ (immutable deep)
115+ (immutable suffix)))
116+
117+ ; Slice -> ConcatTree -> ConcatTree
118+ (define (tree-cons a b)
119+ (make-ConcatTree
120+ a
121+ (if (null? (ConcatTree-deep b))
122+ (ConcatTree-prefix b)
123+ (cons (ConcatTree-prefix b) (ConcatTree-deep b)))
124+ (ConcatTree-suffix b)))
125+
126+ ; ConcatTree -> Slice -> ConcatTree
127+ (define (tree-snoc a b)
128+ (make-ConcatTree
129+ (ConcatTree-prefix a)
130+ (if (null? (ConcatTree-deep a))
131+ (ConcatTree-suffix a)
132+ (cons (ConcatTree-deep a) (ConcatTree-suffix a)))
133+ b))
134+
135+ ; ConcatTree -> ConcatTree -> ConcatTree
136+ (define (concat a b)
137+ (make-ConcatTree
138+ (ConcatTree-prefix a)
139+ (cond
140+ [(and (null? (ConcatTree-deep a)) (null? (ConcatTree-deep b)))
141+ (cons (ConcatTree-suffix a) (ConcatTree-prefix b))]
142+ [(null? (ConcatTree-deep a))
143+ (cons (cons (ConcatTree-suffix a) (ConcatTree-prefix b))
144+ (ConcatTree-deep b))]
145+ [(null? (ConcatTree-deep b))
146+ (cons (ConcatTree-deep a)
147+ (cons (ConcatTree-suffix a) (ConcatTree-prefix b)))]
148+ [else
149+ (cons
150+ (cons (ConcatTree-deep a)
151+ (cons (ConcatTree-suffix a) (ConcatTree-prefix b)))
152+ (ConcatTree-deep b))])
153+ (ConcatTree-suffix b)))
154+
155+ (define (pstring-compact? str)
156+ (or
157+ (Slice? str)
158+ (and (Concat? str) (Slice? (Concat-str str)))))
159+
160+ ; fixnum -> ConcatTree -> Slice
161+ (define (compact-tree len str)
162+
163+ ; Copies the rope binary tree into an already allocated bytevector
164+ ; of the correct size
165+ (define (copy-tree! buffer buffer-index tree)
166+ (cond
167+ [(null? tree) buffer-index]
168+ [(pair? tree)
169+ (let ([at-1 (copy-tree! buffer buffer-index (car tree))])
170+ (copy-tree! buffer at-1 (cdr tree)))]
171+ [else
172+ (begin
173+ (pstring-buffer-copy! (Slice-buffer tree)
174+ (Slice-offset tree)
175+ buffer
176+ buffer-index
177+ (Slice-length tree))
178+ (fx+ buffer-index (Slice-length tree)))]))
179+
180+ (let* ([buffer (pstring-buffer-alloc len)]
181+ [left (ConcatTree-prefix str)]
182+ [right (ConcatTree-suffix str)])
183+ (pstring-buffer-copy! (Slice-buffer left)
184+ (Slice-offset left)
185+ buffer
186+ 0
187+ (Slice-length left))
188+ (let ([buffer-index (copy-tree! buffer (Slice-length left) (ConcatTree-deep str))])
189+ (pstring-buffer-copy! (Slice-buffer right)
190+ (Slice-offset right)
191+ buffer
192+ buffer-index
193+ (Slice-length right))
194+ (make-Slice buffer 0 len))))
195+
196+ ; Compact the string and memoize
197+ ; Concat -> Slice
198+ (define (compact! c)
199+ (let ([s (compact-tree (Concat-length c) (Concat-str c))])
200+ (set-Concat-str! c s)
201+ s))
202+
203+ (define (pstring-compact! str)
204+ (cond
205+ [(Concat? str)
206+ (if (Slice? (Concat-str str))
207+ ; already compacted, return the memoized slice
208+ (Concat-str str)
209+ (compact! str))]
210+ [else str]))
211+
212+
213+ ;
214+ ; Constructors
215+ ;
216+
217+ (define empty-pstring (make-Slice (make-immobile-bytevector 0) 0 0))
218+
219+ ; Make a string of length `n` in code units
220+ (define (make-pstring-of-length n)
221+ (make-Slice (pstring-buffer-alloc n) 0 n))
222+
223+ ; Makes a string of one scheme char
224+ ;
225+ ; NOTE: this only takes a PS char which is guaranteed to
226+ ; be only one code unit in size
227+ (define (pstring-singleton c)
228+ (let ([bv (pstring-buffer-alloc 1)])
229+ (pstring-buffer-set! bv 0 (char->integer c))
230+ (make-Slice bv 0 1)))
231+
232+ ; Makes a string from a list of chars
233+ ; NOTE: this only takes in PS chars which are guaranteed to
234+ ; be only one code unit in size
235+ (define (list->pstring . chars)
236+ (let* ([len (length chars)]
237+ [cv (pstring-buffer-alloc len)])
238+ (let loop ([i 0] [rest chars])
239+ (if (null? rest)
240+ cv
241+ (begin
242+ (pstring-buffer-set! cv i (char->integer (car rest)))
243+ (loop (fx1+ i) (cdr rest)))))
244+ (make-Slice cv 0 len)))
245+
246+ ; Macro that encodes literal scheme strings to `pstrings`
247+ ; at compile time.
248+ (define-syntax string->pstring
249+ (lambda (x)
250+ (syntax-case x ()
251+ [(string->pstring s)
252+ (let ([d (syntax->datum #'s)])
253+ (if (string? d)
254+ (let ([bv (string->utf16-immobile d)])
255+ #`(make-Slice #,bv 0 #,(fx/ (bytevector-length bv) 2)))
256+ #'(let ([bv (string->utf16-immobile s)])
257+ (make-Slice bv 0 (fx/ (bytevector-length bv) 2)))))])))
258+
259+ ; Makes a pstring from a list of code point scalar values.
260+ (define (code-points->pstring . xs)
261+ (let ([bv (string->utf16 (apply string (map integer->char xs)) (native-endianness))])
262+ (make-Slice bv 0 (fx/ (bytevector-length bv) code-unit-length))))
263+
264+ ; Makes a pstring from a number
265+ (define number->pstring
266+ (case-lambda
267+ [(n) (string->pstring (number->string n))]
268+ [(n radix) (string->pstring (number->string n radix))]))
269+
270+ ; Makes a pstring from a flexvector of scheme chars
271+ (define (char-flexvector->pstring v)
272+ (let* ([len (srfi:214:flexvector-length v)]
273+ [bv (pstring-buffer-alloc len)])
274+ (srfi:214:flexvector-for-each/index
275+ (lambda (i c)
276+ (pstring-buffer-set! bv i (char->integer c)))
277+ v)
278+ (make-Slice bv 0 len)))
279+
280+ ;
281+ ; Comparisons
282+ ;
283+
284+ (define (pstring-empty? str)
285+ (fx=? (pstring-length str) 0))
286+
287+ ; Fast equality check based on object reference.
288+ (define (pstring-slice-eq? x y)
289+ (and
290+ (Slice? x)
291+ (Slice? y)
292+ (and (fx=? (Slice-length x) (Slice-length y))
293+ (fx=? (Slice-offset x) (Slice-offset y))
294+ (eq? (Slice-buffer x) (Slice-buffer y)))))
295+
296+ (define (pstring=? x y)
297+ ; Assumes the buffers have the same length
298+ (define (pstring-equal-code-units? x y)
299+ (let ([cursor-x (pstring->cursor x)]
300+ [cursor-y (pstring->cursor y)])
301+ (let loop ([n 0]
302+ [ch-x (pstring-cursor-read-code-unit cursor-x)]
303+ [ch-y (pstring-cursor-read-code-unit cursor-y)])
304+ (or
305+ (or (eof-object? ch-x) (eof-object? ch-y))
306+ (and (fx=? ch-x ch-y)
307+ (loop (fx1+ n)
308+ (pstring-cursor-read-code-unit cursor-x)
309+ (pstring-cursor-read-code-unit cursor-y)))))))
310+ (and
311+ (fx=? (pstring-length x) (pstring-length y))
312+ (or
313+ ; Do they point to the same object in memory?
314+ (and (Slice? x)
315+ (Slice? y)
316+ (fx=? (Slice-offset x) (Slice-offset y))
317+ (eq? (Slice-buffer x) (Slice-buffer y)))
318+ (pstring-equal-code-units? x y))))
319+
320+ (define (pstring<? x y)
321+ (and
322+ (not (pstring-slice-eq? x y))
323+ (let ([cursor-x (pstring->cursor x)] [cursor-y (pstring->cursor y)])
324+ (let loop ([ch-x (pstring-cursor-read-char cursor-x)]
325+ [ch-y (pstring-cursor-read-char cursor-y)])
326+ (or
327+ (and (eof-object? ch-x)
328+ (not (eof-object? ch-y)))
329+ (and (not (eof-object? ch-x))
330+ (not (eof-object? ch-y))
331+ (or (char<? ch-x ch-y)
332+ (and (char=? ch-x ch-y)
333+ (loop
334+ (pstring-cursor-read-char cursor-x)
335+ (pstring-cursor-read-char cursor-y))))))))))
336+
337+ (define (pstring>? x y)
338+ (and
339+ (not (pstring-slice-eq? x y))
340+ (let ([cursor-x (pstring->cursor x)]
341+ [cursor-y (pstring->cursor y)])
342+ (let loop ([ch-x (pstring-cursor-read-char cursor-x)]
343+ [ch-y (pstring-cursor-read-char cursor-y)])
344+ (or
345+ ; is x longer than y?
346+ (and (not (eof-object? ch-x))
347+ (eof-object? ch-y))
348+ (and
349+ (not (eof-object? ch-x))
350+ (not (eof-object? ch-y))
351+ (or (char>? ch-x ch-y)
352+ (and (char=? ch-x ch-y)
353+ (loop (pstring-cursor-read-char cursor-x)
354+ (pstring-cursor-read-char cursor-y))))))))))
355+
356+ (define (pstring<=? x y)
357+ (or
358+ (pstring-slice-eq? x y)
359+ (let ([cursor-x (pstring->cursor x)]
360+ [cursor-y (pstring->cursor y)])
361+ (let loop ([ch-x (pstring-cursor-read-char cursor-x)]
362+ [ch-y (pstring-cursor-read-char cursor-y)])
363+ (or
364+ (and
365+ (eof-object? ch-x)
366+ (eof-object? ch-y))
367+ (and (eof-object? ch-x)
368+ (not (eof-object? ch-y)))
369+ (and
370+ (not (eof-object? ch-x))
371+ (not (eof-object? ch-y))
372+ (or (char<? ch-x ch-y)
373+ (and (char=? ch-x ch-y)
374+ (loop (pstring-cursor-read-char cursor-x)
375+ (pstring-cursor-read-char cursor-y))))))))))
376+
377+ (define (pstring>=? x y)
378+ (or
379+ (pstring-slice-eq? x y)
380+ (let ([cursor-x (pstring->cursor x)]
381+ [cursor-y (pstring->cursor y)])
382+ (let loop ([ch-x (pstring-cursor-read-char cursor-x)]
383+ [ch-y (pstring-cursor-read-char cursor-y)])
384+ (or
385+ (and
386+ (eof-object? ch-x)
387+ (eof-object? ch-y))
388+ (and (not (eof-object? ch-x))
389+ (eof-object? ch-y))
390+ (and
391+ (not (eof-object? ch-x))
392+ (not (eof-object? ch-y))
393+ (or (char>? ch-x ch-y)
394+ (and (char=? ch-x ch-y)
395+ (loop (pstring-cursor-read-char cursor-x)
396+ (pstring-cursor-read-char cursor-y))))))))))
397+
398+
399+ ;
400+ ; Accessors
401+ ;
402+
403+ ; Gets first code unit scalar value
404+ (define (slice-ref-first str)
405+ (pstring-buffer-ref (Slice-buffer str) (Slice-offset str)))
406+
407+ ; Get last code unit scalar value
408+ (define (slice-ref-last str)
409+ (pstring-buffer-ref (Slice-buffer str) (fx- (fx+ (Slice-offset str) (Slice-length str)) 1)))
410+
411+ (define (pstring-ref-code-unit str n)
412+ (let ([slice (pstring-compact! str)])
413+ (let ([bv (Slice-buffer slice)])
414+ (if (fx<? n (Slice-length slice))
415+ (pstring-buffer-ref bv (fx+ n (Slice-offset slice)))
416+ ; not enough bytes to read a full code unit
417+ (raise-continuable
418+ (make-message-condition
419+ (format "pstring-ref-code-unit ~d is not a valid index" n)))))))
420+
421+ ; Gets the char at index `n`.
422+ ;
423+ ; Constant-time ref, like string-ref.
424+ (define (pstring-ref str n)
425+ (integer->char (pstring-ref-code-unit str n)))
426+
427+ ; Returns the address to the beginning of the string
428+ (define (slice-&ref slice)
429+ (pstring-buffer-&ref (Slice-buffer slice) (Slice-offset slice)))
430+
431+ ; Gets the code point scalar value at index `n`
432+ (define (pstring-ref-code-point str n)
433+ (let ([cur (pstring->cursor str)])
434+ (let loop ([cp (pstring-cursor-read-code-point cur)])
435+ (cond
436+ [(eof-object? cp)
437+ (raise-continuable
438+ (make-message-condition
439+ (format "pstring-ref-code-point: ~d is not a valid index" n)))]
440+ [(fx>? (pstring-cursor-offset cur) (fx+ (Slice-offset str) n)) cp]
441+ [else (loop (pstring-cursor-read-code-point cur))]))))
442+
443+ ; Length in code points
444+ (define (pstring-length-code-points s)
445+ (let ([cur (pstring->cursor s)])
446+ (let loop ([i 0] [cp (pstring-cursor-read-code-point cur)])
447+ (if (eof-object? cp)
448+ i
449+ (loop (fx1+ i) (pstring-cursor-read-code-point cur))))))
450+
451+ ; Finds the starting index of first found `pattern`
452+ (define (pstring-index-of str pattern)
453+ (if (pstring-empty? pattern)
454+ 0 ; special case for zero-length patterns
455+ (let loop ([candidate #f] ; the index of the first matching char
456+ [str-idx 0]
457+ [pattern-idx 0])
458+ (cond
459+ ; Found the end of the pattern, we are done
460+ [(fx=? (pstring-length pattern) pattern-idx) candidate]
461+ ; In the middle of matching but we have no more input. No match found.
462+ [(fx=? (pstring-length str) str-idx) #f]
463+ [else
464+ (let ([str-cu (pstring-ref-code-unit str str-idx)]
465+ [pattern-cu (pstring-ref-code-unit pattern pattern-idx)])
466+ (if (fx=? str-cu pattern-cu)
467+ ; Found a match for char, remember this candidate and advance to next char
468+ (loop (or candidate str-idx) (fx1+ str-idx) (fx1+ pattern-idx))
469+ (loop #f
470+ (if candidate
471+ ; No match, rewind back to the possible next candidate
472+ (fx1+ candidate)
473+ ; No match and we didn't have any candidate so just advance to next char
474+ (fx1+ str-idx))
475+ 0)))]))))
476+
477+ ; Finds the index of last occurence of `pattern`.
478+ (define (pstring-last-index-of str pattern)
479+ (if (pstring-empty? pattern)
480+ (pstring-length str)
481+ (let loop ([last-match-candidate #f]
482+ [candidate #f] ; the index of the first matching char
483+ [str-idx 0] ; haystack
484+ [pattern-idx 0]) ; chars left to be found
485+ (cond
486+ [(and (fx<? str-idx (pstring-length str)) (fx=? (pstring-length pattern) pattern-idx))
487+ ; found a match but haystack not consumed, continue searching
488+ (loop candidate #f str-idx 0)]
489+ ; Reached the end of input and pattern, so we are done
490+ [(fx=? (pstring-length pattern) pattern-idx) candidate]
491+ ; In the middle of matching but we have no more input.
492+ [(fx=? str-idx (pstring-length str)) last-match-candidate]
493+ [else
494+ (let ([pc (pstring-ref-code-unit pattern pattern-idx)]
495+ [ic (pstring-ref-code-unit str str-idx)])
496+ (if (fx=? pc ic)
497+ ; Found a match for char, advance to next char
498+ (loop last-match-candidate (or candidate str-idx) (fx1+ str-idx) (fx1+ pattern-idx))
499+ (loop last-match-candidate
500+ #f
501+ (if candidate
502+ ; No match, rewind back to the possible next candidate
503+ (fx1+ candidate)
504+ ; No match and we didn't have any candidate so just advance to next char
505+ (fx1+ str-idx))
506+ 0)))]))))
507+
508+
509+ ;
510+ ; Conversions
511+ ;
512+
513+ (define (pstring->string str)
514+ (let ([slice (pstring-compact! str)])
515+ (utf16-immobile->string (Slice-buffer slice) (Slice-offset slice) (Slice-length slice))))
516+
517+ (define pstring->number
518+ (case-lambda
519+ [(str) (string->number (pstring->string str))]
520+ [(str radix) (string->number (pstring->string str) radix)]))
521+
522+ (define (pstring->symbol str)
523+ (string->symbol (pstring->string str)))
524+
525+ (define (symbol->pstring sym)
526+ (string->pstring (symbol->string sym)))
527+
528+ ; Turns a pstring to a flexvector of chars
529+ (define (pstring->char-flexvector str)
530+ (let* ([len (pstring-length str)]
531+ [fv (srfi:214:make-flexvector len)]
532+ [cur (pstring->cursor str)])
533+ (let loop ([i 0] [c (pstring-cursor-read-char cur)])
534+ (cond
535+ [(eof-object? c) fv]
536+ [else
537+ (begin
538+ (srfi:214:flexvector-set! fv i c)
539+ (loop (fx1+ i) (pstring-cursor-read-char cur)))]))))
540+
541+ ; Turns a pstring to a list of chars
542+ (define (pstring->list str)
543+ (let ([cur (pstring->cursor str)])
544+ (let loop ([ch (pstring-cursor-read-char cur)] [ls '()])
545+ (if (eof-object? ch)
546+ (reverse ls)
547+ (loop (pstring-cursor-read-char cur) (cons ch ls))))))
548+
549+ ; Turns a pstring to a flexvector of code points
550+ (define (pstring->code-point-flexvector str)
551+ (define (reverse-list->flexvector xs len)
552+ (let ([fv (srfi:214:make-flexvector len)])
553+ (let loop ([rest xs] [i (fx1- len)])
554+ (when (not (null? rest))
555+ (srfi:214:flexvector-set! fv i (car rest))
556+ (loop (cdr rest) (fx1- i))))
557+ fv))
558+
559+ (let ([cur (pstring->cursor str)])
560+ (let loop ([ch (pstring-cursor-read-code-point cur)] [ls '()] [len 0])
561+ (if (eof-object? ch)
562+ (reverse-list->flexvector ls len)
563+ (loop (pstring-cursor-read-code-point cur) (cons ch ls) (fx1+ len))))))
564+
565+
566+ ;
567+ ; Joining & splitting
568+ ;
569+
570+ (define (pstring-append a b)
571+ (cond
572+ [(and (Concat? a) (Concat? b))
573+ (cond
574+ ; If both are memoized compacted strings, then concat the slices
575+ [(and (Slice? (Concat-str a)) (Slice? (Concat-str b)))
576+ (make-Concat
577+ (fx+ (Concat-length a) (Concat-length b))
578+ (make-ConcatTree
579+ (Concat-str a)
580+ '()
581+ (Concat-str b)))]
582+ [(Slice? (Concat-str a))
583+ (make-Concat
584+ (fx+ (Slice-length (Concat-str a)) (Concat-length b))
585+ (tree-cons (Concat-str a) (Concat-str b)))]
586+ [(Slice? (Concat-str b))
587+ (make-Concat
588+ (fx+ (Concat-length a) (Slice-length (Concat-str b)))
589+ (tree-snoc (Concat-str a) (Concat-str b)))]
590+ [else
591+ (make-Concat
592+ (fx+ (Concat-length a) (Concat-length b))
593+ (concat (Concat-str a) (Concat-str b)))])]
594+ [(Concat? a)
595+ (if (fx=? (Slice-length b) 0)
596+ a
597+ (make-Concat
598+ (fx+ (Concat-length a) (Slice-length b))
599+ (if (Slice? (Concat-str a))
600+ (make-ConcatTree
601+ (Concat-str a)
602+ '()
603+ b)
604+ (tree-snoc (Concat-str a) b))))]
605+ [(Concat? b)
606+ (if (fx=? (Slice-length a) 0)
607+ b
608+ (make-Concat
609+ (fx+ (Slice-length a) (Concat-length b))
610+ (if (Slice? (Concat-str b))
611+ (make-ConcatTree
612+ a
613+ '()
614+ (Concat-str b))
615+ (tree-cons a (Concat-str b)))))]
616+ [(and (fx=? (Slice-length a) 0) (fx=? (Slice-length b) 0))
617+ empty-pstring]
618+ [(fx=? (Slice-length a) 0) b]
619+ [(fx=? (Slice-length b) 0) a]
620+ [else
621+ (make-Concat
622+ (fx+ (Slice-length a) (Slice-length b))
623+ (make-ConcatTree
624+ a
625+ '()
626+ b))]))
627+
628+ (define (pstring-concat . xs)
629+ (fold-right pstring-append empty-pstring xs))
630+
631+ ; Create a new pstring by joining a flexvector of pstrings using a separator
632+ (define (pstring-join-with xs sep)
633+ (let* ([len (srfi:214:flexvector-fold (lambda (len s) (fx+ len (pstring-length s))) 0 xs)]
634+ [xs-count (srfi:214:flexvector-length xs)]
635+ [separator-count (if (fx=? xs-count 0) 0 (fx1- xs-count))]
636+ [separator (pstring-compact! sep)]
637+ [separator-len (Slice-length separator)]
638+ [bv-len (fx+ len (fx* separator-count separator-len))]
639+ [bv (pstring-buffer-alloc bv-len)])
640+ (let loop ([i 0] [bi 0])
641+ (if (fx<? i xs-count)
642+ (let* ([s (pstring-compact! (srfi:214:flexvector-ref xs i))]
643+ [len (Slice-length s)])
644+ (if (fx>? i 0)
645+ (begin
646+ (pstring-buffer-copy!
647+ (Slice-buffer separator)
648+ (Slice-offset separator)
649+ bv
650+ (fx+ bi)
651+ separator-len)
652+ (pstring-buffer-copy!
653+ (Slice-buffer s)
654+ (Slice-offset s)
655+ bv
656+ (fx+ bi separator-len)
657+ len)
658+ (loop (fx1+ i) (fx+ bi len separator-len)))
659+ (begin
660+ (pstring-buffer-copy! (Slice-buffer s) (Slice-offset s) bv bi len)
661+ (loop (fx1+ i) (fx+ bi len)))))
662+ (make-Slice bv 0 bv-len)))))
663+
664+ ; Splits a pstring into a flexvector of pstrings using a pattern
665+ (define (pstring-split str pattern)
666+ (cond
667+ [(pstring-empty? str) (srfi:214:flexvector)]
668+ [(pstring-empty? pattern)
669+ (let* ([len (pstring-length str)]
670+ [fv (srfi:214:make-flexvector len)]
671+ [cur (pstring->cursor str)])
672+ (let loop ([i 0] [ch (pstring-cursor-read-char cur)])
673+ (cond
674+ [(eof-object? ch) fv]
675+ [else
676+ (begin
677+ (srfi:214:flexvector-set! fv i (pstring-singleton ch))
678+ (loop (fx1+ i) (pstring-cursor-read-char cur)))])))]
679+ [else
680+ (let* ([all-indices (all-index-of str pattern)]
681+ [vec (srfi:214:make-flexvector (fx1+ (length all-indices)))])
682+ (let loop ([indices all-indices]
683+ [i 0]
684+ [pi 0])
685+ (if (null? indices)
686+ (begin
687+ (srfi:214:flexvector-set! vec i (pstring-slice str pi))
688+ vec)
689+ (let ([index (car indices)])
690+ (srfi:214:flexvector-set! vec i (pstring-slice str pi index))
691+ (loop (cdr indices) (fx1+ i) (fx+ index (Slice-length pattern)))))))]))
692+
693+
694+ ;
695+ ; Slicing
696+ ;
697+
698+ ; Slice -> fixnum -> fixnum -> Slice
699+ (define slice
700+ (case-lambda
701+ [(str start)
702+ (slice str start (pstring-length str))]
703+ [(str start end)
704+ (let* ([start-index (fxmin (fxmax 0 start) (Slice-length str))]
705+ [end-index (fxmin (fxmax 0 end) (Slice-length str))]
706+ [len (fx- end-index start-index)])
707+ (if (fx<? len 0)
708+ empty-pstring
709+ (make-Slice
710+ (Slice-buffer str)
711+ (fx+ (Slice-offset str) start-index)
712+ len)))]))
713+
714+ ; The primitive constant-time slice operation.
715+ ; Takes in a` start` index and optionally an `end` index.
716+ (define pstring-slice
717+ (case-lambda
718+ [(str start)
719+ (pstring-slice str start (pstring-length str))]
720+ [(str start end)
721+ (cond
722+ ; Already a Slice?
723+ [(Slice? str) (slice str start end)]
724+ [(and (Concat? str) (ConcatTree? (Concat-str str)))
725+ (let* ([tree (Concat-str str)]
726+ [suffix-start
727+ (fx+ (Slice-length (ConcatTree-prefix tree))
728+ (fx- (Concat-length str)
729+ (Slice-length (ConcatTree-prefix tree))
730+ (Slice-length (ConcatTree-suffix tree))))])
731+ (cond
732+ ; Entirely reachable in the prefix?
733+ [(fx<=? end (Slice-length (ConcatTree-prefix tree)))
734+ (slice (ConcatTree-prefix tree) start end)]
735+ ; Entirely reachable in the suffix?
736+ [(fx>=? start suffix-start)
737+ (slice (ConcatTree-suffix tree)
738+ (fx- start suffix-start)
739+ (fx- end suffix-start))]
740+ ; TODO When `str` is null, slice can reach both prefix and suffix
741+ ; []
742+ [else
743+ (let ([s (compact! str)])
744+ (slice s start end))]))]
745+ ; It's a compacted string
746+ [else
747+ (slice (Concat-str str) start end)])]))
748+
749+ (define (pstring-take str n)
750+ (pstring-slice str 0 n))
751+
752+ (define (pstring-drop str n)
753+ (pstring-slice str n))
754+
755+ ; Linear-time `take` on code points.
756+ (define (pstring-take-code-points str n)
757+ (if (fx<? n 1)
758+ empty-pstring
759+ (let ([cur (pstring->cursor str)])
760+ (let loop ([i n])
761+ (if (fx=? i 0)
762+ (pstring-take str (fx- (pstring-cursor-offset cur) (Slice-offset str)))
763+ (let ([cp (pstring-cursor-read-code-point cur)])
764+ (cond
765+ [(eof-object? cp) str]
766+ [else (loop (fx1- i))])))))))
767+
768+ ; Like pstring-drop but without bounds checks
769+ (define (slice-unsafe-drop s n)
770+ (make-Slice
771+ (Slice-buffer s)
772+ (fx+ (Slice-offset s) n)
773+ (fx- (Slice-length s) n)))
774+
775+ ; Returns the first char and the rest of the pstring
776+ (define (pstring-uncons-char str)
777+ (let-values ([(head tail) (pstring-uncons-code-unit str)])
778+ (values (integer->char head) tail)))
779+
780+ ; Returns the first code unit scalar and the rest of the pstring
781+ (define (pstring-uncons-code-unit str)
782+ (if (pstring-empty? str)
783+ (raise-continuable
784+ (make-message-condition
785+ (format "pstring-uncons-code-unit: cannot uncons an empty pstring ~a" str)))
786+ (let* ([slice (pstring-compact! str)]
787+ [w1 (slice-ref-first slice)]
788+ [tail (slice-unsafe-drop slice 1)])
789+ (values w1 tail))))
790+
791+
792+ ;
793+ ; Modifications
794+ ;
795+
796+ (define (pstring-downcase str)
797+ (let* ([src (pstring-compact! str)]
798+ ; The output might be twice the length of the input in some languages
799+ [dst-len (fx1+ (fx* (Slice-length src) 2))]
800+ [dst (pstring-buffer-alloc dst-len)]
801+ [errorcode-addr (foreign-alloc (foreign-sizeof 'int))]
802+ [errorcode-ptr (make-ftype-pointer int errorcode-addr)])
803+ ; ICU requires that we set the initial error code value to 0
804+ (ftype-set! int () errorcode-ptr 0 0)
805+ (let* ([len (u_strToLower (pstring-buffer-&ref dst 0) dst-len (slice-&ref src) (Slice-length src) 0 errorcode-addr)]
806+ [errorcode (ftype-ref int () (make-ftype-pointer int errorcode-addr) 0)])
807+ (foreign-free errorcode-addr)
808+ (if (not (= errorcode 0))
809+ (error "pstring-downcase" (format "error calling u_strToLower, error code ~a" errorcode))
810+ (make-Slice dst 0 len)))))
811+
812+ (define (pstring-upcase str)
813+ (let* ([src (pstring-compact! str)]
814+ ; The output might be twice the length of the input in some languages
815+ [dst-len (fx1+ (fx* (Slice-length src) 2))]
816+ [dst (pstring-buffer-alloc dst-len)]
817+ [errorcode-addr (foreign-alloc (foreign-sizeof 'int))]
818+ [errorcode-ptr (make-ftype-pointer int errorcode-addr)])
819+ ; ICU requires that we set the initial error code value to 0
820+ (ftype-set! int () errorcode-ptr 0 0)
821+ (let* ([len (u_strToUpper (pstring-buffer-&ref dst 0) dst-len (slice-&ref src) (Slice-length src) 0 errorcode-addr)]
822+ [errorcode (ftype-ref int () (make-ftype-pointer int errorcode-addr) 0)])
823+ (foreign-free errorcode-addr)
824+ (if (not (= errorcode 0))
825+ (error "pstring-upcase" (format "error calling u_strToUpper, error code ~a" errorcode))
826+ (make-Slice dst 0 len)))))
827+
828+ ; Trim whitespace around the pstring
829+ (define (pstring-trim str)
830+ (define (whitespace? c)
831+ (or
832+ ; Whitespace characters
833+ (fx=? c #x0009)
834+ (fx=? c #x000B)
835+ (fx=? c #x000C)
836+ (fx=? c #x0020)
837+ (fx=? c #x00A0)
838+ (fx=? c #xFEFF)
839+
840+ ; Line terminators
841+ (fx=? c #x000A)
842+ (fx=? c #x000D)
843+ (fx=? c #x2028)
844+ (fx=? c #x2029)))
845+
846+ (let* ([cur (pstring->cursor str)]
847+ [suffix
848+ (let loop ([u (pstring-cursor-peek-code-unit cur)])
849+ (cond
850+ [(eof-object? u) (cursor->pstring cur)]
851+ [(whitespace? u) (begin
852+ (pstring-cursor-read-code-unit cur)
853+ (loop (pstring-cursor-peek-code-unit cur)))]
854+ [else (cursor->pstring cur)]))])
855+ (let loop ([rest suffix])
856+ (if (pstring-empty? rest)
857+ rest
858+ (let ([last (slice-ref-last rest)]
859+ [prefix (pstring-take rest (fx1- (Slice-length rest)))])
860+ (if (whitespace? last) (loop prefix) rest))))))
861+
862+ ; Replace the first occurence of `pattern` with `replacement`
863+ (define (pstring-replace str pattern replacement)
864+ (if (pstring-empty? pattern)
865+ str
866+ (let ([i (pstring-index-of str pattern)])
867+ (if (not i)
868+ str
869+ (let* ([len (fx+ (fx- (Slice-length str) (Slice-length pattern))
870+ (Slice-length replacement))]
871+ [bv (pstring-buffer-alloc len)])
872+ (pstring-buffer-copy! (Slice-buffer str) (Slice-offset str) bv 0 i)
873+ (pstring-buffer-copy! (Slice-buffer replacement)
874+ (Slice-offset replacement)
875+ bv
876+ i
877+ (Slice-length replacement))
878+ (pstring-buffer-copy! (Slice-buffer str)
879+ (fx+ (Slice-offset str) i (Slice-length pattern))
880+ bv
881+ (fx+ i (Slice-length replacement))
882+ (fx- (Slice-length str) i (Slice-length pattern)))
883+ (make-Slice bv 0 len))))))
884+
885+ ; Find all occurences and return their indices as a list
886+ (define (all-index-of str pattern)
887+ (let go ([start 0])
888+ (let ([slice (pstring-drop str start)])
889+ (if (or (pstring-empty? str) (pstring-empty? pattern))
890+ '()
891+ (let ([i (pstring-index-of slice pattern)])
892+ (if i
893+ (cons (fx+ start i)
894+ (go (fx+ start i (Slice-length pattern))))
895+ '()))))))
896+
897+ ; Replace all occurences of `pattern` with `replacement`
898+ (define (pstring-replace-all str pattern replacement)
899+ (let ([slice (pstring-compact! str)])
900+ (if (pstring-empty? slice)
901+ slice
902+ (let* ([is (all-index-of slice pattern)]
903+ [replacements-delta (fx* (length is)
904+ (fx- (Slice-length pattern)
905+ (Slice-length replacement)))]
906+ [len (fx- (Slice-length slice) replacements-delta)]
907+ [bv (pstring-buffer-alloc len)])
908+ (let loop ([stri 0] ; where we are at str
909+ [bvi 0] ; where we are at bv
910+ [rest is])
911+ (if (null? rest)
912+ ; copy the left-overs into place
913+ (pstring-buffer-copy! (Slice-buffer slice)
914+ (fx+ (Slice-offset slice) stri)
915+ bv
916+ bvi
917+ (fx- (Slice-length slice) stri))
918+ (let* ([i (car rest)] [before-len (fx- i stri)])
919+ ; copy stuff before the match
920+ (pstring-buffer-copy! (Slice-buffer slice)
921+ (fx+ (Slice-offset slice) stri)
922+ bv
923+ bvi
924+ before-len)
925+ ; the replacement itself
926+ (pstring-buffer-copy! (Slice-buffer replacement)
927+ (Slice-offset replacement)
928+ bv
929+ (fx+ bvi before-len)
930+ (Slice-length replacement))
931+ (loop
932+ (fx+ i (Slice-length pattern))
933+ (fx+ (fx+ bvi before-len) (Slice-length replacement))
934+ (cdr rest)))))
935+ (make-Slice bv 0 len)))))
936+
937+
938+ ;
939+ ; Regex
940+ ;
941+
942+ (define-structure
943+ (regex code match-data source flags))
944+
945+ ; Replace match(es) using the replacement returned by calling `f` with the match.
946+ ;
947+ ; Regex -> Slice -> (String -> flexvector String -> String) -> String
948+ (define (pstring-regex-replace-by regex subject f)
949+ (let ([subject-slice (pstring-compact! subject)])
950+ (if (regex-has-flag regex PCRE2_SUBSTITUTE_GLOBAL)
951+ (pstring-regex-replace-all-by regex subject-slice f)
952+ (pstring-regex-replace-single-by regex subject-slice f))))
953+
954+ (define identity (lambda (x) x))
955+
956+ ; Replace all matches using the replacement returned by calling `f` with the match.
957+ ;
958+ ; Regex -> Slice -> (String -> flexvector String -> String) -> String
959+ (define (pstring-regex-replace-all-by regex str f)
960+ (let*-values ([(delta all-matches)
961+ (let match-next ([sub-str str] [delta 0] [all-matches-reverse '()])
962+ (let ([matches (pstring-regex-match regex sub-str identity #f)])
963+ (if (and matches (fx>? (srfi:214:flexvector-length matches) 0))
964+ (let* ([match (srfi:214:flexvector-ref matches 0)]
965+ [_ (srfi:214:flexvector-remove-front! matches)]
966+ [replacement (pstring-compact! (f match matches))])
967+ (match-next
968+ ; Should slice be used here?
969+ (make-Slice
970+ (Slice-buffer sub-str)
971+ (fx+ (Slice-offset match) (Slice-length match))
972+ (fx- (Slice-length sub-str)
973+ (fx- (fx+ (Slice-offset match) (Slice-length match))
974+ (Slice-offset sub-str))))
975+ (fx+ delta (fx- (Slice-length replacement) (Slice-length match)))
976+ (cons (cons match replacement) all-matches-reverse)))
977+ (values delta (reverse all-matches-reverse)))))]
978+ [(len) (fx+ (Slice-length str) delta)]
979+ [(bv) (pstring-buffer-alloc len)])
980+ (let loop ([stri (Slice-offset str)] [bvi 0] [rest all-matches])
981+ (if (null? rest)
982+ ; copy the left-overs into place
983+ (pstring-buffer-copy!
984+ (Slice-buffer str)
985+ stri
986+ bv
987+ bvi
988+ (fx- (Slice-length str) (fx- stri (Slice-offset str))))
989+ (let* ([match (caar rest)]
990+ [replacement (cdar rest)]
991+ [i (Slice-offset match)]
992+ [before-len (fx- i stri)])
993+ ; copy stuff before the match
994+ (pstring-buffer-copy! (Slice-buffer str) stri bv bvi before-len)
995+ ; the replacement itself
996+ (pstring-buffer-copy!
997+ (Slice-buffer replacement)
998+ (Slice-offset replacement)
999+ bv
1000+ (fx+ bvi before-len)
1001+ (Slice-length replacement))
1002+ (loop
1003+ (fx+ (Slice-offset match) (Slice-length match))
1004+ (fx+ (fx+ bvi before-len) (Slice-length replacement))
1005+ (cdr rest)))))
1006+
1007+ (make-Slice bv 0 len)))
1008+
1009+ ; Replace the first match using the replacement returned by calling `f` with the match.
1010+ ;
1011+ ; Regex -> Slice -> (String -> flexvector String -> String) -> String
1012+ (define (pstring-regex-replace-single-by regex str f)
1013+ (let ([matches (pstring-regex-match regex str identity #f)])
1014+ (if (and matches (fx>? (srfi:214:flexvector-length matches) 0))
1015+ (let* ([match (srfi:214:flexvector-ref matches 0)]
1016+ [_ (srfi:214:flexvector-remove-front! matches)]
1017+ [replacement (pstring-compact! (f match matches))]
1018+ [delta (fx- (Slice-length replacement) (Slice-length match))]
1019+ [len (fx+ (Slice-length str) delta)]
1020+ [buf (pstring-buffer-alloc len)])
1021+ (let* ([before-len (fx- (Slice-offset match) (Slice-offset str))])
1022+ ; copy stuff before the match
1023+ (pstring-buffer-copy!
1024+ (Slice-buffer str)
1025+ (Slice-offset str)
1026+ buf
1027+ 0
1028+ before-len)
1029+ ; the replacement itself
1030+ (pstring-buffer-copy!
1031+ (Slice-buffer replacement)
1032+ (Slice-offset replacement)
1033+ buf
1034+ before-len
1035+ (Slice-length replacement))
1036+ ; copy the stuff after the match
1037+ (pstring-buffer-copy!
1038+ (Slice-buffer str)
1039+ (fx+ (Slice-offset match) (Slice-length match))
1040+ buf
1041+ (fx+ before-len (Slice-length replacement))
1042+ (fx- (Slice-length str)
1043+ (fx+ before-len (Slice-length match))))
1044+ (make-Slice buf 0 len)))
1045+ str)))
1046+
1047+ ; Replace a match with `replacement`
1048+ (define (pstring-regex-replace regex subject replacement)
1049+ (let* ([subject-slice (pstring-compact! subject)]
1050+ [replacement-slice (pstring-compact! replacement)]
1051+ [match-data (pcre2_match_data_create_from_pattern_16 (regex-code regex) 0)]
1052+ [buf-len (make-ftype-pointer size_t (foreign-alloc (foreign-sizeof 'size_t)))]
1053+ [subject-addr (slice-&ref subject-slice)]
1054+ [subject-len (Slice-length subject-slice)]
1055+ [replacement-addr (slice-&ref replacement-slice)]
1056+ [replacement-len (Slice-length replacement-slice)]
1057+ [start-offset 0]
1058+ [match-context 0]
1059+ ; first calculate the size of the output buffer by passing in 0 as the buf size
1060+ ; and using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
1061+ [_ (ftype-set! size_t () buf-len 0 0)]
1062+ [res (pcre2_substitute_16
1063+ (regex-code regex)
1064+ subject-addr
1065+ subject-len
1066+ start-offset
1067+ (fxlogor (fxlogand (regex-flags regex) PCRE2_SUBSTITUTE_GLOBAL)
1068+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH)
1069+ match-data
1070+ match-context
1071+ replacement-addr
1072+ replacement-len
1073+ ; basically a null pointer
1074+ (make-ftype-pointer unsigned-16 0)
1075+ (ftype-&ref size_t () buf-len))]
1076+ [len (ftype-ref size_t () buf-len 0)]
1077+ ; NOTE we allocate space for the trailing NULL code unit,
1078+ ; but this should be fine because `pstring` has it's own `length`
1079+ ; so it won't ever read that NULL code unit.
1080+ [buf (pstring-buffer-alloc (ftype-ref size_t () buf-len 0))]
1081+ ; now do the actual substitution
1082+ [res2 (pcre2_substitute_16
1083+ (regex-code regex)
1084+ subject-addr
1085+ subject-len
1086+ start-offset
1087+ (fxlogand (regex-flags regex) PCRE2_SUBSTITUTE_GLOBAL)
1088+ match-data
1089+ match-context
1090+ replacement-addr
1091+ replacement-len
1092+ (pstring-buffer-&ref buf 0)
1093+ (ftype-&ref size_t () buf-len))])
1094+ (foreign-free (ftype-pointer-address buf-len))
1095+ ; Subtract NULL code unit from length
1096+ (make-Slice buf 0 (fx1- len))))
1097+
1098+ (define (pstring-regex-split regex str)
1099+ (cond
1100+ [(pstring=? (regex-source regex) empty-pstring)
1101+ (srfi:214:flexvector-map pstring-singleton (pstring->char-flexvector str))]
1102+ [else
1103+ (let* ([str-slice (pstring-compact! str)]
1104+ [all-matches
1105+ (let match-next ([sub-str str-slice] [all-matches-reverse '()])
1106+ (let ([matches (pstring-regex-match regex sub-str identity #f)])
1107+ (if (and matches (fx>? (srfi:214:flexvector-length matches) 0))
1108+ (let* ([match (srfi:214:flexvector-ref matches 0)])
1109+ (match-next
1110+ ; Should slice be used here?
1111+ (make-Slice
1112+ (Slice-buffer sub-str)
1113+ (fx+ (Slice-offset match) (Slice-length match))
1114+ (fx- (Slice-length sub-str)
1115+ (fx- (fx+ (Slice-offset match) (Slice-length match))
1116+ (Slice-offset sub-str))))
1117+ (cons match all-matches-reverse)))
1118+ (reverse all-matches-reverse))))])
1119+ (let* ([match-count (length all-matches)]
1120+ [fv (srfi:214:make-flexvector (fx1+ match-count))])
1121+ (let loop ([stri (Slice-offset str-slice)] [rest all-matches] [match-idx 0])
1122+ (if (null? rest)
1123+ ; copy rest of the string as the last element
1124+ (begin
1125+ (srfi:214:flexvector-set! fv match-idx (pstring-drop str-slice (fx- stri (Slice-offset str-slice))))
1126+ fv)
1127+ (let* ([prefix-len (fx- (Slice-offset (car rest)) stri)]
1128+ [start-idx (fx- stri (Slice-offset str-slice))]
1129+ [end-idx (fx+ start-idx prefix-len)])
1130+ (srfi:214:flexvector-set! fv match-idx (pstring-slice str-slice start-idx end-idx))
1131+ (loop (fx+ stri prefix-len (Slice-length (car rest))) (cdr rest) (fx1+ match-idx)))))))]))
1132+
1133+ ; Compiles a regex pattern to a regex.
1134+ (define pstring-make-regex
1135+ (case-lambda
1136+ [(str) (pstring-make-regex str '())]
1137+ [(str flags)
1138+ (let* ([slice (pstring-compact! str)]
1139+ [errorcode (foreign-alloc 4)]
1140+ [erroroffset (foreign-alloc 4)]
1141+ [options (flags->options flags)]
1142+ [code (pcre2_compile_16
1143+ (slice-&ref slice)
1144+ (Slice-length slice)
1145+ options
1146+ errorcode
1147+ erroroffset
1148+ 0)])
1149+ (foreign-free errorcode)
1150+ (foreign-free erroroffset)
1151+ (if (fx=? code 0)
1152+ #f
1153+ (begin
1154+ (pcre2_jit_compile_16 code PCRE2_JIT_COMPLETE)
1155+ (finalizer (make-regex code (pcre2_match_data_create_from_pattern_16 code 0) slice options)
1156+ (lambda (r)
1157+ (pcre2_code_free_16 (regex-code r))
1158+ (pcre2_match_data_free_16 (regex-match-data r)))))))]))
1159+
1160+ ; Performs a regex match and then calls `on-match` for a successful match
1161+ ; and `nomatch` for a non-match.
1162+ (define (pstring-regex-match regex subject on-match nomatch)
1163+ (let* ([subject-slice (pstring-compact! subject)]
1164+ [match-data (regex-match-data regex)]
1165+ [rc (pcre2_match_16
1166+ (regex-code regex)
1167+ (slice-&ref subject-slice)
1168+ (Slice-length subject-slice)
1169+ 0
1170+ 0
1171+ match-data
1172+ 0)])
1173+ (if (fx<? rc 0)
1174+ #f
1175+ (let* ([ovector (pcre2_get_ovector_pointer_16 match-data)]
1176+ [count (pcre2_get_ovector_count_16 match-data)]
1177+ [out (srfi:214:make-flexvector count)])
1178+ (let recur ([i 0])
1179+ (if (fx<? i count)
1180+ (let ([sub-start (foreign-ref 'size_t ovector (fx* (fx* i 2) (foreign-sizeof 'size_t)))])
1181+ ; TODO how do we get this value (PCRE2_UNSET) in a portable way?
1182+ (if (= sub-start 18446744073709551615)
1183+ (begin (srfi:214:flexvector-set! out i nomatch)
1184+ (recur (fx1+ i)))
1185+ (let* ([sub-end (foreign-ref 'size_t ovector (fx* (fx1+ (fx* i 2)) (foreign-sizeof 'size_t)))]
1186+ [sub-len (fx- sub-end sub-start)]
1187+ [match-str (make-Slice
1188+ (Slice-buffer subject-slice)
1189+ (fx+ (Slice-offset subject-slice) sub-start)
1190+ sub-len)])
1191+ (srfi:214:flexvector-set! out i (on-match match-str))
1192+ (recur (fx1+ i)))))
1193+ out))))))
1194+
1195+ ; Finds the index of the first match using a regex
1196+ (define (pstring-regex-search regex subject)
1197+ (let* ([subject-slice (pstring-compact! subject)]
1198+ [match-data (pcre2_match_data_create_from_pattern_16 (regex-code regex) 0)]
1199+ [rc (pcre2_match_16
1200+ (regex-code regex)
1201+ (slice-&ref subject-slice)
1202+ (Slice-length subject-slice)
1203+ 0
1204+ 0
1205+ match-data
1206+ 0)])
1207+ (if (fx<? rc 0)
1208+ #f
1209+ (let* ([ovector (pcre2_get_ovector_pointer_16 match-data)]
1210+ [match-index (foreign-ref 'size_t ovector 0)])
1211+ match-index))))
1212+
1213+
1214+ ;
1215+ ; Regex flags
1216+ ;
1217+
1218+ (define (flags->options flags)
1219+ (define (flag->bitmask flag)
1220+ (cond
1221+ [(eq? flag 'dotAll) PCRE2_DOTALL]
1222+ [(eq? flag 'ignoreCase) PCRE2_CASELESS]
1223+ [(eq? flag 'multiline) PCRE2_MULTILINE]
1224+ [(eq? flag 'global) PCRE2_SUBSTITUTE_GLOBAL]
1225+ [else 0]))
1226+
1227+ (fold-right
1228+ (lambda (flag acc)
1229+ (let ([m (flag->bitmask (car flag))])
1230+ (if (cdr flag) (fxlogor m acc) acc)))
1231+ DEFAULT_FLAGS
1232+ flags))
1233+
1234+ ;
1235+ ; PCRE bindings
1236+ ;
1237+
1238+ ; The used PCRE flags.
1239+ ;
1240+ ; See full list of flags here:
1241+ ; <https://github.com/PCRE2Project/pcre2/blob/7b649dce27f1adf67c4d266f3a051941dcf38cb3/src/pcre2.h.in>
1242+ (define PCRE2_ALT_BSUX #x00000002)
1243+ (define PCRE2_EXTRA_ALT_BSUX #x00000020)
1244+ (define PCRE2_SUBSTITUTE_GLOBAL #x00000100)
1245+ (define PCRE2_CASELESS #x00000008)
1246+ (define PCRE2_MULTILINE #x00000400)
1247+ (define PCRE2_DOTALL #x00000020)
1248+
1249+ (define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH #x00001000)
1250+
1251+ (define PCRE2_JIT_COMPLETE #x00000001)
1252+
1253+ (define DEFAULT_FLAGS (fxlogor PCRE2_ALT_BSUX
1254+ PCRE2_EXTRA_ALT_BSUX))
1255+
1256+ (define (regex-has-flag regex flag)
1257+ (fx>? (fxlogand (regex-flags regex) flag) 0))
1258+
1259+ (define pcre-init
1260+ (case (machine-type)
1261+ ; Not tested at all with Windows
1262+ ; [(i3nt ti3nt a6nt ta6nt) (load-shared-object "libpcre2-16.dll")]
1263+ [(i3osx ti3osx a6osx ta6osx arm64osx tarm64osx) (load-shared-object "libpcre2-16.dylib")]
1264+ [(i3le ti3le a6le ta6le arm64le tarm64le) (load-shared-object "libpcre2-16.so")]
1265+ [else (error "purescm"
1266+ (format "Failed to load libpcre2: machine-type ~s not supported." (machine-type)))]))
1267+
1268+ (define pcre2_compile_16
1269+ (foreign-procedure "pcre2_compile_16" ((* unsigned-16) size_t unsigned-32 uptr uptr uptr)
1270+ uptr))
1271+
1272+ (define pcre2_match_data_create_from_pattern_16
1273+ (foreign-procedure "pcre2_match_data_create_from_pattern_16" (uptr uptr)
1274+ uptr))
1275+
1276+ (define pcre2_match_16
1277+ (foreign-procedure "pcre2_match_16" (uptr (* unsigned-16) size_t size_t unsigned-32 uptr uptr)
1278+ int))
1279+
1280+ (define pcre2_substitute_16
1281+ (foreign-procedure "pcre2_substitute_16" (uptr (* unsigned-16) size_t size_t unsigned-32 uptr uptr (* unsigned-16) size_t (* unsigned-16) (* size_t))
1282+ int))
1283+
1284+ (define pcre2_get_ovector_pointer_16
1285+ (foreign-procedure "pcre2_get_ovector_pointer_16" (uptr)
1286+ uptr))
1287+
1288+ (define pcre2_get_ovector_count_16
1289+ (foreign-procedure "pcre2_get_ovector_count_16" (uptr)
1290+ unsigned-32))
1291+
1292+ (define pcre2_match_data_free_16
1293+ (foreign-procedure "pcre2_match_data_free_16" (uptr)
1294+ void))
1295+
1296+ (define pcre2_code_free_16
1297+ (foreign-procedure "pcre2_code_free_16" (uptr)
1298+ void))
1299+
1300+ (define pcre2_jit_compile_16
1301+ (foreign-procedure "pcre2_jit_compile_16" (uptr unsigned-32)
1302+ void))
1303+
1304+
1305+ ;
1306+ ; ICU bindings
1307+ ;
1308+
1309+ (define icu-init
1310+ (case (machine-type)
1311+ ; [(i3nt ti3nt a6nt ta6nt) (load-shared-object "libicuuc.dll")]
1312+ [(i3osx ti3osx a6osx ta6osx arm64osx tarm64osx) (load-shared-object "libicuuc.dylib")]
1313+ [(i3le ti3le a6le ta6le arm64le tarm64le) (load-shared-object "libicuuc.so")]
1314+ [else (error "purescm"
1315+ (format "Failed to load libicuuc, machine-type ~s not supported." (machine-type)))]))
1316+
1317+ (define u_strToUpper
1318+ (foreign-procedure "u_strToUpper_74" ((* unsigned-16) integer-32 (* unsigned-16) integer-32 uptr uptr)
1319+ integer-32))
1320+
1321+ (define u_strToLower
1322+ (foreign-procedure "u_strToLower_74" ((* unsigned-16) integer-32 (* unsigned-16) integer-32 uptr uptr)
1323+ integer-32))
1324+
1325+
1326+ ;
1327+ ; Cursor
1328+ ;
1329+ ; An abstraction much like scheme ports that allows looping over a string
1330+ ; without doing extra allocations
1331+ ;
1332+
1333+ (define-record pstring-cursor (buffer offset end-offset))
1334+
1335+ (define (pstring->cursor s)
1336+ (let ([str (pstring-compact! s)])
1337+ (make-pstring-cursor
1338+ (Slice-buffer str)
1339+ (Slice-offset str)
1340+ (fx+ (Slice-offset str) (Slice-length str)))))
1341+
1342+ ; Slice the underlying buffer starting from where the cursor is pointing to
1343+ (define (cursor->pstring cur)
1344+ (make-Slice (pstring-cursor-buffer cur)
1345+ (pstring-cursor-offset cur)
1346+ (fx- (pstring-cursor-end-offset cur) (pstring-cursor-offset cur))))
1347+
1348+ (define (pstring-cursor-read-code-unit cur)
1349+ (if (fx<? (pstring-cursor-offset cur) (pstring-cursor-end-offset cur))
1350+ (let ([offset (pstring-cursor-offset cur)])
1351+ (set-pstring-cursor-offset! cur (fx1+ offset))
1352+ (pstring-buffer-ref (pstring-cursor-buffer cur) offset))
1353+ (eof-object)))
1354+
1355+ (define (pstring-cursor-peek-code-unit cur)
1356+ (if (fx<? (pstring-cursor-offset cur) (pstring-cursor-end-offset cur))
1357+ (pstring-buffer-ref (pstring-cursor-buffer cur) (pstring-cursor-offset cur))
1358+ (eof-object)))
1359+
1360+ (define (pstring-cursor-read-char cur)
1361+ (let ([cp (pstring-cursor-read-code-point cur)])
1362+ (if (eof-object? cp)
1363+ (eof-object)
1364+ (integer->char cp))))
1365+
1366+ (define (pstring-cursor-peek-char cur)
1367+ (let ([cp (pstring-cursor-peek-code-point cur)])
1368+ (if (eof-object? cp)
1369+ (eof-object)
1370+ (integer->char cp))))
1371+
1372+ (define (pstring-cursor-read-code-point cur)
1373+ (if (fx<? (pstring-cursor-offset cur) (pstring-cursor-end-offset cur))
1374+ (let ([buf (pstring-cursor-buffer cur)]
1375+ [offset (pstring-cursor-offset cur)]
1376+ [end-offset (pstring-cursor-end-offset cur)])
1377+ (let ([w1 (pstring-buffer-ref buf offset)])
1378+ (cond
1379+ ; Two-word encoding? Check for high surrogate
1380+ [(and (fx<= #xD800 w1 #xDBFF) (fx>=? (fx- end-offset offset) 2))
1381+ (let ([w2 (pstring-buffer-ref buf (fx1+ offset))])
1382+ ; low surrogate?
1383+ (if (fx<= #xDC00 w2 #xDFFF)
1384+ (begin
1385+ (set-pstring-cursor-offset! cur (fx+ offset 2))
1386+ (fx+
1387+ (fxlogor
1388+ (fxsll (fx- w1 #xD800) 10)
1389+ (fx- w2 #xDC00))
1390+ #x10000))
1391+ ; low surrogate not found, just return the high surrogate
1392+ (begin
1393+ (set-pstring-cursor-offset! cur (fx1+ offset))
1394+ 65533)))]
1395+ ; misplaced continuation word?
1396+ [(fx<= #xDC00 w1 #xDFFF)
1397+ (begin
1398+ (set-pstring-cursor-offset! cur (fx1+ offset))
1399+ 65533)]
1400+ ; one-word encoding
1401+ [else
1402+ (begin
1403+ (set-pstring-cursor-offset! cur (fx1+ offset))
1404+ w1)])))
1405+ (eof-object)))
1406+
1407+ (define (pstring-cursor-peek-code-point cur)
1408+ (if (fx<? (pstring-cursor-offset cur) (pstring-cursor-end-offset cur))
1409+ (let ([buf (pstring-cursor-buffer cur)]
1410+ [offset (pstring-cursor-offset cur)]
1411+ [end-offset (pstring-cursor-end-offset cur)])
1412+ (let ([w1 (pstring-buffer-ref buf offset)])
1413+ (cond
1414+ ; Two-word encoding? Check for high surrogate
1415+ [(and (fx<= #xD800 w1 #xDBFF) (fx>=? (fx- end-offset offset) 2))
1416+ (let ([w2 (pstring-buffer-ref buf (fx1+ offset))])
1417+ ; low surrogate?
1418+ (if (fx<= #xDC00 w2 #xDFFF)
1419+ (fx+
1420+ (fxlogor
1421+ (fxsll (fx- w1 #xD800) 10)
1422+ (fx- w2 #xDC00))
1423+ #x10000)
1424+ 65533))]
1425+ ; misplaced continuation word?
1426+ [(fx<= #xDC00 w1 #xDFFF) 65533]
1427+ ; one-word encoding
1428+ [else w1])))
1429+ (eof-object)))
1430+
1431+
1432+ )
1433+
lib/purescm/runtime.ssnew file+149
@@ -0,0 +1,149 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (purescm runtime)
5+ (export
6+ list-cons
7+ record-set
8+ record-ref
9+ record-has
10+ record-remove
11+ array-length
12+ array-ref
13+ make-array
14+ define-lazy
15+ lazy
16+ boolean<?
17+ boolean<=?
18+ boolean>=?
19+ boolean>?
20+ string->pstring
21+ pstring-concat
22+ pstring=?
23+ pstring>?
24+ pstring>=?
25+ pstring<?
26+ pstring<=?
27+ fail)
28+ (import
29+ (chezscheme)
30+ (only (purescm pstring) string->pstring
31+ pstring-concat
32+ pstring=?
33+ pstring>?
34+ pstring>=?
35+ pstring<?
36+ pstring<=?)
37+ (prefix (srfi :214) srfi:214:))
38+
39+ ;
40+ ; Booleans
41+ ;
42+
43+ (define boolean->integer
44+ (lambda (x)
45+ (if x 1 0)))
46+
47+ (define boolean>?
48+ (lambda (x)
49+ (lambda (y)
50+ (fx>? (boolean->integer x) (boolean->integer y)))))
51+
52+ (define boolean>=?
53+ (lambda (x)
54+ (lambda (y)
55+ (fx>=? (boolean->integer x) (boolean->integer y)))))
56+
57+ (define boolean<=?
58+ (lambda (x)
59+ (lambda (y)
60+ (fx<=? (boolean->integer x) (boolean->integer y)))))
61+
62+ (define boolean<?
63+ (lambda (x)
64+ (lambda (y)
65+ (fx<? (boolean->integer x) (boolean->integer y)))))
66+
67+ ;
68+ ; Arrays
69+ ;
70+
71+ (define make-array srfi:214:flexvector)
72+
73+ (define array-ref srfi:214:flexvector-ref)
74+
75+ (define array-length srfi:214:flexvector-length)
76+
77+
78+ ;
79+ ; Records
80+ ;
81+
82+ (define (record-has rec k)
83+ (let ([res (assq k rec)])
84+ (not (eq? res #f))))
85+
86+ (define (record-ref rec k)
87+ (let ([res (assq k rec)])
88+ (if (not res)
89+ (raise-continuable
90+ (condition
91+ (make-error)
92+ (make-message-condition (format "Record key ~a not defined in ~a" k rec))))
93+ (cdr res))))
94+
95+ (define (record-remove rec k)
96+ (if (null? rec)
97+ rec
98+ (if (eq? (caar rec) k)
99+ (cdr rec)
100+ (cons (car rec) (record-remove (cdr rec) k)))))
101+
102+ (define (record-set rec k v)
103+ (cons (cons k v) (record-remove rec k)))
104+
105+
106+ ;
107+ ; Lists
108+ ;
109+
110+ (define list-cons
111+ (lambda (x) (lambda (xs) (cons x xs))))
112+
113+
114+ ;
115+ ; Lazy bindings
116+ ;
117+
118+ (define-syntax define-lazy
119+ (syntax-rules ()
120+ [(_ id ident module body ...)
121+ (define id (lazy ident module (lambda () body ...)))]))
122+
123+ (define (lazy ident module f)
124+ (let ([state 0]
125+ [value #f])
126+ (lambda ()
127+ (cond
128+ [(eq? state 2) value]
129+ [(eq? state 1) (error #f (format "~a was needed before it finished initializing (module ~a)" ident module))]
130+ [else
131+ (begin
132+ (set! state 1)
133+ (set! value (f))
134+ (set! state 2)
135+ value)]))))
136+
137+
138+ ;
139+ ; Runtime failures
140+ ;
141+
142+ (define (fail)
143+ (raise-continuable
144+ (condition
145+ (make-error)
146+ (make-message-condition "Failed pattern match"))))
147+
148+
149+ )
lib/purescm/stack-trace.ssnew file+29
@@ -0,0 +1,29 @@
1+(library (purescm stack-trace)
2+ (export print-stack-trace)
3+ (import (chezscheme))
4+
5+ ; Prints a stack trace from an exception
6+ ;
7+ ; See discussion: <https://github.com/cisco/ChezScheme/issues/128>
8+ (define (print-stack-trace e)
9+
10+ (define (get-func-name c)
11+ (let ([cc ((c 'code) 'name)])
12+ (if cc cc "--main--")))
13+
14+ (display-condition e)
15+ (newline)
16+
17+ (let loop ([insp (inspect/object (condition-continuation e))])
18+ (call/cc
19+ (lambda (ret)
20+ (when (fx>? (insp 'depth) 1)
21+ (call-with-values
22+ (lambda () (insp 'source-path))
23+ (case-lambda
24+ [(file line column)
25+ (printf " at ~a (~a:~a,~a)\n" (get-func-name insp) file line column)]
26+ [else (ret)]))
27+ (loop (insp 'link)))))))
28+
29+ )
lib/purescm/test/bytevector-test.ssnew file+307
@@ -0,0 +1,307 @@
1+(library (purescm test bytevector-test)
2+ (export main)
3+ (import (chezscheme)
4+ (prefix (srfi :214) fv:)
5+ (purescm bytevector))
6+
7+ (define (assert-true msg v)
8+ (unless v
9+ (error 'bytevector-test (format "FAIL: ~a" msg))))
10+
11+ (define main
12+ (lambda ()
13+
14+ ;; ============================================================
15+ ;; Construction
16+ ;; ============================================================
17+
18+ (assert-true "make 0" (bytevector? (bytevector-make 0)))
19+ (assert-true "make 0 length" (fx=? 0 (bv-length (bytevector-make 0))))
20+ (assert-true "make 16 length" (fx=? 16 (bv-length (bytevector-make 16))))
21+
22+ (let ([bv (bytevector-make 4)])
23+ (assert-true "zero-init 0" (fx=? 0 ((bv-ref bv) 0)))
24+ (assert-true "zero-init 3" (fx=? 0 ((bv-ref bv) 3))))
25+
26+ (display " ✓ construction\n")
27+
28+ ;; ============================================================
29+ ;; Ref / set (pure, copy-on-write)
30+ ;; ============================================================
31+
32+ (let* ([bv (bytevector-make 3)]
33+ [bv2 (((bv-set bv) 1) 42)])
34+ (assert-true "set: original unchanged" (fx=? 0 ((bv-ref bv) 1)))
35+ (assert-true "set: copy updated" (fx=? 42 ((bv-ref bv2) 1)))
36+ (assert-true "set: other bytes 0" (fx=? 0 ((bv-ref bv2) 0)))
37+ (assert-true "set: other bytes 2" (fx=? 0 ((bv-ref bv2) 2))))
38+
39+ (display " ✓ ref / set (pure)\n")
40+
41+ ;; ============================================================
42+ ;; Slice
43+ ;; ============================================================
44+
45+ (let* ([bv (bv-from-flexvector (fv:flexvector 10 20 30 40 50))]
46+ [sl (((bv-slice 1) 4) bv)])
47+ (assert-true "slice length" (fx=? 3 (bv-length sl)))
48+ (assert-true "slice [0]" (fx=? 20 ((bv-ref sl) 0)))
49+ (assert-true "slice [1]" (fx=? 30 ((bv-ref sl) 1)))
50+ (assert-true "slice [2]" (fx=? 40 ((bv-ref sl) 2))))
51+
52+ (let ([sl (((bv-slice 2) 2) (bytevector-make 5))])
53+ (assert-true "empty slice" (fx=? 0 (bv-length sl))))
54+
55+ (display " ✓ slice\n")
56+
57+ ;; ============================================================
58+ ;; Concat
59+ ;; ============================================================
60+
61+ (let* ([a (bv-from-flexvector (fv:flexvector 1 2 3))]
62+ [b (bv-from-flexvector (fv:flexvector 4 5))]
63+ [c ((bv-concat a) b)])
64+ (assert-true "concat length" (fx=? 5 (bv-length c)))
65+ (assert-true "concat [0]" (fx=? 1 ((bv-ref c) 0)))
66+ (assert-true "concat [2]" (fx=? 3 ((bv-ref c) 2)))
67+ (assert-true "concat [3]" (fx=? 4 ((bv-ref c) 3)))
68+ (assert-true "concat [4]" (fx=? 5 ((bv-ref c) 4))))
69+
70+ (let* ([a (bv-from-flexvector (fv:flexvector 1 2))]
71+ [e (bytevector-make 0)])
72+ (assert-true "concat a+empty" (fx=? 2 (bv-length ((bv-concat a) e))))
73+ (assert-true "concat empty+a" (fx=? 2 (bv-length ((bv-concat e) a)))))
74+
75+ (display " ✓ concat\n")
76+
77+ ;; ============================================================
78+ ;; Equality
79+ ;; ============================================================
80+
81+ (assert-true "eq empty" ((bv-eq? (bytevector-make 0)) (bytevector-make 0)))
82+ (assert-true "eq same"
83+ ((bv-eq? (bv-from-flexvector (fv:flexvector 1 2 3)))
84+ (bv-from-flexvector (fv:flexvector 1 2 3))))
85+ (assert-true "neq value"
86+ (not ((bv-eq? (bv-from-flexvector (fv:flexvector 1 2 3)))
87+ (bv-from-flexvector (fv:flexvector 1 2 4)))))
88+ (assert-true "neq length"
89+ (not ((bv-eq? (bv-from-flexvector (fv:flexvector 1 2)))
90+ (bv-from-flexvector (fv:flexvector 1 2 3)))))
91+
92+ (display " ✓ equality\n")
93+
94+ ;; ============================================================
95+ ;; Compare (lexicographic)
96+ ;; ============================================================
97+
98+ (assert-true "cmp empty=empty"
99+ (fx=? 0 ((bv-compare (bytevector-make 0)) (bytevector-make 0))))
100+ (assert-true "cmp equal"
101+ (fx=? 0 ((bv-compare (bv-from-flexvector (fv:flexvector 1 2)))
102+ (bv-from-flexvector (fv:flexvector 1 2)))))
103+ (assert-true "cmp less-by-value"
104+ (fx=? -1 ((bv-compare (bv-from-flexvector (fv:flexvector 1 2)))
105+ (bv-from-flexvector (fv:flexvector 1 3)))))
106+ (assert-true "cmp greater-by-value"
107+ (fx=? 1 ((bv-compare (bv-from-flexvector (fv:flexvector 1 3)))
108+ (bv-from-flexvector (fv:flexvector 1 2)))))
109+ (assert-true "cmp shorter<longer"
110+ (fx=? -1 ((bv-compare (bv-from-flexvector (fv:flexvector 1 2)))
111+ (bv-from-flexvector (fv:flexvector 1 2 3)))))
112+
113+ (display " ✓ compare\n")
114+
115+ ;; ============================================================
116+ ;; Flexvector round-trip
117+ ;; ============================================================
118+
119+ (let* ([fv (fv:flexvector 0 127 128 255)]
120+ [bv (bv-from-flexvector fv)]
121+ [fv2 (bv-to-flexvector bv)])
122+ (assert-true "fv->bv length" (fx=? 4 (bv-length bv)))
123+ (assert-true "fv->bv [0]" (fx=? 0 ((bv-ref bv) 0)))
124+ (assert-true "fv->bv [1]" (fx=? 127 ((bv-ref bv) 1)))
125+ (assert-true "fv->bv [2]" (fx=? 128 ((bv-ref bv) 2)))
126+ (assert-true "fv->bv [3]" (fx=? 255 ((bv-ref bv) 3)))
127+ (assert-true "bv->fv length" (fx=? 4 (fv:flexvector-length fv2)))
128+ (assert-true "bv->fv [0]" (fx=? 0 (fv:flexvector-ref fv2 0)))
129+ (assert-true "bv->fv [3]" (fx=? 255 (fv:flexvector-ref fv2 3))))
130+
131+ ;; Values > 255 get masked to low byte
132+ (let* ([fv (fv:flexvector 256 511)]
133+ [bv (bv-from-flexvector fv)])
134+ (assert-true "mask 256->0" (fx=? 0 ((bv-ref bv) 0)))
135+ (assert-true "mask 511->255" (fx=? 255 ((bv-ref bv) 1))))
136+
137+ (display " ✓ flexvector round-trip\n")
138+
139+ ;; ============================================================
140+ ;; String <-> bytevector (UTF-8) — using native Chez strings
141+ ;; ============================================================
142+
143+ (let ([bv (bv-from-utf8 "abc")])
144+ (assert-true "str->bv length" (fx=? 3 (bv-length bv)))
145+ (assert-true "str->bv a" (fx=? 97 ((bv-ref bv) 0)))
146+ (assert-true "str->bv b" (fx=? 98 ((bv-ref bv) 1)))
147+ (assert-true "str->bv c" (fx=? 99 ((bv-ref bv) 2))))
148+
149+ ;; Multi-byte UTF-8
150+ (let ([bv (bv-from-utf8 "ä")])
151+ (assert-true "str->bv ä length" (fx=? 2 (bv-length bv)))
152+ (assert-true "str->bv ä [0]" (fx=? #xC3 ((bv-ref bv) 0)))
153+ (assert-true "str->bv ä [1]" (fx=? #xA4 ((bv-ref bv) 1))))
154+
155+ (assert-true "str->bv empty" (fx=? 0 (bv-length (bv-from-utf8 ""))))
156+
157+ ;; Round-trip
158+ (let* ([s "hello 🌍"]
159+ [bv (bv-from-utf8 s)]
160+ [s2 (bv-to-utf8 bv)])
161+ (assert-true "str round-trip" (string=? s s2)))
162+
163+ (display " ✓ string <-> bytevector (UTF-8)\n")
164+
165+ ;; ============================================================
166+ ;; Hex round-trip — using native Chez strings
167+ ;; ============================================================
168+
169+ (let* ([bv (bv-from-flexvector (fv:flexvector 0 1 15 16 255))]
170+ [hex (bv-to-hex bv)])
171+ (assert-true "to-hex" (string=? hex "00010f10ff"))
172+ (assert-true "hex round-trip" ((bv-eq? bv) (bv-from-hex hex))))
173+
174+ (let ([hex (bv-to-hex (bytevector-make 0))])
175+ (assert-true "hex empty" (string=? hex ""))
176+ (assert-true "hex empty round" (fx=? 0 (bv-length (bv-from-hex hex)))))
177+
178+ ;; Upper-case hex input
179+ (let ([bv (bv-from-hex "DEADBEEF")])
180+ (assert-true "hex upper length" (fx=? 4 (bv-length bv)))
181+ (assert-true "hex upper [0]" (fx=? #xDE ((bv-ref bv) 0)))
182+ (assert-true "hex upper [1]" (fx=? #xAD ((bv-ref bv) 1)))
183+ (assert-true "hex upper [2]" (fx=? #xBE ((bv-ref bv) 2)))
184+ (assert-true "hex upper [3]" (fx=? #xEF ((bv-ref bv) 3))))
185+
186+ (display " ✓ hex round-trip\n")
187+
188+ ;; ============================================================
189+ ;; Mutation: bv-copy-into!
190+ ;; ============================================================
191+
192+ (let ([src (bv-from-flexvector (fv:flexvector 10 20 30 40 50))]
193+ [dst (bytevector-make 8)])
194+ (((((bv-copy-into! src) 1) dst) 2) 3)
195+ (assert-true "copy dst[0]" (fx=? 0 ((bv-ref dst) 0)))
196+ (assert-true "copy dst[1]" (fx=? 0 ((bv-ref dst) 1)))
197+ (assert-true "copy dst[2]" (fx=? 20 ((bv-ref dst) 2)))
198+ (assert-true "copy dst[3]" (fx=? 30 ((bv-ref dst) 3)))
199+ (assert-true "copy dst[4]" (fx=? 40 ((bv-ref dst) 4)))
200+ (assert-true "copy dst[5]" (fx=? 0 ((bv-ref dst) 5))))
201+
202+ (display " ✓ bv-copy-into!\n")
203+
204+ ;; ============================================================
205+ ;; Mutation: bv-xor-into!
206+ ;; ============================================================
207+
208+ (let ([dst (bv-from-flexvector (fv:flexvector #xFF #x00 #xAA #x55))]
209+ [src (bv-from-flexvector (fv:flexvector #xFF #xFF #x55 #xAA))])
210+ (((((bv-xor-into! dst) 0) src) 0) 4)
211+ (assert-true "xor [0]" (fx=? #x00 ((bv-ref dst) 0)))
212+ (assert-true "xor [1]" (fx=? #xFF ((bv-ref dst) 1)))
213+ (assert-true "xor [2]" (fx=? #xFF ((bv-ref dst) 2)))
214+ (assert-true "xor [3]" (fx=? #xFF ((bv-ref dst) 3))))
215+
216+ (let ([dst (bv-from-flexvector (fv:flexvector 0 0 0 0))]
217+ [src (bv-from-flexvector (fv:flexvector #xAA #xBB))])
218+ (((((bv-xor-into! dst) 1) src) 0) 2)
219+ (assert-true "xor offset [0]" (fx=? #x00 ((bv-ref dst) 0)))
220+ (assert-true "xor offset [1]" (fx=? #xAA ((bv-ref dst) 1)))
221+ (assert-true "xor offset [2]" (fx=? #xBB ((bv-ref dst) 2)))
222+ (assert-true "xor offset [3]" (fx=? #x00 ((bv-ref dst) 3))))
223+
224+ (display " ✓ bv-xor-into!\n")
225+
226+ ;; ============================================================
227+ ;; Mutation: bv-fill!
228+ ;; ============================================================
229+
230+ (let ([bv (bytevector-make 5)])
231+ ((((bv-fill! bv) 1) 3) #xCC)
232+ (assert-true "fill [0]" (fx=? #x00 ((bv-ref bv) 0)))
233+ (assert-true "fill [1]" (fx=? #xCC ((bv-ref bv) 1)))
234+ (assert-true "fill [2]" (fx=? #xCC ((bv-ref bv) 2)))
235+ (assert-true "fill [3]" (fx=? #xCC ((bv-ref bv) 3)))
236+ (assert-true "fill [4]" (fx=? #x00 ((bv-ref bv) 4))))
237+
238+ (display " ✓ bv-fill!\n")
239+
240+ ;; ============================================================
241+ ;; Benchmark: bytevector vs flexvector XOR throughput
242+ ;; ============================================================
243+
244+ (display "\n Benchmarks:\n")
245+
246+ (let* ([size (* 1024 1024)]
247+ [iterations 20])
248+
249+ ;; --- Bytevector XOR ---
250+ (let ([a (bytevector-make size)]
251+ [b (bytevector-make size)])
252+ (do ([i 0 (fx+ i 1)]) ((fx= i size))
253+ (bytevector-u8-set! b i (fxlogand i #xFF)))
254+ (collect)
255+ (let ([t0 (current-time 'time-monotonic)])
256+ (do ([iter 0 (fx+ iter 1)]) ((fx= iter iterations))
257+ (((((bv-xor-into! a) 0) b) 0) size))
258+ (let* ([t1 (current-time 'time-monotonic)]
259+ [ns (+ (* (- (time-second t1) (time-second t0)) 1000000000)
260+ (- (time-nanosecond t1) (time-nanosecond t0)))]
261+ [total-mb (/ (* iterations size) 1048576.0)]
262+ [secs (/ ns 1000000000.0)]
263+ [mbps (/ total-mb secs)])
264+ (display (format " bytevector XOR: ~,1f MB/s (~a MiB x ~a iters)\n"
265+ mbps (/ size 1048576) iterations)))))
266+
267+ ;; --- Flexvector XOR ---
268+ (let ([a (fv:make-flexvector size 0)]
269+ [b (fv:make-flexvector size 0)])
270+ (do ([i 0 (fx+ i 1)]) ((fx= i size))
271+ (fv:flexvector-set! b i (fxlogand i #xFF)))
272+ (collect)
273+ (let ([t0 (current-time 'time-monotonic)])
274+ (do ([iter 0 (fx+ iter 1)]) ((fx= iter iterations))
275+ (do ([i 0 (fx+ i 1)]) ((fx= i size))
276+ (fv:flexvector-set! a i
277+ (fxlogxor (fv:flexvector-ref a i)
278+ (fv:flexvector-ref b i)))))
279+ (let* ([t1 (current-time 'time-monotonic)]
280+ [ns (+ (* (- (time-second t1) (time-second t0)) 1000000000)
281+ (- (time-nanosecond t1) (time-nanosecond t0)))]
282+ [total-mb (/ (* iterations size) 1048576.0)]
283+ [secs (/ ns 1000000000.0)]
284+ [mbps (/ total-mb secs)])
285+ (display (format " flexvector XOR: ~,1f MB/s (~a MiB x ~a iters)\n"
286+ mbps (/ size 1048576) iterations)))))
287+
288+ ;; --- Conversion cost ---
289+ (let ([fv (fv:make-flexvector size 0)])
290+ (do ([i 0 (fx+ i 1)]) ((fx= i size))
291+ (fv:flexvector-set! fv i (fxlogand i #xFF)))
292+ (collect)
293+ (let ([t0 (current-time 'time-monotonic)])
294+ (do ([iter 0 (fx+ iter 1)]) ((fx= iter 10))
295+ (bv-from-flexvector fv))
296+ (let* ([t1 (current-time 'time-monotonic)]
297+ [ns (+ (* (- (time-second t1) (time-second t0)) 1000000000)
298+ (- (time-nanosecond t1) (time-nanosecond t0)))]
299+ [total-mb (/ (* 10 size) 1048576.0)]
300+ [secs (/ ns 1000000000.0)]
301+ [mbps (/ total-mb secs)])
302+ (display (format " fv->bv convert: ~,1f MB/s (overhead you eliminate)\n"
303+ mbps))))))
304+
305+ (display "\n")
306+
307+ )))
lib/purescm/test/pstring-test.ssnew file+539
@@ -0,0 +1,539 @@
1+(library (purescm test pstring-test)
2+ (export main)
3+ (import (chezscheme)
4+ (prefix (purescm runtime) rt:)
5+ (prefix (srfi :214) srfi:214:)
6+ (purescm pstring))
7+
8+ (define check-raises
9+ (lambda (thunk)
10+ (call/cc
11+ (lambda (k)
12+ (with-exception-handler
13+ (lambda (e) (k #t))
14+ (lambda () (begin (thunk) #f)))))))
15+
16+ ; Creates a string slice by first making a bigger string and then slicing
17+ ; to get back a slice that equals the original input.
18+ (define (lit s)
19+ (pstring-slice
20+ (pstring-concat
21+ (string->pstring "123")
22+ (string->pstring s)
23+ (string->pstring "456"))
24+ 3
25+ (fx+ 3 (pstring-length (string->pstring s)))))
26+
27+ (define (replace s p r)
28+ (pstring-replace (lit s) (lit p) (lit r)))
29+
30+ (define (replace-all s p r)
31+ (pstring-replace-all (lit s) (lit p) (lit r)))
32+
33+ (define (split s p)
34+ (pstring-split (lit s) (lit p)))
35+
36+ (define (regex-match r s)
37+ (pstring-regex-match (pstring-make-regex r) s (lambda (x) x) #f))
38+
39+ (define (assert-all-pstring f)
40+ (assert (f (string->pstring "foobarbaz")))
41+ (assert (f (lit "foobarbaz")))
42+ (assert (f (pstring-concat (string->pstring "") (string->pstring "foobarbaz"))))
43+ (assert (f (pstring-concat (string->pstring "foobarbaz") (string->pstring ""))))
44+ (assert (f (pstring-concat (string->pstring "fooba") (string->pstring "rbaz"))))
45+ (assert (f (pstring-concat (lit "fooba") (lit "rbaz"))))
46+ (assert (f (pstring-concat (string->pstring "foo") (string->pstring "bar") (string->pstring "baz"))))
47+ (assert (f (pstring-concat (lit "foo") (lit "bar") (lit "baz")))))
48+
49+ (define main
50+ (lambda ()
51+
52+ (assert-all-pstring pstring?)
53+
54+ ;; reffing
55+ (assert (check-raises (lambda () (pstring-ref-code-point (lit "") 0))))
56+ (assert (fx=? 228 (pstring-ref-code-point (lit "ä") 0)))
57+
58+ ;; length in code units
59+ (assert (fx=? 0 (pstring-length (lit ""))))
60+ (assert (fx=? 1 (pstring-length (lit "a"))))
61+ (assert (fx=? 1 (pstring-length (lit "ä"))))
62+ (assert (fx=? 2 (pstring-length (lit "ää"))))
63+ (assert (fx=? 2 (pstring-length (lit "🍔"))))
64+ (assert (fx=? 4 (pstring-length (lit "🍔🍔"))))
65+ (assert-all-pstring (lambda (s) (fx=? (pstring-length s) 9)))
66+
67+ ;; length in code points
68+ (assert (fx=? 0 (pstring-length-code-points (lit ""))))
69+ (assert (fx=? 1 (pstring-length-code-points (lit "a"))))
70+ (assert (fx=? 1 (pstring-length-code-points (lit "ä"))))
71+ (assert (fx=? 2 (pstring-length-code-points (lit "äが"))))
72+ (assert (fx=? 2 (pstring-length-code-points (lit "🍔🍔"))))
73+ (assert-all-pstring (lambda (s) (fx=? (pstring-length-code-points s) 9)))
74+
75+
76+ ;; slicing
77+ (assert (pstring=?
78+ (pstring-slice (lit "foo") 0)
79+ (string->pstring "foo")))
80+ (assert (pstring=?
81+ (pstring-slice (lit "foo") 1)
82+ (string->pstring "oo")))
83+ (assert (pstring=?
84+ (pstring-slice (lit "foo bar") 4 7)
85+ (string->pstring "bar")))
86+ (assert (pstring=?
87+ (pstring-slice (lit "foo bar") 4 100)
88+ (string->pstring "bar")))
89+ (assert (pstring=?
90+ (pstring-slice (lit "foo") -1)
91+ (string->pstring "foo")))
92+ (assert-all-pstring (lambda (s) (pstring=? (pstring-slice s 2 6) (string->pstring "obar"))))
93+
94+ ; Entirely in the prefix
95+ (let ([s (pstring-concat (string->pstring "foo") (string->pstring "bar"))])
96+ (assert (pstring=? (pstring-take s 3) (string->pstring "foo")))
97+ (assert (not (pstring-compact? s))))
98+
99+ ; Reachable within prefix and suffix
100+ (let ([s (pstring-concat (string->pstring "foo") (string->pstring "bar"))])
101+ (assert (pstring=? (pstring-take s 4) (string->pstring "foob")))
102+ (assert (pstring-compact? s)))
103+
104+ ; Reachable within suffix
105+ (let ([s (pstring-concat (string->pstring "foo") (string->pstring "bar"))])
106+ (assert (pstring=? (pstring-drop s 3) (string->pstring "bar")))
107+ (assert (not (pstring-compact? s))))
108+
109+ ;; take
110+ (assert (pstring=? (pstring-take (lit "foo") -1) (lit "")))
111+ (assert (pstring=? (pstring-take (lit "foo") 0) (lit "")))
112+ (assert (pstring=? (pstring-take (lit "foo") 1) (lit "f")))
113+ (assert (pstring=? (pstring-take (lit "foo") 2) (lit "fo")))
114+ (assert (pstring=? (pstring-take (lit "foo") -3) (lit "")))
115+ (assert (pstring=? (pstring-take (lit "foo") 10) (lit "foo")))
116+
117+ ;; drop
118+ (assert (pstring=? (pstring-drop (lit "foo") -1) (lit "foo")))
119+ (assert (pstring=? (pstring-drop (lit "foo") 0) (lit "foo")))
120+ (assert (pstring=? (pstring-drop (lit "foo") 1) (lit "oo")))
121+ (assert (pstring=? (pstring-drop (lit "foo") 2) (lit "o")))
122+ (assert (pstring=? (pstring-drop (lit "foo") 10) (lit "")))
123+ (assert (pstring=? (pstring-take (pstring-drop (lit "foo bar baz") 4) 3) (lit "bar")))
124+
125+ ;; index-of
126+ (assert (fx=? 0 (pstring-index-of (lit "foo bar") (lit ""))))
127+ (assert (fx=? 0 (pstring-index-of (lit "") (lit ""))))
128+ (assert (not (pstring-index-of (lit "foo bar") (lit "baz"))))
129+ (assert (fx=? 0 (pstring-index-of (lit "foo bar") (lit "f"))))
130+ (assert (fx=? 4 (pstring-index-of (lit "foo bar") (lit "b"))))
131+ (assert (fx=? 4 (pstring-index-of (lit "foo bar") (lit "bar"))))
132+ (assert (fx=? 3 (pstring-index-of (lit "fo foo") (lit "foo"))))
133+ (assert (fx=? 1 (pstring-index-of (lit "zza") (lit "za"))))
134+ (assert (fx=? 0 (pstring-index-of (lit "𝕒𝕓𝕔") (lit "𝕒"))))
135+ (assert (fx=? 2 (pstring-index-of (lit "𝕒𝕓𝕔") (lit "𝕓"))))
136+ (assert (fx=? 1 (pstring-index-of (lit "11112") (lit "1112"))))
137+ (assert-all-pstring (lambda (s) (fx=? 2 (pstring-index-of s (string->pstring "obar")))))
138+
139+ ;; last-index-of
140+ (assert (fx=? 7 (pstring-last-index-of (lit "foo bar") (lit ""))))
141+ (assert (fx=? 0 (pstring-last-index-of (lit "") (lit ""))))
142+ (assert (not (pstring-index-of (lit "foo bar") (lit "baz"))))
143+ (assert (fx=? 8 (pstring-last-index-of (lit "foo bar foo") (lit "foo"))))
144+ (assert (fx=? 6 (pstring-last-index-of (lit "1112 1112") (lit "112"))))
145+ (assert-all-pstring (lambda (s) (fx=? 6 (pstring-last-index-of s (string->pstring "ba")))))
146+
147+ ;; comparisons
148+ (assert (pstring=? (lit "abc") (lit "abc")))
149+ (assert (pstring=? (lit "𝕒𝕓𝕔") (lit "𝕒𝕓𝕔")))
150+ (assert-all-pstring (lambda (s) (pstring=? s s)))
151+ (assert (pstring<? (lit "fo") (lit "foo")))
152+ (assert (pstring<? (lit "a") (lit "z")))
153+ (assert (pstring<? (lit "az") (lit "z")))
154+ (assert (not (pstring<? (lit "foreign") (lit "else"))))
155+ (assert (not (pstring<? (lit "") (lit ""))))
156+ (assert (not (pstring>? (lit "a") (lit "a"))))
157+ (assert (not (pstring>? (lit "a") (lit "aa"))))
158+ (assert (not (pstring>? (lit "") (lit ""))))
159+ (assert (not (pstring>? (lit "else") (lit "foreign"))))
160+ (assert (pstring>=? (lit "") (lit "")))
161+ (assert (pstring>=? (lit "zoo") (lit "zoo")))
162+ (assert (pstring>=? (lit "zoo") (lit "zo")))
163+ (assert (not (pstring>=? (lit "zo") (lit "zoo"))))
164+ (assert (let ([s (lit "foo")]) (pstring>=? s s)))
165+
166+ (assert (pstring<=? (lit "") (lit "")))
167+ (assert (not (pstring<=? (lit "zoo") (lit "zo"))))
168+ (assert (pstring<=? (lit "zo") (lit "zoo")))
169+ (assert (let ([s (lit "foo")]) (pstring<=? s s)))
170+
171+ ;; casing
172+ (assert (pstring=? (pstring-downcase (lit "")) (lit "")))
173+ (assert (pstring=? (pstring-downcase (lit "foo")) (lit "foo")))
174+ (assert (pstring=? (pstring-downcase (lit "FOO")) (lit "foo")))
175+ (assert (pstring=? (pstring-upcase (lit "")) (lit "")))
176+ (assert (pstring=? (pstring-upcase (lit "FOO")) (lit "FOO")))
177+ (assert (pstring=? (pstring-upcase (lit "foo")) (lit "FOO")))
178+ (assert (pstring=? (pstring-upcase (lit "ß")) (lit "SS")))
179+ (assert (pstring=? (pstring-upcase (lit "straße")) (lit "STRASSE")))
180+ (assert (not (pstring=? (pstring-upcase (lit "foo")) (lit "FOo"))))
181+
182+ (assert (pstring=?
183+ (char-flexvector->pstring (srfi:214:flexvector))
184+ (lit "")))
185+ (assert (pstring=?
186+ (char-flexvector->pstring (srfi:214:flexvector #\f #\o #\o))
187+ (lit "foo")))
188+
189+ (assert (srfi:214:flexvector=?
190+ equal?
191+ (pstring->char-flexvector (lit ""))
192+ (srfi:214:flexvector)))
193+ (assert (srfi:214:flexvector=?
194+ equal?
195+ (pstring->char-flexvector (lit "a"))
196+ (srfi:214:flexvector #\a)))
197+ (assert (srfi:214:flexvector=?
198+ equal?
199+ (pstring->char-flexvector (lit "foo"))
200+ (srfi:214:flexvector #\f #\o #\o)))
201+ (assert-all-pstring (lambda (s)
202+ (srfi:214:flexvector=?
203+ equal?
204+ (pstring->char-flexvector s)
205+ (srfi:214:flexvector #\f #\o #\o #\b #\a #\r #\b #\a #\z))))
206+
207+ (assert (srfi:214:flexvector=?
208+ equal?
209+ (pstring->code-point-flexvector (lit ""))
210+ (srfi:214:flexvector)))
211+ (assert (srfi:214:flexvector=?
212+ equal?
213+ (pstring->code-point-flexvector (lit "b 𝐀𝐀"))
214+ (srfi:214:flexvector #x62 #x20 #x1D400 #x1D400)))
215+
216+ (assert (pstring=? (replace "" "bar" "foo") (lit "")))
217+ (assert (pstring=? (replace "foo" "foo" "bar") (lit "bar")))
218+ (assert (pstring=? (replace "foo" "" "bar") (lit "foo")))
219+ (assert (pstring=? (replace "javascript" "java" "pure") (lit "purescript")))
220+ (assert (pstring=? (replace "foo bar" " bar" "") (lit "foo")))
221+ (assert (pstring=? (replace "𝕒𝕓𝕔" "𝕒" "a") (lit "a𝕓𝕔")))
222+ (assert (pstring=? (replace "abc" "b" "") (lit "ac")))
223+ (assert (pstring=? (replace "𝕒𝕓𝕔" "𝕓" "") (lit "𝕒𝕔")))
224+ (assert (pstring=? (replace "𝕒𝕓𝕔" "𝕔" "") (lit "𝕒𝕓")))
225+ (assert (pstring=? (replace "𝕒𝕓𝕔" "𝕒" "") (lit "𝕓𝕔")))
226+
227+ (assert (pstring=? (replace-all "" "" "") (lit "")))
228+ (assert (pstring=? (replace-all "aaa" "a" "b") (lit "bbb")))
229+ (assert (pstring=? (replace-all "aaac" "a" "b") (lit "bbbc")))
230+ (assert (pstring=? (replace-all "foo foo foo" "foo" "bar") (lit "bar bar bar")))
231+ (assert (pstring=? (replace-all "abbc" "b" "") (lit "ac")))
232+ (assert (pstring=? (replace-all "abbbbbc" "b" "") (lit "ac")))
233+ (assert (pstring=? (replace-all "𝕒𝕓𝕓𝕔" "𝕓" "") (lit "𝕒𝕔")))
234+ (assert (pstring=? (replace-all "𝕒𝕓𝕓𝕔" "𝕓𝕓" "b") (lit "𝕒b𝕔")))
235+ (assert (pstring=? (pstring-replace-all
236+ (pstring-drop (lit "foo 𝕒𝕓𝕓𝕔") 4)
237+ (lit "𝕓𝕓")
238+ (lit "b"))
239+ (lit "𝕒b𝕔")))
240+ (assert-all-pstring (lambda (s)
241+ (pstring=? (pstring-replace-all s (string->pstring "ba") (string->pstring "zz"))
242+ (string->pstring "foozzrzzz"))))
243+
244+ (assert (srfi:214:flexvector=? pstring=? (split "" "a") (srfi:214:flexvector)))
245+ (assert (srfi:214:flexvector=? pstring=? (split "ab" "") (srfi:214:flexvector (lit "a") (lit "b"))))
246+ (assert (srfi:214:flexvector=? pstring=? (split "aabcc" "b") (srfi:214:flexvector (lit "aa") (lit "cc"))))
247+
248+ (assert (pstring=? (pstring-trim (lit " ")) (lit "")))
249+ (assert (pstring=? (pstring-trim (lit " a ")) (lit "a")))
250+ (assert (pstring=? (pstring-trim (lit " ab ")) (lit "ab")))
251+
252+ (assert (pstring=? (pstring-join-with (srfi:214:flexvector) (lit ",")) (lit "")))
253+ (assert (pstring=? (pstring-join-with (srfi:214:flexvector (lit "a")) (lit ",")) (lit "a")))
254+ (assert (pstring=? (pstring-join-with (srfi:214:flexvector (lit "a") (lit "b")) (lit ",")) (lit "a,b")))
255+ (assert (pstring=? (pstring-join-with (srfi:214:flexvector (lit "abc") (lit "def")) (lit " ")) (lit "abc def")))
256+ (assert (pstring=? (pstring-join-with (srfi:214:flexvector (lit "𝕒") (lit "𝕔")) (lit "𝕓")) (lit "𝕒𝕓𝕔")))
257+ (assert-all-pstring (lambda (s)
258+ (pstring=? (pstring-join-with (srfi:214:flexvector s s) (lit ","))
259+ (string->pstring "foobarbaz,foobarbaz"))))
260+
261+ (assert-all-pstring (lambda (s)
262+ (srfi:214:flexvector=? pstring=?
263+ (pstring-split s (lit "b"))
264+ (srfi:214:flexvector (string->pstring "foo")
265+ (string->pstring "ar")
266+ (string->pstring "az")))))
267+
268+ (assert-all-pstring (lambda (s)
269+ (srfi:214:flexvector=? pstring=?
270+ (pstring-split s (lit ""))
271+ (srfi:214:flexvector (string->pstring "f")
272+ (string->pstring "o")
273+ (string->pstring "o")
274+ (string->pstring "b")
275+ (string->pstring "a")
276+ (string->pstring "r")
277+ (string->pstring "b")
278+ (string->pstring "a")
279+ (string->pstring "z")))))
280+
281+ ; Code points
282+
283+ (assert (fx=? 4 (pstring-length-code-points
284+ (code-points->pstring #x61 #x16805 #x16A06 #x7A))))
285+
286+ (assert (pstring=? (pstring-take-code-points (lit "foo") 0) (lit "")))
287+ (assert (pstring=? (pstring-take-code-points (lit "foo") -1) (lit "")))
288+ (assert (pstring=? (pstring-take-code-points (lit "") 2) (lit "")))
289+ (assert (pstring=? (pstring-take-code-points (lit "abc") 2) (lit "ab")))
290+ (assert (pstring=? (pstring-take-code-points (lit "abc") 3) (lit "abc")))
291+ (assert (pstring=? (pstring-take-code-points (lit "𝕒𝕓𝕔") 2) (lit "𝕒𝕓")))
292+ (assert (pstring=? (pstring-take-code-points (lit "𝕒𝕓𝕔") 3) (lit "𝕒𝕓𝕔")))
293+ (assert (pstring=? (pstring-take-code-points (lit "𝕒𝕓𝕔") 4) (lit "𝕒𝕓𝕔")))
294+
295+ ;; regex
296+ (assert (srfi:214:flexvector=?
297+ pstring=?
298+ (regex-match (lit "foo") (lit "foo"))
299+ (srfi:214:flexvector (lit "foo"))))
300+ (assert (not (regex-match (lit "foo") (lit "bar"))))
301+ (assert (srfi:214:flexvector=?
302+ pstring=?
303+ (regex-match (lit "(a)(b)(c)") (lit "abc"))
304+ (srfi:214:flexvector (lit "abc") (lit "a") (lit "b") (lit "c"))))
305+ (assert (srfi:214:flexvector=?
306+ pstring=?
307+ (regex-match (lit "(a|b)(c)") (lit "ac"))
308+ (srfi:214:flexvector (lit "ac") (lit "a") (lit "c"))))
309+ (assert (srfi:214:flexvector=?
310+ pstring=?
311+ (regex-match (lit "(a|b)(c)") (lit "bc"))
312+ (srfi:214:flexvector (lit "bc") (lit "b") (lit "c"))))
313+ (assert (srfi:214:flexvector=?
314+ pstring=?
315+ (regex-match (string->pstring "^[a-z]+$") (lit "abc"))
316+ (srfi:214:flexvector (lit "abc"))))
317+ (assert (srfi:214:flexvector=?
318+ pstring=?
319+ (regex-match (lit "^[a-z]+$") (lit "abc"))
320+ (srfi:214:flexvector (lit "abc"))))
321+ (assert (not (srfi:214:flexvector-ref
322+ (regex-match (lit "(a|(b))|(c)") (lit "ac"))
323+ 2)))
324+ (assert-all-pstring (lambda (s)
325+ (srfi:214:flexvector=?
326+ pstring=?
327+ (regex-match s s)
328+ (srfi:214:flexvector (string->pstring "foobarbaz")))))
329+
330+ (assert (pstring=?
331+ (pstring-regex-replace-by
332+ (pstring-make-regex (lit "a") (list '(global . #f)))
333+ (lit "aaa")
334+ (lambda (m xs) (lit "b")))
335+ (lit "baa")))
336+ (assert (pstring=?
337+ (pstring-regex-replace-by
338+ (pstring-make-regex (lit "foo") (list '(global . #f)))
339+ (lit "bar")
340+ (lambda (m xs) (lit "fail")))
341+ (lit "bar")))
342+ (assert (pstring=?
343+ (pstring-regex-replace-by
344+ (pstring-make-regex (lit "[a-z]") (list '(global . #t)))
345+ (string->pstring "")
346+ (lambda (m xs) (lit "123")))
347+ (string->pstring "")))
348+ (assert (pstring=?
349+ (pstring-regex-replace-by
350+ (pstring-make-regex (lit "aa") (list '(global . #t)))
351+ (lit "bb")
352+ (lambda (m xs) (lit "123")))
353+ (lit "bb")))
354+ (assert (pstring=?
355+ (pstring-regex-replace-by
356+ (pstring-make-regex (lit "b") (list '(global . #t)))
357+ (lit "abc")
358+ (lambda (m xs) (lit "123")))
359+ (lit "a123c")))
360+ (assert (pstring=?
361+ (pstring-regex-replace-by
362+ (pstring-make-regex (lit "a") (list '(global . #t)))
363+ (lit "aaa")
364+ (lambda (m xs) (lit "b")))
365+ (lit "bbb")))
366+ (assert (pstring=?
367+ (pstring-regex-replace-by
368+ (pstring-make-regex (lit "([a-z]{2})") (list '(global . #t)))
369+ (lit "aazz")
370+ (lambda (m xs) (if (pstring=? m (lit "aa")) (lit "foo") (lit "bar"))))
371+ (lit "foobar")))
372+ (assert (pstring=?
373+ (pstring-regex-replace-by
374+ (pstring-make-regex (lit "Hello, ([a-z]+)") (list '(global . #t)))
375+ (lit "Hello, purescript")
376+ (lambda (m xs) (srfi:214:flexvector-ref xs 0)))
377+ (lit "purescript")))
378+ (assert-all-pstring (lambda (s)
379+ (pstring=?
380+ (pstring-regex-replace-by
381+ (pstring-make-regex (lit "foo") '((global . #f)))
382+ s
383+ (lambda (m xs) (lit "FOO")))
384+ (lit "FOObarbaz"))))
385+ (assert-all-pstring (lambda (s)
386+ (pstring=?
387+ (pstring-regex-replace-by
388+ (pstring-make-regex (lit "foo") '((global . #t)))
389+ s
390+ (lambda (m xs) (lit "FOO")))
391+ (lit "FOObarbaz"))))
392+ (assert-all-pstring (lambda (s)
393+ (pstring=?
394+ (pstring-regex-replace-by
395+ (pstring-make-regex s '((global . #f)))
396+ (string->pstring "hello foobarbaz!")
397+ (lambda (m xs) (lit "world")))
398+ (lit "hello world!"))))
399+ (assert-all-pstring (lambda (s)
400+ (pstring=?
401+ (pstring-regex-replace-by
402+ (pstring-make-regex s '((global . #t)))
403+ (string->pstring "hello foobarbaz and foobarbaz!")
404+ (lambda (m xs) (lit "world")))
405+ (lit "hello world and world!"))))
406+ (assert-all-pstring (lambda (s)
407+ (pstring=?
408+ (pstring-regex-replace-by
409+ (pstring-make-regex s '((global . #f)))
410+ (string->pstring "hello foobarbaz!")
411+ (lambda (m xs) s))
412+ (lit "hello foobarbaz!"))))
413+ (assert-all-pstring (lambda (s)
414+ (pstring=?
415+ (pstring-regex-replace-by
416+ (pstring-make-regex s '((global . #t)))
417+ (string->pstring "hello foobarbaz and foobarbaz!")
418+ (lambda (m xs) s))
419+ (lit "hello foobarbaz and foobarbaz!"))))
420+
421+ ; replace
422+ (assert (pstring=?
423+ (pstring-regex-replace
424+ (pstring-make-regex (lit "a") (list '(global . #f)))
425+ (lit "aaa")
426+ (lit "b"))
427+ (lit "baa")))
428+ (assert (pstring=?
429+ (pstring-regex-replace
430+ (pstring-make-regex (lit "a") (list '(global . #t)))
431+ (lit "aaa")
432+ (lit "b"))
433+ (lit "bbb")))
434+ (assert-all-pstring (lambda (s)
435+ (pstring=?
436+ (pstring-regex-replace
437+ (pstring-make-regex (string->pstring "foo") '((global . #t)))
438+ s
439+ (lit "FOO"))
440+ (lit "FOObarbaz"))))
441+ (assert-all-pstring (lambda (s)
442+ (pstring=?
443+ (pstring-regex-replace
444+ (pstring-make-regex s '((global . #t)))
445+ (string->pstring "hello foobarbaz!")
446+ (lit "world"))
447+ (lit "hello world!"))))
448+ (assert-all-pstring (lambda (s)
449+ (pstring=?
450+ (pstring-regex-replace
451+ (pstring-make-regex s '((global . #t)))
452+ (string->pstring "hello foobarbaz!")
453+ s)
454+ (lit "hello foobarbaz!"))))
455+
456+
457+ ; search
458+ (assert (not
459+ (pstring-regex-search
460+ (pstring-make-regex (lit "a") (list '(global . #f)))
461+ (lit "b"))))
462+ (assert (not
463+ (pstring-regex-search
464+ (pstring-make-regex (lit "a") (list '(global . #f)))
465+ (lit ""))))
466+ (assert (equal?
467+ (pstring-regex-search
468+ (pstring-make-regex (lit "a") (list '(global . #f)))
469+ (lit "abc"))
470+ 0))
471+ (assert (equal?
472+ (pstring-regex-search
473+ (pstring-make-regex (lit "b") (list '(global . #f)))
474+ (lit "abc"))
475+ 1))
476+ (assert (equal?
477+ (pstring-regex-search
478+ (pstring-make-regex (lit "c") (list '(global . #f)))
479+ (lit "abc"))
480+ 2))
481+ (assert-all-pstring (lambda (s)
482+ (equal?
483+ (pstring-regex-search
484+ (pstring-make-regex s (list '(global . #f)))
485+ s)
486+ 0)))
487+
488+ ; regex-split
489+
490+ (assert (srfi:214:flexvector=?
491+ pstring=?
492+ (pstring-regex-split (pstring-make-regex (lit "")) (lit ""))
493+ (srfi:214:flexvector)))
494+ (assert (srfi:214:flexvector=?
495+ pstring=?
496+ (pstring-regex-split (pstring-make-regex (lit "")) (lit "abc"))
497+ (srfi:214:flexvector (lit "a") (lit "b") (lit "c"))))
498+ (assert (srfi:214:flexvector=?
499+ pstring=?
500+ (pstring-regex-split (pstring-make-regex (lit ",")) (lit ""))
501+ (srfi:214:flexvector (lit ""))))
502+ (assert (srfi:214:flexvector=?
503+ pstring=?
504+ (pstring-regex-split (pstring-make-regex (lit ",")) (lit "a,b,"))
505+ (srfi:214:flexvector (lit "a") (lit "b") (lit ""))))
506+ (assert (srfi:214:flexvector=?
507+ pstring=?
508+ (pstring-regex-split (pstring-make-regex (lit ",")) (lit "a,b,c"))
509+ (srfi:214:flexvector (lit "a") (lit "b") (lit "c"))))
510+ (assert (srfi:214:flexvector=?
511+ pstring=?
512+ (pstring-regex-split (pstring-make-regex (lit "[,.]")) (lit "a,b,c.de"))
513+ (srfi:214:flexvector (lit "a") (lit "b") (lit "c") (lit "de"))))
514+ (assert (srfi:214:flexvector=?
515+ pstring=?
516+ (pstring-regex-split (pstring-make-regex (lit "🍔")) (lit "𝕒🍔𝕓🍔𝕔🍔de"))
517+ (srfi:214:flexvector (lit "𝕒") (lit "𝕓") (lit "𝕔") (lit "de"))))
518+ (assert-all-pstring (lambda (s)
519+ (srfi:214:flexvector=?
520+ pstring=?
521+ (pstring-regex-split (pstring-make-regex s) (lit "hello foobarbaz world"))
522+ (srfi:214:flexvector (lit "hello ") (lit " world")))))
523+ (assert-all-pstring (lambda (s)
524+ (srfi:214:flexvector=?
525+ pstring=?
526+ (pstring-regex-split (pstring-make-regex (string->pstring "bar")) s)
527+ (srfi:214:flexvector (lit "foo") (lit "baz")))))
528+
529+ (assert (eqv? (eof-object) (pstring-cursor-peek-char (pstring->cursor (lit "")))))
530+ (assert (eqv? #\f (pstring-cursor-peek-char (pstring->cursor (lit "foo")))))
531+
532+ (let ([cur (pstring->cursor (lit "foo"))])
533+ (assert (eqv? #\f (pstring-cursor-read-char cur)))
534+ (assert (eqv? #\o (pstring-cursor-read-char cur)))
535+ (assert (eqv? #\o (pstring-cursor-read-char cur)))
536+ (assert (eqv? (eof-object) (pstring-cursor-read-char cur))))
537+
538+ ))
539+ )
lib/srfi/:0.slsnew file+11
@@ -0,0 +1,11 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a0.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :0)
10+ (export cond-expand)
11+ (import (srfi :0 cond-expand)))
lib/srfi/:0/cond-expand.guile.slsnew file+9
@@ -0,0 +1,9 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a0/cond-expand.guile.sls
7+(library (srfi srfi-0)
8+ (export cond-expand)
9+ (import (only (guile) cond-expand)))
lib/srfi/:0/cond-expand.slsnew file+44
@@ -0,0 +1,44 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a0/cond-expand.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :0 cond-expand)
11+ (export cond-expand)
12+ (import
13+ (rnrs)
14+ (for (only (srfi private registry) expand-time-features)
15+ expand))
16+ (define-syntax cond-expand
17+ (lambda (stx)
18+ (syntax-case stx (and or not else)
19+ [(_) (syntax-violation #f "unfulfilled cond-expand" stx)]
20+ [(_ (else body ...)) #'(begin body ...)]
21+ [(_ ((and) body ...) more-clauses ...) #'(begin body ...)]
22+ [(_ ((and req1 req2 ...) body ...) more-clauses ...)
23+ #'(cond-expand
24+ (req1
25+ (cond-expand ((and req2 ...) body ...) more-clauses ...))
26+ more-clauses
27+ ...)]
28+ [(_ ((or) body ...) more-clauses ...)
29+ #'(cond-expand more-clauses ...)]
30+ [(_ ((or req1 req2 ...) body ...) more-clauses ...)
31+ #'(cond-expand
32+ (req1 (begin body ...))
33+ (else
34+ (cond-expand ((or req2 ...) body ...) more-clauses ...)))]
35+ [(_ ((not req) body ...) more-clauses ...)
36+ #'(cond-expand
37+ (req (cond-expand more-clauses ...))
38+ (else body ...))]
39+ [(_ (feature-id body ...) more-clauses ...)
40+ (if (member
41+ (syntax->datum #'feature-id)
42+ expand-time-features)
43+ #'(begin body ...)
44+ #'(cond-expand more-clauses ...))]))))
lib/srfi/:1.slsnew file+34
@@ -0,0 +1,34 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a1.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :1)
10+ (export alist-cons alist-copy alist-delete alist-delete! any
11+ append append! append-map append-map! append-reverse
12+ append-reverse! assoc assq assv break break! caaaar caaadr
13+ caaar caadar caaddr caadr caar cadaar cadadr cadar caddar
14+ cadddr caddr cadr car car+cdr cdaaar cdaadr cdaar cdadar
15+ cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr
16+ cddr cdr circular-list circular-list? concatenate
17+ concatenate! cons cons* count delete delete!
18+ delete-duplicates delete-duplicates! dotted-list? drop
19+ drop-right drop-right! drop-while eighth every fifth filter
20+ filter! filter-map find find-tail first fold fold-right
21+ for-each fourth iota last last-pair length length+ list
22+ list-copy list-index list-ref list-tabulate list=
23+ lset-adjoin lset-diff+intersection lset-diff+intersection!
24+ lset-difference lset-difference! lset-intersection
25+ lset-intersection! lset-union lset-union! lset-xor lset-xor!
26+ lset<= lset= make-list map map! map-in-order member memq
27+ memv ninth not-pair? null-list? null? pair-fold
28+ pair-fold-right pair-for-each pair? partition partition!
29+ proper-list? reduce reduce-right remove remove! reverse
30+ reverse! second set-car! set-cdr! seventh sixth span span!
31+ split-at split-at! take take! take-right take-while
32+ take-while! tenth third unfold unfold-right unzip1 unzip2
33+ unzip3 unzip4 unzip5 xcons zip)
34+ (import (srfi :1 lists)))
lib/srfi/:1/lists.slsnew file+1594
@@ -0,0 +1,1594 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a1/lists.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+;;;;;; File header: %3a1/srfi-1-reference.scm
11+;;; SRFI-1 list-processing library -*- Scheme -*-
12+;;; Reference implementation
13+;;;
14+;;; Copyright (c) 1998, 1999 by Olin Shivers. You may do as you please with
15+;;; this code as long as you do not remove this copyright notice or
16+;;; hold me liable for its use. Please send bug reports to shivers@ai.mit.edu.
17+;;; -Olin
18+(library (srfi :1 lists)
19+ (export xcons make-list list-tabulate list-copy proper-list?
20+ circular-list? dotted-list? not-pair? null-list? list=
21+ circular-list length+ iota first second third fourth fifth
22+ sixth seventh eighth ninth tenth car+cdr take drop
23+ take-right drop-right take! drop-right! split-at split-at!
24+ last last-pair zip unzip1 unzip2 unzip3 unzip4 unzip5 count
25+ append! append-reverse append-reverse! concatenate
26+ concatenate! unfold fold pair-fold reduce unfold-right
27+ pair-fold-right reduce-right append-map append-map! map!
28+ pair-for-each filter-map map-in-order filter! partition!
29+ remove! find-tail any every list-index take-while drop-while
30+ take-while! span break span! break! delete delete!
31+ alist-cons alist-copy delete-duplicates delete-duplicates!
32+ alist-delete alist-delete! reverse! lset<= lset= lset-adjoin
33+ lset-union lset-intersection lset-difference lset-xor
34+ lset-diff+intersection lset-union! lset-intersection!
35+ lset-difference! lset-xor! lset-diff+intersection! append
36+ assq assv caaaar caaadr caaar caadar caaddr caadr caar
37+ cadaar cadadr cadar caddar cadddr caddr cadr car cdaaar
38+ cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar
39+ cdddar cddddr cdddr cddr cdr cons cons* length list list-ref
40+ memq memv null? pair? reverse set-car! set-cdr! assoc filter
41+ find fold-right for-each map member partition remove)
42+ (import
43+ (rename
44+ (except (rnrs) find filter fold-right map partition remove)
45+ (assoc r6rs:assoc)
46+ (for-each r6rs:for-each)
47+ (member r6rs:member))
48+ (rnrs mutable-pairs) (srfi :8 receive)
49+ (srfi :23 error tricks) (for (srfi private vanish) expand)
50+ (srfi private check-arg) (srfi private include))
51+ (let-syntax ([define (vanish-define define (cons*))])
52+ (SRFI-23-error->R6RS
53+ "(library (srfi :1 lists))"
54+ (begin
55+ (define (xcons d a) (cons a d))
56+ (define make-list
57+ (case-lambda
58+ [(len) (make-list len #f)]
59+ [(len elt)
60+ (check-arg index? len make-list)
61+ (do ([i len (fx- i 1)] [ans '() (cons elt ans)])
62+ ((fx<=? i 0) ans))]))
63+ (define (list-tabulate len proc)
64+ (check-arg index? len list-tabulate)
65+ (check-arg procedure? proc list-tabulate)
66+ (do ([i (fx- len 1) (fx- i 1)]
67+ [ans '() (cons (proc i) ans)])
68+ ((fx<? i 0) ans)))
69+ (define cons*
70+ (case-lambda
71+ [(first) first]
72+ [(first second) (cons first second)]
73+ [(first second third . rest)
74+ (cons
75+ first
76+ (cons
77+ second
78+ (let recur ([x third] [rest rest])
79+ (if (pair? rest)
80+ (cons x (recur (car rest) (cdr rest)))
81+ x))))]))
82+ (define (list-copy lis)
83+ (let recur ([lis lis])
84+ (if (pair? lis) (cons (car lis) (recur (cdr lis))) lis)))
85+ (define iota
86+ (case-lambda
87+ [(count) (iota count 0 1)]
88+ [(count start) (iota count start 1)]
89+ [(count start step)
90+ (check-arg index? count iota)
91+ (check-arg number? start iota)
92+ (check-arg number? step iota)
93+ (let loop ([cur start] [n 0])
94+ (if (fx=? n count)
95+ '()
96+ (cons cur (loop (fx+ cur step) (fx+ 1 n)))))]))
97+ (define (circular-list val1 . vals)
98+ (let ([ans (cons val1 vals)])
99+ (set-cdr! (last-pair ans) ans)
100+ ans))
101+ (define (proper-list? x)
102+ (let lp ([x x] [lag x])
103+ (if (pair? x)
104+ (let ([x (cdr x)])
105+ (if (pair? x)
106+ (let ([x (cdr x)] [lag (cdr lag)])
107+ (and (not (eq? x lag)) (lp x lag)))
108+ (null? x)))
109+ (null? x))))
110+ (define (dotted-list? x)
111+ (let lp ([x x] [lag x])
112+ (if (pair? x)
113+ (let ([x (cdr x)])
114+ (if (pair? x)
115+ (let ([x (cdr x)] [lag (cdr lag)])
116+ (and (not (eq? x lag)) (lp x lag)))
117+ (not (null? x))))
118+ (not (null? x)))))
119+ (define (circular-list? x)
120+ (let lp ([x x] [lag x])
121+ (and (pair? x)
122+ (let ([x (cdr x)])
123+ (and (pair? x)
124+ (let ([x (cdr x)] [lag (cdr lag)])
125+ (or (eq? x lag) (lp x lag))))))))
126+ (define (not-pair? x) (not (pair? x)))
127+ (define (null-list? l)
128+ (cond
129+ [(pair? l) #f]
130+ [(null? l) #t]
131+ [else (error "null-list?: argument out of domain" l)]))
132+ (define list=
133+ (case-lambda
134+ [(elt=) #t]
135+ [(elt= list-a) #t]
136+ [(elt= list-a list-b)
137+ (or (eq? list-a list-b)
138+ (let loop ([list-a list-a] [list-b list-b])
139+ (if (null-list? list-a)
140+ (null-list? list-b)
141+ (and (not (null-list? list-b))
142+ (elt= (car list-a) (car list-b))
143+ (loop (cdr list-a) (cdr list-b))))))]
144+ [(elt= list-a list-b list-c . lists)
145+ (and (list= elt= list-a list-b)
146+ (list= elt= list-b list-c)
147+ (or (null? lists)
148+ (let loop ([list-a list-c] [lists lists])
149+ (let ([list-b (car lists)] [others (cdr lists)])
150+ (and (list= elt= list-a list-b)
151+ (or (null? others)
152+ (loop list-b others)))))))]))
153+ (define (length+ x)
154+ (let loop ([x x] [len 0])
155+ (if (null? x)
156+ len
157+ (if (fx>? len 20)
158+ (let lp ([x (cdr x)] [lag x] [len (fx+ len 1)])
159+ (if (pair? x)
160+ (let ([x (cdr x)] [len (fx+ len 1)])
161+ (if (pair? x)
162+ (let ([x (cdr x)]
163+ [lag (cdr lag)]
164+ [len (fx+ len 1)])
165+ (and (not (eq? x lag)) (lp x lag len)))
166+ len))
167+ len))
168+ (loop (cdr x) (fx+ len 1))))))
169+ (define (zip list1 . more-lists)
170+ (apply map list list1 more-lists))
171+ (define first car)
172+ (define second cadr)
173+ (define third caddr)
174+ (define fourth cadddr)
175+ (define (fifth x) (car (cddddr x)))
176+ (define (sixth x) (cadr (cddddr x)))
177+ (define (seventh x) (caddr (cddddr x)))
178+ (define (eighth x) (cadddr (cddddr x)))
179+ (define (ninth x) (car (cddddr (cddddr x))))
180+ (define (tenth x) (cadr (cddddr (cddddr x))))
181+ (define (car+cdr pair) (values (car pair) (cdr pair)))
182+ (define (take lis k)
183+ (check-arg fixnum? k take)
184+ (let recur ([lis lis] [k k])
185+ (if (zero? k)
186+ '()
187+ (cons (car lis) (recur (cdr lis) (- k 1))))))
188+ (define (drop lis k)
189+ (check-arg fixnum? k drop)
190+ (let iter ([lis lis] [k k])
191+ (if (zero? k) lis (iter (cdr lis) (- k 1)))))
192+ (define (take! lis k)
193+ (check-arg fixnum? k take!)
194+ (if (zero? k)
195+ '()
196+ (begin (set-cdr! (drop lis (- k 1)) '()) lis)))
197+ (define (take-right lis k)
198+ (check-arg fixnum? k take-right)
199+ (let lp ([lag lis] [lead (drop lis k)])
200+ (if (pair? lead) (lp (cdr lag) (cdr lead)) lag)))
201+ (define (drop-right lis k)
202+ (check-arg fixnum? k drop-right)
203+ (let recur ([lag lis] [lead (drop lis k)])
204+ (if (pair? lead)
205+ (cons (car lag) (recur (cdr lag) (cdr lead)))
206+ '())))
207+ (define (drop-right! lis k)
208+ (check-arg fixnum? k drop-right!)
209+ (let ([lead (drop lis k)])
210+ (if (pair? lead)
211+ (let lp ([lag lis] [lead (cdr lead)])
212+ (if (pair? lead)
213+ (lp (cdr lag) (cdr lead))
214+ (begin (set-cdr! lag '()) lis)))
215+ '())))
216+ (define (split-at x k)
217+ (check-arg fixnum? k split-at)
218+ (let recur ([lis x] [k k])
219+ (if (zero? k)
220+ (values '() lis)
221+ (receive
222+ (prefix suffix)
223+ (recur (cdr lis) (- k 1))
224+ (values (cons (car lis) prefix) suffix)))))
225+ (define (split-at! x k)
226+ (check-arg fixnum? k split-at!)
227+ (if (zero? k)
228+ (values '() x)
229+ (let* ([prev (drop x (- k 1))] [suffix (cdr prev)])
230+ (set-cdr! prev '())
231+ (values x suffix))))
232+ (define (last lis) (car (last-pair lis)))
233+ (define (last-pair lis)
234+ (check-arg pair? lis last-pair)
235+ (let lp ([lis lis])
236+ (let ([tail (cdr lis)]) (if (pair? tail) (lp tail) lis))))
237+ (define (unzip1 lis) (map car lis))
238+ (define (unzip2 lis)
239+ (let recur ([lis lis])
240+ (if (null-list? lis)
241+ (values lis lis)
242+ (let ([elt (car lis)])
243+ (receive
244+ (a b)
245+ (recur (cdr lis))
246+ (values (cons (car elt) a) (cons (cadr elt) b)))))))
247+ (define (unzip3 lis)
248+ (let recur ([lis lis])
249+ (if (null-list? lis)
250+ (values lis lis lis)
251+ (let ([elt (car lis)])
252+ (receive
253+ (a b c)
254+ (recur (cdr lis))
255+ (values
256+ (cons (car elt) a)
257+ (cons (cadr elt) b)
258+ (cons (caddr elt) c)))))))
259+ (define (unzip4 lis)
260+ (let recur ([lis lis])
261+ (if (null-list? lis)
262+ (values lis lis lis lis)
263+ (let ([elt (car lis)])
264+ (receive
265+ (a b c d)
266+ (recur (cdr lis))
267+ (values
268+ (cons (car elt) a)
269+ (cons (cadr elt) b)
270+ (cons (caddr elt) c)
271+ (cons (cadddr elt) d)))))))
272+ (define (unzip5 lis)
273+ (let recur ([lis lis])
274+ (if (null-list? lis)
275+ (values lis lis lis lis lis)
276+ (let ([elt (car lis)])
277+ (receive
278+ (a b c d e)
279+ (recur (cdr lis))
280+ (values (cons (car elt) a) (cons (cadr elt) b)
281+ (cons (caddr elt) c) (cons (cadddr elt) d)
282+ (cons (car (cddddr elt)) e)))))))
283+ (define append!
284+ (case-lambda
285+ [() '()]
286+ [(lis1) lis1]
287+ [(lis1 lis2)
288+ (cond
289+ [(null? lis2) lis1]
290+ [(null? lis1) lis2]
291+ [else (set-cdr! (last-pair lis1) lis2) lis1])]
292+ [(lis1 lis2 lis3 . lists)
293+ (let ([append-2! (lambda (lis1 lis2)
294+ (set-cdr! (last-pair lis1) lis2)
295+ lis1)]
296+ [lists (delete '() lists)])
297+ (if (null? lists)
298+ (if (null? lis3)
299+ (append! lis1 lis2)
300+ (let* ([lis (if (null? lis2)
301+ lis3
302+ (append-2! lis2 lis3))]
303+ [lis (if (null? lis1)
304+ lis
305+ (append-2! lis1 lis))])
306+ lis))
307+ (let* ([lis (let loop ([lis (car lists)]
308+ [lists (cdr lists)])
309+ (if (null? lists)
310+ lis
311+ (append-2!
312+ lis
313+ (loop (car lists) (cdr lists)))))]
314+ [lis (if (null? lis3) lis (append-2! lis3 lis))]
315+ [lis (if (null? lis2) lis (append-2! lis2 lis))]
316+ [lis (if (null? lis1) lis (append-2! lis1 lis))])
317+ lis)))]))
318+ (define (append-reverse rev-head tail)
319+ (let lp ([rev-head rev-head] [tail tail])
320+ (if (null-list? rev-head)
321+ tail
322+ (lp (cdr rev-head) (cons (car rev-head) tail)))))
323+ (define (append-reverse! rev-head tail)
324+ (let lp ([rev-head rev-head] [tail tail])
325+ (if (null-list? rev-head)
326+ tail
327+ (let ([next-rev (cdr rev-head)])
328+ (set-cdr! rev-head tail)
329+ (lp next-rev rev-head)))))
330+ (define (concatenate lists) (reduce-right append '() lists))
331+ (define (concatenate! lists)
332+ (reduce-right append! '() lists))
333+ (define (%cdrs lists)
334+ (let f ([ls lists])
335+ (if (pair? ls)
336+ (let ([x (car ls)])
337+ (if (null? x) '() (cons (cdr x) (f (cdr ls)))))
338+ '())))
339+ (define (%cars+ lists last-elt)
340+ (let recur ([lists lists])
341+ (if (pair? lists)
342+ (cons (caar lists) (recur (cdr lists)))
343+ (list last-elt))))
344+ (define (%cars+cdrs lists)
345+ (let f ([ls lists])
346+ (if (pair? ls)
347+ (let ([x (car ls)])
348+ (if (null-list? x)
349+ (values '() '())
350+ (receive
351+ (cars cdrs)
352+ (f (cdr ls))
353+ (values (cons (car x) cars) (cons (cdr x) cdrs)))))
354+ (values '() '()))))
355+ (define (%cars+cdrs+ lists cars-final)
356+ (let f ([ls lists])
357+ (if (pair? ls)
358+ (let ([x (car ls)])
359+ (if (null-list? x)
360+ (values '() '())
361+ (receive
362+ (cars cdrs)
363+ (f (cdr ls))
364+ (values (cons (car x) cars) (cons (cdr x) cdrs)))))
365+ (values (list cars-final) '()))))
366+ (define (%cars+cdrs/no-test lists)
367+ (let recur ([lists lists])
368+ (if (pair? lists)
369+ (receive
370+ (list other-lists)
371+ (car+cdr lists)
372+ (receive
373+ (a d)
374+ (car+cdr list)
375+ (receive
376+ (cars cdrs)
377+ (recur other-lists)
378+ (values (cons a cars) (cons d cdrs)))))
379+ (values '() '()))))
380+ (define count
381+ (case-lambda
382+ [(pred list1)
383+ (check-arg procedure? pred count)
384+ (let lp ([lis list1] [i 0])
385+ (if (null-list? lis)
386+ i
387+ (lp (cdr lis) (if (pred (car lis)) (fx+ i 1) i))))]
388+ [(pred list1 . lists)
389+ (check-arg procedure? pred count)
390+ (let lp ([list1 list1] [lists lists] [i 0])
391+ (if (null-list? list1)
392+ i
393+ (receive
394+ (as ds)
395+ (%cars+cdrs lists)
396+ (if (null? as)
397+ i
398+ (lp (cdr list1)
399+ ds
400+ (if (apply pred (car list1) as)
401+ (fx+ i 1)
402+ i))))))]))
403+ (define unfold-right
404+ (case-lambda
405+ [(p f g seed) (unfold-right p f g seed '())]
406+ [(p f g seed tail)
407+ (check-arg procedure? p unfold-right)
408+ (check-arg procedure? f unfold-right)
409+ (check-arg procedure? g unfold-right)
410+ (let lp ([seed seed] [ans tail])
411+ (if (p seed) ans (lp (g seed) (cons (f seed) ans))))]))
412+ (define unfold
413+ (case-lambda
414+ [(p f g seed)
415+ (check-arg procedure? p unfold)
416+ (check-arg procedure? f unfold)
417+ (check-arg procedure? g unfold)
418+ (let recur ([seed seed])
419+ (if (p seed) '() (cons (f seed) (recur (g seed)))))]
420+ [(p f g seed tail-gen)
421+ (check-arg procedure? p unfold)
422+ (check-arg procedure? f unfold)
423+ (check-arg procedure? g unfold)
424+ (let recur ([seed seed])
425+ (if (p seed)
426+ (tail-gen seed)
427+ (cons (f seed) (recur (g seed)))))]))
428+ (define fold
429+ (case-lambda
430+ [(kons knil lis1)
431+ (check-arg procedure? kons fold)
432+ (let lp ([lis lis1] [ans knil])
433+ (if (null-list? lis)
434+ ans
435+ (lp (cdr lis) (kons (car lis) ans))))]
436+ [(kons knil lis1 lis2)
437+ (check-arg procedure? kons fold)
438+ (let lp ([lis1 lis1] [lis2 lis2] [ans knil])
439+ (if (or (null-list? lis1) (null-list? lis2))
440+ ans
441+ (lp (cdr lis1)
442+ (cdr lis2)
443+ (kons (car lis1) (car lis2) ans))))]
444+ [(kons knil . lists)
445+ (check-arg procedure? kons fold)
446+ (let lp ([lists lists] [ans knil])
447+ (receive
448+ (cars+ans cdrs)
449+ (%cars+cdrs+ lists ans)
450+ (if (null? cars+ans)
451+ ans
452+ (lp cdrs (apply kons cars+ans)))))]))
453+ (define fold-right
454+ (case-lambda
455+ [(kons knil lis1)
456+ (check-arg procedure? kons fold-right)
457+ (let recur ([lis lis1])
458+ (if (null-list? lis)
459+ knil
460+ (kons (car lis) (recur (cdr lis)))))]
461+ [(kons knil lis1 lis2)
462+ (check-arg procedure? kons fold-right)
463+ (let recur ([lis1 lis1] [lis2 lis2])
464+ (if (or (null-list? lis1) (null-list? lis2))
465+ knil
466+ (kons
467+ (car lis1)
468+ (car lis2)
469+ (recur (cdr lis1) (cdr lis2)))))]
470+ [(kons knil . lists)
471+ (check-arg procedure? kons fold-right)
472+ (let recur ([lists lists])
473+ (let ([cdrs (%cdrs lists)])
474+ (if (null? cdrs)
475+ knil
476+ (apply kons (%cars+ lists (recur cdrs))))))]))
477+ (define pair-fold-right
478+ (case-lambda
479+ [(f zero lis1)
480+ (check-arg procedure? f pair-fold-right)
481+ (let recur ([lis lis1])
482+ (if (null-list? lis) zero (f lis (recur (cdr lis)))))]
483+ [(f zero lis1 lis2 . lists)
484+ (check-arg procedure? f pair-fold-right)
485+ (let recur ([lis1 lis1] [lis2 lis2] [lists lists])
486+ (if (or (null-list? lis1) (null-list? lis2))
487+ zero
488+ (let ([cdrs (%cdrs lists)])
489+ (if (null? cdrs)
490+ zero
491+ (apply
492+ f
493+ lis1
494+ lis2
495+ (append!
496+ lists
497+ (list
498+ (recur (cdr lis1) (cdr lis2) cdrs))))))))]))
499+ (define pair-fold
500+ (case-lambda
501+ [(f zero lis1)
502+ (check-arg procedure? f pair-fold)
503+ (let lp ([lis lis1] [ans zero])
504+ (if (null? lis)
505+ ans
506+ (let ([tail (cdr lis)]) (lp tail (f lis ans)))))]
507+ [(f zero lis1 lis2 . lists)
508+ (check-arg procedure? f pair-fold)
509+ (let lp ([lis1 lis1] [lis2 lis2] [lists lists] [ans zero])
510+ (if (or (null-list? lis1) (null-list? lis2))
511+ ans
512+ (let ([tails (%cdrs lists)])
513+ (if (null? tails)
514+ ans
515+ (lp (cdr lis1)
516+ (cdr lis2)
517+ tails
518+ (apply
519+ f
520+ lis1
521+ lis2
522+ (append! lists (list ans))))))))]))
523+ (define (reduce f ridentity lis)
524+ (check-arg procedure? f reduce)
525+ (if (null-list? lis)
526+ ridentity
527+ (fold f (car lis) (cdr lis))))
528+ (define (reduce-right f ridentity lis)
529+ (check-arg procedure? f reduce-right)
530+ (if (null-list? lis)
531+ ridentity
532+ (let recur ([head (car lis)] [lis (cdr lis)])
533+ (if (pair? lis)
534+ (f head (recur (car lis) (cdr lis)))
535+ head))))
536+ (define append-map
537+ (case-lambda
538+ [(f lis1) (really-append-map append-map append f lis1)]
539+ [(f lis1 lis2)
540+ (really-append-map append-map append f lis1 lis2)]
541+ [(f lis1 lis2 . lists)
542+ (really-append-map append-map append f lis1 lis2 lists)]))
543+ (define append-map!
544+ (case-lambda
545+ [(f lis1) (really-append-map append-map! append! f lis1)]
546+ [(f lis1 lis2)
547+ (really-append-map append-map! append! f lis1 lis2)]
548+ [(f lis1 lis2 . lists)
549+ (really-append-map append-map! append! f lis1 lis2 lists)]))
550+ (define really-append-map
551+ (case-lambda
552+ [(who appender f lis1)
553+ (check-arg procedure? f who)
554+ (if (null-list? lis1)
555+ '()
556+ (let recur ([elt (car lis1)] [rest (cdr lis1)])
557+ (let ([vals (f elt)])
558+ (if (null-list? rest)
559+ vals
560+ (appender vals (recur (car rest) (cdr rest)))))))]
561+ [(who appender f lis1 lis2)
562+ (check-arg procedure? f who)
563+ (if (or (null-list? lis1) (null-list? lis2))
564+ '()
565+ (let recur ([lis1 lis1] [lis2 lis2])
566+ (let ([vals (f (car lis1) (car lis2))]
567+ [lis1 (cdr lis1)]
568+ [lis2 (cdr lis2)])
569+ (if (or (null-list? lis1) (null-list? lis2))
570+ vals
571+ (appender vals (recur lis1 lis2))))))]
572+ [(who appender f lis1 lis2 lists)
573+ (check-arg procedure? f who)
574+ (if (or (null-list? lis1) (null-list? lis2))
575+ '()
576+ (receive
577+ (cars cdrs)
578+ (%cars+cdrs lists)
579+ (if (null? cars)
580+ '()
581+ (let recur ([lis1 lis1]
582+ [lis2 lis2]
583+ [cars cars]
584+ [cdrs cdrs])
585+ (let ([vals (apply f (car lis1) (car lis2) cars)]
586+ [lis1 (cdr lis1)]
587+ [lis2 (cdr lis2)])
588+ (if (or (null-list? lis1) (null-list? lis2))
589+ vals
590+ (receive
591+ (cars2 cdrs2)
592+ (%cars+cdrs cdrs)
593+ (if (null? cars2)
594+ vals
595+ (appender
596+ vals
597+ (recur
598+ lis1
599+ lis2
600+ cars2
601+ cdrs2))))))))))]))
602+ (define pair-for-each
603+ (case-lambda
604+ [(proc lis1)
605+ (check-arg procedure? proc pair-for-each)
606+ (let lp ([lis lis1])
607+ (if (not (null-list? lis))
608+ (let ([tail (cdr lis)]) (proc lis) (lp tail))))]
609+ [(proc lis1 lis2 . lists)
610+ (check-arg procedure? proc pair-for-each)
611+ (let lp ([lis1 lis1] [lis2 lis2] [lists lists])
612+ (if (and (pair? lis1) (pair? lis2))
613+ (let ([tails (%cdrs lists)])
614+ (if (pair? tails)
615+ (begin
616+ (apply proc lis1 lis2 lists)
617+ (lp (cdr lis1) (cdr lis2) tails))))))]))
618+ (define map!
619+ (case-lambda
620+ [(f lis1)
621+ (check-arg procedure? f map!)
622+ (let lp ([lis1 lis1])
623+ (when (not (null-list? lis1))
624+ (set-car! lis1 (f (car lis1)))
625+ (lp (cdr lis1))))
626+ lis1]
627+ [(f lis1 lis2)
628+ (check-arg procedure? f map!)
629+ (let lp ([lis1 lis1] [lis2 lis2])
630+ (when (not (null-list? lis1))
631+ (set-car! lis1 (f (car lis1) (car lis2)))
632+ (lp (cdr lis1) (cdr lis2))))
633+ lis1]
634+ [(f lis1 lis2 lis3 . lists)
635+ (check-arg procedure? f map!)
636+ (let lp ([lis1 lis1] [lis2 lis2] [lis3 lis3] [lists lists])
637+ (when (not (null-list? lis1))
638+ (receive
639+ (heads tails)
640+ (%cars+cdrs/no-test lists)
641+ (set-car!
642+ lis1
643+ (apply f (car lis1) (car lis2) (car lis3) heads))
644+ (lp (cdr lis1) (cdr lis2) (cdr lis3) tails))))
645+ lis1]))
646+ (define filter-map
647+ (case-lambda
648+ [(f lis1)
649+ (check-arg procedure? f filter-map)
650+ (let recur ([lis lis1])
651+ (if (null-list? lis)
652+ '()
653+ (let ([tail (recur (cdr lis))])
654+ (cond
655+ [(f (car lis)) => (lambda (x) (cons x tail))]
656+ [else tail]))))]
657+ [(f lis1 . lists)
658+ (check-arg procedure? f filter-map)
659+ (let recur ([lis1 lis1] [lists lists])
660+ (if (null-list? lis1)
661+ '()
662+ (receive
663+ (cars cdrs)
664+ (%cars+cdrs lists)
665+ (if (pair? cars)
666+ (cond
667+ [(apply f (car lis1) cars) =>
668+ (lambda (x) (cons x (recur (cdr lis1) cdrs)))]
669+ [else (recur (cdr lis1) cdrs)])
670+ '()))))]))
671+ (define map-in-order
672+ (case-lambda
673+ [(f lis1)
674+ (check-arg procedure? f map-in-order)
675+ (let recur ([lis lis1])
676+ (if (null-list? lis)
677+ lis
678+ (let ([tail (cdr lis)] [x (f (car lis))])
679+ (cons x (recur tail)))))]
680+ [(f lis1 lis2)
681+ (check-arg procedure? f map-in-order)
682+ (let recur ([lis1 lis1] [lis2 lis2])
683+ (if (and (pair? lis1) (pair? lis2))
684+ (let ([x (f (car lis1) (car lis2))])
685+ (cons x (recur (cdr lis1) (cdr lis2))))
686+ '()))]
687+ [(f lis1 lis2 . lists)
688+ (check-arg procedure? f map-in-order)
689+ (let recur ([lis1 lis1] [lis2 lis2] [lists lists])
690+ (receive
691+ (cars cdrs)
692+ (%cars+cdrs lists)
693+ (if (and (pair? lis1) (pair? lis2) (pair? cars))
694+ (let ([x (apply f (car lis1) (car lis2) cars)])
695+ (cons x (recur (cdr lis1) (cdr lis2) cdrs)))
696+ '())))]))
697+ (define map map-in-order)
698+ (define for-each
699+ (case-lambda
700+ [(f lis1) (r6rs:for-each f lis1)]
701+ [(f lis1 lis2)
702+ (check-arg procedure? f for-each)
703+ (let recur ([lis1 lis1] [lis2 lis2])
704+ (unless (or (null-list? lis1) (null-list? lis2))
705+ (f (car lis1) (car lis2))
706+ (recur (cdr lis1) (cdr lis2))))]
707+ [(f lis1 lis2 . lists)
708+ (check-arg procedure? f for-each)
709+ (let recur ([lis1 lis1] [lis2 lis2] [lists lists])
710+ (unless (or (null-list? lis1) (null-list? lis2))
711+ (receive
712+ (cars cdrs)
713+ (%cars+cdrs lists)
714+ (when (pair? cars)
715+ (apply f (car lis1) (car lis2) cars)
716+ (recur (cdr lis1) (cdr lis2) cdrs)))))]))
717+ (define (filter pred lis)
718+ (check-arg procedure? pred filter)
719+ (let recur ([lis lis])
720+ (if (null-list? lis)
721+ lis
722+ (let ([head (car lis)] [tail (cdr lis)])
723+ (if (pred head)
724+ (let ([new-tail (recur tail)])
725+ (if (eq? tail new-tail) lis (cons head new-tail)))
726+ (recur tail))))))
727+ (define (filter! pred lis)
728+ (check-arg procedure? pred filter!)
729+ (let lp ([ans lis])
730+ (cond
731+ [(null-list? ans) ans]
732+ [(not (pred (car ans))) (lp (cdr ans))]
733+ [else
734+ (letrec ([scan-in (lambda (prev lis)
735+ (if (pair? lis)
736+ (if (pred (car lis))
737+ (scan-in lis (cdr lis))
738+ (scan-out prev (cdr lis)))))]
739+ [scan-out (lambda (prev lis)
740+ (let lp ([lis lis])
741+ (if (pair? lis)
742+ (if (pred (car lis))
743+ (begin
744+ (set-cdr! prev lis)
745+ (scan-in lis (cdr lis)))
746+ (lp (cdr lis)))
747+ (set-cdr! prev lis))))])
748+ (scan-in ans (cdr ans))
749+ ans)])))
750+ (define (partition pred lis)
751+ (check-arg procedure? pred partition)
752+ (let recur ([lis lis])
753+ (if (null-list? lis)
754+ (values lis lis)
755+ (let ([elt (car lis)] [tail (cdr lis)])
756+ (receive
757+ (in out)
758+ (recur tail)
759+ (if (pred elt)
760+ (values (if (pair? out) (cons elt in) lis) out)
761+ (values
762+ in
763+ (if (pair? in) (cons elt out) lis))))))))
764+ (define (partition! pred lis)
765+ (check-arg procedure? pred partition!)
766+ (if (null-list? lis)
767+ (values lis lis)
768+ (letrec ([scan-in (lambda (in-prev out-prev lis)
769+ (let lp ([in-prev in-prev] [lis lis])
770+ (if (pair? lis)
771+ (if (pred (car lis))
772+ (lp lis (cdr lis))
773+ (begin
774+ (set-cdr! out-prev lis)
775+ (scan-out
776+ in-prev
777+ lis
778+ (cdr lis))))
779+ (set-cdr! out-prev lis))))]
780+ [scan-out (lambda (in-prev out-prev lis)
781+ (let lp ([out-prev out-prev] [lis lis])
782+ (if (pair? lis)
783+ (if (pred (car lis))
784+ (begin
785+ (set-cdr! in-prev lis)
786+ (scan-in
787+ lis
788+ out-prev
789+ (cdr lis)))
790+ (lp lis (cdr lis)))
791+ (set-cdr! in-prev lis))))])
792+ (if (pred (car lis))
793+ (let lp ([prev-l lis] [l (cdr lis)])
794+ (cond
795+ [(not (pair? l)) (values lis l)]
796+ [(pred (car l)) (lp l (cdr l))]
797+ [else (scan-out prev-l l (cdr l)) (values lis l)]))
798+ (let lp ([prev-l lis] [l (cdr lis)])
799+ (cond
800+ [(not (pair? l)) (values l lis)]
801+ [(pred (car l))
802+ (scan-in l prev-l (cdr l))
803+ (values l lis)]
804+ [else (lp l (cdr l))]))))))
805+ (define (remove pred lis)
806+ (check-arg procedure? pred remove)
807+ (let recur ([lis lis])
808+ (if (null-list? lis)
809+ lis
810+ (let ([head (car lis)] [tail (cdr lis)])
811+ (if (not (pred head))
812+ (let ([new-tail (recur tail)])
813+ (if (eq? tail new-tail) lis (cons head new-tail)))
814+ (recur tail))))))
815+ (define (remove! pred lis)
816+ (check-arg procedure? pred remove!)
817+ (let lp ([ans lis])
818+ (cond
819+ [(null-list? ans) ans]
820+ [(pred (car ans)) (lp (cdr ans))]
821+ [else
822+ (letrec ([scan-in (lambda (prev lis)
823+ (if (pair? lis)
824+ (if (not (pred (car lis)))
825+ (scan-in lis (cdr lis))
826+ (scan-out prev (cdr lis)))))]
827+ [scan-out (lambda (prev lis)
828+ (let lp ([lis lis])
829+ (if (pair? lis)
830+ (if (not (pred (car lis)))
831+ (begin
832+ (set-cdr! prev lis)
833+ (scan-in lis (cdr lis)))
834+ (lp (cdr lis)))
835+ (set-cdr! prev lis))))])
836+ (scan-in ans (cdr ans))
837+ ans)])))
838+ (define delete
839+ (case-lambda
840+ [(x lis) (delete x lis equal?)]
841+ [(x lis elt=)
842+ (let recur ([lis lis])
843+ (if (null-list? lis)
844+ lis
845+ (let ([head (car lis)] [tail (cdr lis)])
846+ (if (not (elt= x head))
847+ (let ([new-tail (recur tail)])
848+ (if (eq? tail new-tail)
849+ lis
850+ (cons head new-tail)))
851+ (recur tail)))))]))
852+ (define delete!
853+ (case-lambda
854+ [(x lis) (delete! x lis equal?)]
855+ [(x lis elt=)
856+ (let lp ([ans lis])
857+ (cond
858+ [(null-list? ans) ans]
859+ [(elt= x (car ans)) (lp (cdr ans))]
860+ [else
861+ (letrec ([scan-in (lambda (prev lis)
862+ (if (pair? lis)
863+ (if (not (elt= x (car lis)))
864+ (scan-in lis (cdr lis))
865+ (scan-out prev (cdr lis)))))]
866+ [scan-out (lambda (prev lis)
867+ (let lp ([lis lis])
868+ (if (pair? lis)
869+ (if (not (elt= x (car lis)))
870+ (begin
871+ (set-cdr! prev lis)
872+ (scan-in lis (cdr lis)))
873+ (lp (cdr lis)))
874+ (set-cdr! prev lis))))])
875+ (scan-in ans (cdr ans))
876+ ans)]))]))
877+ (define member
878+ (case-lambda
879+ [(x lis) (r6rs:member x lis)]
880+ [(x lis elt=)
881+ (let lp ([lis lis])
882+ (and (not (null-list? lis))
883+ (if (elt= x (car lis)) lis (lp (cdr lis)))))]))
884+ (define delete-duplicates
885+ (case-lambda
886+ [(lis) (delete-duplicates lis equal?)]
887+ [(lis elt=)
888+ (check-arg procedure? elt= delete-duplicates)
889+ (let recur ([lis lis])
890+ (if (null-list? lis)
891+ lis
892+ (let* ([x (car lis)]
893+ [tail (cdr lis)]
894+ [new-tail (recur (delete x tail elt=))])
895+ (if (eq? tail new-tail) lis (cons x new-tail)))))]))
896+ (define delete-duplicates!
897+ (case-lambda
898+ [(lis) (delete-duplicates! lis equal?)]
899+ [(lis elt=)
900+ (check-arg procedure? elt= delete-duplicates!)
901+ (let recur ([lis lis])
902+ (if (null-list? lis)
903+ lis
904+ (let* ([x (car lis)]
905+ [tail (cdr lis)]
906+ [new-tail (recur (delete! x tail elt=))])
907+ (if (not (eq? tail new-tail)) (set-cdr! lis new-tail))
908+ lis)))]))
909+ (define assoc
910+ (case-lambda
911+ [(x lis) (r6rs:assoc x lis)]
912+ [(x lis elt=)
913+ (let loop ([lis lis])
914+ (if (pair? lis)
915+ (let ([entry (car lis)])
916+ (if (elt= x (car entry)) entry (loop (cdr lis))))
917+ #f))]))
918+ (define (alist-cons key datum alist)
919+ (cons (cons key datum) alist))
920+ (define (alist-copy alist)
921+ (map (lambda (elt) (cons (car elt) (cdr elt))) alist))
922+ (define alist-delete
923+ (case-lambda
924+ [(key alist)
925+ (remove (lambda (elt) (equal? key (car elt))) alist)]
926+ [(key alist elt=)
927+ (remove (lambda (elt) (elt= key (car elt))) alist)]))
928+ (define alist-delete!
929+ (case-lambda
930+ [(key alist)
931+ (remove! (lambda (elt) (equal? key (car elt))) alist)]
932+ [(key alist elt=)
933+ (remove! (lambda (elt) (elt= key (car elt))) alist)]))
934+ (define (find pred lis)
935+ (check-arg procedure? pred find)
936+ (let loop ([lis lis])
937+ (if (pair? lis)
938+ (let ([head (car lis)])
939+ (if (pred head) head (loop (cdr lis))))
940+ #f)))
941+ (define (find-tail pred lis)
942+ (check-arg procedure? pred find-tail)
943+ (let lp ([lis lis])
944+ (and (not (null-list? lis))
945+ (if (pred (car lis)) lis (lp (cdr lis))))))
946+ (define (take-while pred lis)
947+ (check-arg procedure? pred take-while)
948+ (let recur ([lis lis])
949+ (if (null-list? lis)
950+ '()
951+ (let ([x (car lis)])
952+ (if (pred x) (cons x (recur (cdr lis))) '())))))
953+ (define (drop-while pred lis)
954+ (check-arg procedure? pred drop-while)
955+ (let lp ([lis lis])
956+ (if (null-list? lis)
957+ '()
958+ (if (pred (car lis)) (lp (cdr lis)) lis))))
959+ (define (take-while! pred lis)
960+ (check-arg procedure? pred take-while!)
961+ (if (or (null-list? lis) (not (pred (car lis))))
962+ '()
963+ (begin
964+ (let lp ([prev lis] [rest (cdr lis)])
965+ (if (pair? rest)
966+ (let ([x (car rest)])
967+ (if (pred x)
968+ (lp rest (cdr rest))
969+ (set-cdr! prev '())))))
970+ lis)))
971+ (define (span pred lis)
972+ (check-arg procedure? pred span)
973+ (let recur ([lis lis])
974+ (if (null-list? lis)
975+ (values '() '())
976+ (let ([x (car lis)])
977+ (if (pred x)
978+ (receive
979+ (prefix suffix)
980+ (recur (cdr lis))
981+ (values (cons x prefix) suffix))
982+ (values '() lis))))))
983+ (define (span! pred lis)
984+ (check-arg procedure? pred span!)
985+ (if (or (null-list? lis) (not (pred (car lis))))
986+ (values '() lis)
987+ (let ([suffix (let lp ([prev lis] [rest (cdr lis)])
988+ (if (null-list? rest)
989+ rest
990+ (let ([x (car rest)])
991+ (if (pred x)
992+ (lp rest (cdr rest))
993+ (begin
994+ (set-cdr! prev '())
995+ rest)))))])
996+ (values lis suffix))))
997+ (define (break pred lis)
998+ (check-arg procedure? pred break)
999+ (let recur ([lis lis])
1000+ (if (null-list? lis)
1001+ (values '() '())
1002+ (let ([x (car lis)])
1003+ (if (not (pred x))
1004+ (receive
1005+ (prefix suffix)
1006+ (recur (cdr lis))
1007+ (values (cons x prefix) suffix))
1008+ (values '() lis))))))
1009+ (define (break! pred lis)
1010+ (check-arg procedure? pred break!)
1011+ (if (or (null-list? lis) (pred (car lis)))
1012+ (values '() lis)
1013+ (let ([suffix (let lp ([prev lis] [rest (cdr lis)])
1014+ (if (null-list? rest)
1015+ rest
1016+ (let ([x (car rest)])
1017+ (if (not (pred x))
1018+ (lp rest (cdr rest))
1019+ (begin
1020+ (set-cdr! prev '())
1021+ rest)))))])
1022+ (values lis suffix))))
1023+ (define any
1024+ (case-lambda
1025+ [(pred lis1)
1026+ (check-arg procedure? pred any)
1027+ (and (not (null-list? lis1))
1028+ (let loop ([head (car lis1)] [tail (cdr lis1)])
1029+ (if (null-list? tail)
1030+ (pred head)
1031+ (or (pred head) (loop (car tail) (cdr tail))))))]
1032+ [(pred lis1 lis2)
1033+ (check-arg procedure? pred any)
1034+ (and (not (null-list? lis1))
1035+ (not (null-list? lis2))
1036+ (let loop ([head1 (car lis1)]
1037+ [tail1 (cdr lis1)]
1038+ [head2 (car lis2)]
1039+ [tail2 (cdr lis2)])
1040+ (if (or (null-list? tail1) (null-list? tail2))
1041+ (pred head1 head2)
1042+ (or (pred head1 head2)
1043+ (loop
1044+ (car tail1)
1045+ (cdr tail1)
1046+ (car tail2)
1047+ (cdr tail2))))))]
1048+ [(pred lis1 lis2 . lists)
1049+ (check-arg procedure? pred any)
1050+ (and (not (null-list? lis1))
1051+ (not (null-list? lis2))
1052+ (receive
1053+ (heads tails)
1054+ (%cars+cdrs lists)
1055+ (and (pair? heads)
1056+ (let loop ([head1 (car lis1)]
1057+ [tail1 (cdr lis1)]
1058+ [head2 (car lis2)]
1059+ [tail2 (cdr lis2)]
1060+ [heads heads]
1061+ [tails tails])
1062+ (if (or (null-list? tail1) (null-list? tail2))
1063+ (apply pred head1 head2 heads)
1064+ (receive
1065+ (next-heads next-tails)
1066+ (%cars+cdrs tails)
1067+ (if (null? next-tails)
1068+ (apply pred head1 head2 heads)
1069+ (or (apply pred head1 head2 heads)
1070+ (loop (car tail1) (cdr tail1)
1071+ (car tail2) (cdr tail2)
1072+ next-heads
1073+ next-tails)))))))))]))
1074+ (define every
1075+ (case-lambda
1076+ [(pred lis1)
1077+ (check-arg procedure? pred every)
1078+ (or (null-list? lis1)
1079+ (let loop ([head (car lis1)] [tail (cdr lis1)])
1080+ (if (null-list? tail)
1081+ (pred head)
1082+ (and (pred head) (loop (car tail) (cdr tail))))))]
1083+ [(pred lis1 lis2)
1084+ (check-arg procedure? pred every)
1085+ (or (null-list? lis1)
1086+ (null-list? lis2)
1087+ (let loop ([head1 (car lis1)]
1088+ [tail1 (cdr lis1)]
1089+ [head2 (car lis2)]
1090+ [tail2 (cdr lis2)])
1091+ (if (or (null-list? tail1) (null-list? tail2))
1092+ (pred head1 head2)
1093+ (and (pred head1 head2)
1094+ (loop
1095+ (car tail1)
1096+ (cdr tail1)
1097+ (car tail2)
1098+ (cdr tail2))))))]
1099+ [(pred lis1 lis2 . lists)
1100+ (check-arg procedure? pred every)
1101+ (or (null-list? lis1)
1102+ (null-list? lis2)
1103+ (receive
1104+ (heads tails)
1105+ (%cars+cdrs lists)
1106+ (or (not (pair? heads))
1107+ (let loop ([head1 (car lis1)]
1108+ [tail1 (cdr lis1)]
1109+ [head2 (car lis2)]
1110+ [tail2 (cdr lis2)]
1111+ [heads heads]
1112+ [tails tails])
1113+ (if (or (null-list? tail1) (null-list? tail2))
1114+ (apply pred head1 head2 heads)
1115+ (receive
1116+ (next-heads next-tails)
1117+ (%cars+cdrs tails)
1118+ (if (null? next-tails)
1119+ (apply pred head1 head2 heads)
1120+ (and (apply pred head1 head2 heads)
1121+ (loop (car tail1) (cdr tail1)
1122+ (car tail2) (cdr tail2)
1123+ next-heads next-tails)))))))))]))
1124+ (define list-index
1125+ (case-lambda
1126+ [(pred lis1)
1127+ (check-arg procedure? pred list-index)
1128+ (let loop ([lis lis1] [n 0])
1129+ (and (not (null-list? lis))
1130+ (if (pred (car lis)) n (loop (cdr lis) (fx+ n 1)))))]
1131+ [(pred lis1 lis2)
1132+ (check-arg procedure? pred list-index)
1133+ (let loop ([lis1 lis1] [lis2 lis2] [n 0])
1134+ (and (not (or (null-list? lis1) (null-list? lis2)))
1135+ (if (pred (car lis1) (car lis2))
1136+ n
1137+ (loop (cdr lis1) (cdr lis2) (fx+ n 1)))))]
1138+ [(pred lis1 lis2 lis3 . lists)
1139+ (check-arg procedure? pred list-index)
1140+ (let loop ([lis1 lis1]
1141+ [lis2 lis2]
1142+ [lis3 lis3]
1143+ [lists lists]
1144+ [n 0])
1145+ (and (not (or (null-list? lis1)
1146+ (null-list? lis2)
1147+ (null-list? lis3)))
1148+ (receive
1149+ (heads tails)
1150+ (%cars+cdrs lists)
1151+ (and (not (null? heads))
1152+ (if (apply pred (car lis1) (car lis2) (car lis3)
1153+ heads)
1154+ n
1155+ (loop (cdr lis1) (cdr lis2) (cdr lis3) tails
1156+ (fx+ n 1)))))))]))
1157+ (define (reverse! lis)
1158+ (let lp ([lis lis] [ans '()])
1159+ (if (null-list? lis)
1160+ ans
1161+ (let ([tail (cdr lis)])
1162+ (set-cdr! lis ans)
1163+ (lp tail lis)))))
1164+ (define (%lset2<= = lis1 lis2)
1165+ (every (lambda (x) (member x lis2 =)) lis1))
1166+ (define lset<=
1167+ (case-lambda
1168+ [(=) (check-arg procedure? = lset<=) #t]
1169+ [(= lis1) (check-arg procedure? = lset<=) #t]
1170+ [(= lis1 lis2)
1171+ (check-arg procedure? = lset<=)
1172+ (or (eq? lis1 lis2) (%lset2<= = lis1 lis2))]
1173+ [(= lis1 lis2 lis3 . lists)
1174+ (check-arg procedure? = lset<=)
1175+ (and (or (eq? lis1 lis2) (%lset2<= = lis1 lis2))
1176+ (or (eq? lis2 lis3) (%lset2<= = lis2 lis3))
1177+ (or (null? lists)
1178+ (let loop ([lis1 lis3]
1179+ [lis2 (car lists)]
1180+ [lists (cdr lists)])
1181+ (and (or (eq? lis1 lis2) (%lset2<= = lis1 lis2))
1182+ (or (null? lists)
1183+ (loop
1184+ lis2
1185+ (car lists)
1186+ (cdr lists)))))))]))
1187+ (define lset=
1188+ (case-lambda
1189+ [(=) (check-arg procedure? = lset=) #t]
1190+ [(= lis1) (check-arg procedure? = lset=) #t]
1191+ [(= lis1 lis2)
1192+ (check-arg procedure? = lset=)
1193+ (or (eq? lis1 lis2)
1194+ (and (%lset2<= = lis1 lis2) (%lset2<= = lis2 lis1)))]
1195+ [(= lis1 lis2 lis3 . lists)
1196+ (check-arg procedure? = lset=)
1197+ (and (or (eq? lis1 lis2)
1198+ (and (%lset2<= = lis1 lis2) (%lset2<= = lis2 lis1)))
1199+ (or (eq? lis2 lis3)
1200+ (and (%lset2<= = lis2 lis3) (%lset2<= = lis3 lis2)))
1201+ (or (null? lists)
1202+ (let loop ([lis1 lis3]
1203+ [lis2 (car lists)]
1204+ [lists (cdr lists)])
1205+ (and (or (eq? lis1 lis2)
1206+ (and (%lset2<= = lis1 lis2)
1207+ (%lset2<= = lis2 lis1)))
1208+ (or (null? lists)
1209+ (loop
1210+ lis2
1211+ (car lists)
1212+ (cdr lists)))))))]))
1213+ (define lset-adjoin
1214+ (case-lambda
1215+ [(= lis) lis]
1216+ [(= lis elt)
1217+ (check-arg procedure? = lset-adjoin)
1218+ (if (member elt lis) lis (cons elt lis))]
1219+ [(= lis elt1 elt2)
1220+ (check-arg procedure? = lset-adjoin)
1221+ (let* ([lis (if (member elt1 lis) lis (cons elt1 lis))]
1222+ [lis (if (member elt2 lis) lis (cons elt2 lis))])
1223+ lis)]
1224+ [(= lis elt1 elt2 elt3 . elts)
1225+ (check-arg procedure? = lset-adjoin)
1226+ (let* ([lis (if (member elt1 lis) lis (cons elt1 lis))]
1227+ [lis (if (member elt2 lis) lis (cons elt2 lis))]
1228+ [lis (if (member elt3 lis) lis (cons elt3 lis))])
1229+ (if (null? elts)
1230+ lis
1231+ (fold
1232+ (lambda (elt ans)
1233+ (if (member elt ans =) ans (cons elt ans)))
1234+ lis
1235+ elts)))]))
1236+ (define lset-union
1237+ (let ([lset-union-2 (lambda (= lis1 lis2)
1238+ (cond
1239+ [(null? lis1) lis2]
1240+ [(null? lis2) lis1]
1241+ [(eq? lis1 lis2) lis1]
1242+ [else
1243+ (fold
1244+ (lambda (elt ans)
1245+ (if (member elt ans =)
1246+ ans
1247+ (cons elt ans)))
1248+ lis1
1249+ lis2)]))])
1250+ (case-lambda
1251+ [(=) (check-arg procedure? = lset-union) '()]
1252+ [(= lis1) (check-arg procedure? = lset-union) lis1]
1253+ [(= lis1 lis2)
1254+ (check-arg procedure? = lset-union)
1255+ (lset-union-2 = lis1 lis2)]
1256+ [(= lis1 lis2 lis3 . lists)
1257+ (check-arg procedure? = lset-union)
1258+ (let* ([lis (lset-union-2 = lis1 lis2)]
1259+ [lis (lset-union-2 = lis lis3)])
1260+ (if (null? lists)
1261+ lis
1262+ (fold
1263+ (lambda (lis2 lis1) (lset-union-2 = lis1 lis2))
1264+ lis
1265+ lists)))])))
1266+ (define lset-union!
1267+ (let ([lset-union-2! (lambda (= lis1 lis2)
1268+ (cond
1269+ [(null? lis1) lis2]
1270+ [(null? lis2) lis1]
1271+ [(eq? lis1 lis2) lis1]
1272+ [else
1273+ (pair-fold
1274+ (lambda (pair ans)
1275+ (let ([elt (car pair)])
1276+ (if (member elt ans =)
1277+ ans
1278+ (begin
1279+ (set-cdr! pair ans)
1280+ pair))))
1281+ lis1
1282+ lis2)]))])
1283+ (case-lambda
1284+ [(=) (check-arg procedure? = lset-union!) '()]
1285+ [(= lis1) (check-arg procedure? = lset-union!) lis1]
1286+ [(= lis1 lis2)
1287+ (check-arg procedure? = lset-union!)
1288+ (lset-union-2! = lis1 lis2)]
1289+ [(= lis1 lis2 lis3 . lists)
1290+ (check-arg procedure? = lset-union!)
1291+ (let* ([lis (lset-union-2! = lis1 lis2)]
1292+ [lis (lset-union-2! = lis lis3)])
1293+ (if (null? lists)
1294+ lis
1295+ (fold
1296+ (lambda (lis1 lis2) (lset-union-2! = lis1 lis2))
1297+ lis
1298+ lists)))])))
1299+ (define lset-intersection
1300+ (case-lambda
1301+ [(= lis1) (check-arg procedure? = lset-intersection) lis1]
1302+ [(= lis1 lis2)
1303+ (check-arg procedure? = lset-intersection)
1304+ (cond
1305+ [(or (null-list? lis1) (eq? lis1 lis2)) lis1]
1306+ [(null-list? lis2) lis2]
1307+ [else (filter (lambda (x) (member x lis2 =)) lis1)])]
1308+ [(= lis1 lis2 lis3 . lists)
1309+ (check-arg procedure? = lset-intersection)
1310+ (cond
1311+ [(or (null-list? lis1)
1312+ (null-list? lis2)
1313+ (null-list? lis3)
1314+ (any null-list? lists))
1315+ '()]
1316+ [(eq? lis2 lis1)
1317+ (if (eq? lis3 lis1)
1318+ (apply lset-intersection = lis1 lists)
1319+ (apply lset-intersection = lis1 lis3 lists))]
1320+ [(or (eq? lis3 lis1) (eq? lis3 lis2))
1321+ (apply lset-intersection = lis1 lis2 lists)]
1322+ [else
1323+ (let* ([lists (remove
1324+ (lambda (lis)
1325+ (or (eq? lis lis1)
1326+ (eq? lis lis2)
1327+ (eq? lis lis3)))
1328+ lists)])
1329+ (filter
1330+ (lambda (x)
1331+ (and (member x lis2 =)
1332+ (member x lis3 =)
1333+ (every (lambda (lis) (member x lis =)) lists)))
1334+ lis1))])]))
1335+ (define lset-intersection!
1336+ (case-lambda
1337+ [(= lis1) (check-arg procedure? = lset-intersection!) lis1]
1338+ [(= lis1 lis2)
1339+ (check-arg procedure? = lset-intersection!)
1340+ (cond
1341+ [(or (null-list? lis2) (eq? lis1 lis2)) lis1]
1342+ [(null-list? lis1) lis2]
1343+ [else (filter! (lambda (x) (member x lis2 =)) lis1)])]
1344+ [(= lis1 lis2 lis3 . lists)
1345+ (check-arg procedure? = lset-intersection!)
1346+ (cond
1347+ [(or (null-list? lis1)
1348+ (null-list? lis2)
1349+ (null-list? lis3)
1350+ (any null-list? lists))
1351+ '()]
1352+ [(eq? lis2 lis1)
1353+ (if (eq? lis3 lis1)
1354+ (apply lset-intersection! = lis1 lists)
1355+ (apply lset-intersection! = lis1 lis3 lists))]
1356+ [(or (eq? lis3 lis1) (eq? lis3 lis2))
1357+ (apply lset-intersection! = lis1 lis2 lists)]
1358+ [else
1359+ (let ([lists (remove
1360+ (lambda (lis)
1361+ (or (eq? lis lis1)
1362+ (eq? lis lis2)
1363+ (eq? lis lis3)))
1364+ lists)])
1365+ (filter!
1366+ (lambda (x)
1367+ (and (member x lis2 =)
1368+ (member x lis3 =)
1369+ (every (lambda (lis) (member x lis =)) lists)))
1370+ lis1))])]))
1371+ (define lset-difference
1372+ (case-lambda
1373+ [(= lis1) (check-arg procedure? = lset-difference) lis1]
1374+ [(= lis1 lis2)
1375+ (check-arg procedure? = lset-difference)
1376+ (cond
1377+ [(null-list? lis2) lis1]
1378+ [(or (null-list? lis1) (eq? lis1 lis2)) '()]
1379+ [else (filter (lambda (x) (not (member x lis2 =))) lis1)])]
1380+ [(= lis1 lis2 lis3 . lists)
1381+ (check-arg procedure? = lset-difference)
1382+ (cond
1383+ [(or (null-list? lis1)
1384+ (eq? lis1 lis2)
1385+ (eq? lis1 lis3)
1386+ (memq lis1 lists))
1387+ '()]
1388+ [(null? lis2)
1389+ (if (null? lis3)
1390+ (apply lset-difference lis1 lists)
1391+ (apply lset-difference lis1 lis3 lists))]
1392+ [(or (null? lis3) (eq? lis3 lis2))
1393+ (apply lset-difference lis1 lis2 lists)]
1394+ [else
1395+ (let ([lists (remove
1396+ (lambda (lis)
1397+ (or (null? lis)
1398+ (eq? lis lis2)
1399+ (eq? lis lis3)))
1400+ lists)])
1401+ (filter
1402+ (lambda (x)
1403+ (and (not (member x lis2 =))
1404+ (not (member x lis3 =))
1405+ (every
1406+ (lambda (lis) (not (member x lis =)))
1407+ lists)))
1408+ lis1))])]))
1409+ (define lset-difference!
1410+ (case-lambda
1411+ [(= lis1) (check-arg procedure? = lset-difference!) lis1]
1412+ [(= lis1 lis2)
1413+ (check-arg procedure? = lset-difference!)
1414+ (cond
1415+ [(null-list? lis2) lis1]
1416+ [(or (null-list? lis1) (eq? lis1 lis2)) '()]
1417+ [else (filter! (lambda (x) (not (member x lis2 =))) lis1)])]
1418+ [(= lis1 lis2 lis3 . lists)
1419+ (check-arg procedure? = lset-difference!)
1420+ (cond
1421+ [(or (null-list? lis1)
1422+ (eq? lis1 lis2)
1423+ (eq? lis1 lis3)
1424+ (memq lis1 lists))
1425+ '()]
1426+ [(null? lis2)
1427+ (if (null? lis3)
1428+ (apply lset-difference lis1 lists)
1429+ (apply lset-difference lis1 lis3 lists))]
1430+ [(or (null? lis3) (eq? lis3 lis2))
1431+ (apply lset-difference lis1 lis2 lists)]
1432+ [else
1433+ (let ([lists (remove
1434+ (lambda (lis)
1435+ (or (null? lis)
1436+ (eq? lis lis2)
1437+ (eq? lis lis3)))
1438+ lists)])
1439+ (filter!
1440+ (lambda (x)
1441+ (and (not (member x lis2 =))
1442+ (every
1443+ (lambda (lis) (not (member x lis =)))
1444+ lists)))
1445+ lis1))])]))
1446+ (define lset-xor
1447+ (let ([lset-xor-2 (lambda (= b a)
1448+ (receive
1449+ (a-b a-int-b)
1450+ (lset-diff+intersection = a b)
1451+ (cond
1452+ [(null? a-b) (lset-difference = b a)]
1453+ [(null? a-int-b) (append b a)]
1454+ [else
1455+ (fold
1456+ (lambda (xb ans)
1457+ (if (member xb a-int-b =)
1458+ ans
1459+ (cons xb ans)))
1460+ a-b
1461+ b)])))])
1462+ (case-lambda
1463+ [(=) (check-arg procedure? = lset-xor) '()]
1464+ [(= a) (check-arg procedure? = lset-xor) a]
1465+ [(= a b)
1466+ (check-arg procedure? = lset-xor)
1467+ (lset-xor-2 = b a)]
1468+ [(= a b c . lists)
1469+ (check-arg procedure? = lset-xor)
1470+ (let* ([lis (lset-xor-2 = b a)] [lis (lset-xor-2 = c lis)])
1471+ (if (null? lists)
1472+ lis
1473+ (fold
1474+ (lambda (b a) (lset-xor-2 = b a))
1475+ lis
1476+ lists)))])))
1477+ (define lset-xor!
1478+ (let ([lset-xor-2! (lambda (= b a)
1479+ (receive
1480+ (a-b a-int-b)
1481+ (lset-diff+intersection! = a b)
1482+ (cond
1483+ [(null? a-b) (lset-difference! = b a)]
1484+ [(null? a-int-b) (append! b a)]
1485+ [else
1486+ (pair-fold
1487+ (lambda (b-pair ans)
1488+ (if (member (car b-pair) a-int-b =)
1489+ ans
1490+ (begin
1491+ (set-cdr! b-pair ans)
1492+ b-pair)))
1493+ a-b
1494+ b)])))])
1495+ (case-lambda
1496+ [(=) (check-arg procedure? = lset-xor!) '()]
1497+ [(= a) (check-arg procedure? = lset-xor!) a]
1498+ [(= a b)
1499+ (check-arg procedure? = lset-xor!)
1500+ (lset-xor-2! = b a)]
1501+ [(= a b c . lists)
1502+ (check-arg procedure? = lset-xor!)
1503+ (let* ([lis (lset-xor-2! = b a)]
1504+ [lis (lset-xor-2! = c lis)])
1505+ (if (null? lists)
1506+ lis
1507+ (fold
1508+ (lambda (b a) (lset-xor-2! = b a))
1509+ lis
1510+ lists)))])))
1511+ (define lset-diff+intersection
1512+ (case-lambda
1513+ [(= lis1)
1514+ (check-arg procedure? = lset-diff+intersection)
1515+ (values lis1 '())]
1516+ [(= lis1 lis2)
1517+ (check-arg procedure? = lset-diff+intersection)
1518+ (cond
1519+ [(or (null-list? lis1) (eq? lis1 lis2)) (values '() lis1)]
1520+ [(null-list? lis2) (values lis1 '())]
1521+ [else
1522+ (partition
1523+ (lambda (elt) (not (member elt lis2 =)))
1524+ lis1)])]
1525+ [(= lis1 lis2 lis3 . lists)
1526+ (check-arg procedure? = lset-diff+intersection)
1527+ (cond
1528+ [(or (null-list? lis1)
1529+ (eq? lis1 lis2)
1530+ (eq? lis1 lis3)
1531+ (memq lis1 lists))
1532+ (values '() lis1)]
1533+ [(null-list? lis2)
1534+ (if (null-list? lis3)
1535+ (apply lset-diff+intersection = lis1 lists)
1536+ (apply lset-diff+intersection = lis1 lis3 lists))]
1537+ [(or (null-list? lis3) (eq? lis3 lis2))
1538+ (apply lset-diff+intersection = lis1 lis2 lists)]
1539+ [else
1540+ (let ([lists (remove
1541+ (lambda (lis)
1542+ (or (null? lis)
1543+ (eq? lis lis2)
1544+ (eq? lis lis3)))
1545+ lists)])
1546+ (partition
1547+ (lambda (elt)
1548+ (not (or (member elt lis2 =)
1549+ (member elt lis3 =)
1550+ (any (lambda (lis) (member elt lis =))
1551+ lists))))
1552+ lis1))])]))
1553+ (define lset-diff+intersection!
1554+ (case-lambda
1555+ [(= lis1)
1556+ (check-arg procedure? = lset-diff+intersection!)
1557+ (values lis1 '())]
1558+ [(= lis1 lis2)
1559+ (check-arg procedure? = lset-diff+intersection!)
1560+ (cond
1561+ [(or (null-list? lis1) (eq? lis1 lis2)) (values '() lis1)]
1562+ [(null-list? lis2) (values lis1 '())]
1563+ [else
1564+ (partition!
1565+ (lambda (elt) (not (member elt lis2 =)))
1566+ lis1)])]
1567+ [(= lis1 lis2 lis3 . lists)
1568+ (check-arg procedure? = lset-diff+intersection!)
1569+ (cond
1570+ [(or (null-list? lis1)
1571+ (eq? lis1 lis2)
1572+ (eq? lis1 lis3)
1573+ (memq lis1 lists))
1574+ (values '() lis1)]
1575+ [(null-list? lis2)
1576+ (if (null-list? lis3)
1577+ (apply lset-diff+intersection! = lis1 lists)
1578+ (apply lset-diff+intersection! = lis1 lis3 lists))]
1579+ [(or (null-list? lis3) (eq? lis3 lis2))
1580+ (apply lset-diff+intersection = lis1 lis2 lists)]
1581+ [else
1582+ (let ([lists (remove
1583+ (lambda (lis)
1584+ (or (null? lis)
1585+ (eq? lis lis2)
1586+ (eq? lis lis3)))
1587+ lists)])
1588+ (partition!
1589+ (lambda (elt)
1590+ (not (or (member elt lis2 =)
1591+ (member elt lis3 =)
1592+ (any (lambda (lis) (member elt lis =))
1593+ lists))))
1594+ lis1))])]))))))
lib/srfi/:126.slsnew file+23
@@ -0,0 +1,23 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a126.sls
7+(library (srfi :126)
8+ (export make-eq-hashtable make-eqv-hashtable make-hashtable
9+ alist->eq-hashtable alist->eqv-hashtable alist->hashtable
10+ weakness hashtable? hashtable-size hashtable-ref
11+ hashtable-set! hashtable-delete! hashtable-contains?
12+ hashtable-lookup hashtable-update! hashtable-intern!
13+ hashtable-copy hashtable-clear! hashtable-empty-copy
14+ hashtable-keys hashtable-values hashtable-entries
15+ hashtable-key-list hashtable-value-list
16+ hashtable-entry-lists hashtable-walk hashtable-update-all!
17+ hashtable-prune! hashtable-merge! hashtable-sum
18+ hashtable-map->lset hashtable-find hashtable-empty?
19+ hashtable-pop! hashtable-inc! hashtable-dec!
20+ hashtable-equivalence-function hashtable-hash-function
21+ hashtable-weakness hashtable-mutable? hash-salt equal-hash
22+ string-hash string-ci-hash symbol-hash)
23+ (import (srfi :126 r6rs-hashtables)))
lib/srfi/:128.slsnew file+19
@@ -0,0 +1,19 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a128.sls
7+(library (srfi :128)
8+ (export comparator? comparator-ordered? comparator-hashable?
9+ make-comparator make-pair-comparator make-list-comparator
10+ make-vector-comparator make-eq-comparator
11+ make-eqv-comparator make-equal-comparator boolean-hash
12+ char-hash char-ci-hash string-hash string-ci-hash
13+ symbol-hash number-hash make-default-comparator default-hash
14+ comparator-register-default! comparator-type-test-predicate
15+ comparator-equality-predicate comparator-ordering-predicate
16+ comparator-hash-function comparator-test-type
17+ comparator-check-type comparator-hash hash-bound hash-salt
18+ =? <? >? <=? >=? comparator-if<=>)
19+ (import (srfi :128 comparators)))
lib/srfi/:133.slsnew file+17
@@ -0,0 +1,17 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a133.sls
7+(library (srfi :133)
8+ (export vector-unfold vector-unfold-right vector-reverse-copy
9+ vector-concatenate vector-append-subvectors vector-empty?
10+ vector= vector-fold vector-fold-right vector-map!
11+ vector-count vector-cumulate vector-index vector-index-right
12+ vector-skip vector-skip-right vector-binary-search
13+ vector-any vector-every vector-partition vector-swap!
14+ vector-reverse! vector-reverse-copy! vector-unfold!
15+ vector-unfold-right! reverse-vector->list
16+ reverse-list->vector)
17+ (import (srfi :133 vectors)))
lib/srfi/:133/vectors.slsnew file+885
@@ -0,0 +1,885 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a133/vectors.sls
7+;;;;;; File header: %3a133/vectors-impl.scm
8+;;;;;; SRFI 43: Vector library -*- Scheme -*-
9+;;;
10+;;; $Id$
11+;;;
12+;;; Taylor Campbell wrote this code; he places it in the public domain.
13+;;; Will Clinger [wdc] made some corrections, also in the public domain.
14+;;; John Cowan modified this code for SRFI 133; his changes are also in
15+;;; the public domain. However, in jurisdictions where it is not possible
16+;;; to dedicate something to the public domain, the entire implementation
17+;;; is made available under the same license as SRFI 133.
18+(library (srfi :133 vectors)
19+ (export vector-unfold vector-unfold-right vector-copy
20+ vector-reverse-copy vector-append vector-concatenate
21+ vector-append-subvectors vector-empty? vector= vector-fold
22+ vector-fold-right vector-map vector-map! vector-for-each
23+ vector-count vector-cumulate vector-index vector-skip
24+ vector-index-right vector-skip-right vector-binary-search
25+ vector-any vector-every vector-partition vector-swap!
26+ vector-fill! vector-reverse! vector-copy!
27+ vector-reverse-copy! vector-unfold! vector-unfold-right!
28+ vector->list reverse-vector->list list->vector
29+ reverse-list->vector vector->string string->vector)
30+ (import
31+ (rename
32+ (rnrs)
33+ (vector-fill! rnrs:vector-fill!)
34+ (vector->list rnrs:vector->list)
35+ (list->vector rnrs:list->vector))
36+ (rnrs mutable-strings)
37+ (srfi private include))
38+ (begin
39+ (define-syntax receive
40+ (syntax-rules ()
41+ [(receive ?formals ?producer ?body1 ?body2 ...)
42+ (call-with-values
43+ (lambda () ?producer)
44+ (lambda ?formals ?body1 ?body2 ...))]))
45+ (define-syntax let*-optionals
46+ (syntax-rules ()
47+ [(let*-optionals (?x ...) ((?var ?default) ...) ?body1
48+ ?body2 ...)
49+ (let ([args (?x ...)])
50+ (let*-optionals args ((?var ?default) ...) ?body1 ?body2
51+ ...))]
52+ [(let*-optionals ?args ((?var ?default) ...) ?body1 ?body2
53+ ...)
54+ (let*-optionals:aux ?args ?args ((?var ?default) ...) ?body1
55+ ?body2 ...)]))
56+ (define-syntax let*-optionals:aux
57+ (syntax-rules ()
58+ [(aux ?orig-args-var ?args-var () ?body1 ?body2 ...)
59+ (if (null? ?args-var)
60+ (let () ?body1 ?body2 ...)
61+ (error "too many arguments"
62+ (length ?orig-args-var)
63+ ?orig-args-var))]
64+ [(aux ?orig-args-var ?args-var ((?var ?default) ?more ...)
65+ ?body1 ?body2 ...)
66+ (if (null? ?args-var)
67+ (let* ([?var ?default] ?more ...) ?body1 ?body2 ...)
68+ (let ([?var (car ?args-var)] [new-args (cdr ?args-var)])
69+ (let*-optionals:aux ?orig-args-var new-args (?more ...)
70+ ?body1 ?body2 ...)))]))
71+ (define (nonneg-int? x)
72+ (and (integer? x) (not (negative? x))))
73+ (define (between? x y z) (and (< x y) (<= y z)))
74+ (define (unspecified-value) (if #f #f))
75+ (define (vectors-ref vectors i)
76+ (map (lambda (v) (vector-ref v i)) vectors))
77+ (define (check-type pred? value callee)
78+ (if (pred? value)
79+ value
80+ (check-type
81+ pred?
82+ (error "erroneous value"
83+ (list pred? value)
84+ `(while calling ,callee))
85+ callee)))
86+ (define (check-index vec index callee)
87+ (let ([index (check-type integer? index callee)])
88+ (cond
89+ [(< index 0)
90+ (check-index
91+ vec
92+ (error "vector index too low"
93+ index
94+ `(into vector ,vec)
95+ `(while calling ,callee))
96+ callee)]
97+ [(>= index (vector-length vec))
98+ (check-index
99+ vec
100+ (error "vector index too high"
101+ index
102+ `(into vector ,vec)
103+ `(while calling ,callee))
104+ callee)]
105+ [else index])))
106+ (define (check-indices vec start start-name end end-name
107+ callee)
108+ (let ([lose (lambda things
109+ (apply
110+ error
111+ "vector range out of bounds"
112+ (append things `(vector was ,vec) `(,start-name was ,start)
113+ `(,end-name was ,end) `(while calling ,callee))))]
114+ [start (check-type integer? start callee)]
115+ [end (check-type integer? end callee)])
116+ (cond
117+ [(> start end)
118+ (receive
119+ (new-start new-end)
120+ (lose `(,end-name < ,start-name))
121+ (check-indices vec new-start start-name new-end end-name
122+ callee))]
123+ [(< start 0)
124+ (check-indices vec (lose `(,start-name < 0)) start-name end
125+ end-name callee)]
126+ [(>= start (vector-length vec))
127+ (check-indices vec
128+ (lose `(,start-name > len) `(len was ,(vector-length vec)))
129+ start-name end end-name callee)]
130+ [(> end (vector-length vec))
131+ (check-indices vec start start-name
132+ (lose `(,end-name > len) `(len was ,(vector-length vec)))
133+ end-name callee)]
134+ [else (values start end)])))
135+ (define (vector-parse-start+end vec args start-name end-name
136+ callee)
137+ (let ([len (vector-length vec)])
138+ (cond
139+ [(null? args) (values 0 len)]
140+ [(null? (cdr args))
141+ (check-indices vec (car args) start-name len end-name
142+ callee)]
143+ [(null? (cddr args))
144+ (check-indices vec (car args) start-name (cadr args)
145+ end-name callee)]
146+ [else
147+ (error "too many arguments"
148+ `(extra args were ,(cddr args))
149+ `(while calling ,callee))])))
150+ (define-syntax let-vector-start+end
151+ (syntax-rules ()
152+ [(let-vector-start+end ?callee ?vec ?args (?start ?end)
153+ ?body1 ?body2 ...)
154+ (let ([?vec (check-type vector? ?vec ?callee)])
155+ (receive (?start ?end)
156+ (vector-parse-start+end ?vec ?args '?start '?end ?callee)
157+ ?body1 ?body2 ...))]))
158+ (define %smallest-length
159+ (letrec ([loop (lambda (vector-list length callee)
160+ (if (null? vector-list)
161+ length
162+ (loop
163+ (cdr vector-list)
164+ (min (vector-length
165+ (check-type
166+ vector?
167+ (car vector-list)
168+ callee))
169+ length)
170+ callee)))])
171+ loop))
172+ (define %vector-copy!
173+ (letrec ([loop/l->r (lambda (target source send i j)
174+ (cond
175+ [(< i send)
176+ (vector-set! target j (vector-ref source i))
177+ (loop/l->r target source send (+ i 1)
178+ (+ j 1))]))]
179+ [loop/r->l (lambda (target source sstart i j)
180+ (cond
181+ [(>= i sstart)
182+ (vector-set! target j (vector-ref source i))
183+ (loop/r->l target source sstart (- i 1)
184+ (- j 1))]))])
185+ (lambda (target tstart source sstart send)
186+ (if (> sstart tstart)
187+ (loop/l->r target source send sstart tstart)
188+ (loop/r->l target source sstart (- send 1)
189+ (+ -1 tstart send (- sstart)))))))
190+ (define %vector-reverse-copy!
191+ (letrec ([loop (lambda (target source sstart i j)
192+ (cond
193+ [(>= i sstart)
194+ (vector-set! target j (vector-ref source i))
195+ (loop target source sstart (- i 1) (+ j 1))]))])
196+ (lambda (target tstart source sstart send)
197+ (loop target source sstart (- send 1) tstart))))
198+ (define %vector-reverse!
199+ (letrec ([loop (lambda (vec i j)
200+ (cond
201+ [(<= i j)
202+ (let ([v (vector-ref vec i)])
203+ (vector-set! vec i (vector-ref vec j))
204+ (vector-set! vec j v)
205+ (loop vec (+ i 1) (- j 1)))]))])
206+ (lambda (vec start end) (loop vec start (- end 1)))))
207+ (define %vector-fold1
208+ (letrec ([loop (lambda (kons knil len vec i)
209+ (if (= i len)
210+ knil
211+ (loop kons (kons knil (vector-ref vec i)) len
212+ vec (+ i 1))))])
213+ (lambda (kons knil len vec) (loop kons knil len vec 0))))
214+ (define %vector-fold2+
215+ (letrec ([loop (lambda (kons knil len vectors i)
216+ (if (= i len)
217+ knil
218+ (loop kons
219+ (apply kons knil (vectors-ref vectors i)) len
220+ vectors (+ i 1))))])
221+ (lambda (kons knil len vectors)
222+ (loop kons knil len vectors 0))))
223+ (define %vector-map1!
224+ (letrec ([loop (lambda (f target vec i)
225+ (if (zero? i)
226+ target
227+ (let ([j (- i 1)])
228+ (vector-set! target j (f (vector-ref vec j)))
229+ (loop f target vec j))))])
230+ (lambda (f target vec len) (loop f target vec len))))
231+ (define %vector-map2+!
232+ (letrec ([loop (lambda (f target vectors i)
233+ (if (zero? i)
234+ target
235+ (let ([j (- i 1)])
236+ (vector-set!
237+ target
238+ j
239+ (apply f (vectors-ref vectors j)))
240+ (loop f target vectors j))))])
241+ (lambda (f target vectors len)
242+ (loop f target vectors len))))
243+ (define (vector-unfold f length . initial-seeds)
244+ (define vec (make-vector length))
245+ (apply vector-unfold! f vec 0 length initial-seeds)
246+ vec)
247+ (define vector-unfold!
248+ (letrec ([tabulate! (lambda (f vec i len)
249+ (cond
250+ [(< i len)
251+ (vector-set! vec i (f i))
252+ (tabulate! f vec (+ i 1) len)]))]
253+ [unfold1! (lambda (f vec i len seed)
254+ (if (< i len)
255+ (receive
256+ (elt new-seed)
257+ (f i seed)
258+ (vector-set! vec i elt)
259+ (unfold1! f vec (+ i 1) len new-seed))))]
260+ [unfold2+! (lambda (f vec i len seeds)
261+ (if (< i len)
262+ (receive
263+ (elt . new-seeds)
264+ (apply f i seeds)
265+ (vector-set! vec i elt)
266+ (unfold2+! f vec (+ i 1) len
267+ new-seeds))))])
268+ (lambda (f vec start end . initial-seeds)
269+ (let ([f (check-type procedure? f vector-unfold!)]
270+ [start (check-type nonneg-int? start vector-unfold!)]
271+ [end (check-type nonneg-int? end vector-unfold!)])
272+ (let ()
273+ (cond
274+ [(null? initial-seeds) (tabulate! f vec start end)]
275+ [(null? (cdr initial-seeds))
276+ (unfold1! f vec start end (car initial-seeds))]
277+ [else (unfold2+! f vec start end initial-seeds)]))))))
278+ (define (vector-unfold-right f len . initial-seeds)
279+ (define vec (make-vector len))
280+ (apply vector-unfold-right! f vec 0 len initial-seeds)
281+ vec)
282+ (define (vector-unfold-right! f vec start end .
283+ initial-seeds)
284+ (letrec ([tabulate! (lambda (f vec i)
285+ (cond
286+ [(>= i start)
287+ (vector-set! vec i (f i))
288+ (tabulate! f vec (- i 1))]))]
289+ [unfold1! (lambda (f vec i seed)
290+ (if (>= i start)
291+ (receive
292+ (elt new-seed)
293+ (f i seed)
294+ (vector-set! vec i elt)
295+ (unfold1! f vec (- i 1) new-seed))))]
296+ [unfold2+! (lambda (f vec i seeds)
297+ (if (>= i start)
298+ (receive
299+ (elt . new-seeds)
300+ (apply f i seeds)
301+ (vector-set! vec i elt)
302+ (unfold2+! f vec (- i 1) new-seeds))))])
303+ (let ([f (check-type procedure? f vector-unfold-right!)]
304+ [start (check-type nonneg-int? start vector-unfold-right!)]
305+ [end (check-type nonneg-int? end vector-unfold-right!)])
306+ (let ([i (- end 1)])
307+ (cond
308+ [(null? initial-seeds) (tabulate! f vec i)]
309+ [(null? (cdr initial-seeds))
310+ (unfold1! f vec i (car initial-seeds))]
311+ [else (unfold2+! f vec i initial-seeds)])))))
312+ (define (vector-copy vec . args)
313+ (let ([vec (check-type vector? vec vector-copy)])
314+ (receive
315+ (start end fill)
316+ (vector-copy:parse-args vec args)
317+ (let ([new-vector (make-vector (- end start) fill)])
318+ (%vector-copy! new-vector 0 vec start
319+ (if (> end (vector-length vec)) (vector-length vec) end))
320+ new-vector))))
321+ (define (vector-copy:parse-args vec args)
322+ (define (parse-args start end n fill)
323+ (let ([start (check-type nonneg-int? start vector-copy)]
324+ [end (check-type nonneg-int? end vector-copy)])
325+ (cond
326+ [(and (<= 0 start end) (<= start n))
327+ (values start end fill)]
328+ [else
329+ (error "illegal arguments"
330+ `(while calling ,vector-copy)
331+ `(start was ,start)
332+ `(end was ,end)
333+ `(vector was ,vec))])))
334+ (let ([n (vector-length vec)])
335+ (cond
336+ [(null? args) (parse-args 0 n n (unspecified-value))]
337+ [(null? (cdr args))
338+ (parse-args (car args) n n (unspecified-value))]
339+ [(null? (cddr args))
340+ (parse-args (car args) (cadr args) n (unspecified-value))]
341+ [(null? (cdddr args))
342+ (parse-args (car args) (cadr args) n (caddr args))]
343+ [else
344+ (error "too many arguments" vector-copy (cdddr args))])))
345+ (define (vector-reverse-copy vec . maybe-start+end)
346+ (let-vector-start+end vector-reverse-copy vec maybe-start+end (start end)
347+ (let ([new (make-vector (- end start))])
348+ (%vector-reverse-copy! new 0 vec start end)
349+ new)))
350+ (define (vector-append . vectors)
351+ (vector-concatenate:aux vectors vector-append))
352+ (define (vector-concatenate vector-list)
353+ (vector-concatenate:aux vector-list vector-concatenate))
354+ (define vector-concatenate:aux
355+ (letrec ([compute-length (lambda (vectors len callee)
356+ (if (null? vectors)
357+ len
358+ (let ([vec (check-type
359+ vector?
360+ (car vectors)
361+ callee)])
362+ (compute-length
363+ (cdr vectors)
364+ (+ (vector-length vec) len)
365+ callee))))]
366+ [concatenate! (lambda (vectors target to)
367+ (if (null? vectors)
368+ target
369+ (let* ([vec1 (car vectors)]
370+ [len (vector-length vec1)])
371+ (%vector-copy! target to vec1 0 len)
372+ (concatenate!
373+ (cdr vectors)
374+ target
375+ (+ to len)))))])
376+ (lambda (vectors callee)
377+ (cond
378+ [(null? vectors) (make-vector 0)]
379+ [(null? (cdr vectors))
380+ (let* ([vec (check-type vector? (car vectors) callee)]
381+ [len (vector-length vec)]
382+ [new (make-vector len)])
383+ (%vector-copy! new 0 vec 0 len)
384+ new)]
385+ [else
386+ (let ([new-vector (make-vector
387+ (compute-length vectors 0 callee))])
388+ (concatenate! vectors new-vector 0)
389+ new-vector)]))))
390+ (define (vector-append-subvectors . args)
391+ (define (gather-args args)
392+ (let loop ([args args] [vecs '()] [starts '()] [ends '()])
393+ (if (null? args)
394+ (values (reverse vecs) (reverse starts) (reverse ends))
395+ (loop
396+ (cdddr args)
397+ (cons (car args) vecs)
398+ (cons (cadr args) starts)
399+ (cons (caddr args) ends)))))
400+ (define (total-length starts ends)
401+ (let loop ([count 0] [starts starts] [ends ends])
402+ (if (null? starts)
403+ count
404+ (let ([start (car starts)] [end (car ends)])
405+ (loop (+ count (- end start)) (cdr starts) (cdr ends))))))
406+ (define (copy-each! result vecs starts ends)
407+ (let loop ([at 0] [vecs vecs] [starts starts] [ends ends])
408+ (if (null? vecs)
409+ result
410+ (let ([vec (car vecs)]
411+ [start (car starts)]
412+ [end (car ends)])
413+ (%vector-copy! result at vec start end)
414+ (loop
415+ (+ at (- end start))
416+ (cdr vecs)
417+ (cdr starts)
418+ (cdr ends))))))
419+ (receive
420+ (vecs starts ends)
421+ (gather-args args)
422+ (define result (make-vector (total-length starts ends)))
423+ (copy-each! result vecs starts ends)))
424+ (define (vector-empty? vec)
425+ (let ([vec (check-type vector? vec vector-empty?)])
426+ (zero? (vector-length vec))))
427+ (define (vector= elt=? . vectors)
428+ (let ([elt=? (check-type procedure? elt=? vector=)])
429+ (cond
430+ [(null? vectors) #t]
431+ [(null? (cdr vectors))
432+ (check-type vector? (car vectors) vector=)
433+ #t]
434+ [else
435+ (let loop ([vecs vectors])
436+ (let ([vec1 (check-type vector? (car vecs) vector=)]
437+ [vec2+ (cdr vecs)])
438+ (or (null? vec2+)
439+ (and (binary-vector= elt=? vec1 (car vec2+))
440+ (loop vec2+)))))])))
441+ (define (binary-vector= elt=? vector-a vector-b)
442+ (or (eq? vector-a vector-b)
443+ (let ([length-a (vector-length vector-a)]
444+ [length-b (vector-length vector-b)])
445+ (letrec ([loop (lambda (i)
446+ (or (= i length-a)
447+ (and (< i length-b)
448+ (test
449+ (vector-ref vector-a i)
450+ (vector-ref vector-b i)
451+ i))))]
452+ [test (lambda (elt-a elt-b i)
453+ (and (or (eq? elt-a elt-b)
454+ (elt=? elt-a elt-b))
455+ (loop (+ i 1))))])
456+ (and (= length-a length-b) (loop 0))))))
457+ (define (vector-fold kons knil vec . vectors)
458+ (let ([kons (check-type procedure? kons vector-fold)]
459+ [vec (check-type vector? vec vector-fold)])
460+ (if (null? vectors)
461+ (%vector-fold1 kons knil (vector-length vec) vec)
462+ (%vector-fold2+
463+ kons
464+ knil
465+ (%smallest-length vectors (vector-length vec) vector-fold)
466+ (cons vec vectors)))))
467+ (define vector-fold-right
468+ (letrec ([loop1 (lambda (kons knil vec i)
469+ (if (negative? i)
470+ knil
471+ (loop1
472+ kons
473+ (kons knil (vector-ref vec i))
474+ vec
475+ (- i 1))))]
476+ [loop2+ (lambda (kons knil vectors i)
477+ (if (negative? i)
478+ knil
479+ (loop2+
480+ kons
481+ (apply kons knil (vectors-ref vectors i))
482+ vectors
483+ (- i 1))))])
484+ (lambda (kons knil vec . vectors)
485+ (let ([kons (check-type procedure? kons vector-fold-right)]
486+ [vec (check-type vector? vec vector-fold-right)])
487+ (if (null? vectors)
488+ (loop1 kons knil vec (- (vector-length vec) 1))
489+ (loop2+
490+ kons
491+ knil
492+ (cons vec vectors)
493+ (- (%smallest-length
494+ vectors
495+ (vector-length vec)
496+ vector-fold-right)
497+ 1)))))))
498+ (define (vector-map! f vec . vectors)
499+ (let ([f (check-type procedure? f vector-map!)]
500+ [vec (check-type vector? vec vector-map!)])
501+ (if (null? vectors)
502+ (%vector-map1! f vec vec (vector-length vec))
503+ (%vector-map2+!
504+ f
505+ vec
506+ (cons vec vectors)
507+ (%smallest-length vectors (vector-length vec) vector-map!)))
508+ (unspecified-value)))
509+ (define (vector-count pred? vec . vectors)
510+ (let ([pred? (check-type procedure? pred? vector-count)]
511+ [vec (check-type vector? vec vector-count)])
512+ (if (null? vectors)
513+ (%vector-fold1
514+ (lambda (count elt) (if (pred? elt) (+ count 1) count))
515+ 0
516+ (vector-length vec)
517+ vec)
518+ (%vector-fold2+
519+ (lambda (count . elts)
520+ (if (apply pred? elts) (+ count 1) count))
521+ 0
522+ (%smallest-length vectors (vector-length vec) vector-count)
523+ (cons vec vectors)))))
524+ (define (vector-cumulate f vec knil)
525+ (let* ([len (vector-length vec)] [result (make-vector len)])
526+ (let loop ([i 0] [left knil])
527+ (if (= i len)
528+ result
529+ (let* ([right (vector-ref vec i)] [r (f left right)])
530+ (vector-set! result i r)
531+ (loop (+ i 1) r))))))
532+ (define (vector-index pred? vec . vectors)
533+ (vector-index/skip pred? vec vectors vector-index))
534+ (define (vector-skip pred? vec . vectors)
535+ (vector-index/skip
536+ (lambda elts (not (apply pred? elts)))
537+ vec
538+ vectors
539+ vector-skip))
540+ (define vector-index/skip
541+ (letrec ([loop1 (lambda (pred? vec len i)
542+ (cond
543+ [(= i len) #f]
544+ [(pred? (vector-ref vec i)) i]
545+ [else (loop1 pred? vec len (+ i 1))]))]
546+ [loop2+ (lambda (pred? vectors len i)
547+ (cond
548+ [(= i len) #f]
549+ [(apply pred? (vectors-ref vectors i)) i]
550+ [else (loop2+ pred? vectors len (+ i 1))]))])
551+ (lambda (pred? vec vectors callee)
552+ (let ([pred? (check-type procedure? pred? callee)]
553+ [vec (check-type vector? vec callee)])
554+ (if (null? vectors)
555+ (loop1 pred? vec (vector-length vec) 0)
556+ (loop2+
557+ pred?
558+ (cons vec vectors)
559+ (%smallest-length vectors (vector-length vec) callee)
560+ 0))))))
561+ (define (vector-index-right pred? vec . vectors)
562+ (vector-index/skip-right
563+ pred?
564+ vec
565+ vectors
566+ vector-index-right))
567+ (define (vector-skip-right pred? vec . vectors)
568+ (vector-index/skip-right
569+ (lambda elts (not (apply pred? elts)))
570+ vec
571+ vectors
572+ vector-index-right))
573+ (define vector-index/skip-right
574+ (letrec ([loop1 (lambda (pred? vec i)
575+ (cond
576+ [(negative? i) #f]
577+ [(pred? (vector-ref vec i)) i]
578+ [else (loop1 pred? vec (- i 1))]))]
579+ [loop2+ (lambda (pred? vectors i)
580+ (cond
581+ [(negative? i) #f]
582+ [(apply pred? (vectors-ref vectors i)) i]
583+ [else (loop2+ pred? vectors (- i 1))]))])
584+ (lambda (pred? vec vectors callee)
585+ (let ([pred? (check-type procedure? pred? callee)]
586+ [vec (check-type vector? vec callee)])
587+ (if (null? vectors)
588+ (loop1 pred? vec (- (vector-length vec) 1))
589+ (loop2+
590+ pred?
591+ (cons vec vectors)
592+ (- (%smallest-length vectors (vector-length vec) callee)
593+ 1)))))))
594+ (define (vector-binary-search vec value cmp .
595+ maybe-start+end)
596+ (let ([cmp (check-type
597+ procedure?
598+ cmp
599+ vector-binary-search)])
600+ (let-vector-start+end vector-binary-search vec maybe-start+end (start end)
601+ (let loop ([start start] [end end] [j #f])
602+ (let ([i (div (+ start end) 2)])
603+ (if (or (= start end) (and j (= i j)))
604+ #f
605+ (let ([comparison (check-type
606+ integer?
607+ (cmp (vector-ref vec i) value)
608+ `(,cmp for ,vector-binary-search))])
609+ (cond
610+ [(zero? comparison) i]
611+ [(positive? comparison) (loop start i i)]
612+ [else (loop i end i)]))))))))
613+ (define vector-any
614+ (letrec ([loop1 (lambda (pred? vec i len len-1)
615+ (and (not (= i len))
616+ (if (= i len-1)
617+ (pred? (vector-ref vec i))
618+ (or (pred? (vector-ref vec i))
619+ (loop1 pred? vec (+ i 1) len
620+ len-1)))))]
621+ [loop2+ (lambda (pred? vectors i len len-1)
622+ (and (not (= i len))
623+ (if (= i len-1)
624+ (apply pred? (vectors-ref vectors i))
625+ (or (apply pred? (vectors-ref vectors i))
626+ (loop2+ pred? vectors (+ i 1) len
627+ len-1)))))])
628+ (lambda (pred? vec . vectors)
629+ (let ([pred? (check-type procedure? pred? vector-any)]
630+ [vec (check-type vector? vec vector-any)])
631+ (if (null? vectors)
632+ (let ([len (vector-length vec)])
633+ (loop1 pred? vec 0 len (- len 1)))
634+ (let ([len (%smallest-length
635+ vectors
636+ (vector-length vec)
637+ vector-any)])
638+ (loop2+ pred? (cons vec vectors) 0 len (- len 1))))))))
639+ (define vector-every
640+ (letrec ([loop1 (lambda (pred? vec i len len-1)
641+ (or (= i len)
642+ (if (= i len-1)
643+ (pred? (vector-ref vec i))
644+ (and (pred? (vector-ref vec i))
645+ (loop1 pred? vec (+ i 1) len
646+ len-1)))))]
647+ [loop2+ (lambda (pred? vectors i len len-1)
648+ (or (= i len)
649+ (if (= i len-1)
650+ (apply pred? (vectors-ref vectors i))
651+ (and (apply pred? (vectors-ref vectors i))
652+ (loop2+ pred? vectors (+ i 1) len
653+ len-1)))))])
654+ (lambda (pred? vec . vectors)
655+ (let ([pred? (check-type procedure? pred? vector-every)]
656+ [vec (check-type vector? vec vector-every)])
657+ (if (null? vectors)
658+ (let ([len (vector-length vec)])
659+ (loop1 pred? vec 0 len (- len 1)))
660+ (let ([len (%smallest-length
661+ vectors
662+ (vector-length vec)
663+ vector-every)])
664+ (loop2+ pred? (cons vec vectors) 0 len (- len 1))))))))
665+ (define (vector-partition pred? vec)
666+ (let* ([len (vector-length vec)]
667+ [cnt (vector-count pred? vec)]
668+ [result (make-vector len)])
669+ (let loop ([i 0] [yes 0] [no cnt])
670+ (if (= i len)
671+ (values result cnt)
672+ (let ([elem (vector-ref vec i)])
673+ (if (pred? elem)
674+ (begin
675+ (vector-set! result yes elem)
676+ (loop (+ i 1) (+ yes 1) no))
677+ (begin
678+ (vector-set! result no elem)
679+ (loop (+ i 1) yes (+ no 1)))))))))
680+ (define (vector-swap! vec i j)
681+ (let ([vec (check-type vector? vec vector-swap!)])
682+ (let ([i (check-index vec i vector-swap!)]
683+ [j (check-index vec j vector-swap!)])
684+ (let ([x (vector-ref vec i)])
685+ (vector-set! vec i (vector-ref vec j))
686+ (vector-set! vec j x)))))
687+ (define $check-types
688+ (case-lambda
689+ [(who v start)
690+ (check-type vector? v who)
691+ (check-indices v start 'start (vector-length v) 'end who)]
692+ [(who v start end)
693+ (check-type vector? v who)
694+ (check-indices v start 'start end 'end who)]))
695+ (define vector-fill!
696+ (let ()
697+ (define $vector-fill!
698+ (lambda (vec value start end)
699+ (do ([i start (+ i 1)])
700+ ((= i end))
701+ (vector-set! vec i value))))
702+ (case-lambda
703+ [(vec value) (rnrs:vector-fill! vec value)]
704+ [(vec value start)
705+ ($check-types 'vector-fill! vec start)
706+ ($vector-fill! vec value start (vector-length vec))]
707+ [(vec value start end)
708+ ($check-types 'vector-fill! vec start end)
709+ ($vector-fill! vec value start end)])))
710+ (define (vector-copy! target tstart source .
711+ maybe-sstart+send)
712+ (define (doit! sstart send source-length)
713+ (let ([tstart (check-type nonneg-int? tstart vector-copy!)]
714+ [sstart (check-type nonneg-int? sstart vector-copy!)]
715+ [send (check-type nonneg-int? send vector-copy!)])
716+ (cond
717+ [(and (<= 0 sstart send source-length)
718+ (<= (+ tstart (- send sstart)) (vector-length target)))
719+ (%vector-copy! target tstart source sstart send)]
720+ [else
721+ (error "illegal arguments"
722+ `(while calling ,vector-copy!)
723+ `(target was ,target)
724+ `(target-length was ,(vector-length target))
725+ `(tstart was ,tstart)
726+ `(source was ,source)
727+ `(source-length was ,source-length)
728+ `(sstart was ,sstart)
729+ `(send was ,send))])))
730+ (let ([n (vector-length source)])
731+ (cond
732+ [(null? maybe-sstart+send) (doit! 0 n n)]
733+ [(null? (cdr maybe-sstart+send))
734+ (doit! (car maybe-sstart+send) n n)]
735+ [(null? (cddr maybe-sstart+send))
736+ (doit! (car maybe-sstart+send) (cadr maybe-sstart+send) n)]
737+ [else
738+ (error "too many arguments"
739+ vector-copy!
740+ (cddr maybe-sstart+send))])))
741+ (define (vector-reverse-copy! target tstart source .
742+ maybe-sstart+send)
743+ (define (doit! sstart send source-length)
744+ (let ([tstart (check-type
745+ nonneg-int?
746+ tstart
747+ vector-reverse-copy!)]
748+ [sstart (check-type
749+ nonneg-int?
750+ sstart
751+ vector-reverse-copy!)]
752+ [send (check-type nonneg-int? send vector-reverse-copy!)])
753+ (cond
754+ [(and (eq? target source)
755+ (or (between? sstart tstart send)
756+ (between? tstart sstart (+ tstart (- send sstart)))))
757+ (error "vector range for self-copying overlaps"
758+ vector-reverse-copy!
759+ `(vector was ,target)
760+ `(tstart was ,tstart)
761+ `(sstart was ,sstart)
762+ `(send was ,send))]
763+ [(and (<= 0 sstart send source-length)
764+ (<= (+ tstart (- send sstart)) (vector-length target)))
765+ (%vector-reverse-copy! target tstart source sstart send)]
766+ [else
767+ (error "illegal arguments"
768+ `(while calling ,vector-reverse-copy!)
769+ `(target was ,target)
770+ `(target-length was ,(vector-length target))
771+ `(tstart was ,tstart)
772+ `(source was ,source)
773+ `(source-length was ,source-length)
774+ `(sstart was ,sstart)
775+ `(send was ,send))])))
776+ (let ([n (vector-length source)])
777+ (cond
778+ [(null? maybe-sstart+send) (doit! 0 n n)]
779+ [(null? (cdr maybe-sstart+send))
780+ (doit! (car maybe-sstart+send) n n)]
781+ [(null? (cddr maybe-sstart+send))
782+ (doit! (car maybe-sstart+send) (cadr maybe-sstart+send) n)]
783+ [else
784+ (error "too many arguments"
785+ vector-reverse-copy!
786+ (cddr maybe-sstart+send))])))
787+ (define (vector-reverse! vec . start+end)
788+ (let-vector-start+end vector-reverse! vec start+end
789+ (start end) (%vector-reverse! vec start end)))
790+ (define vector->list
791+ (let ()
792+ (define ($vector->list vec start end)
793+ (do ([i (- end 1) (- i 1)]
794+ [result '() (cons (vector-ref vec i) result)])
795+ ((< i start) result)))
796+ (case-lambda
797+ [(vec) (rnrs:vector->list vec)]
798+ [(vec start)
799+ ($check-types 'vector->list vec start)
800+ ($vector->list vec start (vector-length vec))]
801+ [(vec start end)
802+ ($check-types 'vector->list vec start end)
803+ ($vector->list vec start (vector-length vec))])))
804+ (define (reverse-vector->list vec . maybe-start+end)
805+ (let-vector-start+end reverse-vector->list vec maybe-start+end (start end)
806+ (do ([i start (+ i 1)]
807+ [result '() (cons (vector-ref vec i) result)])
808+ ((= i end) result))))
809+ (define list->vector
810+ (case-lambda
811+ [(lst) (rnrs:list->vector lst)]
812+ [(lst start)
813+ (check-type nonneg-int? start list->vector)
814+ (rnrs:list->vector (list-tail lst start))]
815+ [(lst start end)
816+ (check-type nonneg-int? start list->vector)
817+ (check-type nonneg-int? end list->vector)
818+ (unless (<= start end)
819+ (error 'list->vector "start is greater than end" start end))
820+ (let ([len (- end start)])
821+ (let ([v (make-vector len)])
822+ (let loop ([i 0] [ls (list-tail lst start)])
823+ (unless (= i len)
824+ (unless (pair? ls)
825+ (if (null? ls)
826+ (error 'list->vector "list too short" lst start end)
827+ (error 'list->vector "improper list" lst)))
828+ (vector-set! v i (car ls))
829+ (loop (fx+ i 1) (cdr ls))))
830+ v))]))
831+ (define (reverse-list->vector lst . maybe-start+end)
832+ (let*-optionals
833+ maybe-start+end
834+ ((start 0) (end (length lst)))
835+ (let ([start (check-type
836+ nonneg-int?
837+ start
838+ reverse-list->vector)]
839+ [end (check-type nonneg-int? end reverse-list->vector)])
840+ ((lambda (f)
841+ (vector-unfold-right f (- end start) (list-tail lst start)))
842+ (lambda (index l)
843+ (cond
844+ [(null? l)
845+ (error "list too short"
846+ `(list was ,lst)
847+ `(attempted end was ,end)
848+ `(while calling ,reverse-list->vector))]
849+ [(pair? l) (values (car l) (cdr l))]
850+ [else
851+ (error "erroneous value"
852+ (list list? lst)
853+ `(while calling ,reverse-list->vector))]))))))
854+ (define (vector->string vec . maybe-start+end)
855+ (let* ([len (vector-length vec)]
856+ [start (if (null? maybe-start+end) 0 (car maybe-start+end))]
857+ [end (if (null? maybe-start+end)
858+ len
859+ (if (null? (cdr maybe-start+end))
860+ len
861+ (cadr maybe-start+end)))]
862+ [size (- end start)])
863+ (define result (make-string size))
864+ (let loop ([at 0] [i start])
865+ (if (= i end)
866+ result
867+ (begin
868+ (string-set! result at (vector-ref vec i))
869+ (loop (+ at 1) (+ i 1)))))))
870+ (define (string->vector str . maybe-start+end)
871+ (let* ([len (string-length str)]
872+ [start (if (null? maybe-start+end) 0 (car maybe-start+end))]
873+ [end (if (null? maybe-start+end)
874+ len
875+ (if (null? (cdr maybe-start+end))
876+ len
877+ (cadr maybe-start+end)))]
878+ [size (- end start)])
879+ (define result (make-vector size))
880+ (let loop ([at 0] [i start])
881+ (if (= i end)
882+ result
883+ (begin
884+ (vector-set! result at (string-ref str i))
885+ (loop (+ at 1) (+ i 1)))))))))
lib/srfi/:133/vectors.sls3a132.slsnew file+6
@@ -0,0 +1,6 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a133/vectors.sls3a132.sls
lib/srfi/:152.slsnew file+28
@@ -0,0 +1,28 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a152.sls
7+(library (srfi :152)
8+ (export string? string-null? string-every string-any
9+ make-string string string-tabulate string-unfold
10+ string-unfold-right string->vector string->list
11+ vector->string list->string reverse-list->string
12+ string-length string-ref substring string-copy string-take
13+ string-take-right string-drop string-drop-right string-pad
14+ string-pad-right string-trim string-trim-right
15+ string-trim-both string-replace string=? string-ci=?
16+ string<? string-ci<? string>? string-ci>? string<=?
17+ string-ci<=? string>=? string-ci>=? string-prefix-length
18+ string-suffix-length string-prefix? string-suffix?
19+ string-index string-index-right string-skip
20+ string-skip-right string-contains string-contains-right
21+ string-take-while string-take-while-right string-drop-while
22+ string-drop-while-right string-break string-span
23+ string-append string-concatenate string-concatenate-reverse
24+ string-join string-fold string-fold-right string-map
25+ string-for-each string-count string-filter string-remove
26+ string-replicate string-segment string-split read-string
27+ write-string string-set! string-fill! string-copy!)
28+ (import (srfi :152 strings)))
lib/srfi/:152/strings.slsnew file+1015
@@ -0,0 +1,1015 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a152/strings.sls
7+;;;;;; File header: %3a152/macros.scm
8+;;;; Definitions of macros
9+;;;;;; File header: %3a152/portable.scm
10+;;; SRFI 130 string library reference implementation -*- Scheme -*-
11+;;; Olin Shivers 7/2000
12+;;; John Cowan 4/2016
13+;;;
14+;;; Copyright (c) 1988-1994 Massachusetts Institute of Technology.
15+;;; Copyright (c) 1998, 1999, 2000 Olin Shivers.
16+;;; Copyright (c) 2016 John Cowan.
17+;;; The details of the copyrights appear at the end of the file. Short
18+;;; summary: BSD-style open source.
19+;;;;;; File header: %3a152/r7rs-shim.scm
20+;;;;;; File header: %3a152/extend-comparisons.scm
21+;;; Extend comparisons to 0 and 1 arguments.
22+;; 2017-10-04 Sudarshan S Chawathe <chaw@eip10.org>
23+(library (srfi :152 strings)
24+ (export string? string-null? string-every string-any
25+ make-string string string-tabulate string-unfold
26+ string-unfold-right string->vector string->list
27+ vector->string list->string reverse-list->string
28+ string-length string-ref substring string-copy string-take
29+ string-take-right string-drop string-drop-right string-pad
30+ string-pad-right string-trim string-trim-right
31+ string-trim-both string-replace string=? string-ci=?
32+ string<? string-ci<? string>? string-ci>? string<=?
33+ string-ci<=? string>=? string-ci>=? string-prefix-length
34+ string-suffix-length string-prefix? string-suffix?
35+ string-index string-index-right string-skip
36+ string-skip-right string-contains string-contains-right
37+ string-take-while string-take-while-right string-drop-while
38+ string-drop-while-right string-break string-span
39+ string-append string-concatenate string-concatenate-reverse
40+ string-join string-fold string-fold-right string-map
41+ string-for-each string-count string-filter string-remove
42+ string-replicate string-segment string-split read-string
43+ write-string string-set! string-fill! string-copy!)
44+ (import
45+ (rename
46+ (except (rnrs) string->list string-for-each string-copy
47+ error)
48+ (string=? base-string=?) (string<? base-string<?)
49+ (string>? base-string>?) (string<=? base-string<=?)
50+ (string>=? base-string>=?) (string-ci=? base-string-ci=?)
51+ (string-ci<? base-string-ci<?)
52+ (string-ci>? base-string-ci>?)
53+ (string-ci<=? base-string-ci<=?)
54+ (string-ci>=? base-string-ci>=?))
55+ (except (rnrs mutable-strings) string-fill!) (rnrs r5rs)
56+ (srfi :0) (srfi :23) (srfi private include))
57+ (begin
58+ (define-syntax receive
59+ (syntax-rules ()
60+ [(receive formals expression body ...)
61+ (call-with-values
62+ (lambda () expression)
63+ (lambda formals body ...))]))
64+ (define-syntax let-optionals*
65+ (syntax-rules ()
66+ [(let-optionals* arg (opt-clause ...) body ...)
67+ (let ([rest arg])
68+ (%let-optionals* rest (opt-clause ...) body ...))]))
69+ (define-syntax %let-optionals*
70+ (syntax-rules ()
71+ [(%let-optionals*
72+ arg
73+ (((var ...) xparser) opt-clause ...)
74+ body
75+ ...)
76+ (call-with-values
77+ (lambda () (xparser arg))
78+ (lambda (rest var ...)
79+ (%let-optionals* rest (opt-clause ...) body ...)))]
80+ [(%let-optionals*
81+ arg
82+ ((var default) opt-clause ...)
83+ body
84+ ...)
85+ (call-with-values
86+ (lambda ()
87+ (if (null? arg)
88+ (values default '())
89+ (values (car arg) (cdr arg))))
90+ (lambda (var rest)
91+ (%let-optionals* rest (opt-clause ...) body ...)))]
92+ [(%let-optionals*
93+ arg
94+ ((var default test) opt-clause ...)
95+ body
96+ ...)
97+ (call-with-values
98+ (lambda ()
99+ (if (null? arg)
100+ (values default '())
101+ (let ([var (car arg)])
102+ (if test
103+ (values var (cdr arg))
104+ (error "arg failed LET-OPT test" var)))))
105+ (lambda (var rest)
106+ (%let-optionals* rest (opt-clause ...) body ...)))]
107+ [(%let-optionals*
108+ arg
109+ ((var default test supplied?) opt-clause ...)
110+ body
111+ ...)
112+ (call-with-values
113+ (lambda ()
114+ (if (null? arg)
115+ (values default #f '())
116+ (let ([var (car arg)])
117+ (if test
118+ (values var #t (cdr arg))
119+ (error "arg failed LET-OPT test" var)))))
120+ (lambda (var supplied? rest)
121+ (%let-optionals* rest (opt-clause ...) body ...)))]
122+ [(%let-optionals* arg (rest) body ...)
123+ (let ([rest arg]) body ...)]
124+ [(%let-optionals* arg () body ...)
125+ (if (null? arg)
126+ (begin body ...)
127+ (error "Too many arguments in let-opt" arg))])))
128+ (begin
129+ (define check-arg
130+ (lambda (pred val proc)
131+ (if (pred val) val (error "Bad arg" val pred proc))))
132+ (define (add1 n) (+ 1 n))
133+ (define-syntax let-string-start+end
134+ (syntax-rules ()
135+ [(let-string-start+end (start end) proc s-exp args-exp body
136+ ...)
137+ (receive
138+ (start end)
139+ (string-parse-final-start+end proc s-exp args-exp)
140+ body
141+ ...)]
142+ [(let-string-start+end (start end rest) proc s-exp args-exp
143+ body ...)
144+ (receive
145+ (rest start end)
146+ (string-parse-start+end proc s-exp args-exp)
147+ body
148+ ...)]))
149+ (define-syntax let-string-start+end2
150+ (syntax-rules ()
151+ [(l-s-s+e2 (start1 end1 start2 end2) proc s1 s2 args body
152+ ...)
153+ (let ([procv proc])
154+ (let-string-start+end (start1 end1 rest) procv s1 args
155+ (let-string-start+end (start2 end2) procv s2 rest body
156+ ...)))]))
157+ (define (string-parse-start+end proc s args)
158+ (if (not (string? s)) (error "Non-string value" proc s))
159+ (let ([slen (string-length s)])
160+ (if (pair? args)
161+ (let ([start (car args)] [args (cdr args)])
162+ (if (and (integer? start) (exact? start) (>= start 0))
163+ (receive
164+ (end args)
165+ (if (pair? args)
166+ (let ([end (car args)] [args (cdr args)])
167+ (if (and (integer? end)
168+ (exact? end)
169+ (<= end slen))
170+ (values end args)
171+ (error "Illegal substring END spec"
172+ proc
173+ end
174+ s)))
175+ (values slen args))
176+ (if (<= start end)
177+ (values args start end)
178+ (error "Illegal substring START/END spec"
179+ proc
180+ start
181+ end
182+ s)))
183+ (error "Illegal substring START spec" proc start s)))
184+ (values '() 0 slen))))
185+ (define (string-parse-final-start+end proc s args)
186+ (receive
187+ (rest start end)
188+ (string-parse-start+end proc s args)
189+ (if (pair? rest)
190+ (error "Extra arguments to procedure" proc rest)
191+ (values start end))))
192+ (define (substring-spec-ok? s start end)
193+ (and (string? s)
194+ (integer? start)
195+ (exact? start)
196+ (integer? end)
197+ (exact? end)
198+ (<= 0 start)
199+ (<= start end)
200+ (<= end (string-length s))))
201+ (define (check-substring-spec proc s start end)
202+ (if (not (substring-spec-ok? s start end))
203+ (error "Illegal substring spec." proc s start end)))
204+ (define (%substring s start end)
205+ (if (and (zero? start) (= end (string-length s)))
206+ s
207+ (substring s start end)))
208+ (define (string-fold kons knil s . maybe-start+end)
209+ (check-arg procedure? kons string-fold)
210+ (let-string-start+end (start end) string-fold s maybe-start+end
211+ (let lp ([v knil] [i start])
212+ (if (< i end) (lp (kons (string-ref s i) v) (+ i 1)) v))))
213+ (define (string-fold-right kons knil s . maybe-start+end)
214+ (check-arg procedure? kons string-fold-right)
215+ (let-string-start+end (start end) string-fold-right s maybe-start+end
216+ (let lp ([v knil] [i (- end 1)])
217+ (if (>= i start)
218+ (lp (kons (string-ref s i) v) (- i 1))
219+ v))))
220+ (define (string-unfold p f g seed . base+make-final)
221+ (check-arg procedure? p string-unfold)
222+ (check-arg procedure? f string-unfold)
223+ (check-arg procedure? g string-unfold)
224+ (let-optionals*
225+ base+make-final
226+ ((base "" (string? base))
227+ (make-final (lambda (x) "") (procedure? make-final)))
228+ (let lp ([chunks '()]
229+ [nchars 0]
230+ [chunk (make-string 40)]
231+ [chunk-len 40]
232+ [i 0]
233+ [seed seed])
234+ (let lp2 ([i i] [seed seed])
235+ (if (not (p seed))
236+ (let ([c (f seed)] [seed (g seed)])
237+ (if (< i chunk-len)
238+ (begin (string-set! chunk i c) (lp2 (+ i 1) seed))
239+ (let* ([nchars2 (+ chunk-len nchars)]
240+ [chunk-len2 (min 4096 nchars2)]
241+ [new-chunk (make-string chunk-len2)])
242+ (string-set! new-chunk 0 c)
243+ (lp (cons chunk chunks) (+ nchars chunk-len)
244+ new-chunk chunk-len2 1 seed))))
245+ (let* ([final (make-final seed)]
246+ [flen (string-length final)]
247+ [base-len (string-length base)]
248+ [j (+ base-len nchars i)]
249+ [ans (make-string (+ j flen))])
250+ (%string-copy! ans j final 0 flen)
251+ (let ([j (- j i)])
252+ (%string-copy! ans j chunk 0 i)
253+ (let lp ([j j] [chunks chunks])
254+ (if (pair? chunks)
255+ (let* ([chunk (car chunks)]
256+ [chunks (cdr chunks)]
257+ [chunk-len (string-length chunk)]
258+ [j (- j chunk-len)])
259+ (%string-copy! ans j chunk 0 chunk-len)
260+ (lp j chunks)))))
261+ (%string-copy! ans 0 base 0 base-len)
262+ ans))))))
263+ (define (string-unfold-right p f g seed . base+make-final)
264+ (let-optionals*
265+ base+make-final
266+ ((base "" (string? base))
267+ (make-final (lambda (x) "") (procedure? make-final)))
268+ (let lp ([chunks '()]
269+ [nchars 0]
270+ [chunk (make-string 40)]
271+ [chunk-len 40]
272+ [i 40]
273+ [seed seed])
274+ (let lp2 ([i i] [seed seed])
275+ (if (not (p seed))
276+ (let ([c (f seed)] [seed (g seed)])
277+ (if (> i 0)
278+ (let ([i (- i 1)])
279+ (string-set! chunk i c)
280+ (lp2 i seed))
281+ (let* ([nchars2 (+ chunk-len nchars)]
282+ [chunk-len2 (min 4096 nchars2)]
283+ [new-chunk (make-string chunk-len2)]
284+ [i (- chunk-len2 1)])
285+ (string-set! new-chunk i c)
286+ (lp (cons chunk chunks) (+ nchars chunk-len)
287+ new-chunk chunk-len2 i seed))))
288+ (let* ([final (make-final seed)]
289+ [flen (string-length final)]
290+ [base-len (string-length base)]
291+ [chunk-used (- chunk-len i)]
292+ [j (+ base-len nchars chunk-used)]
293+ [ans (make-string (+ j flen))])
294+ (%string-copy! ans 0 final 0 flen)
295+ (%string-copy! ans flen chunk i chunk-len)
296+ (let lp ([j (+ flen chunk-used)] [chunks chunks])
297+ (if (pair? chunks)
298+ (let* ([chunk (car chunks)]
299+ [chunks (cdr chunks)]
300+ [chunk-len (string-length chunk)])
301+ (%string-copy! ans j chunk 0 chunk-len)
302+ (lp (+ j chunk-len) chunks))
303+ (%string-copy! ans j base 0 base-len)))
304+ ans))))))
305+ (define (string-every criterion s . maybe-start+end)
306+ (let-string-start+end (start end) string-every s maybe-start+end
307+ (or (= start end)
308+ (let lp ([i start])
309+ (let ([c (string-ref s i)] [i1 (+ i 1)])
310+ (if (= i1 end)
311+ (criterion c)
312+ (and (criterion c) (lp i1))))))))
313+ (define (string-any criterion s . maybe-start+end)
314+ (let-string-start+end (start end) string-any s maybe-start+end
315+ (and (< start end)
316+ (let lp ([i start])
317+ (let ([c (string-ref s i)] [i1 (+ i 1)])
318+ (if (= i1 end)
319+ (criterion c)
320+ (or (criterion c) (lp i1))))))))
321+ (define (string-tabulate proc len)
322+ (check-arg procedure? proc string-tabulate)
323+ (check-arg
324+ (lambda (val) (and (integer? val) (exact? val) (<= 0 val)))
325+ len
326+ string-tabulate)
327+ (let ([s (make-string len)])
328+ (do ([i (- len 1) (- i 1)])
329+ ((< i 0))
330+ (string-set! s i (proc i)))
331+ s))
332+ (define (%string-prefix-length s1 start1 end1 s2 start2
333+ end2)
334+ (let* ([delta (min (- end1 start1) (- end2 start2))]
335+ [end1 (+ start1 delta)])
336+ (if (and (eq? s1 s2) (= start1 start2))
337+ delta
338+ (let lp ([i start1] [j start2])
339+ (if (or (>= i end1)
340+ (not (char=? (string-ref s1 i) (string-ref s2 j))))
341+ (- i start1)
342+ (lp (+ i 1) (+ j 1)))))))
343+ (define (%string-suffix-length s1 start1 end1 s2 start2
344+ end2)
345+ (let* ([delta (min (- end1 start1) (- end2 start2))]
346+ [start1 (- end1 delta)])
347+ (if (and (eq? s1 s2) (= end1 end2))
348+ delta
349+ (let lp ([i (- end1 1)] [j (- end2 1)])
350+ (if (or (< i start1)
351+ (not (char=? (string-ref s1 i) (string-ref s2 j))))
352+ (- (- end1 i) 1)
353+ (lp (- i 1) (- j 1)))))))
354+ (define (string-prefix-length s1 s2 . maybe-starts+ends)
355+ (let-string-start+end2 (start1 end1 start2 end2) string-prefix-length s1 s2
356+ maybe-starts+ends
357+ (%string-prefix-length s1 start1 end1 s2 start2 end2)))
358+ (define (string-suffix-length s1 s2 . maybe-starts+ends)
359+ (let-string-start+end2 (start1 end1 start2 end2) string-suffix-length s1 s2
360+ maybe-starts+ends
361+ (%string-suffix-length s1 start1 end1 s2 start2 end2)))
362+ (define (string-prefix? s1 s2 . maybe-starts+ends)
363+ (let-string-start+end2 (start1 end1 start2 end2) string-prefix? s1 s2
364+ maybe-starts+ends
365+ (%string-prefix? s1 start1 end1 s2 start2 end2)))
366+ (define (string-suffix? s1 s2 . maybe-starts+ends)
367+ (let-string-start+end2 (start1 end1 start2 end2) string-suffix? s1 s2
368+ maybe-starts+ends
369+ (%string-suffix? s1 start1 end1 s2 start2 end2)))
370+ (define (%string-prefix? s1 start1 end1 s2 start2 end2)
371+ (let ([len1 (- end1 start1)])
372+ (and (<= len1 (- end2 start2))
373+ (= (%string-prefix-length s1 start1 end1 s2 start2 end2)
374+ len1))))
375+ (define (%string-suffix? s1 start1 end1 s2 start2 end2)
376+ (let ([len1 (- end1 start1)])
377+ (and (<= len1 (- end2 start2))
378+ (= len1
379+ (%string-suffix-length s1 start1 end1 s2 start2 end2)))))
380+ (define (string-take s n)
381+ (check-arg string? s string-take)
382+ (check-arg
383+ (lambda (val)
384+ (and (integer? n) (exact? n) (<= 0 n (string-length s))))
385+ n
386+ string-take)
387+ (%substring s 0 n))
388+ (define (string-take-right s n)
389+ (check-arg string? s string-take-right)
390+ (let ([len (string-length s)])
391+ (check-arg
392+ (lambda (val) (and (integer? n) (exact? n) (<= 0 n len)))
393+ n
394+ string-take-right)
395+ (%substring s (- len n) len)))
396+ (define (string-drop s n)
397+ (check-arg string? s string-drop)
398+ (let ([len (string-length s)])
399+ (check-arg
400+ (lambda (val) (and (integer? n) (exact? n) (<= 0 n len)))
401+ n
402+ string-drop)
403+ (%substring s n len)))
404+ (define (string-drop-right s n)
405+ (check-arg string? s string-drop-right)
406+ (let ([len (string-length s)])
407+ (check-arg
408+ (lambda (val) (and (integer? n) (exact? n) (<= 0 n len)))
409+ n
410+ string-drop-right)
411+ (%substring s 0 (- len n))))
412+ (define (string-trim s . criterion+start+end)
413+ (let-optionals*
414+ criterion+start+end
415+ ((criterion char-whitespace?) rest)
416+ (let-string-start+end (start end) string-trim s rest
417+ (cond
418+ [(string-skip s criterion start end) =>
419+ (lambda (i) (%substring s i end))]
420+ [else ""]))))
421+ (define (string-trim-right s . criterion+start+end)
422+ (let-optionals*
423+ criterion+start+end
424+ ((criterion char-whitespace?) rest)
425+ (let-string-start+end (start end) string-trim-right s rest
426+ (cond
427+ [(string-skip-right s criterion start end) =>
428+ (lambda (i) (%substring s start (+ 1 i)))]
429+ [else ""]))))
430+ (define (string-trim-both s . criterion+start+end)
431+ (let-optionals*
432+ criterion+start+end
433+ ((criterion char-whitespace?) rest)
434+ (let-string-start+end (start end) string-trim-both s rest
435+ (cond
436+ [(string-skip s criterion start end) =>
437+ (lambda (i)
438+ (%substring
439+ s
440+ i
441+ (+ 1 (string-skip-right s criterion i end))))]
442+ [else ""]))))
443+ (define (string-pad-right s n . char+start+end)
444+ (let-optionals*
445+ char+start+end
446+ ((char #\space (char? char)) rest)
447+ (let-string-start+end (start end) string-pad-right s rest
448+ (check-arg
449+ (lambda (n) (and (integer? n) (exact? n) (<= 0 n)))
450+ n
451+ string-pad-right)
452+ (let ([len (- end start)])
453+ (if (<= n len)
454+ (%substring s start (+ start n))
455+ (let ([ans (make-string n char)])
456+ (%string-copy! ans 0 s start end)
457+ ans))))))
458+ (define (string-pad s n . char+start+end)
459+ (let-optionals*
460+ char+start+end
461+ ((char #\space (char? char)) rest)
462+ (let-string-start+end (start end) string-pad s rest
463+ (check-arg
464+ (lambda (n) (and (integer? n) (exact? n) (<= 0 n)))
465+ n
466+ string-pad)
467+ (let ([len (- end start)])
468+ (if (<= n len)
469+ (%substring s (- end n) end)
470+ (let ([ans (make-string n char)])
471+ (%string-copy! ans (- n len) s start end)
472+ ans))))))
473+ (define (string-remove criterion s . maybe-start+end)
474+ (let-string-start+end (start end) string-remove s maybe-start+end
475+ (let* ([slen (- end start)]
476+ [temp (make-string slen)]
477+ [ans-len (string-fold
478+ (lambda (c i)
479+ (if (criterion c)
480+ i
481+ (begin (string-set! temp i c) (+ i 1))))
482+ 0 s start end)])
483+ (if (= ans-len slen) temp (substring temp 0 ans-len)))))
484+ (define (string-filter criterion s . maybe-start+end)
485+ (let-string-start+end (start end) string-filter s maybe-start+end
486+ (let* ([slen (- end start)]
487+ [temp (make-string slen)]
488+ [ans-len (string-fold
489+ (lambda (c i)
490+ (if (criterion c)
491+ (begin (string-set! temp i c) (+ i 1))
492+ i))
493+ 0 s start end)])
494+ (if (= ans-len slen) temp (substring temp 0 ans-len)))))
495+ (define (string-index str criterion . maybe-start+end)
496+ (let-string-start+end (start end) string-index str maybe-start+end
497+ (let lp ([i start])
498+ (and (< i end)
499+ (if (criterion (string-ref str i)) i (lp (+ i 1)))))))
500+ (define (string-index-right str criterion . maybe-start+end)
501+ (let-string-start+end (start end) string-index-right str maybe-start+end
502+ (let lp ([i (- end 1)])
503+ (and (>= i start)
504+ (if (criterion (string-ref str i)) i (lp (- i 1)))))))
505+ (define (string-skip str criterion . maybe-start+end)
506+ (let-string-start+end (start end) string-skip str maybe-start+end
507+ (let lp ([i start])
508+ (and (< i end)
509+ (if (criterion (string-ref str i)) (lp (+ i 1)) i)))))
510+ (define (string-skip-right str criterion . maybe-start+end)
511+ (let-string-start+end (start end) string-skip-right str maybe-start+end
512+ (let lp ([i (- end 1)])
513+ (and (>= i start)
514+ (if (criterion (string-ref str i)) (lp (- i 1)) i)))))
515+ (define (string-take-while s criterion . maybe-start+end)
516+ (let-string-start+end (start end) string-take-while s maybe-start+end
517+ (let ([idx (string-skip s criterion start end)])
518+ (if idx (%substring s 0 idx) ""))))
519+ (define (string-take-while-right s criterion .
520+ maybe-start+end)
521+ (let-string-start+end (start end) string-take-while s maybe-start+end
522+ (let ([idx (string-skip-right s criterion start end)])
523+ (if idx (%substring s (+ idx 1) (string-length s)) ""))))
524+ (define (string-drop-while s criterion . maybe-start+end)
525+ (let-string-start+end (start end) string-drop-while s maybe-start+end
526+ (let ([idx (string-skip s criterion start end)])
527+ (if idx (%substring s idx (string-length s)) s))))
528+ (define (string-drop-while-right s criterion .
529+ maybe-start+end)
530+ (let-string-start+end (start end) string-drop-while s maybe-start+end
531+ (let ([idx (string-skip-right s criterion start end)])
532+ (if idx (%substring s 0 (+ idx 1)) s))))
533+ (define (string-span s criterion . maybe-start+end)
534+ (let-string-start+end (start end) string-span s maybe-start+end
535+ (let ([idx (string-skip s criterion start end)])
536+ (if idx
537+ (values
538+ (%substring s 0 idx)
539+ (%substring s idx (string-length s)))
540+ (values "" s)))))
541+ (define (string-break s criterion . maybe-start+end)
542+ (let-string-start+end (start end) string-break s maybe-start+end
543+ (let ([idx (string-index s criterion start end)])
544+ (if idx
545+ (values
546+ (%substring s 0 idx)
547+ (%substring s idx (string-length s)))
548+ (values s "")))))
549+ (define (string-count s criterion . maybe-start+end)
550+ (let-string-start+end (start end) string-count s maybe-start+end
551+ (do ([i start (+ i 1)]
552+ [count 0 (if (criterion (string-ref s i))
553+ (+ count 1)
554+ count)])
555+ ((>= i end) count))))
556+ (define (%string-copy! to tstart from fstart fend)
557+ (if (> fstart tstart)
558+ (do ([i fstart (+ i 1)] [j tstart (+ j 1)])
559+ ((>= i fend))
560+ (string-set! to j (string-ref from i)))
561+ (do ([i (- fend 1) (- i 1)]
562+ [j (+ -1 tstart (- fend fstart)) (- j 1)])
563+ ((< i fstart))
564+ (string-set! to j (string-ref from i)))))
565+ (define (string-contains text pattern . maybe-starts+ends)
566+ (let-string-start+end2 (t-start t-end p-start p-end) string-contains text pattern
567+ maybe-starts+ends
568+ (%kmp-search pattern text char=? p-start p-end t-start
569+ t-end)))
570+ (define (string-contains-right text pattern .
571+ maybe-starts+ends)
572+ (let-string-start+end2 (t-start t-end p-start p-end) string-contains-right text
573+ pattern maybe-starts+ends
574+ (let* ([t-len (string-length text)]
575+ [p-len (string-length pattern)]
576+ [p-size (- p-end p-start)]
577+ [rt-start (- t-len t-end)]
578+ [rt-end (- t-len t-start)]
579+ [rp-start (- p-len p-end)]
580+ [rp-end (- p-len p-start)]
581+ [res (%kmp-search (string-reverse pattern)
582+ (string-reverse text) char=? rp-start rp-end rt-start
583+ rt-end)])
584+ (if res (- t-len res p-size) #f))))
585+ (define (%kmp-search pattern text c= p-start p-end t-start
586+ t-end)
587+ (let ([plen (- p-end p-start)]
588+ [rv (make-kmp-restart-vector pattern c= p-start p-end)])
589+ (let lp ([ti t-start]
590+ [pi 0]
591+ [tj (- t-end t-start)]
592+ [pj plen])
593+ (if (= pi plen)
594+ (- ti plen)
595+ (and (<= pj tj)
596+ (if (c= (string-ref text ti)
597+ (string-ref pattern (+ p-start pi)))
598+ (lp (+ 1 ti) (+ 1 pi) (- tj 1) (- pj 1))
599+ (let ([pi (vector-ref rv pi)])
600+ (if (= pi -1)
601+ (lp (+ ti 1) 0 (- tj 1) plen)
602+ (lp ti pi tj (- plen pi))))))))))
603+ (define (make-kmp-restart-vector pattern .
604+ maybe-c=+start+end)
605+ (let-optionals*
606+ maybe-c=+start+end
607+ ((c= char=?) rest)
608+ (receive
609+ (rest2 start end)
610+ (string-parse-start+end
611+ make-kmp-restart-vector
612+ pattern
613+ rest)
614+ (let* ([rvlen (- end start)] [rv (make-vector rvlen -1)])
615+ (if (> rvlen 0)
616+ (let ([rvlen-1 (- rvlen 1)]
617+ [c0 (string-ref pattern start)])
618+ (let lp1 ([i 0] [j -1] [k start])
619+ (if (< i rvlen-1)
620+ (let lp2 ([j j])
621+ (cond
622+ [(= j -1)
623+ (let ([i1 (+ i 1)]
624+ [ck+1 (string-ref pattern (add1 k))])
625+ (vector-set! rv i1 (if (c= ck+1 c0) -1 0))
626+ (lp1 i1 0 (+ k 1)))]
627+ [(c= (string-ref pattern k)
628+ (string-ref pattern (+ j start)))
629+ (let* ([i1 (+ 1 i)] [j1 (+ 1 j)])
630+ (vector-set! rv i1 j1)
631+ (lp1 i1 j1 (+ k 1)))]
632+ [else (lp2 (vector-ref rv j))]))))))
633+ rv))))
634+ (define (kmp-step pat rv c i c= p-start)
635+ (let lp ([i i])
636+ (if (c= c (string-ref pat (+ i p-start)))
637+ (+ i 1)
638+ (let ([i (vector-ref rv i)]) (if (= i -1) 0 (lp i))))))
639+ (define (string-kmp-partial-search pat rv s i .
640+ c=+p-start+s-start+s-end)
641+ (let-optionals*
642+ c=+p-start+s-start+s-end
643+ ((c= char=?) (p-start 0) rest)
644+ (receive
645+ (rest2 s-start s-end)
646+ (string-parse-start+end string-kmp-partial-search s rest)
647+ (let ([patlen (vector-length rv)])
648+ (let lp ([si s-start] [vi i])
649+ (cond
650+ [(= vi patlen) (- si)]
651+ [(= si s-end) vi]
652+ [else
653+ (let ([c (string-ref s si)])
654+ (lp (+ si 1)
655+ (let lp2 ([vi vi])
656+ (if (c= c (string-ref pat (+ vi p-start)))
657+ (+ vi 1)
658+ (let ([vi (vector-ref rv vi)])
659+ (if (= vi -1) 0 (lp2 vi)))))))]))))))
660+ (define (string-null? s) (zero? (string-length s)))
661+ (define (string-reverse s . maybe-start+end)
662+ (let-string-start+end (start end) string-reverse s maybe-start+end
663+ (let* ([len (- end start)] [ans (make-string len)])
664+ (do ([i start (+ i 1)] [j (- len 1) (- j 1)])
665+ ((< j 0))
666+ (string-set! ans j (string-ref s i)))
667+ ans)))
668+ (define (reverse-list->string clist)
669+ (let* ([len (length clist)] [s (make-string len)])
670+ (do ([i (- len 1) (- i 1)] [clist clist (cdr clist)])
671+ ((not (pair? clist)))
672+ (string-set! s i (car clist)))
673+ s))
674+ (define (string-concatenate strings)
675+ (let* ([total (do ([strings strings (cdr strings)]
676+ [i 0 (+ i (string-length (car strings)))])
677+ ((not (pair? strings)) i))]
678+ [ans (make-string total)])
679+ (let lp ([i 0] [strings strings])
680+ (if (pair? strings)
681+ (let* ([s (car strings)] [slen (string-length s)])
682+ (%string-copy! ans i s 0 slen)
683+ (lp (+ i slen) (cdr strings)))))
684+ ans))
685+ (define (string-concatenate-reverse string-list .
686+ maybe-final+end)
687+ (let-optionals*
688+ maybe-final+end
689+ ((final "" (string? final))
690+ (end (string-length final)
691+ (and (integer? end)
692+ (exact? end)
693+ (<= 0 end (string-length final)))))
694+ (let ([len (let lp ([sum 0] [lis string-list])
695+ (if (pair? lis)
696+ (lp (+ sum (string-length (car lis))) (cdr lis))
697+ sum))])
698+ (%finish-string-concatenate-reverse
699+ len
700+ string-list
701+ final
702+ end))))
703+ (define (%finish-string-concatenate-reverse len string-list
704+ final end)
705+ (let ([ans (make-string (+ end len))])
706+ (%string-copy! ans len final 0 end)
707+ (let lp ([i len] [lis string-list])
708+ (if (pair? lis)
709+ (let* ([s (car lis)]
710+ [lis (cdr lis)]
711+ [slen (string-length s)]
712+ [i (- i slen)])
713+ (%string-copy! ans i s 0 slen)
714+ (lp i lis))))
715+ ans))
716+ (define (string-replace s1 s2 start1 end1 . maybe-start+end)
717+ (check-substring-spec string-replace s1 start1 end1)
718+ (let-string-start+end (start2 end2) string-replace s2 maybe-start+end
719+ (let* ([slen1 (string-length s1)]
720+ [sublen2 (- end2 start2)]
721+ [alen (+ (- slen1 (- end1 start1)) sublen2)]
722+ [ans (make-string alen)])
723+ (%string-copy! ans 0 s1 0 start1)
724+ (%string-copy! ans start1 s2 start2 end2)
725+ (%string-copy! ans (+ start1 sublen2) s1 end1 slen1)
726+ ans)))
727+ (define (string-split s delimiter . args)
728+ (if (not (string? s)) (error "string expected" s))
729+ (if (not (string? delimiter))
730+ (error "string expected" delimiter))
731+ (let ([slen (string-length s)])
732+ (receive (grammar limit no-limit start end)
733+ (if (pair? args)
734+ (if (pair? (cdr args))
735+ (if (pair? (cddr args))
736+ (if (pair? (cdddr args))
737+ (values (car args) (cadr args) #f (caddr args)
738+ (cadddr args))
739+ (values (car args) (cadr args) #f (caddr args)
740+ slen))
741+ (values (car args) (cadr args) #f 0 slen))
742+ (values (car args) #f #t 0 slen))
743+ (values 'infix #f #t 0 slen))
744+ (if (not (memq grammar '(infix strict-infix prefix suffix)))
745+ (error "grammar must be one of (infix strict-infix prefix suffix)"
746+ grammar))
747+ (if (not limit) (set! no-limit #t))
748+ (if (not (or no-limit
749+ (and (integer? limit) (exact? limit) (>= limit 0))))
750+ (error "limit must be exact nonnegative integer or #f"
751+ limit))
752+ (if (not (and (integer? start) (exact? start)))
753+ (error "start argument must be exact integer" start))
754+ (if (not (<= 0 start slen))
755+ (error "start argument out of range" start))
756+ (if (not (<= 0 end slen))
757+ (error "end argument out of range" end))
758+ (if (not (<= start end))
759+ (error "start argument is greater than end argument"
760+ (list start end)))
761+ (cond
762+ [(= start end)
763+ (if (eq? grammar 'strict-infix)
764+ (error "empty string cannot be spilt with strict-infix grammar")
765+ '())]
766+ [(string-null? delimiter)
767+ (%string-split-chars s start end limit)]
768+ [else
769+ (%string-split s start end delimiter grammar limit)]))))
770+ (define (%string-split-chars s start end limit)
771+ (if (not limit)
772+ (map string (string->list s start end))
773+ (let loop ([r '()] [c start] [n 0])
774+ (cond
775+ [(= c end) (reverse r)]
776+ [(>= n limit) (reverse (cons (substring s c end) r))]
777+ [else
778+ (loop
779+ (cons (string (string-ref s c)) r)
780+ (+ c 1)
781+ (+ n 1))]))))
782+ (define (%string-split s start end delimiter grammar limit)
783+ (let ([dlen (string-length delimiter)])
784+ (define (finish r c)
785+ (let ([rest (substring s c end)])
786+ (if (and (eq? grammar 'suffix) (string-null? rest))
787+ (reverse r)
788+ (reverse (cons rest r)))))
789+ (define (scan r c n)
790+ (if (and limit (>= n limit))
791+ (finish r c)
792+ (let ([i (string-contains s delimiter c end)])
793+ (if i
794+ (let ([fragment (substring s c i)])
795+ (if (and (= n 0)
796+ (eq? grammar 'prefix)
797+ (string-null? fragment))
798+ (scan r (+ i dlen) (+ n 1))
799+ (scan (cons fragment r) (+ i dlen) (+ n 1))))
800+ (finish r c)))))
801+ (scan '() start 0)))
802+ (define (string-replicate s from . maybe-to+start+end)
803+ (check-arg
804+ (lambda (val) (and (integer? val) (exact? val)))
805+ from
806+ string-replicate)
807+ (receive
808+ (to start end)
809+ (if (pair? maybe-to+start+end)
810+ (let-string-start+end (start end) string-replicate s (cdr maybe-to+start+end)
811+ (let ([to (car maybe-to+start+end)])
812+ (check-arg
813+ (lambda (val)
814+ (and (integer? val) (exact? val) (<= from val)))
815+ to
816+ string-replicate)
817+ (values to start end)))
818+ (let ([slen (string-length
819+ (check-arg string? s string-replicate))])
820+ (values (+ from slen) 0 slen)))
821+ (let ([slen (- end start)] [anslen (- to from)])
822+ (cond
823+ [(zero? anslen) ""]
824+ [(zero? slen)
825+ (error "Cannot replicate empty (sub)string"
826+ string-replicate
827+ s
828+ from
829+ to
830+ start
831+ end)]
832+ [(= 1 slen) (make-string anslen (string-ref s start))]
833+ [(= (floor (/ from slen)) (floor (/ to slen)))
834+ (substring
835+ s
836+ (+ start (modulo from slen))
837+ (+ start (modulo to slen)))]
838+ [else
839+ (let ([ans (make-string anslen)])
840+ (%multispan-repcopy! ans 0 s from to start end)
841+ ans)]))))
842+ (define (%multispan-repcopy! target tstart s sfrom sto start
843+ end)
844+ (let* ([slen (- end start)]
845+ [i0 (+ start (modulo sfrom slen))]
846+ [total-chars (- sto sfrom)])
847+ (%string-copy! target tstart s i0 end)
848+ (let* ([ncopied (- end i0)]
849+ [nleft (- total-chars ncopied)]
850+ [nspans (quotient nleft slen)])
851+ (do ([i (+ tstart ncopied) (+ i slen)]
852+ [nspans nspans (- nspans 1)])
853+ ((zero? nspans)
854+ (%string-copy! target i s start
855+ (+ start (- total-chars (- i tstart)))))
856+ (%string-copy! target i s start end)))))
857+ (define (string-join strings . delim+grammar)
858+ (let-optionals*
859+ delim+grammar
860+ ((delim " " (string? delim)) (grammar 'infix))
861+ (let ([buildit (lambda (lis final)
862+ (let recur ([lis lis])
863+ (if (pair? lis)
864+ (cons
865+ delim
866+ (cons (car lis) (recur (cdr lis))))
867+ final)))])
868+ (cond
869+ [(pair? strings)
870+ (string-concatenate
871+ (case grammar
872+ [(infix strict-infix)
873+ (cons (car strings) (buildit (cdr strings) '()))]
874+ [(prefix) (buildit strings '())]
875+ [(suffix)
876+ (cons
877+ (car strings)
878+ (buildit (cdr strings) (list delim)))]
879+ [else
880+ (error "Illegal join grammar" grammar string-join)]))]
881+ [(not (null? strings))
882+ (error "STRINGS parameter not list." strings string-join)]
883+ [(eq? grammar 'strict-infix)
884+ (error "Empty list cannot be joined with STRICT-INFIX grammar."
885+ string-join)]
886+ [else ""]))))
887+ (define (string-segment str k)
888+ (if (< k 1) (error "minimum segment size is 1" k))
889+ (let ([len (string-length str)])
890+ (let loop ([start 0] [result '()])
891+ (if (= start len)
892+ (reverse result)
893+ (let ([end (min (+ start k) len)])
894+ (loop end (cons (%substring str start end) result))))))))
895+ (begin
896+ (define (string-fill! s char . maybe-start+end)
897+ (check-arg char? char string-fill!)
898+ (let-string-start+end (start end) string-fill! s maybe-start+end
899+ (do ([i (- end 1) (- i 1)])
900+ ((< i start))
901+ (string-set! s i char))))
902+ (define (string-copy! to tstart from . maybe-fstart+fend)
903+ (let-string-start+end (fstart fend) string-copy! from maybe-fstart+fend
904+ (check-arg integer? tstart string-copy!)
905+ (check-substring-spec
906+ string-copy!
907+ to
908+ tstart
909+ (+ tstart (- fend fstart)))
910+ (%string-copy! to tstart from fstart fend)))
911+ (define (string->list s . maybe-start+end)
912+ (let-string-start+end (start end) string->list s maybe-start+end
913+ (do ([i (- end 1) (- i 1)]
914+ [ans '() (cons (string-ref s i) ans)])
915+ ((< i start) ans))))
916+ (define (string->vector s . maybe-start+end)
917+ (let-string-start+end (start end) string->vector s maybe-start+end
918+ (let ([vector (make-vector (- end start))])
919+ (do ([i (- end 1) (- i 1)])
920+ ((< i start) vector)
921+ (vector-set! vector (- i start) (string-ref s i))))))
922+ (define (vector->string vector . maybe-start+end)
923+ (let ([start 0] [end (vector-length vector)])
924+ (case (length maybe-start+end)
925+ [(1) (set! start (car maybe-start+end))]
926+ [(2) (set! end (cadr maybe-start+end))])
927+ (let ([s (make-string (- end start))])
928+ (do ([i (- end 1) (- i 1)])
929+ ((< i start) s)
930+ (string-set! s (- i start) (vector-ref vector i))))))
931+ (define (string-map f x . rest)
932+ (define (string-map1 f x)
933+ (list->string (map f (string->list x))))
934+ (define (string-map2 f x y)
935+ (list->string (map f (string->list x) (string->list y))))
936+ (define (string-mapn f lists)
937+ (list->string (apply map f (map string->list lists))))
938+ (case (length rest)
939+ [(0) (string-map1 f x)]
940+ [(1) (string-map2 f x (car rest))]
941+ [else (string-mapn f (cons x rest))]))
942+ (define (string-for-each f s . rest)
943+ (define (for-each1 i n)
944+ (if (< i n)
945+ (begin (f (string-ref s i)) (for-each1 (+ i 1) n))
946+ (if #f #f)))
947+ (define (for-each2 s2 i n)
948+ (if (< i n)
949+ (begin
950+ (f (string-ref s i) (string-ref s2 i))
951+ (for-each2 s2 (+ i 1) n))
952+ (if #f #f)))
953+ (define (for-each-n revstrings i n)
954+ (if (< i n)
955+ (do ([rev revstrings (cdr rev)]
956+ [chars '() (cons (string-ref (car rev) i) chars)])
957+ ((null? rev)
958+ (apply f chars)
959+ (for-each-n revstrings (+ i 1) n)))
960+ (if #f #f)))
961+ (let ([n (string-length s)])
962+ (cond
963+ [(null? rest) (for-each1 0 n)]
964+ [(and (null? (cdr rest))
965+ (string? (car rest))
966+ (= n (string-length (car rest))))
967+ (for-each2 (car rest) 0 n)]
968+ [else
969+ (let ([args (cons s rest)])
970+ (do ([ss rest (cdr ss)])
971+ ((null? ss) (for-each-n (reverse args) 0 n))
972+ (let ([x (car ss)])
973+ (if (or (not (string? x)) (not (= n (string-length x))))
974+ (error "illegal-arguments" (cons f args))))))])))
975+ (define (string-copy s . maybe-start+end)
976+ (let-string-start+end (start end) string-copy! s
977+ maybe-start+end (%substring s start end)))
978+ (cond-expand
979+ (chicken)
980+ (else
981+ (define read-string
982+ (case-lambda
983+ [(k) (read-string k (current-input-port))]
984+ [(k port)
985+ (let loop ([i 0] [o '()])
986+ (if (>= i k)
987+ (list->string (reverse o))
988+ (let ([c (read-char port)])
989+ (if (eof-object? c)
990+ (if (= i 0) c (list->string (reverse o)))
991+ (loop (+ i 1) (cons c o))))))]))))
992+ (define write-string
993+ (case-lambda
994+ [(str) (display str)]
995+ [(str port) (display str port)]
996+ [(str port start)
997+ (write-string str port start (string-length str))]
998+ [(str port start end)
999+ (display (%substring str start end) port)])))
1000+ (begin
1001+ (define-syntax define-comparison/base/pairs
1002+ (syntax-rules ()
1003+ [(_ (name . base-name) ...)
1004+ (begin
1005+ (define (name . strs)
1006+ (or (null? strs) (null? (cdr strs)) (apply base-name strs)))
1007+ ...)]))
1008+ (define-comparison/base/pairs (string=? . base-string=?) (string<? . base-string<?)
1009+ (string>? . base-string>?) (string<=? . base-string<=?)
1010+ (string>=? . base-string>=?)
1011+ (string-ci=? . base-string-ci=?)
1012+ (string-ci<? . base-string-ci<?)
1013+ (string-ci>? . base-string-ci>?)
1014+ (string-ci<=? . base-string-ci<=?)
1015+ (string-ci>=? . base-string-ci>=?))))
lib/srfi/:158.slsnew file+25
@@ -0,0 +1,25 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a158.sls
7+(library (srfi :158)
8+ (export generator circular-generator make-iota-generator
9+ make-range-generator make-coroutine-generator
10+ list->generator vector->generator reverse-vector->generator
11+ string->generator bytevector->generator
12+ make-for-each-generator make-unfold-generator gcons* gappend
13+ gflatten ggroup gmerge gmap gcombine gfilter gremove
14+ gstate-filter gtake gdrop gtake-while gdrop-while gdelete
15+ gdelete-neighbor-dups gindex gselect generator->list
16+ generator->reverse-list generator->vector generator->vector!
17+ generator->string generator-fold generator-for-each
18+ generator-map->list generator-find generator-count
19+ generator-any generator-every generator-unfold
20+ make-accumulator count-accumulator list-accumulator
21+ reverse-list-accumulator vector-accumulator
22+ reverse-vector-accumulator vector-accumulator!
23+ string-accumulator bytevector-accumulator
24+ bytevector-accumulator! sum-accumulator product-accumulator)
25+ (import (srfi :158 generators-and-accumulators)))
lib/srfi/:158/generators-and-accumulators.slsnew file+457
@@ -0,0 +1,457 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a158/generators-and-accumulators.sls
7+;;;;;; File header: %3a158/srfi-158-impl.scm
8+;; reference implementation from: https://github.com/scheme-requests-for-implementation/srfi-158
9+(library (srfi :158 generators-and-accumulators)
10+ (export generator circular-generator make-iota-generator
11+ make-range-generator make-coroutine-generator
12+ list->generator vector->generator reverse-vector->generator
13+ string->generator bytevector->generator
14+ make-for-each-generator make-unfold-generator gcons* gappend
15+ gflatten ggroup gmerge gmap gcombine gfilter gremove
16+ gstate-filter gtake gdrop gtake-while gdrop-while gdelete
17+ gdelete-neighbor-dups gindex gselect generator->list
18+ generator->reverse-list generator->vector generator->vector!
19+ generator->string generator-fold generator-for-each
20+ generator-map->list generator-find generator-count
21+ generator-any generator-every generator-unfold
22+ make-accumulator count-accumulator list-accumulator
23+ reverse-list-accumulator vector-accumulator
24+ reverse-vector-accumulator vector-accumulator!
25+ string-accumulator bytevector-accumulator
26+ bytevector-accumulator! sum-accumulator product-accumulator)
27+ (import (rnrs) (only (srfi :1) make-list)
28+ (only (chezscheme) call/1cc) (srfi private include)
29+ (srfi private define-values))
30+ (begin
31+ (define (any pred ls)
32+ (if (null? (cdr ls))
33+ (pred (car ls))
34+ ((lambda (x) (if x x (any pred (cdr ls))))
35+ (pred (car ls)))))
36+ (define (list->bytevector list)
37+ (let ([vec (make-bytevector (length list) 0)])
38+ (let loop ([i 0] [list list])
39+ (if (null? list)
40+ vec
41+ (begin
42+ (bytevector-u8-set! vec i (car list))
43+ (loop (+ i 1) (cdr list)))))))
44+ (define (generator . args)
45+ (lambda ()
46+ (if (null? args)
47+ (eof-object)
48+ (let ([next (car args)]) (set! args (cdr args)) next))))
49+ (define (circular-generator . args)
50+ (let ([base-args args])
51+ (lambda ()
52+ (when (null? args) (set! args base-args))
53+ (let ([next (car args)]) (set! args (cdr args)) next))))
54+ (define make-iota-generator
55+ (case-lambda
56+ [(count) (make-iota-generator count 0 1)]
57+ [(count start) (make-iota-generator count start 1)]
58+ [(count start step) (make-iota count start step)]))
59+ (define (make-iota count start step)
60+ (lambda ()
61+ (cond
62+ [(<= count 0) (eof-object)]
63+ [else
64+ (let ([result start])
65+ (set! count (- count 1))
66+ (set! start (+ start step))
67+ result)])))
68+ (define make-range-generator
69+ (case-lambda
70+ [(start end) (make-range-generator start end 1)]
71+ [(start) (make-infinite-range-generator start)]
72+ [(start end step)
73+ (set! start (- (+ start step) step))
74+ (lambda ()
75+ (if (< start end)
76+ (let ([v start]) (set! start (+ start step)) v)
77+ (eof-object)))]))
78+ (define (make-infinite-range-generator start)
79+ (lambda ()
80+ (let ([result start]) (set! start (+ start 1)) result)))
81+ (define (make-coroutine-generator proc)
82+ (define return #f)
83+ (define resume #f)
84+ (define yield
85+ (lambda (v)
86+ (call/cc (lambda (r) (set! resume r) (return v)))))
87+ (lambda ()
88+ (call/1cc
89+ (lambda (cc)
90+ (set! return cc)
91+ (if resume
92+ (resume (if #f #f))
93+ (begin
94+ (proc yield)
95+ (set! resume (lambda (v) (return (eof-object))))
96+ (return (eof-object))))))))
97+ (define (list->generator lst)
98+ (lambda ()
99+ (if (null? lst)
100+ (eof-object)
101+ (let ([next (car lst)]) (set! lst (cdr lst)) next))))
102+ (define vector->generator
103+ (case-lambda
104+ [(vec) (vector->generator vec 0 (vector-length vec))]
105+ [(vec start)
106+ (vector->generator vec start (vector-length vec))]
107+ [(vec start end)
108+ (lambda ()
109+ (if (>= start end)
110+ (eof-object)
111+ (let ([next (vector-ref vec start)])
112+ (set! start (+ start 1))
113+ next)))]))
114+ (define reverse-vector->generator
115+ (case-lambda
116+ [(vec)
117+ (reverse-vector->generator vec 0 (vector-length vec))]
118+ [(vec start)
119+ (reverse-vector->generator vec start (vector-length vec))]
120+ [(vec start end)
121+ (lambda ()
122+ (if (>= start end)
123+ (eof-object)
124+ (let ([next (vector-ref vec (- end 1))])
125+ (set! end (- end 1))
126+ next)))]))
127+ (define string->generator
128+ (case-lambda
129+ [(str) (string->generator str 0 (string-length str))]
130+ [(str start)
131+ (string->generator str start (string-length str))]
132+ [(str start end)
133+ (lambda ()
134+ (if (>= start end)
135+ (eof-object)
136+ (let ([next (string-ref str start)])
137+ (set! start (+ start 1))
138+ next)))]))
139+ (define bytevector->generator
140+ (case-lambda
141+ [(str)
142+ (bytevector->generator str 0 (bytevector-length str))]
143+ [(str start)
144+ (bytevector->generator str start (bytevector-length str))]
145+ [(str start end)
146+ (lambda ()
147+ (if (>= start end)
148+ (eof-object)
149+ (let ([next (bytevector-u8-ref str start)])
150+ (set! start (+ start 1))
151+ next)))]))
152+ (define (make-for-each-generator for-each obj)
153+ (make-coroutine-generator
154+ (lambda (yield) (for-each yield obj))))
155+ (define (make-unfold-generator stop? mapper successor seed)
156+ (make-coroutine-generator
157+ (lambda (yield)
158+ (let loop ([s seed])
159+ (if (stop? s)
160+ (if #f #f)
161+ (begin (yield (mapper s)) (loop (successor s))))))))
162+ (define (gcons* . args)
163+ (lambda ()
164+ (if (null? args)
165+ (eof-object)
166+ (if (= (length args) 1)
167+ ((car args))
168+ (let ([v (car args)]) (set! args (cdr args)) v)))))
169+ (define (gappend . args)
170+ (lambda ()
171+ (if (null? args)
172+ (eof-object)
173+ (let loop ([v ((car args))])
174+ (if (eof-object? v)
175+ (begin
176+ (set! args (cdr args))
177+ (if (null? args) (eof-object) (loop ((car args)))))
178+ v)))))
179+ (define (gflatten gen)
180+ (let ([state '()])
181+ (lambda ()
182+ (if (null? state) (set! state (gen)))
183+ (if (eof-object? state)
184+ state
185+ (let ([obj (car state)]) (set! state (cdr state)) obj)))))
186+ (define ggroup
187+ (case-lambda
188+ [(gen k) (simple-ggroup gen k)]
189+ [(gen k padding)
190+ (padded-ggroup (simple-ggroup gen k) k padding)]))
191+ (define (simple-ggroup gen k)
192+ (lambda ()
193+ (let loop ([item (gen)] [result '()] [count (- k 1)])
194+ (if (eof-object? item)
195+ (if (null? result) item (reverse result))
196+ (if (= count 0)
197+ (reverse (cons item result))
198+ (loop (gen) (cons item result) (- count 1)))))))
199+ (define (padded-ggroup gen k padding)
200+ (lambda ()
201+ (let ([item (gen)])
202+ (if (eof-object? item)
203+ item
204+ (let ([len (length item)])
205+ (if (= len k)
206+ item
207+ (append item (make-list (- k len) padding))))))))
208+ (define gmerge
209+ (case-lambda
210+ [(<) (error #f "wrong number of arguments for gmerge")]
211+ [(< gen) gen]
212+ [(< genleft genright)
213+ (let ([left (genleft)] [right (genright)])
214+ (lambda ()
215+ (cond
216+ [(and (eof-object? left) (eof-object? right)) left]
217+ [(eof-object? left)
218+ (let ([obj right]) (set! right (genright)) obj)]
219+ [(eof-object? right)
220+ (let ([obj left]) (set! left (genleft)) obj)]
221+ [(< right left)
222+ (let ([obj right]) (set! right (genright)) obj)]
223+ [else (let ([obj left]) (set! left (genleft)) obj)])))]
224+ [(< . gens)
225+ (apply
226+ gmerge
227+ <
228+ (let loop ([gens gens] [gs '()])
229+ (cond
230+ [(null? gens) (reverse gs)]
231+ [(null? (cdr gens)) (reverse (cons (car gens) gs))]
232+ [else
233+ (loop
234+ (cddr gens)
235+ (cons (gmerge < (car gens) (cadr gens)) gs))])))]))
236+ (define gmap
237+ (case-lambda
238+ [(proc) (error #f "wrong number of arguments for gmap")]
239+ [(proc gen)
240+ (lambda ()
241+ (let ([item (gen)])
242+ (if (eof-object? item) item (proc item))))]
243+ [(proc . gens)
244+ (lambda ()
245+ (let ([items (map (lambda (x) (x)) gens)])
246+ (if (any eof-object? items)
247+ (eof-object)
248+ (apply proc items))))]))
249+ (define (gcombine proc seed . gens)
250+ (lambda ()
251+ (define items (map (lambda (x) (x)) gens))
252+ (if (any eof-object? items)
253+ (eof-object)
254+ (let ()
255+ (define-values (value newseed)
256+ (apply proc (append items (list seed))))
257+ (set! seed newseed)
258+ value))))
259+ (define (gfilter pred gen)
260+ (lambda ()
261+ (let loop ()
262+ (let ([next (gen)])
263+ (if (or (eof-object? next) (pred next)) next (loop))))))
264+ (define (gstate-filter proc seed gen)
265+ (let ([state seed])
266+ (lambda ()
267+ (let loop ([item (gen)])
268+ (if (eof-object? item)
269+ item
270+ (let-values ([(yes newstate) (proc item state)])
271+ (set! state newstate)
272+ (if yes item (loop (gen)))))))))
273+ (define (gremove pred gen)
274+ (gfilter (lambda (v) (not (pred v))) gen))
275+ (define gtake
276+ (case-lambda
277+ [(gen k) (gtake gen k (eof-object))]
278+ [(gen k padding)
279+ (define (%gtake gen k)
280+ (lambda ()
281+ (if (zero? k) (eof-object) (begin (set! k (- k 1)) (gen)))))
282+ (%gtake (gappend gen (lambda () padding)) k)]))
283+ (define (gdrop gen k)
284+ (lambda () (do () ((<= k 0)) (set! k (- k 1)) (gen)) (gen)))
285+ (define (gdrop-while pred gen)
286+ (define found #f)
287+ (lambda ()
288+ (let loop ()
289+ (let ([val (gen)])
290+ (cond
291+ [found val]
292+ [(and (not (eof-object? val)) (pred val)) (loop)]
293+ [else (set! found #t) val])))))
294+ (define (gtake-while pred gen)
295+ (lambda ()
296+ (let ([next (gen)])
297+ (if (eof-object? next)
298+ next
299+ (if (pred next)
300+ next
301+ (begin (set! gen (generator)) (gen)))))))
302+ (define gdelete
303+ (case-lambda
304+ [(item gen) (gdelete item gen equal?)]
305+ [(item gen ==)
306+ (lambda ()
307+ (let loop ([v (gen)])
308+ (cond
309+ [(eof-object? v) (eof-object)]
310+ [(== item v) (loop (gen))]
311+ [else v])))]))
312+ (define gdelete-neighbor-dups
313+ (case-lambda
314+ [(gen) (gdelete-neighbor-dups gen equal?)]
315+ [(gen ==)
316+ (define firsttime #t)
317+ (define prev #f)
318+ (lambda ()
319+ (if firsttime
320+ (begin (set! firsttime #f) (set! prev (gen)) prev)
321+ (let loop ([v (gen)])
322+ (cond
323+ [(eof-object? v) v]
324+ [(== prev v) (loop (gen))]
325+ [else (set! prev v) v]))))]))
326+ (define (gindex value-gen index-gen)
327+ (let ([done? #f] [count 0])
328+ (lambda ()
329+ (if done?
330+ (eof-object)
331+ (let loop ([value (value-gen)] [index (index-gen)])
332+ (cond
333+ [(or (eof-object? value) (eof-object? index))
334+ (set! done? #t)
335+ (eof-object)]
336+ [(= index count) (set! count (+ count 1)) value]
337+ [else
338+ (set! count (+ count 1))
339+ (loop (value-gen) index)]))))))
340+ (define (gselect value-gen truth-gen)
341+ (let ([done? #f])
342+ (lambda ()
343+ (if done?
344+ (eof-object)
345+ (let loop ([value (value-gen)] [truth (truth-gen)])
346+ (cond
347+ [(or (eof-object? value) (eof-object? truth))
348+ (set! done? #t)
349+ (eof-object)]
350+ [truth value]
351+ [else (loop (value-gen) (truth-gen))]))))))
352+ (define generator->list
353+ (case-lambda
354+ [(gen n) (generator->list (gtake gen n))]
355+ [(gen) (reverse (generator->reverse-list gen))]))
356+ (define generator->reverse-list
357+ (case-lambda
358+ [(gen n) (generator->reverse-list (gtake gen n))]
359+ [(gen) (generator-fold cons '() gen)]))
360+ (define generator->vector
361+ (case-lambda
362+ [(gen) (list->vector (generator->list gen))]
363+ [(gen n) (list->vector (generator->list gen n))]))
364+ (define (generator->vector! vector at gen)
365+ (let loop ([value (gen)] [count 0] [at at])
366+ (cond
367+ [(eof-object? value) count]
368+ [(>= at (vector-length vector)) count]
369+ [else
370+ (begin
371+ (vector-set! vector at value)
372+ (loop (gen) (+ count 1) (+ at 1)))])))
373+ (define generator->string
374+ (case-lambda
375+ [(gen) (list->string (generator->list gen))]
376+ [(gen n) (list->string (generator->list gen n))]))
377+ (define (generator-fold f seed . gs)
378+ (define (inner-fold seed)
379+ (let ([vs (map (lambda (g) (g)) gs)])
380+ (if (any eof-object? vs)
381+ seed
382+ (inner-fold (apply f (append vs (list seed)))))))
383+ (inner-fold seed))
384+ (define (generator-for-each f . gs)
385+ (let loop ()
386+ (let ([vs (map (lambda (g) (g)) gs)])
387+ (if (any eof-object? vs)
388+ (if #f #f)
389+ (begin (apply f vs) (loop))))))
390+ (define (generator-map->list f . gs)
391+ (let loop ([result '()])
392+ (let ([vs (map (lambda (g) (g)) gs)])
393+ (if (any eof-object? vs)
394+ (reverse result)
395+ (loop (cons (apply f vs) result))))))
396+ (define (generator-find pred g)
397+ (let loop ([v (g)])
398+ (if (or (pred v) (eof-object? v)) v (loop (g)))))
399+ (define (generator-count pred g)
400+ (generator-fold (lambda (v n) (if (pred v) (+ 1 n) n)) 0 g))
401+ (define (generator-any pred g)
402+ (let loop ([v (g)])
403+ (if (eof-object? v) #f (if (pred v) #t (loop (g))))))
404+ (define (generator-every pred g)
405+ (let loop ([v (g)])
406+ (if (eof-object? v) #t (if (pred v) (loop (g)) #f))))
407+ (define (generator-unfold g unfold . args)
408+ (apply unfold eof-object? (lambda (x) x) (lambda (x) (g))
409+ (g) args))
410+ (define (make-accumulator kons knil finalize)
411+ (let ([state knil])
412+ (lambda (obj)
413+ (if (eof-object? obj)
414+ (finalize state)
415+ (set! state (kons obj state))))))
416+ (define (count-accumulator)
417+ (make-accumulator
418+ (lambda (obj state) (+ 1 state))
419+ 0
420+ (lambda (x) x)))
421+ (define (list-accumulator)
422+ (make-accumulator cons '() reverse))
423+ (define (reverse-list-accumulator)
424+ (make-accumulator cons '() (lambda (x) x)))
425+ (define (vector-accumulator)
426+ (make-accumulator
427+ cons
428+ '()
429+ (lambda (x) (list->vector (reverse x)))))
430+ (define (reverse-vector-accumulator)
431+ (make-accumulator cons '() list->vector))
432+ (define (vector-accumulator! vec at)
433+ (lambda (obj)
434+ (if (eof-object? obj)
435+ vec
436+ (begin (vector-set! vec at obj) (set! at (+ at 1))))))
437+ (define (bytevector-accumulator)
438+ (make-accumulator
439+ cons
440+ '()
441+ (lambda (x) (list->bytevector (reverse x)))))
442+ (define (bytevector-accumulator! bytevec at)
443+ (lambda (obj)
444+ (if (eof-object? obj)
445+ bytevec
446+ (begin
447+ (bytevector-u8-set! bytevec at obj)
448+ (set! at (+ at 1))))))
449+ (define (string-accumulator)
450+ (make-accumulator
451+ cons
452+ '()
453+ (lambda (lst) (list->string (reverse lst)))))
454+ (define (sum-accumulator)
455+ (make-accumulator + 0 (lambda (x) x)))
456+ (define (product-accumulator)
457+ (make-accumulator * 1 (lambda (x) x)))))
lib/srfi/:19.slsnew file+39
@@ -0,0 +1,39 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :19)
10+ (export add-duration add-duration! copy-time current-date
11+ current-julian-day current-modified-julian-day current-time
12+ date->julian-day date->modified-julian-day date->string
13+ date->time-monotonic date->time-tai date->time-utc date-day
14+ date-hour date-minute date-month date-nanosecond date-second
15+ date-week-day date-week-number date-year date-year-day
16+ date-zone-offset date? julian-day->date
17+ julian-day->time-monotonic julian-day->time-tai
18+ julian-day->time-utc make-date make-time
19+ modified-julian-day->date
20+ modified-julian-day->time-monotonic
21+ modified-julian-day->time-tai modified-julian-day->time-utc
22+ set-time-nanosecond! set-time-second! set-time-type!
23+ string->date subtract-duration subtract-duration!
24+ time-difference time-difference! time-duration
25+ time-monotonic time-monotonic->date
26+ time-monotonic->julian-day
27+ time-monotonic->modified-julian-day time-monotonic->time-tai
28+ time-monotonic->time-tai! time-monotonic->time-utc
29+ time-monotonic->time-utc! time-nanosecond time-process
30+ time-resolution time-second time-tai time-tai->date
31+ time-tai->julian-day time-tai->modified-julian-day
32+ time-tai->time-monotonic time-tai->time-monotonic!
33+ time-tai->time-utc time-tai->time-utc! time-thread time-type
34+ time-utc time-utc->date time-utc->julian-day
35+ time-utc->modified-julian-day time-utc->time-monotonic
36+ time-utc->time-monotonic! time-utc->time-tai
37+ time-utc->time-tai! time<=? time<? time=? time>=? time>?
38+ time?)
39+ (import (srfi :19 time)))
lib/srfi/:19/time.slsnew file+1533
@@ -0,0 +1,1533 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+;;;;;; File header: %3a19/srfi-19.scm
11+;; SRFI-19: Time Data Types and Procedures.
12+;;
13+;; Copyright (C) I/NET, Inc. (2000, 2002, 2003). All Rights Reserved.
14+;;
15+;; Permission is hereby granted, free of charge, to any person obtaining
16+;; a copy of this software and associated documentation files (the
17+;; "Software"), to deal in the Software without restriction, including
18+;; without limitation the rights to use, copy, modify, merge, publish,
19+;; distribute, sublicense, and/or sell copies of the Software, and to
20+;; permit persons to whom the Software is furnished to do so, subject to
21+;; the following conditions:
22+;;
23+;; The above copyright notice and this permission notice shall be
24+;; included in all copies or substantial portions of the Software.
25+;;
26+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31+;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32+;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33+(library (srfi :19 time)
34+ (export time-duration time-monotonic time-process time-tai
35+ time-thread time-utc current-date current-julian-day
36+ current-modified-julian-day current-time time-resolution
37+ make-time time? time-type time-nanosecond time-second
38+ set-time-type! set-time-nanosecond! set-time-second!
39+ copy-time time<=? time<? time=? time>=? time>?
40+ time-difference time-difference! add-duration add-duration!
41+ subtract-duration subtract-duration! make-date date?
42+ date-nanosecond date-second date-minute date-hour date-day
43+ date-month date-year date-zone-offset date-year-day
44+ date-week-day date-week-number date->julian-day
45+ date->modified-julian-day date->time-monotonic
46+ date->time-tai date->time-utc julian-day->date
47+ julian-day->time-monotonic julian-day->time-tai
48+ julian-day->time-utc modified-julian-day->date
49+ modified-julian-day->time-monotonic
50+ modified-julian-day->time-tai modified-julian-day->time-utc
51+ time-monotonic->date time-monotonic->julian-day
52+ time-monotonic->modified-julian-day time-monotonic->time-tai
53+ time-monotonic->time-tai! time-monotonic->time-utc
54+ time-monotonic->time-utc! time-tai->date
55+ time-tai->julian-day time-tai->modified-julian-day
56+ time-tai->time-monotonic time-tai->time-monotonic!
57+ time-tai->time-utc time-tai->time-utc! time-utc->date
58+ time-utc->julian-day time-utc->modified-julian-day
59+ time-utc->time-monotonic time-utc->time-monotonic!
60+ time-utc->time-tai time-utc->time-tai! date->string
61+ string->date)
62+ (import (rnrs) (rnrs r5rs) (rnrs mutable-strings)
63+ (prefix (srfi :19 time compat) host:)
64+ (srfi :6 basic-string-ports)
65+ (for (srfi private vanish) expand) (srfi private include))
66+ (define-syntax define-struct
67+ (lambda (stx)
68+ (define (id-append x . r)
69+ (datum->syntax
70+ x
71+ (string->symbol
72+ (apply
73+ string-append
74+ (map (lambda (y)
75+ (if (identifier? y)
76+ (symbol->string (syntax->datum y))
77+ y))
78+ r)))))
79+ (syntax-case stx ()
80+ [(_ name (field ...) _)
81+ (with-syntax ([(accessor ...) (map (lambda (x)
82+ (id-append x #'name "-" x))
83+ #'(field ...))]
84+ [(mutator ...) (map (lambda (x)
85+ (id-append x "set-" #'name "-"
86+ x "!"))
87+ #'(field ...))])
88+ #'(define-record-type name
89+ (fields (mutable field accessor mutator) ...)))])))
90+ (define read-line get-line)
91+ (define (tm:time-error caller type value)
92+ (define (message x)
93+ (if (symbol? x)
94+ (list->string
95+ (map (lambda (c) (if (char=? #\- c) #\space c))
96+ (string->list (symbol->string x))))
97+ (call-with-string-output-port
98+ (lambda (sop) (write x sop)))))
99+ (apply
100+ assertion-violation
101+ caller
102+ (message type)
103+ (if value (list value) '())))
104+ (define (my:time-helper current-time type proc)
105+ (let ([x (current-time)])
106+ (make-time
107+ type
108+ (host:time-nanosecond x)
109+ (proc (host:time-second x)))))
110+ (define (my:leap-second-helper s)
111+ (+ s (tm:leap-second-delta s)))
112+ (define (tm:current-time-utc)
113+ (my:time-helper host:current-time time-utc values))
114+ (define (tm:current-time-tai)
115+ (my:time-helper
116+ host:current-time
117+ time-tai
118+ my:leap-second-helper))
119+ (define (tm:current-time-monotonic)
120+ (my:time-helper
121+ host:current-time
122+ time-monotonic
123+ my:leap-second-helper))
124+ (define (tm:current-time-thread)
125+ (my:time-helper
126+ host:cumulative-thread-time
127+ time-thread
128+ values))
129+ (define (tm:current-time-process)
130+ (my:time-helper
131+ host:cumulative-process-time
132+ time-process
133+ values))
134+ (define (tm:current-time-gc)
135+ (my:time-helper host:cumulative-gc-time time-gc values))
136+ (define (time-resolution . clock-type) host:time-resolution)
137+ (define (tm:local-tz-offset) host:timezone-offset)
138+ (define eof (eof-object))
139+ (let-syntax ([define (vanish-define
140+ define
141+ (tm:time-error-types tm:time-error tm:get-time-of-day
142+ tm:current-time-utc tm:current-time-tai
143+ tm:current-time-ms-time
144+ tm:current-time-monotonic tm:current-time-thread
145+ tm:current-time-process tm:current-time-gc
146+ time-resolution set-date-nanosecond!
147+ set-date-second! set-date-minute! set-date-hour!
148+ set-date-day! set-date-month! set-date-year!
149+ set-date-zone-offset! tm:local-tz-offset))])
150+ (begin
151+ (define-syntax receive
152+ (syntax-rules ()
153+ [(receive formals expression body ...)
154+ (call-with-values
155+ (lambda () expression)
156+ (lambda formals body ...))]))
157+ (define-syntax :optional
158+ (syntax-rules ()
159+ [(_ val default-value)
160+ (if (null? val) default-value (car val))]))
161+ (define time-tai 'time-tai)
162+ (define time-utc 'time-utc)
163+ (define time-monotonic 'time-monotonic)
164+ (define time-thread 'time-thread)
165+ (define time-process 'time-process)
166+ (define time-duration 'time-duration)
167+ (define time-gc 'time-gc)
168+ (define tm:locale-number-separator ".")
169+ (define tm:locale-abbr-weekday-vector
170+ (vector "Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"))
171+ (define tm:locale-long-weekday-vector
172+ (vector "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday"
173+ "Friday" "Saturday"))
174+ (define tm:locale-abbr-month-vector
175+ (vector "" "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug"
176+ "Sep" "Oct" "Nov" "Dec"))
177+ (define tm:locale-long-month-vector
178+ (vector "" "January" "February" "March" "April" "May" "June"
179+ "July" "August" "September" "October" "November"
180+ "December"))
181+ (define tm:locale-pm "PM")
182+ (define tm:locale-am "AM")
183+ (define tm:locale-date-time-format "~a ~b ~d ~H:~M:~S~z ~Y")
184+ (define tm:locale-short-date-format "~m/~d/~y")
185+ (define tm:locale-time-format "~H:~M:~S")
186+ (define tm:iso-8601-date-time-format "~Y-~m-~dT~H:~M:~S~z")
187+ (define tm:nano (expt 10 9))
188+ (define tm:sid 86400)
189+ (define tm:sihd 43200)
190+ (define tm:tai-epoch-in-jd 4881175/2)
191+ (define tm:time-error-types
192+ '(invalid-clock-type unsupported-clock-type incompatible-time-types not-duration
193+ dates-are-immutable bad-date-format-string
194+ bad-date-template-string invalid-month-specification))
195+ (define (tm:time-error caller type value)
196+ (if (member type tm:time-error-types)
197+ (if value
198+ (error caller "TIME-ERROR type ~S: ~S" type value)
199+ (error caller "TIME-ERROR type ~S" type))
200+ (error caller "TIME-ERROR unsupported error type ~S" type)))
201+ (define (tm:read-tai-utc-data filename)
202+ (define (convert-jd jd)
203+ (* (- (inexact->exact jd) tm:tai-epoch-in-jd) tm:sid))
204+ (define (convert-sec sec) (inexact->exact sec))
205+ (let ([port (open-input-file filename)] [table '()])
206+ (let loop ([line (read-line port)])
207+ (if (not (eq? line eof))
208+ (begin
209+ (let* ([data (read
210+ (open-input-string
211+ (string-append "(" line ")")))]
212+ [year (car data)]
213+ [jd (cadddr (cdr data))]
214+ [secs (cadddr (cdddr data))])
215+ (if (>= year 1972)
216+ (set! table
217+ (cons
218+ (cons (convert-jd jd) (convert-sec secs))
219+ table)))
220+ (loop (read-line port))))))
221+ table))
222+ (define tm:leap-second-table
223+ '((1483228800 . 37) (1435708800 . 36) (1341100800 . 35)
224+ (1230768000 . 34) (1136073600 . 33) (915148800 . 32)
225+ (867715200 . 31) (820454400 . 30) (773020800 . 29)
226+ (741484800 . 28) (709948800 . 27) (662688000 . 26)
227+ (631152000 . 25) (567993600 . 24) (489024000 . 23)
228+ (425865600 . 22) (394329600 . 21) (362793600 . 20)
229+ (315532800 . 19) (283996800 . 18) (252460800 . 17)
230+ (220924800 . 16) (189302400 . 15) (157766400 . 14)
231+ (126230400 . 13) (94694400 . 12) (78796800 . 11)
232+ (63072000 . 10)))
233+ (define (read-leap-second-table filename)
234+ (set! tm:leap-second-table (tm:read-tai-utc-data filename))
235+ (values))
236+ (define (tm:leap-second-delta utc-seconds)
237+ (letrec ([lsd (lambda (table)
238+ (cond
239+ [(>= utc-seconds (caar table)) (cdar table)]
240+ [else (lsd (cdr table))]))])
241+ (if (< utc-seconds (* (- 1972 1970) 365 tm:sid))
242+ 0
243+ (lsd tm:leap-second-table))))
244+ (define (tm:leap-second-neg-delta tai-seconds)
245+ (letrec ([lsd (lambda (table)
246+ (cond
247+ [(null? table) 0]
248+ [(<= (cdar table) (- tai-seconds (caar table)))
249+ (cdar table)]
250+ [else (lsd (cdr table))]))])
251+ (if (< tai-seconds (* (- 1972 1970) 365 tm:sid))
252+ 0
253+ (lsd tm:leap-second-table))))
254+ (define-struct
255+ time
256+ (type nanosecond second)
257+ (make-inspector))
258+ (define (copy-time time)
259+ (make-time
260+ (time-type time)
261+ (time-nanosecond time)
262+ (time-second time)))
263+ (define (tm:get-time-of-day)
264+ (values
265+ (current-seconds)
266+ (abs (remainder (current-milliseconds) 1000))))
267+ (define (tm:current-time-utc)
268+ (receive
269+ (seconds ms)
270+ (tm:get-time-of-day)
271+ (make-time time-utc (* ms 10000) seconds)))
272+ (define (tm:current-time-tai)
273+ (receive
274+ (seconds ms)
275+ (tm:get-time-of-day)
276+ (make-time
277+ time-tai
278+ (* ms 10000)
279+ (+ seconds (tm:leap-second-delta seconds)))))
280+ (define (tm:current-time-ms-time time-type proc)
281+ (let ([current-ms (proc)])
282+ (make-time
283+ time-type
284+ (* (remainder current-ms 1000) 10000)
285+ (quotient current-ms 10000))))
286+ (define (tm:current-time-monotonic)
287+ (receive
288+ (seconds ms)
289+ (tm:get-time-of-day)
290+ (make-time
291+ time-monotonic
292+ (* ms 10000)
293+ (+ seconds (tm:leap-second-delta seconds)))))
294+ (define (tm:current-time-thread)
295+ (tm:current-time-ms-time
296+ time-process
297+ current-process-milliseconds))
298+ (define (tm:current-time-process)
299+ (tm:current-time-ms-time
300+ time-process
301+ current-process-milliseconds))
302+ (define (tm:current-time-gc)
303+ (tm:current-time-ms-time time-gc current-gc-milliseconds))
304+ (define (current-time . clock-type)
305+ (let ([clock-type (:optional clock-type time-utc)])
306+ (cond
307+ [(eq? clock-type time-tai) (tm:current-time-tai)]
308+ [(eq? clock-type time-utc) (tm:current-time-utc)]
309+ [(eq? clock-type time-monotonic)
310+ (tm:current-time-monotonic)]
311+ [(eq? clock-type time-thread) (tm:current-time-thread)]
312+ [(eq? clock-type time-process) (tm:current-time-process)]
313+ [(eq? clock-type time-gc) (tm:current-time-gc)]
314+ [else
315+ (tm:time-error
316+ 'current-time
317+ 'invalid-clock-type
318+ clock-type)])))
319+ (define (time-resolution . clock-type)
320+ (let ([clock-type (:optional clock-type time-utc)])
321+ (cond
322+ [(eq? clock-type time-tai) 10000]
323+ [(eq? clock-type time-utc) 10000]
324+ [(eq? clock-type time-monotonic) 10000]
325+ [(eq? clock-type time-thread) 10000]
326+ [(eq? clock-type time-process) 10000]
327+ [(eq? clock-type time-gc) 10000]
328+ [else
329+ (tm:time-error
330+ 'time-resolution
331+ 'invalid-clock-type
332+ clock-type)])))
333+ (define (tm:time-compare-check time1 time2 caller)
334+ (if (or (not (and (time? time1) (time? time2)))
335+ (not (eq? (time-type time1) (time-type time2))))
336+ (tm:time-error caller 'incompatible-time-types #f)
337+ #t))
338+ (define (time=? time1 time2)
339+ (tm:time-compare-check time1 time2 'time=?)
340+ (and (= (time-second time1) (time-second time2))
341+ (= (time-nanosecond time1) (time-nanosecond time2))))
342+ (define (time>? time1 time2)
343+ (tm:time-compare-check time1 time2 'time>?)
344+ (or (> (time-second time1) (time-second time2))
345+ (and (= (time-second time1) (time-second time2))
346+ (> (time-nanosecond time1) (time-nanosecond time2)))))
347+ (define (time<? time1 time2)
348+ (tm:time-compare-check time1 time2 'time<?)
349+ (or (< (time-second time1) (time-second time2))
350+ (and (= (time-second time1) (time-second time2))
351+ (< (time-nanosecond time1) (time-nanosecond time2)))))
352+ (define (time>=? time1 time2)
353+ (tm:time-compare-check time1 time2 'time>=?)
354+ (or (> (time-second time1) (time-second time2))
355+ (and (= (time-second time1) (time-second time2))
356+ (>= (time-nanosecond time1) (time-nanosecond time2)))))
357+ (define (time<=? time1 time2)
358+ (tm:time-compare-check time1 time2 'time<=?)
359+ (or (< (time-second time1) (time-second time2))
360+ (and (= (time-second time1) (time-second time2))
361+ (<= (time-nanosecond time1) (time-nanosecond time2)))))
362+ (define (tm:time->nanoseconds time)
363+ (define (sign1 n) (if (negative? n) -1 1))
364+ (+ (* (time-second time) tm:nano) (time-nanosecond time)))
365+ (define (tm:nanoseconds->time time-type nanoseconds)
366+ (make-time
367+ time-type
368+ (remainder nanoseconds tm:nano)
369+ (quotient nanoseconds tm:nano)))
370+ (define (tm:nanoseconds->values nanoseconds)
371+ (values
372+ (abs (remainder nanoseconds tm:nano))
373+ (quotient nanoseconds tm:nano)))
374+ (define (tm:time-difference time1 time2 time3)
375+ (if (or (not (and (time? time1) (time? time2)))
376+ (not (eq? (time-type time1) (time-type time2))))
377+ (tm:time-error
378+ 'time-difference
379+ 'incompatible-time-types
380+ #f))
381+ (set-time-type! time3 time-duration)
382+ (if (time=? time1 time2)
383+ (begin
384+ (set-time-second! time3 0)
385+ (set-time-nanosecond! time3 0))
386+ (receive
387+ (nanos secs)
388+ (tm:nanoseconds->values
389+ (- (tm:time->nanoseconds time1)
390+ (tm:time->nanoseconds time2)))
391+ (set-time-second! time3 secs)
392+ (set-time-nanosecond! time3 nanos)))
393+ time3)
394+ (define (time-difference time1 time2)
395+ (tm:time-difference time1 time2 (make-time #f #f #f)))
396+ (define (time-difference! time1 time2)
397+ (tm:time-difference time1 time2 time1))
398+ (define (tm:add-duration time1 duration time3)
399+ (if (not (and (time? time1) (time? duration)))
400+ (tm:time-error 'add-duration 'incompatible-time-types #f))
401+ (if (not (eq? (time-type duration) time-duration))
402+ (tm:time-error 'add-duration 'not-duration duration)
403+ (let ([sec-plus (+ (time-second time1)
404+ (time-second duration))]
405+ [nsec-plus (+ (time-nanosecond time1)
406+ (time-nanosecond duration))])
407+ (let ([r (remainder nsec-plus tm:nano)]
408+ [q (quotient nsec-plus tm:nano)])
409+ (if (negative? r)
410+ (begin
411+ (set-time-second! time3 (+ sec-plus q -1))
412+ (set-time-nanosecond! time3 (+ tm:nano r)))
413+ (begin
414+ (set-time-second! time3 (+ sec-plus q))
415+ (set-time-nanosecond! time3 r)))
416+ time3))))
417+ (define (add-duration time1 duration)
418+ (tm:add-duration
419+ time1
420+ duration
421+ (make-time (time-type time1) #f #f)))
422+ (define (add-duration! time1 duration)
423+ (tm:add-duration time1 duration time1))
424+ (define (tm:subtract-duration time1 duration time3)
425+ (if (not (and (time? time1) (time? duration)))
426+ (tm:time-error 'add-duration 'incompatible-time-types #f))
427+ (if (not (eq? (time-type duration) time-duration))
428+ (tm:time-error 'tm:subtract-duration 'not-duration duration)
429+ (let ([sec-minus (- (time-second time1)
430+ (time-second duration))]
431+ [nsec-minus (- (time-nanosecond time1)
432+ (time-nanosecond duration))])
433+ (let ([r (remainder nsec-minus tm:nano)]
434+ [q (quotient nsec-minus tm:nano)])
435+ (if (negative? r)
436+ (begin
437+ (set-time-second! time3 (- sec-minus q 1))
438+ (set-time-nanosecond! time3 (+ tm:nano r)))
439+ (begin
440+ (set-time-second! time3 (- sec-minus q))
441+ (set-time-nanosecond! time3 r)))
442+ time3))))
443+ (define (subtract-duration time1 duration)
444+ (tm:subtract-duration
445+ time1
446+ duration
447+ (make-time (time-type time1) #f #f)))
448+ (define (subtract-duration! time1 duration)
449+ (tm:subtract-duration time1 duration time1))
450+ (define (tm:time-tai->time-utc! time-in time-out caller)
451+ (if (not (eq? (time-type time-in) time-tai))
452+ (tm:time-error caller 'incompatible-time-types time-in))
453+ (set-time-type! time-out time-utc)
454+ (set-time-nanosecond! time-out (time-nanosecond time-in))
455+ (set-time-second!
456+ time-out
457+ (- (time-second time-in)
458+ (tm:leap-second-neg-delta (time-second time-in))))
459+ time-out)
460+ (define (time-tai->time-utc time-in)
461+ (tm:time-tai->time-utc!
462+ time-in
463+ (make-time #f #f #f)
464+ 'time-tai->time-utc))
465+ (define (time-tai->time-utc! time-in)
466+ (tm:time-tai->time-utc!
467+ time-in
468+ time-in
469+ 'time-tai->time-utc!))
470+ (define (tm:time-utc->time-tai! time-in time-out caller)
471+ (if (not (eq? (time-type time-in) time-utc))
472+ (tm:time-error caller 'incompatible-time-types time-in))
473+ (set-time-type! time-out time-tai)
474+ (set-time-nanosecond! time-out (time-nanosecond time-in))
475+ (set-time-second!
476+ time-out
477+ (+ (time-second time-in)
478+ (tm:leap-second-delta (time-second time-in))))
479+ time-out)
480+ (define (time-utc->time-tai time-in)
481+ (tm:time-utc->time-tai!
482+ time-in
483+ (make-time #f #f #f)
484+ 'time-utc->time-tai))
485+ (define (time-utc->time-tai! time-in)
486+ (tm:time-utc->time-tai!
487+ time-in
488+ time-in
489+ 'time-utc->time-tai!))
490+ (define (time-monotonic->time-utc time-in)
491+ (if (not (eq? (time-type time-in) time-monotonic))
492+ (tm:time-error
493+ 'time-monotoinc->time-utc
494+ 'incompatible-time-types
495+ time-in))
496+ (let ([ntime (copy-time time-in)])
497+ (set-time-type! ntime time-tai)
498+ (tm:time-tai->time-utc!
499+ ntime
500+ ntime
501+ 'time-monotonic->time-utc)))
502+ (define (time-monotonic->time-utc! time-in)
503+ (if (not (eq? (time-type time-in) time-monotonic))
504+ (tm:time-error
505+ 'time-monotonic->time-utc!
506+ 'incompatible-time-types
507+ time-in))
508+ (set-time-type! time-in time-tai)
509+ (tm:time-tai->time-utc!
510+ time-in
511+ time-in
512+ 'time-monotonic->time-utc))
513+ (define (time-monotonic->time-tai time-in)
514+ (if (not (eq? (time-type time-in) time-monotonic))
515+ (tm:time-error
516+ 'time-monotonic->time-tai
517+ 'incompatible-time-types
518+ time-in))
519+ (let ([ntime (copy-time time-in)])
520+ (set-time-type! ntime time-tai)
521+ ntime))
522+ (define (time-monotonic->time-tai! time-in)
523+ (if (not (eq? (time-type time-in) time-monotonic))
524+ (tm:time-error
525+ 'time-monotonic->time-tai!
526+ 'incompatible-time-types
527+ time-in))
528+ (set-time-type! time-in time-tai)
529+ time-in)
530+ (define (time-utc->time-monotonic time-in)
531+ (if (not (eq? (time-type time-in) time-utc))
532+ (tm:time-error
533+ 'time-utc->time-monotonic
534+ 'incompatible-time-types
535+ time-in))
536+ (let ([ntime (tm:time-utc->time-tai!
537+ time-in
538+ (make-time #f #f #f)
539+ 'time-utc->time-monotonic)])
540+ (set-time-type! ntime time-monotonic)
541+ ntime))
542+ (define (time-utc->time-monotonic! time-in)
543+ (if (not (eq? (time-type time-in) time-utc))
544+ (tm:time-error
545+ 'time-utc->time-montonic!
546+ 'incompatible-time-types
547+ time-in))
548+ (let ([ntime (tm:time-utc->time-tai!
549+ time-in
550+ time-in
551+ 'time-utc->time-monotonic!)])
552+ (set-time-type! ntime time-monotonic)
553+ ntime))
554+ (define (time-tai->time-monotonic time-in)
555+ (if (not (eq? (time-type time-in) time-tai))
556+ (tm:time-error
557+ 'time-tai->time-monotonic
558+ 'incompatible-time-types
559+ time-in))
560+ (let ([ntime (copy-time time-in)])
561+ (set-time-type! ntime time-monotonic)
562+ ntime))
563+ (define (time-tai->time-monotonic! time-in)
564+ (if (not (eq? (time-type time-in) time-tai))
565+ (tm:time-error
566+ 'time-tai->time-monotonic!
567+ 'incompatible-time-types
568+ time-in))
569+ (set-time-type! time-in time-monotonic)
570+ time-in)
571+ (define-struct
572+ date
573+ (nanosecond second minute hour day month year zone-offset)
574+ (make-inspector))
575+ (define tm:set-date-nanosecond! set-date-nanosecond!)
576+ (define tm:set-date-second! set-date-second!)
577+ (define tm:set-date-minute! set-date-minute!)
578+ (define tm:set-date-hour! set-date-hour!)
579+ (define tm:set-date-day! set-date-day!)
580+ (define tm:set-date-month! set-date-month!)
581+ (define tm:set-date-year! set-date-year!)
582+ (define tm:set-date-zone-offset! set-date-zone-offset!)
583+ (define (set-date-second! date val)
584+ (tm:time-error 'set-date-second! 'dates-are-immutable date))
585+ (define (set-date-minute! date val)
586+ (tm:time-error 'set-date-minute! 'dates-are-immutable date))
587+ (define (set-date-day! date val)
588+ (tm:time-error 'set-date-day! 'dates-are-immutable date))
589+ (define (set-date-month! date val)
590+ (tm:time-error 'set-date-month! 'dates-are-immutable date))
591+ (define (set-date-year! date val)
592+ (tm:time-error 'set-date-year! 'dates-are-immutable date))
593+ (define (set-date-zone-offset! date val)
594+ (tm:time-error
595+ 'set-date-zone-offset!
596+ 'dates-are-immutable
597+ date))
598+ (define (tm:encode-julian-day-number day month year)
599+ (let* ([a (quotient (- 14 month) 12)]
600+ [y (- (- (+ year 4800) a) (if (negative? year) -1 0))]
601+ [m (- (+ month (* 12 a)) 3)])
602+ (+ day (quotient (+ (* 153 m) 2) 5) (* 365 y) (quotient y 4)
603+ (- (quotient y 100)) (quotient y 400) -32045)))
604+ (define (tm:char-pos char str index len)
605+ (cond
606+ [(>= index len) #f]
607+ [(char=? (string-ref str index) char) index]
608+ [else (tm:char-pos char str (+ index 1) len)]))
609+ (define (tm:fractional-part r)
610+ (if (integer? r)
611+ "0"
612+ (let ([str (number->string (exact->inexact r))])
613+ (let ([ppos (tm:char-pos #\. str 0 (string-length str))])
614+ (substring str (+ ppos 1) (string-length str))))))
615+ (define (tm:decode-julian-day-number jdn)
616+ (let* ([days (truncate jdn)]
617+ [a (+ days 32044)]
618+ [b (quotient (+ (* 4 a) 3) 146097)]
619+ [c (- a (quotient (* 146097 b) 4))]
620+ [d (quotient (+ (* 4 c) 3) 1461)]
621+ [e (- c (quotient (* 1461 d) 4))]
622+ [m (quotient (+ (* 5 e) 2) 153)]
623+ [y (+ (* 100 b) d -4800 (quotient m 10))])
624+ (values
625+ (* (- jdn days) tm:sid)
626+ (+ e (- (quotient (+ (* 153 m) 2) 5)) 1)
627+ (+ m 3 (* -12 (quotient m 10)))
628+ (if (>= 0 y) (- y 1) y))))
629+ (define (tm:local-tz-offset)
630+ (date-time-zone-offset (seconds->date (current-seconds))))
631+ (define (tm:time->julian-day-number seconds tz-offset)
632+ (+ (/ (+ seconds tz-offset tm:sihd) tm:sid)
633+ tm:tai-epoch-in-jd))
634+ (define (tm:find proc l)
635+ (if (null? l)
636+ #f
637+ (if (proc (car l)) #t (tm:find proc (cdr l)))))
638+ (define (tm:tai-before-leap-second? second)
639+ (tm:find
640+ (lambda (x) (= second (- (+ (car x) (cdr x)) 1)))
641+ tm:leap-second-table))
642+ (define (tm:time->date time tz-offset ttype)
643+ (if (not (eq? (time-type time) ttype))
644+ (tm:time-error 'time->date 'incompatible-time-types time))
645+ (let* ([offset (:optional tz-offset (tm:local-tz-offset))])
646+ (receive
647+ (secs date month year)
648+ (tm:decode-julian-day-number
649+ (tm:time->julian-day-number (time-second time) offset))
650+ (let* ([hours (quotient secs (* 60 60))]
651+ [rem (remainder secs (* 60 60))]
652+ [minutes (quotient rem 60)]
653+ [seconds (remainder rem 60)])
654+ (make-date (time-nanosecond time) seconds minutes hours date
655+ month year offset)))))
656+ (define (time-tai->date time . tz-offset)
657+ (if (tm:tai-before-leap-second? (time-second time))
658+ (let ([d (tm:time->date
659+ (subtract-duration!
660+ (time-tai->time-utc time)
661+ (make-time time-duration 0 1))
662+ tz-offset
663+ time-utc)])
664+ (tm:set-date-second! d 60)
665+ d)
666+ (tm:time->date
667+ (time-tai->time-utc time)
668+ tz-offset
669+ time-utc)))
670+ (define (time-utc->date time . tz-offset)
671+ (tm:time->date time tz-offset time-utc))
672+ (define (time-monotonic->date time . tz-offset)
673+ (tm:time->date time tz-offset time-monotonic))
674+ (define (date->time-utc date)
675+ (let ([nanosecond (date-nanosecond date)]
676+ [second (date-second date)]
677+ [minute (date-minute date)]
678+ [hour (date-hour date)]
679+ [day (date-day date)]
680+ [month (date-month date)]
681+ [year (date-year date)]
682+ [offset (date-zone-offset date)])
683+ (let ([jdays (- (tm:encode-julian-day-number day month year)
684+ tm:tai-epoch-in-jd)])
685+ (make-time
686+ time-utc
687+ nanosecond
688+ (+ (* (- jdays 1/2) 24 60 60) (* hour 60 60) (* minute 60)
689+ second (- offset))))))
690+ (define (date->time-tai d)
691+ (if (= (date-second d) 60)
692+ (subtract-duration!
693+ (time-utc->time-tai! (date->time-utc d))
694+ (make-time time-duration 0 1))
695+ (time-utc->time-tai! (date->time-utc d))))
696+ (define (date->time-monotonic date)
697+ (time-utc->time-monotonic! (date->time-utc date)))
698+ (define (tm:leap-year? year)
699+ (or (= (modulo year 400) 0)
700+ (and (= (modulo year 4) 0) (not (= (modulo year 100) 0)))))
701+ (define (leap-year? date) (tm:leap-year? (date-year date)))
702+ (define tm:month-assoc
703+ '((0 . 0) (1 . 31) (2 . 59) (3 . 90) (4 . 120) (5 . 151)
704+ (6 . 181) (7 . 212) (8 . 243) (9 . 273) (10 . 304)
705+ (11 . 334)))
706+ (define (tm:year-day day month year)
707+ (let ([days-pr (assoc (- month 1) tm:month-assoc)])
708+ (if (not days-pr)
709+ (tm:time-error
710+ 'date-year-day
711+ 'invalid-month-specification
712+ month))
713+ (if (and (tm:leap-year? year) (> month 2))
714+ (+ day (cdr days-pr) 1)
715+ (+ day (cdr days-pr)))))
716+ (define (date-year-day date)
717+ (tm:year-day
718+ (date-day date)
719+ (date-month date)
720+ (date-year date)))
721+ (define (tm:week-day day month year)
722+ (let* ([a (quotient (- 14 month) 12)]
723+ [y (- year a)]
724+ [m (+ month (* 12 a) -2)])
725+ (modulo
726+ (+ day y (quotient y 4) (- (quotient y 100))
727+ (quotient y 400) (quotient (* 31 m) 12))
728+ 7)))
729+ (define (date-week-day date)
730+ (tm:week-day
731+ (date-day date)
732+ (date-month date)
733+ (date-year date)))
734+ (define (tm:days-before-first-week date
735+ day-of-week-starting-week)
736+ (let* ([first-day (make-date 0 0 0 0 1 1 (date-year date)
737+ #f)]
738+ [fdweek-day (date-week-day first-day)])
739+ (modulo (- day-of-week-starting-week fdweek-day) 7)))
740+ (define (date-week-number date day-of-week-starting-week)
741+ (quotient
742+ (- (date-year-day date)
743+ (tm:days-before-first-week date day-of-week-starting-week))
744+ 7))
745+ (define (current-date . tz-offset)
746+ (time-utc->date
747+ (current-time time-utc)
748+ (:optional tz-offset (tm:local-tz-offset))))
749+ (define (tm:natural-year n)
750+ (let* ([current-year (date-year (current-date))]
751+ [current-century (* (quotient current-year 100) 100)])
752+ (cond
753+ [(>= n 100) n]
754+ [(< n 0) n]
755+ [(<= (- (+ current-century n) current-year) 50)
756+ (+ current-century n)]
757+ [else (+ (- current-century 100) n)])))
758+ (define (date->julian-day date)
759+ (let ([nanosecond (date-nanosecond date)]
760+ [second (date-second date)]
761+ [minute (date-minute date)]
762+ [hour (date-hour date)]
763+ [day (date-day date)]
764+ [month (date-month date)]
765+ [year (date-year date)]
766+ [offset (date-zone-offset date)])
767+ (+ (tm:encode-julian-day-number day month year)
768+ (- 1/2)
769+ (+ (/ (/ (+ (* hour 60 60)
770+ (* minute 60)
771+ second
772+ (/ nanosecond tm:nano))
773+ tm:sid)
774+ (- offset))))))
775+ (define (date->modified-julian-day date)
776+ (- (date->julian-day date) 4800001/2))
777+ (define (time-utc->julian-day time)
778+ (if (not (eq? (time-type time) time-utc))
779+ (tm:time-error
780+ 'time-utc->julian-day
781+ 'incompatible-time-types
782+ time))
783+ (+ (/ (+ (time-second time)
784+ (/ (time-nanosecond time) tm:nano))
785+ tm:sid)
786+ tm:tai-epoch-in-jd))
787+ (define (time-utc->modified-julian-day time)
788+ (- (time-utc->julian-day time) 4800001/2))
789+ (define (time-tai->julian-day time)
790+ (if (not (eq? (time-type time) time-tai))
791+ (tm:time-error
792+ 'time-tai->julian-day
793+ 'incompatible-time-types
794+ time))
795+ (+ (/ (+ (- (time-second time)
796+ (tm:leap-second-delta (time-second time)))
797+ (/ (time-nanosecond time) tm:nano))
798+ tm:sid)
799+ tm:tai-epoch-in-jd))
800+ (define (time-tai->modified-julian-day time)
801+ (- (time-tai->julian-day time) 4800001/2))
802+ (define (time-monotonic->julian-day time)
803+ (if (not (eq? (time-type time) time-monotonic))
804+ (tm:time-error
805+ 'time-monotonic->julian-day
806+ 'incompatible-time-types
807+ time))
808+ (+ (/ (+ (- (time-second time)
809+ (tm:leap-second-delta (time-second time)))
810+ (/ (time-nanosecond time) tm:nano))
811+ tm:sid)
812+ tm:tai-epoch-in-jd))
813+ (define (time-monotonic->modified-julian-day time)
814+ (- (time-monotonic->julian-day time) 4800001/2))
815+ (define (julian-day->time-utc jdn)
816+ (let ([nanosecs (* tm:nano
817+ tm:sid
818+ (- jdn tm:tai-epoch-in-jd))])
819+ (make-time
820+ time-utc
821+ (remainder nanosecs tm:nano)
822+ (floor (/ nanosecs tm:nano)))))
823+ (define (julian-day->time-tai jdn)
824+ (time-utc->time-tai! (julian-day->time-utc jdn)))
825+ (define (julian-day->time-monotonic jdn)
826+ (time-utc->time-monotonic! (julian-day->time-utc jdn)))
827+ (define (julian-day->date jdn . tz-offset)
828+ (let ([offset (:optional tz-offset (tm:local-tz-offset))])
829+ (time-utc->date (julian-day->time-utc jdn) offset)))
830+ (define (modified-julian-day->date jdn . tz-offset)
831+ (let ([offset (:optional tz-offset (tm:local-tz-offset))])
832+ (julian-day->date (+ jdn 4800001/2) offset)))
833+ (define (modified-julian-day->time-utc jdn)
834+ (julian-day->time-utc (+ jdn 4800001/2)))
835+ (define (modified-julian-day->time-tai jdn)
836+ (julian-day->time-tai (+ jdn 4800001/2)))
837+ (define (modified-julian-day->time-monotonic jdn)
838+ (julian-day->time-monotonic (+ jdn 4800001/2)))
839+ (define (current-julian-day)
840+ (time-utc->julian-day (current-time time-utc)))
841+ (define (current-modified-julian-day)
842+ (time-utc->modified-julian-day (current-time time-utc)))
843+ (define (tm:padding n pad-with length)
844+ (let* ([str (number->string n)]
845+ [str-len (string-length str)])
846+ (if (or (> str-len length) (not pad-with))
847+ str
848+ (let* ([new-str (make-string length pad-with)]
849+ [new-str-offset (- (string-length new-str) str-len)])
850+ (do ([i 0 (+ i 1)])
851+ ((>= i (string-length str)))
852+ (string-set!
853+ new-str
854+ (+ new-str-offset i)
855+ (string-ref str i)))
856+ new-str))))
857+ (define (tm:last-n-digits i n)
858+ (abs (remainder i (expt 10 n))))
859+ (define (tm:locale-abbr-weekday n)
860+ (vector-ref tm:locale-abbr-weekday-vector n))
861+ (define (tm:locale-long-weekday n)
862+ (vector-ref tm:locale-long-weekday-vector n))
863+ (define (tm:locale-abbr-month n)
864+ (vector-ref tm:locale-abbr-month-vector n))
865+ (define (tm:locale-long-month n)
866+ (vector-ref tm:locale-long-month-vector n))
867+ (define (tm:vector-find needle haystack comparator)
868+ (let ([len (vector-length haystack)])
869+ (define (tm:vector-find-int index)
870+ (cond
871+ [(>= index len) #f]
872+ [(comparator needle (vector-ref haystack index)) index]
873+ [else (tm:vector-find-int (+ index 1))]))
874+ (tm:vector-find-int 0)))
875+ (define (tm:locale-abbr-weekday->index string)
876+ (tm:vector-find
877+ string
878+ tm:locale-abbr-weekday-vector
879+ string=?))
880+ (define (tm:locale-long-weekday->index string)
881+ (tm:vector-find
882+ string
883+ tm:locale-long-weekday-vector
884+ string=?))
885+ (define (tm:locale-abbr-month->index string)
886+ (tm:vector-find
887+ string
888+ tm:locale-abbr-month-vector
889+ string=?))
890+ (define (tm:locale-long-month->index string)
891+ (tm:vector-find
892+ string
893+ tm:locale-long-month-vector
894+ string=?))
895+ (define (tm:locale-print-time-zone date port) (values))
896+ (define (tm:locale-am/pm hr)
897+ (if (> hr 11) tm:locale-pm tm:locale-am))
898+ (define (tm:tz-printer offset port)
899+ (cond
900+ [(= offset 0) (display "Z" port)]
901+ [(negative? offset) (display "-" port)]
902+ [else (display "+" port)])
903+ (if (not (= offset 0))
904+ (let ([hours (abs (quotient offset (* 60 60)))]
905+ [minutes (abs (quotient
906+ (remainder offset (* 60 60))
907+ 60))])
908+ (display (tm:padding hours #\0 2) port)
909+ (display (tm:padding minutes #\0 2) port))))
910+ (define tm:directives
911+ (list
912+ (cons #\~ (lambda (date pad-with port) (display #\~ port)))
913+ (cons
914+ #\a
915+ (lambda (date pad-with port)
916+ (display
917+ (tm:locale-abbr-weekday (date-week-day date))
918+ port)))
919+ (cons
920+ #\A
921+ (lambda (date pad-with port)
922+ (display
923+ (tm:locale-long-weekday (date-week-day date))
924+ port)))
925+ (cons
926+ #\b
927+ (lambda (date pad-with port)
928+ (display (tm:locale-abbr-month (date-month date)) port)))
929+ (cons
930+ #\B
931+ (lambda (date pad-with port)
932+ (display (tm:locale-long-month (date-month date)) port)))
933+ (cons
934+ #\c
935+ (lambda (date pad-with port)
936+ (display
937+ (date->string date tm:locale-date-time-format)
938+ port)))
939+ (cons
940+ #\d
941+ (lambda (date pad-with port)
942+ (display (tm:padding (date-day date) #\0 2) port)))
943+ (cons
944+ #\D
945+ (lambda (date pad-with port)
946+ (display (date->string date "~m/~d/~y") port)))
947+ (cons
948+ #\e
949+ (lambda (date pad-with port)
950+ (display (tm:padding (date-day date) #\space 2) port)))
951+ (cons
952+ #\f
953+ (lambda (date pad-with port)
954+ (if (> (date-nanosecond date) tm:nano)
955+ (display
956+ (tm:padding (+ (date-second date) 1) pad-with 2)
957+ port)
958+ (display (tm:padding (date-second date) pad-with 2) port))
959+ (let* ([ns (tm:fractional-part
960+ (/ (date-nanosecond date) tm:nano 1.0))]
961+ [le (string-length ns)])
962+ (if (> le 2)
963+ (begin
964+ (display tm:locale-number-separator port)
965+ (display (substring ns 2 le) port))))))
966+ (cons
967+ #\h
968+ (lambda (date pad-with port)
969+ (display (date->string date "~b") port)))
970+ (cons
971+ #\H
972+ (lambda (date pad-with port)
973+ (display (tm:padding (date-hour date) pad-with 2) port)))
974+ (cons
975+ #\I
976+ (lambda (date pad-with port)
977+ (let ([hr (date-hour date)])
978+ (if (> hr 12)
979+ (display (tm:padding (- hr 12) pad-with 2) port)
980+ (display (tm:padding hr pad-with 2) port)))))
981+ (cons
982+ #\j
983+ (lambda (date pad-with port)
984+ (display
985+ (tm:padding (date-year-day date) pad-with 3)
986+ port)))
987+ (cons
988+ #\k
989+ (lambda (date pad-with port)
990+ (display (tm:padding (date-hour date) #\space 2) port)))
991+ (cons
992+ #\l
993+ (lambda (date pad-with port)
994+ (let ([hr (if (> (date-hour date) 12)
995+ (- (date-hour date) 12)
996+ (date-hour date))])
997+ (display (tm:padding hr #\space 2) port))))
998+ (cons
999+ #\m
1000+ (lambda (date pad-with port)
1001+ (display (tm:padding (date-month date) pad-with 2) port)))
1002+ (cons
1003+ #\M
1004+ (lambda (date pad-with port)
1005+ (display (tm:padding (date-minute date) pad-with 2) port)))
1006+ (cons #\n (lambda (date pad-with port) (newline port)))
1007+ (cons
1008+ #\N
1009+ (lambda (date pad-with port)
1010+ (display
1011+ (tm:padding (date-nanosecond date) pad-with 9)
1012+ port)))
1013+ (cons
1014+ #\p
1015+ (lambda (date pad-with port)
1016+ (display (tm:locale-am/pm (date-hour date)) port)))
1017+ (cons
1018+ #\r
1019+ (lambda (date pad-with port)
1020+ (display (date->string date "~I:~M:~S ~p") port)))
1021+ (cons
1022+ #\s
1023+ (lambda (date pad-with port)
1024+ (display (time-second (date->time-utc date)) port)))
1025+ (cons
1026+ #\S
1027+ (lambda (date pad-with port)
1028+ (if (> (date-nanosecond date) tm:nano)
1029+ (display
1030+ (tm:padding (+ (date-second date) 1) pad-with 2)
1031+ port)
1032+ (display
1033+ (tm:padding (date-second date) pad-with 2)
1034+ port))))
1035+ (cons
1036+ #\t
1037+ (lambda (date pad-with port)
1038+ (display (integer->char 9) port)))
1039+ (cons
1040+ #\T
1041+ (lambda (date pad-with port)
1042+ (display (date->string date "~H:~M:~S") port)))
1043+ (cons
1044+ #\U
1045+ (lambda (date pad-with port)
1046+ (if (> (tm:days-before-first-week date 0) 0)
1047+ (display
1048+ (tm:padding (+ (date-week-number date 0) 1) #\0 2)
1049+ port)
1050+ (display
1051+ (tm:padding (date-week-number date 0) #\0 2)
1052+ port))))
1053+ (cons
1054+ #\V
1055+ (lambda (date pad-with port)
1056+ (display
1057+ (tm:padding (date-week-number date 1) #\0 2)
1058+ port)))
1059+ (cons
1060+ #\w
1061+ (lambda (date pad-with port)
1062+ (display (date-week-day date) port)))
1063+ (cons
1064+ #\x
1065+ (lambda (date pad-with port)
1066+ (display
1067+ (date->string date tm:locale-short-date-format)
1068+ port)))
1069+ (cons
1070+ #\X
1071+ (lambda (date pad-with port)
1072+ (display (date->string date tm:locale-time-format) port)))
1073+ (cons
1074+ #\W
1075+ (lambda (date pad-with port)
1076+ (if (> (tm:days-before-first-week date 1) 0)
1077+ (display
1078+ (tm:padding (+ (date-week-number date 1) 1) #\0 2)
1079+ port)
1080+ (display
1081+ (tm:padding (date-week-number date 1) #\0 2)
1082+ port))))
1083+ (cons
1084+ #\y
1085+ (lambda (date pad-with port)
1086+ (display
1087+ (tm:padding
1088+ (tm:last-n-digits (date-year date) 2)
1089+ pad-with
1090+ 2)
1091+ port)))
1092+ (cons
1093+ #\Y
1094+ (lambda (date pad-with port)
1095+ (display (tm:padding (date-year date) pad-with 4) port)))
1096+ (cons
1097+ #\z
1098+ (lambda (date pad-with port)
1099+ (tm:tz-printer (date-zone-offset date) port)))
1100+ (cons
1101+ #\Z
1102+ (lambda (date pad-with port)
1103+ (tm:locale-print-time-zone date port)))
1104+ (cons
1105+ #\1
1106+ (lambda (date pad-with port)
1107+ (display (date->string date "~Y-~m-~d") port)))
1108+ (cons
1109+ #\2
1110+ (lambda (date pad-with port)
1111+ (display (date->string date "~k:~M:~S~z") port)))
1112+ (cons
1113+ #\3
1114+ (lambda (date pad-with port)
1115+ (display (date->string date "~k:~M:~S") port)))
1116+ (cons
1117+ #\4
1118+ (lambda (date pad-with port)
1119+ (display (date->string date "~Y-~m-~dT~k:~M:~S~z") port)))
1120+ (cons
1121+ #\5
1122+ (lambda (date pad-with port)
1123+ (display (date->string date "~Y-~m-~dT~k:~M:~S") port)))))
1124+ (define (tm:get-formatter char)
1125+ (let ([associated (assoc char tm:directives)])
1126+ (if associated (cdr associated) #f)))
1127+ (define (tm:date-printer date index format-string str-len
1128+ port)
1129+ (if (>= index str-len)
1130+ (values)
1131+ (let ([current-char (string-ref format-string index)])
1132+ (if (not (char=? current-char #\~))
1133+ (begin
1134+ (display current-char port)
1135+ (tm:date-printer date (+ index 1) format-string str-len
1136+ port))
1137+ (if (= (+ index 1) str-len)
1138+ (tm:time-error
1139+ 'tm:date-printer
1140+ 'bad-date-format-string
1141+ format-string)
1142+ (let ([pad-char? (string-ref
1143+ format-string
1144+ (+ index 1))])
1145+ (cond
1146+ [(char=? pad-char? #\-)
1147+ (if (= (+ index 2) str-len)
1148+ (tm:time-error
1149+ 'tm:date-printer
1150+ 'bad-date-format-string
1151+ format-string)
1152+ (let ([formatter (tm:get-formatter
1153+ (string-ref
1154+ format-string
1155+ (+ index 2)))])
1156+ (if (not formatter)
1157+ (tm:time-error
1158+ 'tm:date-printer
1159+ 'bad-date-format-string
1160+ format-string)
1161+ (begin
1162+ (formatter date #f port)
1163+ (tm:date-printer date (+ index 3)
1164+ format-string str-len port)))))]
1165+ [(char=? pad-char? #\_)
1166+ (if (= (+ index 2) str-len)
1167+ (tm:time-error
1168+ 'tm:date-printer
1169+ 'bad-date-format-string
1170+ format-string)
1171+ (let ([formatter (tm:get-formatter
1172+ (string-ref
1173+ format-string
1174+ (+ index 2)))])
1175+ (if (not formatter)
1176+ (tm:time-error
1177+ 'tm:date-printer
1178+ 'bad-date-format-string
1179+ format-string)
1180+ (begin
1181+ (formatter date #\space port)
1182+ (tm:date-printer date (+ index 3)
1183+ format-string str-len port)))))]
1184+ [else
1185+ (let ([formatter (tm:get-formatter
1186+ (string-ref
1187+ format-string
1188+ (+ index 1)))])
1189+ (if (not formatter)
1190+ (tm:time-error
1191+ 'tm:date-printer
1192+ 'bad-date-format-string
1193+ format-string)
1194+ (begin
1195+ (formatter date #\0 port)
1196+ (tm:date-printer date (+ index 2)
1197+ format-string str-len port))))])))))))
1198+ (define (date->string date . format-string)
1199+ (let ([str-port (open-output-string)]
1200+ [fmt-str (:optional format-string "~c")])
1201+ (tm:date-printer date 0 fmt-str (string-length fmt-str)
1202+ str-port)
1203+ (get-output-string str-port)))
1204+ (define (tm:char->int ch)
1205+ (cond
1206+ [(char=? ch #\0) 0]
1207+ [(char=? ch #\1) 1]
1208+ [(char=? ch #\2) 2]
1209+ [(char=? ch #\3) 3]
1210+ [(char=? ch #\4) 4]
1211+ [(char=? ch #\5) 5]
1212+ [(char=? ch #\6) 6]
1213+ [(char=? ch #\7) 7]
1214+ [(char=? ch #\8) 8]
1215+ [(char=? ch #\9) 9]
1216+ [else
1217+ (tm:time-error
1218+ 'string->date
1219+ 'bad-date-template-string
1220+ (list "Non-integer character" ch))]))
1221+ (define (tm:integer-reader upto port)
1222+ (define (accum-int port accum nchars)
1223+ (let ([ch (peek-char port)])
1224+ (if (or (eof-object? ch)
1225+ (not (char-numeric? ch))
1226+ (and upto (>= nchars upto)))
1227+ accum
1228+ (accum-int
1229+ port
1230+ (+ (* accum 10) (tm:char->int (read-char port)))
1231+ (+ nchars 1)))))
1232+ (accum-int port 0 0))
1233+ (define (tm:make-integer-reader upto)
1234+ (lambda (port) (tm:integer-reader upto port)))
1235+ (define (tm:fractional-integer-reader upto port)
1236+ (define (accum-int port accum nchars)
1237+ (let ([ch (peek-char port)])
1238+ (if (or (eof-object? ch)
1239+ (not (char-numeric? ch))
1240+ (and upto (>= nchars upto)))
1241+ (* accum (expt 10 (- upto nchars)))
1242+ (accum-int
1243+ port
1244+ (+ (* accum 10) (tm:char->int (read-char port)))
1245+ (+ nchars 1)))))
1246+ (accum-int port 0 0))
1247+ (define (tm:make-fractional-integer-reader upto)
1248+ (lambda (port) (tm:fractional-integer-reader upto port)))
1249+ (define (tm:integer-reader-exact n port)
1250+ (let ([padding-ok #t])
1251+ (define (accum-int port accum nchars)
1252+ (let ([ch (peek-char port)])
1253+ (cond
1254+ [(>= nchars n) accum]
1255+ [(eof-object? ch)
1256+ (tm:time-error
1257+ 'string->date
1258+ 'bad-date-template-string
1259+ "Premature ending to integer read.")]
1260+ [(char-numeric? ch)
1261+ (set! padding-ok #f)
1262+ (accum-int
1263+ port
1264+ (+ (* accum 10) (tm:char->int (read-char port)))
1265+ (+ nchars 1))]
1266+ [padding-ok
1267+ (read-char port)
1268+ (accum-int port accum (+ nchars 1))]
1269+ [else
1270+ (tm:time-error
1271+ 'string->date
1272+ 'bad-date-template-string
1273+ "Non-numeric characters in integer read.")])))
1274+ (accum-int port 0 0)))
1275+ (define (tm:make-integer-exact-reader n)
1276+ (lambda (port) (tm:integer-reader-exact n port)))
1277+ (define (tm:zone-reader port)
1278+ (let ([offset 0] [positive? #f])
1279+ (let ([ch (read-char port)])
1280+ (if (eof-object? ch)
1281+ (tm:time-error
1282+ 'string->date
1283+ 'bad-date-template-string
1284+ (list "Invalid time zone +/-" ch)))
1285+ (if (or (char=? ch #\Z) (char=? ch #\z))
1286+ 0
1287+ (begin
1288+ (cond
1289+ [(char=? ch #\+) (set! positive? #t)]
1290+ [(char=? ch #\-) (set! positive? #f)]
1291+ [else
1292+ (tm:time-error
1293+ 'string->date
1294+ 'bad-date-template-string
1295+ (list "Invalid time zone +/-" ch))])
1296+ (let ([ch (read-char port)])
1297+ (if (eof-object? ch)
1298+ (tm:time-error
1299+ 'string->date
1300+ 'bad-date-template-string
1301+ (list "Invalid time zone number" ch)))
1302+ (set! offset (* (tm:char->int ch) 10 60 60)))
1303+ (let ([ch (read-char port)])
1304+ (if (eof-object? ch)
1305+ (tm:time-error
1306+ 'string->date
1307+ 'bad-date-template-string
1308+ (list "Invalid time zone number" ch)))
1309+ (set! offset (+ offset (* (tm:char->int ch) 60 60))))
1310+ (let ([ch (read-char port)])
1311+ (if (eof-object? ch)
1312+ (tm:time-error
1313+ 'string->date
1314+ 'bad-date-template-string
1315+ (list "Invalid time zone number" ch)))
1316+ (set! offset (+ offset (* (tm:char->int ch) 10 60))))
1317+ (let ([ch (read-char port)])
1318+ (if (eof-object? ch)
1319+ (tm:time-error
1320+ 'string->date
1321+ 'bad-date-template-string
1322+ (list "Invalid time zone number" ch)))
1323+ (set! offset (+ offset (* (tm:char->int ch) 60))))
1324+ (if positive? offset (- offset)))))))
1325+ (define (tm:locale-reader port indexer)
1326+ (let ([string-port (open-output-string)])
1327+ (define (read-char-string)
1328+ (let ([ch (peek-char port)])
1329+ (if (char-alphabetic? ch)
1330+ (begin
1331+ (write-char (read-char port) string-port)
1332+ (read-char-string))
1333+ (get-output-string string-port))))
1334+ (let* ([str (read-char-string)] [index (indexer str)])
1335+ (if index
1336+ index
1337+ (tm:time-error
1338+ 'string->date
1339+ 'bad-date-template-string
1340+ (list "Invalid string for " indexer))))))
1341+ (define (tm:make-locale-reader indexer)
1342+ (lambda (port) (tm:locale-reader port indexer)))
1343+ (define (tm:make-char-id-reader char)
1344+ (lambda (port)
1345+ (if (char=? char (read-char port))
1346+ char
1347+ (tm:time-error
1348+ 'string->date
1349+ 'bad-date-template-string
1350+ "Invalid character match."))))
1351+ (define tm:read-directives
1352+ (let ([ireader4 (tm:make-integer-reader 4)]
1353+ [ireader2 (tm:make-integer-reader 2)]
1354+ [fireader9 (tm:make-fractional-integer-reader 9)]
1355+ [ireaderf (tm:make-integer-reader #f)]
1356+ [eireader2 (tm:make-integer-exact-reader 2)]
1357+ [eireader4 (tm:make-integer-exact-reader 4)]
1358+ [locale-reader-abbr-weekday (tm:make-locale-reader
1359+ tm:locale-abbr-weekday->index)]
1360+ [locale-reader-long-weekday (tm:make-locale-reader
1361+ tm:locale-long-weekday->index)]
1362+ [locale-reader-abbr-month (tm:make-locale-reader
1363+ tm:locale-abbr-month->index)]
1364+ [locale-reader-long-month (tm:make-locale-reader
1365+ tm:locale-long-month->index)]
1366+ [char-fail (lambda (ch) #t)]
1367+ [do-nothing (lambda (val object) (values))])
1368+ (list
1369+ (list #\~ char-fail (tm:make-char-id-reader #\~) do-nothing)
1370+ (list
1371+ #\a
1372+ char-alphabetic?
1373+ locale-reader-abbr-weekday
1374+ do-nothing)
1375+ (list
1376+ #\A
1377+ char-alphabetic?
1378+ locale-reader-long-weekday
1379+ do-nothing)
1380+ (list
1381+ #\b
1382+ char-alphabetic?
1383+ locale-reader-abbr-month
1384+ (lambda (val object) (tm:set-date-month! object val)))
1385+ (list
1386+ #\B
1387+ char-alphabetic?
1388+ locale-reader-long-month
1389+ (lambda (val object) (tm:set-date-month! object val)))
1390+ (list
1391+ #\d
1392+ char-numeric?
1393+ ireader2
1394+ (lambda (val object) (tm:set-date-day! object val)))
1395+ (list
1396+ #\e
1397+ char-fail
1398+ eireader2
1399+ (lambda (val object) (tm:set-date-day! object val)))
1400+ (list
1401+ #\h
1402+ char-alphabetic?
1403+ locale-reader-abbr-month
1404+ (lambda (val object) (tm:set-date-month! object val)))
1405+ (list
1406+ #\H
1407+ char-numeric?
1408+ ireader2
1409+ (lambda (val object) (tm:set-date-hour! object val)))
1410+ (list
1411+ #\k
1412+ char-fail
1413+ eireader2
1414+ (lambda (val object) (tm:set-date-hour! object val)))
1415+ (list
1416+ #\m
1417+ char-numeric?
1418+ ireader2
1419+ (lambda (val object) (tm:set-date-month! object val)))
1420+ (list
1421+ #\M
1422+ char-numeric?
1423+ ireader2
1424+ (lambda (val object) (tm:set-date-minute! object val)))
1425+ (list
1426+ #\N
1427+ char-numeric?
1428+ fireader9
1429+ (lambda (val object) (tm:set-date-nanosecond! object val)))
1430+ (list
1431+ #\S
1432+ char-numeric?
1433+ ireader2
1434+ (lambda (val object) (tm:set-date-second! object val)))
1435+ (list
1436+ #\y
1437+ char-fail
1438+ eireader2
1439+ (lambda (val object)
1440+ (tm:set-date-year! object (tm:natural-year val))))
1441+ (list
1442+ #\Y
1443+ char-numeric?
1444+ ireader4
1445+ (lambda (val object) (tm:set-date-year! object val)))
1446+ (list
1447+ #\z
1448+ (lambda (c)
1449+ (or (char=? c #\Z)
1450+ (char=? c #\z)
1451+ (char=? c #\+)
1452+ (char=? c #\-)))
1453+ tm:zone-reader
1454+ (lambda (val object)
1455+ (tm:set-date-zone-offset! object val))))))
1456+ (define (tm:string->date date index format-string str-len
1457+ port template-string)
1458+ (define (skip-until port skipper)
1459+ (let ([ch (peek-char port)])
1460+ (if (eof-object? ch)
1461+ (tm:time-error
1462+ 'string->date
1463+ 'bad-date-format-string
1464+ template-string)
1465+ (if (not (skipper ch))
1466+ (begin (read-char port) (skip-until port skipper))))))
1467+ (if (>= index str-len)
1468+ (begin (values))
1469+ (let ([current-char (string-ref format-string index)])
1470+ (if (not (char=? current-char #\~))
1471+ (let ([port-char (read-char port)])
1472+ (if (or (eof-object? port-char)
1473+ (not (char=? current-char port-char)))
1474+ (tm:time-error
1475+ 'string->date
1476+ 'bad-date-format-string
1477+ template-string))
1478+ (tm:string->date date (+ index 1) format-string str-len
1479+ port template-string))
1480+ (if (> (+ index 1) str-len)
1481+ (tm:time-error
1482+ 'string->date
1483+ 'bad-date-format-string
1484+ template-string)
1485+ (let* ([format-char (string-ref
1486+ format-string
1487+ (+ index 1))]
1488+ [format-info (assoc
1489+ format-char
1490+ tm:read-directives)])
1491+ (if (not format-info)
1492+ (tm:time-error
1493+ 'string->date
1494+ 'bad-date-format-string
1495+ template-string)
1496+ (begin
1497+ (let ([skipper (cadr format-info)]
1498+ [reader (caddr format-info)]
1499+ [actor (cadddr format-info)])
1500+ (skip-until port skipper)
1501+ (let ([val (reader port)])
1502+ (if (eof-object? val)
1503+ (tm:time-error
1504+ 'string->date
1505+ 'bad-date-format-string
1506+ template-string)
1507+ (actor val date)))
1508+ (tm:string->date date (+ index 2)
1509+ format-string str-len port
1510+ template-string))))))))))
1511+ (define (string->date input-string template-string)
1512+ (define (tm:date-ok? date)
1513+ (and (date-nanosecond date)
1514+ (date-second date)
1515+ (date-minute date)
1516+ (date-hour date)
1517+ (date-day date)
1518+ (date-month date)
1519+ (date-year date)
1520+ (date-zone-offset date)))
1521+ (let ([newdate (make-date 0 0 0 0 #f #f #f
1522+ (tm:local-tz-offset))])
1523+ (tm:string->date newdate 0 template-string (string-length template-string)
1524+ (open-input-string input-string) template-string)
1525+ (if (tm:date-ok? newdate)
1526+ newdate
1527+ (tm:time-error
1528+ 'string->date
1529+ 'bad-date-format-string
1530+ (list
1531+ "Incomplete date read. "
1532+ newdate
1533+ template-string))))))))
lib/srfi/:19/time/compat.chezscheme.slsnew file+34
@@ -0,0 +1,34 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.chezscheme.sls
7+;;; Copyright (c) 2012 Aaron W. Hsu <arcfide@sacrideo.us>
8+;;;
9+;;; Permission to use, copy, modify, and distribute this software for
10+;;; any purpose with or without fee is hereby granted, provided that the
11+;;; above copyright notice and this permission notice appear in all
12+;;; copies.
13+;;;
14+;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
15+;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
16+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
17+;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
18+;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
19+;;; OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20+;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21+;;; PERFORMANCE OF THIS SOFTWARE.
22+(library (srfi :19 time compat)
23+ (export time-resolution timezone-offset current-time
24+ cumulative-thread-time
25+ (rename (cpu-time cumulative-process-time))
26+ cumulative-gc-time time-nanosecond time-second)
27+ (import (chezscheme))
28+ (define time-resolution 1)
29+ (define (cumulative-thread-time . args)
30+ (assertion-violation 'cumulative-thread-time
31+ "not implemented"))
32+ (define (cumulative-gc-time) (sstats-gc-cpu (statistics)))
33+ (define timezone-offset
34+ (date-zone-offset (time-utc->date (current-time)))))
lib/srfi/:19/time/compat.ikarus.slsnew file+20
@@ -0,0 +1,20 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.ikarus.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :19 time compat)
11+ (export time-resolution timezone-offset current-time
12+ cumulative-thread-time cumulative-process-time
13+ cumulative-gc-time time-nanosecond time-second)
14+ (import
15+ (rnrs base)
16+ (only (ikarus) current-time time-nanosecond time-second
17+ time-gmt-offset)
18+ (srfi :19 time not-implemented))
19+ (define time-resolution 1000)
20+ (define timezone-offset (time-gmt-offset (current-time))))
lib/srfi/:19/time/compat.ironscheme.slsnew file+39
@@ -0,0 +1,39 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.ironscheme.sls
7+#!r6rs
8+;; Copyright (c) 2009 Derick Eddington. All rights reserved. Licensed under an
9+;; MIT-style license. My license is in the file named LICENSE from the original
10+;; collection this file is distributed with. If this file is redistributed with
11+;; some other collection, my license must also be included.
12+(library (srfi :19 time compat)
13+ (export time-resolution current-time time-nanosecond time-second
14+ timezone-offset cumulative-thread-time
15+ cumulative-process-time cumulative-gc-time)
16+ (import
17+ (rnrs base)
18+ (ironscheme datetime)
19+ (ironscheme process)
20+ (only (srfi :19 time not-implemented) cumulative-gc-time))
21+ (define time-resolution 100)
22+ (define base (datetime->local (make-utc-datetime 1970 1 1)))
23+ (define (current-time) (now))
24+ (define (time-nanosecond t)
25+ (mod (* 100 (ticks (difference t base))) 1000000000))
26+ (define (time-second t)
27+ (exact (truncate (total-seconds (difference t base)))))
28+ (define timezone-offset
29+ (exact
30+ (truncate
31+ (total-seconds (difference (now) (datetime->utc (now)))))))
32+ (define (cumulative-thread-time)
33+ (datetime-add
34+ base
35+ (process-user-cpu-time (get-current-process))))
36+ (define (cumulative-process-time)
37+ (datetime-add
38+ base
39+ (process-total-cpu-time (get-current-process)))))
lib/srfi/:19/time/compat.larceny.slsnew file+28
@@ -0,0 +1,28 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.larceny.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :19 time compat)
11+ (export time-resolution
12+ (rename (my:timezone-offset timezone-offset)) current-time
13+ cumulative-thread-time cumulative-process-time
14+ cumulative-gc-time time-nanosecond time-second)
15+ (import
16+ (rnrs base)
17+ (primitives r5rs:require current-utc-time timezone-offset)
18+ (srfi :19 time not-implemented))
19+ (define dummy (begin (r5rs:require 'time) #f))
20+ (define time-resolution 1000)
21+ (define my:timezone-offset
22+ (let-values ([(secs _) (current-utc-time)])
23+ (timezone-offset secs)))
24+ (define (current-time)
25+ (let-values ([(secs micros) (current-utc-time)])
26+ (cons secs (* micros 1000))))
27+ (define time-nanosecond cdr)
28+ (define time-second car))
lib/srfi/:19/time/compat.loko.slsnew file+24
@@ -0,0 +1,24 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.loko.sls
7+;; Copyright © 2019 Göran Weinholt
8+;; SPDX-License-Identifier: MIT
9+#!r6rs
10+(library (srfi :19 time compat)
11+ (export time-resolution timezone-offset current-time
12+ cumulative-thread-time cumulative-process-time
13+ cumulative-gc-time time-nanosecond time-second)
14+ (import
15+ (rnrs)
16+ (except (loko system time) time-resolution)
17+ (prefix (only (loko system time) time-resolution) loko:))
18+ (define time-resolution
19+ (loko:time-resolution (current-time)))
20+ (define (cumulative-thread-time)
21+ (error 'cumulative-thread-time "not implemented"))
22+ (define (cumulative-gc-time)
23+ (error 'cumulative-gc-time "not implemented"))
24+ (define timezone-offset 0))
lib/srfi/:19/time/compat.mzscheme.slsnew file+37
@@ -0,0 +1,37 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.mzscheme.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :19 time compat)
11+ (export time-resolution timezone-offset current-time
12+ cumulative-thread-time cumulative-process-time
13+ cumulative-gc-time time-nanosecond time-second)
14+ (import
15+ (rnrs base)
16+ (only (scheme base) current-seconds seconds->date
17+ date-time-zone-offset current-inexact-milliseconds
18+ current-thread current-process-milliseconds
19+ current-gc-milliseconds))
20+ (define time-resolution 1000000)
21+ (define timezone-offset
22+ (date-time-zone-offset (seconds->date (current-seconds))))
23+ (define (millis->repr x)
24+ (let-values ([(d m) (div-and-mod x 1000)])
25+ (cons d (* m 1000000))))
26+ (define (current-time)
27+ (millis->repr
28+ (exact (floor (current-inexact-milliseconds)))))
29+ (define (cumulative-thread-time)
30+ (millis->repr
31+ (current-process-milliseconds (current-thread))))
32+ (define (cumulative-process-time)
33+ (millis->repr (current-process-milliseconds #f)))
34+ (define (cumulative-gc-time)
35+ (millis->repr (current-gc-milliseconds)))
36+ (define time-nanosecond cdr)
37+ (define time-second car))
lib/srfi/:19/time/compat.ypsilon.slsnew file+26
@@ -0,0 +1,26 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/compat.ypsilon.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :19 time compat)
11+ (export time-resolution timezone-offset current-time
12+ cumulative-thread-time cumulative-process-time
13+ cumulative-gc-time time-nanosecond time-second)
14+ (import
15+ (rnrs base)
16+ (only (core) microsecond microsecond->utc)
17+ (srfi :19 time not-implemented))
18+ (define time-resolution 1000)
19+ (define timezone-offset
20+ (let ([t (microsecond)])
21+ (/ (- t (microsecond->utc t)) 1000000)))
22+ (define (current-time)
23+ (let-values ([(d m) (div-and-mod (microsecond) 1000000)])
24+ (cons d (* m 1000))))
25+ (define time-nanosecond cdr)
26+ (define time-second car))
lib/srfi/:19/time/not-implemented.slsnew file+24
@@ -0,0 +1,24 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a19/time/not-implemented.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :19 time not-implemented)
11+ (export
12+ cumulative-thread-time
13+ cumulative-process-time
14+ cumulative-gc-time)
15+ (import (rnrs base))
16+ (define (NI who)
17+ (lambda _ (assertion-violation who "not implemented")))
18+ (define-syntax not-implemented
19+ (syntax-rules ()
20+ [(_ name ...) (begin (define name (NI 'name)) ...)]))
21+ (not-implemented
22+ cumulative-thread-time
23+ cumulative-process-time
24+ cumulative-gc-time))
lib/srfi/:214.slsnew file+35
@@ -0,0 +1,35 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a214.sls
7+#!r6rs
8+(library (srfi :214)
9+ (export make-flexvector flexvector flexvector-unfold
10+ flexvector-unfold-right flexvector-copy
11+ flexvector-reverse-copy flexvector-append
12+ flexvector-concatenate flexvector-append-subvectors
13+ flexvector? flexvector-empty? flexvector=? flexvector-ref
14+ flexvector-front flexvector-back flexvector-length
15+ flexvector-add! flexvector-add-front! flexvector-add-back!
16+ flexvector-remove! flexvector-remove-front!
17+ flexvector-remove-back! flexvector-add-all!
18+ flexvector-remove-range! flexvector-clear! flexvector-set!
19+ flexvector-swap! flexvector-fill! flexvector-reverse!
20+ flexvector-copy! flexvector-reverse-copy! flexvector-append!
21+ flexvector-fold flexvector-fold-right flexvector-map
22+ flexvector-map! flexvector-map/index flexvector-map/index!
23+ flexvector-append-map flexvector-append-map/index
24+ flexvector-filter flexvector-filter! flexvector-filter/index
25+ flexvector-filter/index! flexvector-for-each
26+ flexvector-for-each/index flexvector-count
27+ flexvector-cumulate flexvector-index flexvector-index-right
28+ flexvector-skip flexvector-skip-right
29+ flexvector-binary-search flexvector-any flexvector-every
30+ flexvector-partition flexvector->vector flexvector->list
31+ flexvector->string vector->flexvector list->flexvector
32+ string->flexvector reverse-flexvector->list
33+ reverse-list->flexvector generator->flexvector
34+ flexvector->generator)
35+ (import (srfi :214 impl)))
lib/srfi/:214/impl.slsnew file+546
@@ -0,0 +1,546 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a214/impl.sls
7+#!r6rs
8+(library (srfi :214 impl)
9+ (export make-flexvector flexvector flexvector-unfold
10+ flexvector-unfold-right flexvector-copy
11+ flexvector-reverse-copy flexvector-append
12+ flexvector-concatenate flexvector-append-subvectors
13+ flexvector? flexvector-empty? flexvector=? flexvector-ref
14+ flexvector-front flexvector-back flexvector-length
15+ flexvector-add! flexvector-add-front! flexvector-add-back!
16+ flexvector-remove! flexvector-remove-front!
17+ flexvector-remove-back! flexvector-add-all!
18+ flexvector-remove-range! flexvector-clear! flexvector-set!
19+ flexvector-swap! flexvector-fill! flexvector-reverse!
20+ flexvector-copy! flexvector-reverse-copy! flexvector-append!
21+ flexvector-fold flexvector-fold-right flexvector-map
22+ flexvector-map! flexvector-map/index flexvector-map/index!
23+ flexvector-append-map flexvector-append-map/index
24+ flexvector-filter flexvector-filter! flexvector-filter/index
25+ flexvector-filter/index! flexvector-for-each
26+ flexvector-for-each/index flexvector-count
27+ flexvector-cumulate flexvector-index flexvector-index-right
28+ flexvector-skip flexvector-skip-right
29+ flexvector-binary-search flexvector-any flexvector-every
30+ flexvector-partition flexvector->vector flexvector->list
31+ flexvector->string vector->flexvector list->flexvector
32+ string->flexvector reverse-flexvector->list
33+ reverse-list->flexvector generator->flexvector
34+ flexvector->generator)
35+ (import (except (rnrs) vector-fill!) (srfi :26)
36+ (srfi :214 parameters)
37+ (except (srfi :133 vectors) vector->list list->vector)
38+ (srfi :158))
39+ (define (nonnegative? num) (and (number? num) (>= num 0)))
40+ (define (negate pred?)
41+ (lambda args (not (apply pred? args))))
42+ (define (assert-index-validity fv . ids)
43+ (let ([len (flexvector-len fv)])
44+ (for-each
45+ (lambda (i) (assert (and (>= i 0) (< i len))))
46+ ids)))
47+ (define (group lst num)
48+ (define (split l n)
49+ (let loop ([acc (list)] [ls l] [count 0])
50+ (cond
51+ [(>= count n) (values (reverse acc) ls)]
52+ [(null? ls)
53+ (error group "Not enough elements for a group" lst num)]
54+ [else (loop (cons (car ls) acc) (cdr ls) (+ count 1))])))
55+ (assert (positive? num))
56+ (let loop ([acc (list)] [source lst])
57+ (cond
58+ [(null? source) (reverse acc)]
59+ [else
60+ (let-values ([(grp rest) (split source num)])
61+ (loop (cons grp acc) rest))])))
62+ (define-record-type (%flexvector
63+ %make-flexvector
64+ flexvector?)
65+ (nongenerative flexvector-vtlmh5fxbj)
66+ (fields
67+ (mutable vec flexvector-vec flexvector-vec-set!)
68+ (mutable len flexvector-len flexvector-len-set!)))
69+ (define-syntax with-flexvectors
70+ (syntax-rules ()
71+ [(_ (((vec len) fv) rest ...) body ...)
72+ (let* ([fv* fv]
73+ [vec (flexvector-vec fv*)]
74+ [len (flexvector-len fv*)])
75+ (with-flexvectors (rest ...) body ...))]
76+ [(_ () body ...) (let () body ...)]))
77+ (define-syntax with-clamped-range
78+ (syntax-rules ()
79+ [(_ (fv start end) body ...)
80+ (let ([start (max 0 start)]
81+ [end (min end (flexvector-len fv))])
82+ (assert (<= start end))
83+ (let () body ...))]))
84+ (define-syntax define-with-range
85+ (syntax-rules (of)
86+ [(_ (name fv ... start (end of what)) body ...)
87+ (define name
88+ (case-lambda
89+ [(fv ...) (name fv ... 0)]
90+ [(fv ... start) (name fv ... start (flexvector-len what))]
91+ [(fv ... start end)
92+ (with-clamped-range (what start end) body ...)]))]))
93+ (define (shortest-length vecs)
94+ (apply min (map flexvector-len vecs)))
95+ (define-syntax with-shortest-length
96+ (syntax-rules ()
97+ [(_ ((vecs shortest-len) vecs-expr) body ...)
98+ (let* ([vecs vecs-expr]
99+ [shortest-len (shortest-length vecs)])
100+ body
101+ ...)]))
102+ (define (flexvector-cap fv)
103+ (vector-length (flexvector-vec fv)))
104+ (define (ensure-capacity! fv required-cap)
105+ (let ([current-cap (flexvector-cap fv)])
106+ (unless (>= current-cap required-cap)
107+ (let* ([vec (flexvector-vec fv)]
108+ [new-cap ((flexvector-capacity-estimator)
109+ current-cap
110+ required-cap)]
111+ [new-vec (make-vector new-cap)])
112+ (vector-copy! new-vec 0 vec 0 (vector-length vec))
113+ (flexvector-vec-set! fv new-vec)))))
114+ (define (ensure-valid-capacity requested-size)
115+ (assert (and (exact? requested-size) (>= requested-size 0)))
116+ (max requested-size (flexvector-min-capacity)))
117+ (define make-flexvector
118+ (case-lambda
119+ [(size)
120+ (assert (nonnegative? size))
121+ (%make-flexvector
122+ (make-vector (ensure-valid-capacity size))
123+ size)]
124+ [(size fill)
125+ (assert (nonnegative? size))
126+ (%make-flexvector
127+ (make-vector (ensure-valid-capacity size) fill)
128+ size)]))
129+ (define (flexvector . els)
130+ (cond
131+ [(null? els) (make-flexvector 0)]
132+ [else (list->flexvector els)]))
133+ (define (flexvector-unfold pred func gen . seeds)
134+ (let ([fv (flexvector)])
135+ (do ([seeds seeds (let-values ([seeds (apply gen seeds)])
136+ seeds)])
137+ ((apply pred seeds) fv)
138+ (flexvector-add-back! fv (apply func seeds)))))
139+ (define (flexvector-unfold-right pred func gen . seeds)
140+ (let ([fv (apply flexvector-unfold pred func gen seeds)])
141+ (flexvector-reverse! fv)
142+ fv))
143+ (define-with-range
144+ (flexvector-copy fv start (end of fv))
145+ (with-flexvectors
146+ (((vec len) fv))
147+ (let ([result (make-flexvector (- end start))])
148+ (vector-copy! (flexvector-vec result) 0 vec start end)
149+ result)))
150+ (define (flexvector-reverse-copy . args)
151+ (let ([copy (apply flexvector-copy args)])
152+ (flexvector-reverse! copy)
153+ copy))
154+ (define (flexvector-append fv . rest)
155+ (flexvector-concatenate (cons fv rest)))
156+ (define (flexvector-concatenate fvs)
157+ (let* ([total-len (fold-left + 0 (map flexvector-len fvs))]
158+ [result (make-flexvector total-len)])
159+ (let loop ([vecs fvs] [offset 0])
160+ (cond
161+ [(null? vecs) result]
162+ [else
163+ (let ([current (car vecs)])
164+ (flexvector-copy! result offset current)
165+ (loop (cdr vecs) (+ offset (flexvector-len current))))]))))
166+ (define (flexvector-append-subvectors . args)
167+ (let* ([triplets (group args 3)]
168+ [subvecs (map (lambda (triplet)
169+ (apply flexvector-copy triplet))
170+ triplets)])
171+ (flexvector-concatenate subvecs)))
172+ (define (flexvector-empty? fv) (zero? (flexvector-len fv)))
173+ (define (flexvector=? elt=? . fvs)
174+ (define (combine result . es) (and result (apply elt=? es)))
175+ (let ([lens (map flexvector-len fvs)])
176+ (or (null? fvs)
177+ (null? (cdr fvs))
178+ (and (apply = lens)
179+ (apply flexvector-fold combine #t fvs)))))
180+ (define (flexvector-ref fv index)
181+ (with-flexvectors
182+ (((vec len) fv))
183+ (assert-index-validity fv index)
184+ (vector-ref vec index)))
185+ (define (flexvector-front fv) (flexvector-ref fv 0))
186+ (define (flexvector-back fv)
187+ (let ([len (flexvector-len fv)])
188+ (flexvector-ref fv (- len 1))))
189+ (define flexvector-length flexvector-len)
190+ (define (flexvector-add! fv i . els)
191+ (flexvector-add-all! fv i els))
192+ (define (flexvector-add-front! fv . els)
193+ (flexvector-add-all! fv 0 els))
194+ (define (flexvector-add-back! fv . els)
195+ (flexvector-add-all! fv (flexvector-len fv) els))
196+ (define (flexvector-add-all! fv i els)
197+ (let* ([count (length els)]
198+ [len (flexvector-len fv)]
199+ [total-len (+ len count)])
200+ (ensure-capacity! fv total-len)
201+ (let ([vec (flexvector-vec fv)])
202+ (vector-copy! vec (+ i count) vec i len)
203+ (let loop ([ls els] [offset 0])
204+ (cond
205+ [(null? ls) (flexvector-len-set! fv total-len) fv]
206+ [else
207+ (let ([el (car ls)])
208+ (vector-set! vec (+ i offset) el)
209+ (loop (cdr ls) (+ offset 1)))])))))
210+ (define (flexvector-append! fv . fvs)
211+ (let* ([len (flexvector-len fv)]
212+ [total-len (fold-left + len (map flexvector-len fvs))])
213+ (ensure-capacity! fv total-len)
214+ (let ([vec (flexvector-vec fv)])
215+ (let loop ([fvs fvs] [offset len])
216+ (cond
217+ [(null? fvs) (flexvector-len-set! fv total-len) fv]
218+ [else
219+ (with-flexvectors
220+ (((current-vec current-len) (car fvs)))
221+ (vector-copy! vec offset current-vec 0 current-len)
222+ (loop (cdr fvs) (+ offset current-len)))])))))
223+ (define (flexvector-remove! fv i)
224+ (let ([value (flexvector-ref fv i)])
225+ (flexvector-remove-range! fv i (+ i 1))
226+ value))
227+ (define (flexvector-remove-front! fv)
228+ (flexvector-remove! fv 0))
229+ (define (flexvector-remove-back! fv)
230+ (flexvector-remove! fv (- (flexvector-len fv) 1)))
231+ (define flexvector-remove-range!
232+ (case-lambda
233+ [(fv start)
234+ (flexvector-remove-range! fv start (flexvector-len fv))]
235+ [(fv start end)
236+ (with-flexvectors
237+ (((vec len) fv))
238+ (let* ([start (max start 0)]
239+ [end (min len end)]
240+ [move-count (- len end)]
241+ [len-delta (- end start)])
242+ (assert (<= start end))
243+ (unless (zero? move-count)
244+ (vector-copy! vec start vec end (+ end move-count)))
245+ (flexvector-len-set! fv (- len len-delta))
246+ fv))]))
247+ (define (flexvector-clear! fv)
248+ (flexvector-len-set! fv 0)
249+ fv)
250+ (define (flexvector-set! fv i el)
251+ (assert-index-validity fv i)
252+ (with-flexvectors
253+ (((vec len) fv))
254+ (let* ([val (vector-ref vec i)])
255+ (vector-set! vec i el)
256+ val)))
257+ (define (flexvector-swap! fv i j)
258+ (assert-index-validity fv i j)
259+ (with-flexvectors (((vec len) fv)) (vector-swap! vec i j)))
260+ (define-with-range
261+ (flexvector-fill! fv fill start (end of fv))
262+ (with-flexvectors
263+ (((vec len) fv))
264+ (let ([start (max 0 start)] [end (min end len)])
265+ (vector-fill! vec fill start end)
266+ fv)))
267+ (define-with-range
268+ (flexvector-reverse! fv start (end of fv))
269+ (let* ([len (- end start)]
270+ [vec (flexvector-vec fv)]
271+ [half (floor (/ len 2))])
272+ (do ([index 0 (+ index 1)])
273+ ((>= index half) fv)
274+ (let ([jndex (- len index 1)])
275+ (vector-swap! vec (+ start index) (+ start jndex))))))
276+ (define-with-range
277+ (flexvector-copy! to at from start (end of from))
278+ (let* ([len (flexvector-len to)]
279+ [delta (- end start)]
280+ [new-len (+ len delta)])
281+ (assert (and (>= at 0) (<= at len)))
282+ (ensure-capacity! to new-len)
283+ (with-flexvectors
284+ (((to-vec to-len) to) ((from-vec from-len) from))
285+ (vector-copy! to-vec at from-vec start end)
286+ (flexvector-len-set! to (max len (+ at delta)))
287+ to)))
288+ (define-with-range
289+ (flexvector-reverse-copy! to at from start (end of from))
290+ (flexvector-copy! to at from start end)
291+ (flexvector-reverse! to at (+ at (- end start))))
292+ (define (flexvector-fold-impl index-proc reductor initial fv
293+ . rest)
294+ (with-shortest-length
295+ ((vecs shortest-len) (cons fv rest))
296+ (let loop ([index 0] [state initial])
297+ (cond
298+ [(>= index shortest-len) state]
299+ [else
300+ (loop
301+ (+ index 1)
302+ (apply
303+ reductor
304+ state
305+ (map (cut flexvector-ref <> (index-proc index shortest-len))
306+ vecs)))]))))
307+ (define (flexvector-fold reductor initial fv . rest)
308+ (define (left-to-right index len) index)
309+ (apply flexvector-fold-impl left-to-right reductor initial
310+ fv rest))
311+ (define (flexvector-fold-right reductor initial fv . rest)
312+ (define (right-to-left index len) (- len index 1))
313+ (apply flexvector-fold-impl right-to-left reductor initial
314+ fv rest))
315+ (define (flexvector-map/index-into! dst proc fv . rest)
316+ (with-shortest-length
317+ ((vecs shortest-len) (cons fv rest))
318+ (let loop ([index 0])
319+ (cond
320+ [(>= index shortest-len) dst]
321+ [else
322+ (let ([value (apply
323+ proc
324+ index
325+ (map (cut flexvector-ref <> index) vecs))])
326+ (flexvector-set! dst index value)
327+ (loop (+ index 1)))]))))
328+ (define (flexvector-map/index! proc fv . rest)
329+ (apply flexvector-map/index-into! fv proc fv rest))
330+ (define (flexvector-map! proc fv . rest)
331+ (define (ignore-index . args) (apply proc (cdr args)))
332+ (apply flexvector-map/index! ignore-index fv rest))
333+ (define (flexvector-map/index proc fv . rest)
334+ (with-shortest-length
335+ ((vecs shortest-len) (cons fv rest))
336+ (let ([result (make-flexvector shortest-len)])
337+ (apply flexvector-map/index-into! result proc fv rest))))
338+ (define (flexvector-map proc fv . rest)
339+ (define (ignore-index . args) (apply proc (cdr args)))
340+ (apply flexvector-map/index ignore-index fv rest))
341+ (define (flexvector-append-map/index proc fv . rest)
342+ (flexvector-fold
343+ flexvector-append!
344+ (flexvector)
345+ (apply flexvector-map/index proc fv rest)))
346+ (define (flexvector-append-map proc fv . rest)
347+ (flexvector-fold
348+ flexvector-append!
349+ (flexvector)
350+ (apply flexvector-map proc fv rest)))
351+ (define (flexvector-filter/index! pred? fv)
352+ (with-flexvectors
353+ (((vec len) fv))
354+ (let loop ([check-index 0] [fill-index 0])
355+ (cond
356+ [(>= check-index len)
357+ (flexvector-len-set! fv fill-index)
358+ fv]
359+ [(pred? check-index (flexvector-ref fv check-index))
360+ (flexvector-set!
361+ fv
362+ fill-index
363+ (flexvector-ref fv check-index))
364+ (loop (+ check-index 1) (+ fill-index 1))]
365+ [else (loop (+ check-index 1) fill-index)]))))
366+ (define (flexvector-filter! pred? fv)
367+ (define (ignore-index index value) (pred? value))
368+ (flexvector-filter/index! ignore-index fv))
369+ (define (flexvector-filter/index pred? fv)
370+ (flexvector-filter/index! pred? (flexvector-copy fv)))
371+ (define (flexvector-filter pred? fv)
372+ (flexvector-filter! pred? (flexvector-copy fv)))
373+ (define (flexvector-for-each/index proc fv . rest)
374+ (with-shortest-length
375+ ((vecs shortest-len) (cons fv rest))
376+ (do ([index 0 (+ index 1)])
377+ ((>= index shortest-len))
378+ (apply
379+ proc
380+ index
381+ (map (cut flexvector-ref <> index) vecs)))))
382+ (define (flexvector-for-each proc fv . rest)
383+ (define (ignore-index . args) (apply proc (cdr args)))
384+ (apply flexvector-for-each/index ignore-index fv rest))
385+ (define (flexvector-count pred? fv . rest)
386+ (with-shortest-length
387+ ((vecs shortest-len) (cons fv rest))
388+ (let loop ([index 0] [count 0])
389+ (cond
390+ [(>= index shortest-len) count]
391+ [(apply pred? (map (cut flexvector-ref <> index) vecs))
392+ (loop (+ index 1) (+ count 1))]
393+ [else (loop (+ index 1) count)]))))
394+ (define (flexvector-cumulate reductor initial fv)
395+ (with-flexvectors
396+ (((vec len) fv))
397+ (let* ([result (make-flexvector len)]
398+ [new-vec (flexvector-vec result)])
399+ (let loop ([index 0] [state initial])
400+ (cond
401+ [(>= index len) result]
402+ [else
403+ (let ([new-state (reductor state (vector-ref vec index))])
404+ (vector-set! new-vec index new-state)
405+ (loop (+ index 1) new-state))])))))
406+ (define (flexvector-index pred? fv . rest)
407+ (with-shortest-length
408+ ((vecs shortest-len) (cons fv rest))
409+ (let loop ([index 0])
410+ (cond
411+ [(>= index shortest-len) #f]
412+ [(apply pred? (map (cut flexvector-ref <> index) vecs))
413+ index]
414+ [else (loop (+ index 1))]))))
415+ (define (flexvector-index-right pred? fv . rest)
416+ (with-shortest-length
417+ ((vecs shortest-len) (cons fv rest))
418+ (let loop ([index 0])
419+ (cond
420+ [(>= index shortest-len) #f]
421+ [(apply
422+ pred?
423+ (map (cut flexvector-ref <> (- shortest-len index 1)) vecs))
424+ (- shortest-len index 1)]
425+ [else (loop (+ index 1))]))))
426+ (define (flexvector-skip pred? fv . rest)
427+ (apply flexvector-index (negate pred?) fv rest))
428+ (define (flexvector-skip-right pred? fv . rest)
429+ (apply flexvector-index-right (negate pred?) fv rest))
430+ (define-with-range
431+ (flexvector-binary-search fv value comp start (end of fv))
432+ (let ([vec (flexvector-vec fv)])
433+ (vector-binary-search vec value comp start end)))
434+ (define (flexvector-any pred? fv . rest)
435+ (with-shortest-length
436+ ((vecs shortest-len) (cons fv rest))
437+ (let loop ([index 0])
438+ (cond
439+ [(>= index shortest-len) #f]
440+ [(apply pred? (map (cut flexvector-ref <> index) vecs))]
441+ [else (loop (+ index 1))]))))
442+ (define (flexvector-every pred? fv . rest)
443+ (with-shortest-length
444+ ((vecs shortest-len) (cons fv rest))
445+ (let loop ([index 0] [last-value #t])
446+ (cond
447+ [(>= index shortest-len) last-value]
448+ [(apply pred? (map (cut flexvector-ref <> index) vecs)) =>
449+ (lambda (val) (loop (+ index 1) val))]
450+ [else #f]))))
451+ (define (flexvector-partition pred? fv)
452+ (let ([matching (flexvector)] [non-matching (flexvector)])
453+ (flexvector-for-each
454+ (lambda (el)
455+ (flexvector-add-back!
456+ (if (pred? el) matching non-matching)
457+ el))
458+ fv)
459+ (values matching non-matching)))
460+ (define-with-range
461+ (flexvector->vector fv start (end of fv))
462+ (let ([vec (flexvector-vec fv)])
463+ (vector-copy vec start end)))
464+ (define vector->flexvector
465+ (case-lambda
466+ [(vec) (vector->flexvector vec 0)]
467+ [(vec start)
468+ (vector->flexvector vec start (vector-length vec))]
469+ [(vec start end)
470+ (let* ([len (- end start)]
471+ [result (make-flexvector len)]
472+ [fvec (flexvector-vec result)])
473+ (vector-copy! fvec 0 vec start end)
474+ result)]))
475+ (define (flexvector->list-impl finalizer fv start end)
476+ (with-flexvectors
477+ (((vec len) fv))
478+ (let loop ([acc (list)] [index 0])
479+ (cond
480+ [(>= index len) (finalizer acc)]
481+ [else
482+ (loop (cons (vector-ref vec index) acc) (+ index 1))]))))
483+ (define-with-range
484+ (flexvector->list fv start (end of fv))
485+ (flexvector->list-impl reverse fv start end))
486+ (define-with-range
487+ (reverse-flexvector->list fv start (end of fv))
488+ (define (identity l) l)
489+ (flexvector->list-impl identity fv start end))
490+ (define (list->flexvector-impl lst index-func)
491+ (let* ([len (length lst)] [fv (make-flexvector len)])
492+ (let loop ([lst lst] [index 0])
493+ (cond
494+ [(null? lst) fv]
495+ [else
496+ (flexvector-set! fv (index-func len index) (car lst))
497+ (loop (cdr lst) (+ index 1))]))))
498+ (define (list->flexvector lst)
499+ (list->flexvector-impl lst (lambda (len index) index)))
500+ (define (reverse-list->flexvector lst)
501+ (list->flexvector-impl
502+ lst
503+ (lambda (len index) (- len index 1))))
504+ (define-with-range
505+ (flexvector->string fv start (end of fv))
506+ (let-values ([(out fin) (open-string-output-port)])
507+ (with-flexvectors
508+ (((vec len) fv))
509+ (let loop ([index start])
510+ (cond
511+ [(>= index end) (fin)]
512+ [else
513+ (put-char out (vector-ref vec index))
514+ (loop (+ index 1))])))))
515+ (define string->flexvector
516+ (case-lambda
517+ [(str) (string->flexvector str 0)]
518+ [(str start)
519+ (string->flexvector str start (string-length str))]
520+ [(str start end)
521+ (let ([in (open-string-input-port
522+ (substring str start end))]
523+ [fv (flexvector)])
524+ (let loop ([ch (get-char in)])
525+ (cond
526+ [(eof-object? ch) fv]
527+ [else
528+ (flexvector-add-back! fv ch)
529+ (loop (get-char in))])))]))
530+ (define (flexvector->generator fv)
531+ (with-flexvectors
532+ (((vec len) fv))
533+ (let ([index 0])
534+ (lambda ()
535+ (cond
536+ [(>= index len) (eof-object)]
537+ [else
538+ (let ([value (vector-ref vec index)])
539+ (set! index (+ index 1))
540+ value)])))))
541+ (define (generator->flexvector gen)
542+ (let ([fv (flexvector)])
543+ (generator-fold
544+ (lambda (v r) (flexvector-add-back! r v))
545+ fv
546+ gen))))
lib/srfi/:214/parameters.slsnew file+39
@@ -0,0 +1,39 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a214/parameters.sls
7+#!r6rs
8+(library (srfi :214 parameters)
9+ (export
10+ flexvector-min-capacity
11+ flexvector-capacity-estimator)
12+ (import (rnrs) (srfi :39))
13+ (define (assert-valid-capacity-value value)
14+ (assert (and (number? value) (> value 0)))
15+ value)
16+ (define flexvector-min-capacity
17+ (make-parameter 4 assert-valid-capacity-value))
18+ (define (assert-valid-capacity-estimator value)
19+ (assert (procedure? value))
20+ (let* ([example-current 4]
21+ [example-requested 8]
22+ [example-cap (value example-current example-requested)])
23+ (assert
24+ (and (number? example-cap)
25+ (exact? example-cap)
26+ (>= example-cap example-requested)))
27+ value))
28+ (define (multiple-of-current-estimator current requested)
29+ (assert
30+ (and (number? current)
31+ (number? requested)
32+ (> current 0)
33+ (> requested 0)))
34+ (let ([quot (exact (ceiling (/ requested current)))])
35+ (* quot current)))
36+ (define flexvector-capacity-estimator
37+ (make-parameter
38+ multiple-of-current-estimator
39+ assert-valid-capacity-estimator)))
lib/srfi/:23.slsnew file+11
@@ -0,0 +1,11 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a23.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :23)
10+ (export error)
11+ (import (srfi :23 error)))
lib/srfi/:23/error.slsnew file+13
@@ -0,0 +1,13 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a23/error.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :23 error)
11+ (export error)
12+ (import (rename (rnrs base) (error rnrs:error)))
13+ (define (error . args) (apply rnrs:error #f args)))
lib/srfi/:23/error/tricks.slsnew file+43
@@ -0,0 +1,43 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a23/error/tricks.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :23 error tricks)
11+ (export SRFI-23-error->R6RS)
12+ (import (rnrs))
13+ (define-syntax error-wrap
14+ (lambda (stx)
15+ (syntax-case stx ()
16+ [(_ ctxt signal . forms)
17+ (with-syntax ([e (datum->syntax #'ctxt 'error)])
18+ #'(let-syntax ([e (identifier-syntax signal)]) . forms))])))
19+ (define (AV who)
20+ (lambda args (apply assertion-violation who args)))
21+ (define-syntax SRFI-23-error->R6RS
22+ (lambda (stx)
23+ (syntax-case stx ()
24+ [(ctxt ewho . forms)
25+ (with-syntax ([e (datum->syntax #'ctxt 'error)]
26+ [d (datum->syntax #'ctxt 'define)])
27+ #'(let-syntax ([e (identifier-syntax (AV 'ewho))]
28+ [d (lambda (stx)
29+ (syntax-case stx ()
30+ [(kw (id . formals) . body)
31+ (identifier? #'id)
32+ #'(error-wrap
33+ kw
34+ (AV 'id)
35+ (d (id . formals) . body))]
36+ [(kw id . r)
37+ (identifier? #'id)
38+ #'(error-wrap
39+ kw
40+ (AV 'id)
41+ (d id . r))]))])
42+ .
43+ forms))]))))
lib/srfi/:26.slsnew file+11
@@ -0,0 +1,11 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a26.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :26)
10+ (export cut cute <> <...>)
11+ (import (srfi :26 cut)))
lib/srfi/:26/cut.slsnew file+102
@@ -0,0 +1,102 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a26/cut.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+;;;;;; File header: %3a26/cut-impl.scm
11+; REFERENCE IMPLEMENTATION FOR SRFI-26 "CUT"
12+; ==========================================
13+;
14+; Sebastian.Egner@philips.com, 5-Jun-2002.
15+; adapted from the posting by Al Petrofsky <al@petrofsky.org>
16+; placed in the public domain
17+;
18+; The code to handle the variable argument case was originally
19+; proposed by Michael Sperber and has been adapted to the new
20+; syntax of the macro using an explicit rest-slot symbol. The
21+; code to evaluate the non-slots for cute has been proposed by
22+; Dale Jordan. The code to allow a slot for the procedure position
23+; and to process the macro using an internal macro is based on
24+; a suggestion by Al Petrofsky. The code found below is, with
25+; exception of this header and some changes in variable names,
26+; entirely written by Al Petrofsky.
27+;
28+; compliance:
29+; Scheme R5RS (including macros).
30+;
31+; loading this file into Scheme 48 0.57:
32+; ,load cut.scm
33+;
34+; history of this file:
35+; SE, 6-Feb-2002: initial version as 'curry' with ". <>" notation
36+; SE, 14-Feb-2002: revised for <...>
37+; SE, 27-Feb-2002: revised for 'cut'
38+; SE, 03-Jun-2002: revised for proc-slot, cute
39+; SE, 04-Jun-2002: rewritten with internal transformer (no "loop" pattern)
40+; SE, 05-Jun-2002: replace my code by Al's; substituted "constant" etc.
41+; to match the convention in the SRFI-document
42+(library (srfi :26 cut)
43+ (export cut cute <> <...>)
44+ (import (rnrs) (srfi private include))
45+ (begin
46+ (define-syntax srfi-26-internal-cut
47+ (syntax-rules (<> <...>)
48+ [(srfi-26-internal-cut (slot-name ...) (proc arg ...))
49+ (lambda (slot-name ...) ((begin proc) arg ...))]
50+ [(srfi-26-internal-cut (slot-name ...) (proc arg ...) <...>)
51+ (lambda (slot-name ... . rest-slot)
52+ (apply proc arg ... rest-slot))]
53+ [(srfi-26-internal-cut (slot-name ...) (position ...) <> .
54+ se)
55+ (srfi-26-internal-cut
56+ (slot-name ... x)
57+ (position ... x)
58+ .
59+ se)]
60+ [(srfi-26-internal-cut (slot-name ...) (position ...) nse .
61+ se)
62+ (srfi-26-internal-cut
63+ (slot-name ...)
64+ (position ... nse)
65+ .
66+ se)]))
67+ (define-syntax srfi-26-internal-cute
68+ (syntax-rules (<> <...>)
69+ [(srfi-26-internal-cute
70+ (slot-name ...)
71+ nse-bindings
72+ (proc arg ...))
73+ (let nse-bindings (lambda [slot-name ...] [proc arg ...]))]
74+ [(srfi-26-internal-cute
75+ (slot-name ...)
76+ nse-bindings
77+ (proc arg ...)
78+ <...>)
79+ (let nse-bindings (lambda
80+ [slot-name ... . x]
81+ [apply proc arg ... x]))]
82+ [(srfi-26-internal-cute (slot-name ...) nse-bindings
83+ (position ...) <> . se)
84+ (srfi-26-internal-cute (slot-name ... x) nse-bindings
85+ (position ... x) . se)]
86+ [(srfi-26-internal-cute slot-names nse-bindings
87+ (position ...) nse . se)
88+ (srfi-26-internal-cute slot-names ((x nse) . nse-bindings)
89+ (position ... x) . se)]))
90+ (define-syntax <>
91+ (identifier-syntax (error #f "misplaced aux keyword <>")))
92+ (define-syntax <...>
93+ (identifier-syntax (error #f
94+ "misplaced aux keyword <...>")))
95+ (define-syntax cut
96+ (syntax-rules ()
97+ [(cut . slots-or-exprs)
98+ (srfi-26-internal-cut () () . slots-or-exprs)]))
99+ (define-syntax cute
100+ (syntax-rules ()
101+ [(cute . slots-or-exprs)
102+ (srfi-26-internal-cute () () () . slots-or-exprs)]))))
lib/srfi/:27.slsnew file+15
@@ -0,0 +1,15 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a27.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :27)
10+ (export default-random-source make-random-source random-integer
11+ random-real random-source-make-integers
12+ random-source-make-reals random-source-pseudo-randomize!
13+ random-source-randomize! random-source-state-ref
14+ random-source-state-set! random-source?)
15+ (import (srfi :27 random-bits)))
lib/srfi/:27/random-bits.slsnew file+299
@@ -0,0 +1,299 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a27/random-bits.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+;;;;;; File header: %3a27/mrg32k3a-a.scm
11+; 54-BIT INTEGER IMPLEMENTATION OF THE "MRG32K3A"-GENERATOR
12+; =========================================================
13+;
14+; Sebastian.Egner@philips.com, Mar-2002.
15+;
16+; This file is an implementation of Pierre L'Ecuyer's MRG32k3a
17+; pseudo random number generator. Please refer to 'mrg32k3a.scm'
18+; for more information.
19+;
20+; compliance:
21+; Scheme R5RS with integers covering at least {-2^53..2^53-1}.
22+;
23+; history of this file:
24+; SE, 18-Mar-2002: initial version
25+; SE, 22-Mar-2002: comments adjusted, range added
26+; SE, 25-Mar-2002: pack/unpack just return their argument
27+;;;;;; File header: %3a27/mrg32k3a.scm
28+; GENERIC PART OF MRG32k3a-GENERATOR FOR SRFI-27
29+; ==============================================
30+;
31+; Sebastian.Egner@philips.com, 2002.
32+;
33+; This is the generic R5RS-part of the implementation of the MRG32k3a
34+; generator to be used in SRFI-27. It is based on a separate implementation
35+; of the core generator (presumably in native code) and on code to
36+; provide essential functionality not available in R5RS (see below).
37+;
38+; compliance:
39+; Scheme R5RS with integer covering at least {-2^53..2^53-1}.
40+; In addition,
41+; SRFI-23: error
42+;
43+; history of this file:
44+; SE, 22-Mar-2002: refactored from earlier versions
45+; SE, 25-Mar-2002: pack/unpack need not allocate
46+; SE, 27-Mar-2002: changed interface to core generator
47+; SE, 10-Apr-2002: updated spec of mrg32k3a-random-integer
48+(library (srfi :27 random-bits)
49+ (export random-integer random-real default-random-source
50+ make-random-source random-source? random-source-state-ref
51+ random-source-state-set! random-source-randomize!
52+ random-source-pseudo-randomize! random-source-make-integers
53+ random-source-make-reals)
54+ (import (rnrs) (rnrs r5rs)
55+ (only (srfi :19 time) current-time time-nanosecond)
56+ (srfi :23 error tricks) (srfi private include))
57+ (define-record-type (:random-source
58+ :random-source-make
59+ :random-source?)
60+ (fields state-ref state-set! randomize! pseudo-randomize!
61+ make-integers make-reals))
62+ (define (:random-source-current-time)
63+ (time-nanosecond (current-time)))
64+ (SRFI-23-error->R6RS
65+ "(library (srfi :27 random-bits))"
66+ (begin
67+ (define (mrg32k3a-random-m1 state)
68+ (let ([x11 (vector-ref state 0)]
69+ [x12 (vector-ref state 1)]
70+ [x13 (vector-ref state 2)]
71+ [x21 (vector-ref state 3)]
72+ [x22 (vector-ref state 4)]
73+ [x23 (vector-ref state 5)])
74+ (let ([x10 (modulo
75+ (- (* 1403580 x12) (* 810728 x13))
76+ 4294967087)]
77+ [x20 (modulo
78+ (- (* 527612 x21) (* 1370589 x23))
79+ 4294944443)])
80+ (vector-set! state 0 x10)
81+ (vector-set! state 1 x11)
82+ (vector-set! state 2 x12)
83+ (vector-set! state 3 x20)
84+ (vector-set! state 4 x21)
85+ (vector-set! state 5 x22)
86+ (modulo (- x10 x20) 4294967087))))
87+ (define (mrg32k3a-pack-state unpacked-state) unpacked-state)
88+ (define (mrg32k3a-unpack-state state) state)
89+ (define (mrg32k3a-random-range) 4294967087)
90+ (define (mrg32k3a-random-integer state range)
91+ (let* ([q (quotient 4294967087 range)] [qn (* q range)])
92+ (do ([x (mrg32k3a-random-m1 state) (mrg32k3a-random-m1
93+ state)])
94+ ((< x qn) (quotient x q)))))
95+ (define (mrg32k3a-random-real state)
96+ (* 2.328306549295728e-10
97+ (+ 1.0 (mrg32k3a-random-m1 state)))))
98+ (begin
99+ (define (mrg32k3a-state-ref packed-state)
100+ (cons
101+ 'lecuyer-mrg32k3a
102+ (vector->list (mrg32k3a-unpack-state packed-state))))
103+ (define (mrg32k3a-state-set external-state)
104+ (define (check-value x m)
105+ (if (and (integer? x) (exact? x) (<= 0 x (- m 1)))
106+ #t
107+ (error "illegal value" x)))
108+ (if (and (list? external-state)
109+ (= (length external-state) 7)
110+ (eq? (car external-state) 'lecuyer-mrg32k3a))
111+ (let ([s (cdr external-state)])
112+ (check-value (list-ref s 0) mrg32k3a-m1)
113+ (check-value (list-ref s 1) mrg32k3a-m1)
114+ (check-value (list-ref s 2) mrg32k3a-m1)
115+ (check-value (list-ref s 3) mrg32k3a-m2)
116+ (check-value (list-ref s 4) mrg32k3a-m2)
117+ (check-value (list-ref s 5) mrg32k3a-m2)
118+ (if (or (zero?
119+ (+ (list-ref s 0) (list-ref s 1) (list-ref s 2)))
120+ (zero?
121+ (+ (list-ref s 3) (list-ref s 4) (list-ref s 5))))
122+ (error "illegal degenerate state" external-state))
123+ (mrg32k3a-pack-state (list->vector s)))
124+ (error "malformed state" external-state)))
125+ (define mrg32k3a-m1 4294967087)
126+ (define mrg32k3a-m2 4294944443)
127+ (define mrg32k3a-initial-state
128+ '#(1062452522 2961816100 342112271 2854655037 3321940838
129+ 3542344109))
130+ (define mrg32k3a-generators #f)
131+ (define (mrg32k3a-pseudo-randomize-state i j)
132+ (define (product A B)
133+ (define w 65536)
134+ (define w-sqr1 209)
135+ (define w-sqr2 22853)
136+ (define (lc i0 i1 i2 j0 j1 j2 m w-sqr)
137+ (let ([a0h (quotient (vector-ref A i0) w)]
138+ [a0l (modulo (vector-ref A i0) w)]
139+ [a1h (quotient (vector-ref A i1) w)]
140+ [a1l (modulo (vector-ref A i1) w)]
141+ [a2h (quotient (vector-ref A i2) w)]
142+ [a2l (modulo (vector-ref A i2) w)]
143+ [b0h (quotient (vector-ref B j0) w)]
144+ [b0l (modulo (vector-ref B j0) w)]
145+ [b1h (quotient (vector-ref B j1) w)]
146+ [b1l (modulo (vector-ref B j1) w)]
147+ [b2h (quotient (vector-ref B j2) w)]
148+ [b2l (modulo (vector-ref B j2) w)])
149+ (modulo
150+ (+ (* (+ (* a0h b0h) (* a1h b1h) (* a2h b2h)) w-sqr)
151+ (* (+ (* a0h b0l) (* a0l b0h) (* a1h b1l) (* a1l b1h)
152+ (* a2h b2l) (* a2l b2h))
153+ w)
154+ (* a0l b0l) (* a1l b1l) (* a2l b2l))
155+ m)))
156+ (vector (lc 0 1 2 0 3 6 mrg32k3a-m1 w-sqr1)
157+ (lc 0 1 2 1 4 7 mrg32k3a-m1 w-sqr1)
158+ (lc 0 1 2 2 5 8 mrg32k3a-m1 w-sqr1)
159+ (lc 3 4 5 0 3 6 mrg32k3a-m1 w-sqr1)
160+ (lc 3 4 5 1 4 7 mrg32k3a-m1 w-sqr1)
161+ (lc 3 4 5 2 5 8 mrg32k3a-m1 w-sqr1)
162+ (lc 6 7 8 0 3 6 mrg32k3a-m1 w-sqr1)
163+ (lc 6 7 8 1 4 7 mrg32k3a-m1 w-sqr1)
164+ (lc 6 7 8 2 5 8 mrg32k3a-m1 w-sqr1)
165+ (lc 9 10 11 9 12 15 mrg32k3a-m2 w-sqr2)
166+ (lc 9 10 11 10 13 16 mrg32k3a-m2 w-sqr2)
167+ (lc 9 10 11 11 14 17 mrg32k3a-m2 w-sqr2)
168+ (lc 12 13 14 9 12 15 mrg32k3a-m2 w-sqr2)
169+ (lc 12 13 14 10 13 16 mrg32k3a-m2 w-sqr2)
170+ (lc 12 13 14 11 14 17 mrg32k3a-m2 w-sqr2)
171+ (lc 15 16 17 9 12 15 mrg32k3a-m2 w-sqr2)
172+ (lc 15 16 17 10 13 16 mrg32k3a-m2 w-sqr2)
173+ (lc 15 16 17 11 14 17 mrg32k3a-m2 w-sqr2)))
174+ (define (power A e)
175+ (cond
176+ [(zero? e) '#(1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1)]
177+ [(= e 1) A]
178+ [(even? e) (power (product A A) (quotient e 2))]
179+ [else (product (power A (- e 1)) A)]))
180+ (define (power-power A b)
181+ (if (zero? b) A (power-power (product A A) (- b 1))))
182+ (define A
183+ '#(0 1403580 4294156359 1 0 0 0 1 0 527612 0 4293573854 1 0
184+ 0 0 1 0))
185+ (if (not (and (integer? i)
186+ (exact? i)
187+ (integer? j)
188+ (exact? j)))
189+ (error "i j must be exact integer" i j))
190+ (if (not mrg32k3a-generators)
191+ (set! mrg32k3a-generators
192+ (list (power-power A 127) (power-power A 76) (power A 16))))
193+ (let ([M (product
194+ (list-ref mrg32k3a-generators 2)
195+ (product
196+ (power
197+ (list-ref mrg32k3a-generators 0)
198+ (modulo i (expt 2 28)))
199+ (power
200+ (list-ref mrg32k3a-generators 1)
201+ (modulo j (expt 2 28)))))])
202+ (mrg32k3a-pack-state
203+ (vector (vector-ref M 0) (vector-ref M 3) (vector-ref M 6)
204+ (vector-ref M 9) (vector-ref M 12) (vector-ref M 15)))))
205+ (define (mrg32k3a-randomize-state state)
206+ (let* ([m 65536]
207+ [x (modulo (:random-source-current-time) m)])
208+ (define (random-m)
209+ (let ([y (modulo x m)])
210+ (set! x (+ (* 30903 y) (quotient x m)))
211+ y))
212+ (define (random n)
213+ (modulo (+ (* (random-m) m) (random-m)) n))
214+ (let ([m1 mrg32k3a-m1]
215+ [m2 mrg32k3a-m2]
216+ [s (mrg32k3a-unpack-state state)])
217+ (mrg32k3a-pack-state
218+ (vector
219+ (+ 1
220+ (modulo
221+ (+ (vector-ref s 0) (random (- m1 1)))
222+ (- m1 1)))
223+ (modulo (+ (vector-ref s 1) (random m1)) m1)
224+ (modulo (+ (vector-ref s 2) (random m1)) m1)
225+ (+ 1
226+ (modulo
227+ (+ (vector-ref s 3) (random (- m2 1)))
228+ (- m2 1)))
229+ (modulo (+ (vector-ref s 4) (random m2)) m2)
230+ (modulo (+ (vector-ref s 5) (random m2)) m2))))))
231+ (define mrg32k3a-m-max (mrg32k3a-random-range))
232+ (define (mrg32k3a-random-power state k)
233+ (if (= k 1)
234+ (mrg32k3a-random-integer state mrg32k3a-m-max)
235+ (+ (* (mrg32k3a-random-power state (- k 1)) mrg32k3a-m-max)
236+ (mrg32k3a-random-integer state mrg32k3a-m-max))))
237+ (define (mrg32k3a-random-large state n)
238+ (do ([k 2 (+ k 1)]
239+ [mk (* mrg32k3a-m-max mrg32k3a-m-max) (* mk
240+ mrg32k3a-m-max)])
241+ ((>= mk n)
242+ (let* ([mk-by-n (quotient mk n)] [a (* mk-by-n n)])
243+ (do ([x (mrg32k3a-random-power state k) (mrg32k3a-random-power
244+ state
245+ k)])
246+ ((< x a) (quotient x mk-by-n)))))))
247+ (define (mrg32k3a-random-real-mp state unit)
248+ (do ([k 1 (+ k 1)] [u (- (/ 1 unit) 1) (/ u mrg32k3a-m1)])
249+ ((<= u 1)
250+ (/ (exact->inexact (+ (mrg32k3a-random-power state k) 1))
251+ (exact->inexact (+ (expt mrg32k3a-m-max k) 1))))))
252+ (define (make-random-source)
253+ (let ([state (mrg32k3a-pack-state
254+ (list->vector
255+ (vector->list mrg32k3a-initial-state)))])
256+ (:random-source-make (lambda () (mrg32k3a-state-ref state))
257+ (lambda (new-state)
258+ (set! state (mrg32k3a-state-set new-state)))
259+ (lambda () (set! state (mrg32k3a-randomize-state state)))
260+ (lambda (i j)
261+ (set! state (mrg32k3a-pseudo-randomize-state i j)))
262+ (lambda ()
263+ (lambda (n)
264+ (cond
265+ [(not (and (integer? n) (exact? n) (positive? n)))
266+ (error "range must be exact positive integer" n)]
267+ [(<= n mrg32k3a-m-max) (mrg32k3a-random-integer state n)]
268+ [else (mrg32k3a-random-large state n)])))
269+ (lambda args
270+ (cond
271+ [(null? args) (lambda () (mrg32k3a-random-real state))]
272+ [(null? (cdr args))
273+ (let ([unit (car args)])
274+ (cond
275+ [(not (and (real? unit) (< 0 unit 1)))
276+ (error "unit must be real in (0,1)" unit)]
277+ [(<= (- (/ 1 unit) 1) mrg32k3a-m1)
278+ (lambda () (mrg32k3a-random-real state))]
279+ [else
280+ (lambda () (mrg32k3a-random-real-mp state unit))]))]
281+ [else (error "illegal arguments" args)])))))
282+ (define random-source? :random-source?)
283+ (define (random-source-state-ref s)
284+ ((:random-source-state-ref s)))
285+ (define (random-source-state-set! s state)
286+ ((:random-source-state-set! s) state))
287+ (define (random-source-randomize! s)
288+ ((:random-source-randomize! s)))
289+ (define (random-source-pseudo-randomize! s i j)
290+ ((:random-source-pseudo-randomize! s) i j))
291+ (define (random-source-make-integers s)
292+ ((:random-source-make-integers s)))
293+ (define (random-source-make-reals s . unit)
294+ (apply (:random-source-make-reals s) unit))
295+ (define default-random-source (make-random-source))
296+ (define random-integer
297+ (random-source-make-integers default-random-source))
298+ (define random-real
299+ (random-source-make-reals default-random-source)))))
lib/srfi/:39.slsnew file+11
@@ -0,0 +1,11 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :39)
10+ (export make-parameter parameterize)
11+ (import (srfi :39 parameters)))
lib/srfi/:39/parameters.chezscheme.slsnew file+24
@@ -0,0 +1,24 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.chezscheme.sls
7+;;; Copyright (c) 2012 Aaron W. Hsu <arcfide@sacrideo.us>
8+;;;
9+;;; Permission to use, copy, modify, and distribute this software for
10+;;; any purpose with or without fee is hereby granted, provided that the
11+;;; above copyright notice and this permission notice appear in all
12+;;; copies.
13+;;;
14+;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
15+;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
16+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
17+;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
18+;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
19+;;; OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20+;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21+;;; PERFORMANCE OF THIS SOFTWARE.
22+(library (srfi :39 parameters)
23+ (export make-parameter parameterize)
24+ (import (only (chezscheme) make-parameter parameterize)))
lib/srfi/:39/parameters.ikarus.slsnew file+12
@@ -0,0 +1,12 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.ikarus.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :39 parameters)
11+ (export make-parameter parameterize)
12+ (import (only (ikarus) make-parameter parameterize)))
lib/srfi/:39/parameters.ironscheme.slsnew file+14
@@ -0,0 +1,14 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.ironscheme.sls
7+#!r6rs
8+;; Copyright (c) 2009 Derick Eddington. All rights reserved. Licensed under an
9+;; MIT-style license. My license is in the file named LICENSE from the original
10+;; collection this file is distributed with. If this file is redistributed with
11+;; some other collection, my license must also be included.
12+(library (srfi :39 parameters)
13+ (export make-parameter parameterize)
14+ (import (only (ironscheme) make-parameter parameterize)))
lib/srfi/:39/parameters.mzscheme.slsnew file+12
@@ -0,0 +1,12 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.mzscheme.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :39 parameters)
11+ (export make-parameter parameterize)
12+ (import (only (scheme base) make-parameter parameterize)))
lib/srfi/:39/parameters.slsnew file+35
@@ -0,0 +1,35 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :39 parameters)
11+ (export make-parameter parameterize)
12+ (import (rnrs))
13+ (define make-parameter
14+ (case-lambda
15+ [(val) (make-parameter val values)]
16+ [(val guard)
17+ (unless (procedure? guard)
18+ (assertion-violation 'make-parameter
19+ "not a procedure"
20+ guard))
21+ (let ([p (case-lambda [() val] [(x) (set! val (guard x))])])
22+ (p val)
23+ p)]))
24+ (define-syntax parameterize
25+ (lambda (stx)
26+ (syntax-case stx ()
27+ [(_ () b0 b ...) #'(let () b0 b ...)]
28+ [(_ ((p e) ...) b0 b ...)
29+ (with-syntax ([(tp ...) (generate-temporaries #'(p ...))]
30+ [(te ...) (generate-temporaries #'(e ...))])
31+ #'(let ([tp p] ... [te e] ...)
32+ (let ([swap (lambda ()
33+ (let ([t (tp)]) (tp te) (set! te t))
34+ ...)])
35+ (dynamic-wind swap (lambda () b0 b ...) swap))))]))))
lib/srfi/:39/parameters.ypsilon.slsnew file+12
@@ -0,0 +1,12 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a39/parameters.ypsilon.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :39 parameters)
11+ (export make-parameter parameterize)
12+ (import (only (core) make-parameter parameterize)))
lib/srfi/:6.slsnew file+14
@@ -0,0 +1,14 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :6)
10+ (export
11+ get-output-string
12+ open-input-string
13+ open-output-string)
14+ (import (srfi :6 basic-string-ports)))
lib/srfi/:6/basic-string-ports.mzscheme.slsnew file+45
@@ -0,0 +1,45 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports.mzscheme.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :6 basic-string-ports)
11+ (export
12+ (rename (open-string-input-port open-input-string))
13+ open-output-string
14+ get-output-string)
15+ (import
16+ (rnrs)
17+ (only (scheme base) make-weak-hasheq hash-ref hash-set!))
18+ (define accumed-ht (make-weak-hasheq))
19+ (define (open-output-string)
20+ (letrec ([sop (make-custom-textual-output-port "string-output-port"
21+ (lambda (string start count)
22+ (when (positive? count)
23+ (let ([al (hash-ref accumed-ht sop)])
24+ (hash-set!
25+ accumed-ht
26+ sop
27+ (cons
28+ (substring string start (+ start count))
29+ al))))
30+ count)
31+ #f #f #f)])
32+ (hash-set! accumed-ht sop '())
33+ sop))
34+ (define (get-output-string sop)
35+ (if (output-port? sop)
36+ (cond
37+ [(hash-ref accumed-ht sop #f) =>
38+ (lambda (al) (apply string-append (reverse al)))]
39+ [else
40+ (assertion-violation 'get-output-string
41+ "not a string-output-port"
42+ sop)])
43+ (assertion-violation 'get-output-string
44+ "not an output-port"
45+ sop))))
lib/srfi/:6/basic-string-ports.slsnew file+17
@@ -0,0 +1,17 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports.sls
7+#!r6rs
8+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :6 basic-string-ports)
11+ (export
12+ (rename (open-string-input-port open-input-string))
13+ open-output-string
14+ get-output-string)
15+ (import
16+ (only (rnrs io ports) open-string-input-port)
17+ (srfi :6 basic-string-ports compat)))
lib/srfi/:6/basic-string-ports/compat.chezscheme.slsnew file+24
@@ -0,0 +1,24 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.chezscheme.sls
7+;;; Copyright (c) 2012 Aaron W. Hsu <arcfide@sacrideo.us>
8+;;;
9+;;; Permission to use, copy, modify, and distribute this software for
10+;;; any purpose with or without fee is hereby granted, provided that the
11+;;; above copyright notice and this permission notice appear in all
12+;;; copies.
13+;;;
14+;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
15+;;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
16+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
17+;;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
18+;;; DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
19+;;; OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20+;;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21+;;; PERFORMANCE OF THIS SOFTWARE.
22+(library (srfi :6 basic-string-ports compat)
23+ (export open-output-string get-output-string)
24+ (import (chezscheme)))
lib/srfi/:6/basic-string-ports/compat.ikarus.slsnew file+13
@@ -0,0 +1,13 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.ikarus.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :6 basic-string-ports compat)
11+ (export open-output-string get-output-string)
12+ (import
13+ (only (ikarus) open-output-string get-output-string)))
lib/srfi/:6/basic-string-ports/compat.ironscheme.slsnew file+15
@@ -0,0 +1,15 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.ironscheme.sls
7+#!r6rs
8+;; Copyright (c) 2009 Derick Eddington. All rights reserved. Licensed under an
9+;; MIT-style license. My license is in the file named LICENSE from the original
10+;; collection this file is distributed with. If this file is redistributed with
11+;; some other collection, my license must also be included.
12+(library (srfi :6 basic-string-ports compat)
13+ (export open-output-string get-output-string)
14+ (import
15+ (only (ironscheme) open-output-string get-output-string)))
lib/srfi/:6/basic-string-ports/compat.larceny.slsnew file+12
@@ -0,0 +1,12 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.larceny.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :6 basic-string-ports compat)
11+ (export open-output-string get-output-string)
12+ (import (primitives open-output-string get-output-string)))
lib/srfi/:6/basic-string-ports/compat.loko.slsnew file+12
@@ -0,0 +1,12 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.loko.sls
7+;; Copyright © 2019 Göran Weinholt
8+;; SPDX-License-Identifier: MIT
9+#!r6rs
10+(library (srfi :6 basic-string-ports compat)
11+ (export open-output-string get-output-string)
12+ (import (only (loko) open-output-string get-output-string)))
lib/srfi/:6/basic-string-ports/compat.ypsilon.slsnew file+19
@@ -0,0 +1,19 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a6/basic-string-ports/compat.ypsilon.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :6 basic-string-ports compat)
11+ (export
12+ (rename
13+ (make-string-output-port open-output-string)
14+ (get-accumulated-string get-output-string)))
15+ (import
16+ (only
17+ (core)
18+ make-string-output-port
19+ get-accumulated-string)))
lib/srfi/:8.slsnew file+11
@@ -0,0 +1,11 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a8.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :8)
10+ (export receive)
11+ (import (srfi :8 receive)))
lib/srfi/:8/receive.slsnew file+18
@@ -0,0 +1,18 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a8/receive.sls
7+#!r6rs
8+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
9+;; LICENSE from the original collection this file is distributed with.
10+(library (srfi :8 receive)
11+ (export receive)
12+ (import (rnrs))
13+ (define-syntax receive
14+ (syntax-rules ()
15+ [(_ formals expression b b* ...)
16+ (call-with-values
17+ (lambda () expression)
18+ (lambda formals b b* ...))])))
lib/srfi/:99.slsnew file+14
@@ -0,0 +1,14 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99.sls
7+#!r6rs
8+;; Automatically generated by private/make-aliased-libraries.sps
9+(library (srfi :99)
10+ (export define-record-type make-rtd record-rtd record? rtd-accessor
11+ rtd-all-field-names rtd-constructor rtd-field-mutable?
12+ rtd-field-names rtd-mutator rtd-name rtd-parent
13+ rtd-predicate rtd?)
14+ (import (srfi :99 records)))
lib/srfi/:99/records.slsnew file+35
@@ -0,0 +1,35 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records.sls
7+#!r6rs
8+;; Copyright (C) William D Clinger 2008. All Rights Reserved.
9+;;
10+;; Permission is hereby granted, free of charge, to any person obtaining a copy
11+;; of this software and associated documentation files (the "Software"), to deal
12+;; in the Software without restriction, including without limitation the rights
13+;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+;; copies of the Software, and to permit persons to whom the Software is
15+;; furnished to do so, subject to the following conditions:
16+;;
17+;; The above copyright notice and this permission notice shall be included in
18+;; all copies or substantial portions of the Software.
19+;;
20+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO
23+;; SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+(library (srfi :99 records)
28+ (export record? record-rtd rtd-name rtd-parent rtd-field-names
29+ rtd-all-field-names rtd-field-mutable? make-rtd rtd?
30+ rtd-constructor rtd-predicate rtd-accessor rtd-mutator
31+ define-record-type)
32+ (import
33+ (srfi :99 records inspection)
34+ (srfi :99 records procedural)
35+ (srfi :99 records syntactic)))
lib/srfi/:99/records/helper.slsnew file+30
@@ -0,0 +1,30 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/helper.sls
7+#!r6rs
8+;; Copyright (C) William D Clinger 2008. All Rights Reserved.
9+;;
10+;; Permission is hereby granted, free of charge, to any person obtaining a copy
11+;; of this software and associated documentation files (the "Software"), to deal
12+;; in the Software without restriction, including without limitation the rights
13+;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+;; copies of the Software, and to permit persons to whom the Software is
15+;; furnished to do so, subject to the following conditions:
16+;;
17+;; The above copyright notice and this permission notice shall be included in
18+;; all copies or substantial portions of the Software.
19+;;
20+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO
23+;; SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+(library (srfi :99 records helper)
28+ (export rtd?)
29+ (import (rnrs base) (rnrs records procedural))
30+ (define rtd? record-type-descriptor?))
lib/srfi/:99/records/inspection.larceny.slsnew file+10
@@ -0,0 +1,10 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/inspection.larceny.sls
7+(library (srfi :99 records inspection)
8+ (export record? record-rtd rtd-name rtd-parent
9+ rtd-field-names rtd-all-field-names rtd-field-mutable?)
10+ (import (err5rs records inspection)))
lib/srfi/:99/records/inspection.slsnew file+60
@@ -0,0 +1,60 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/inspection.sls
7+#!r6rs
8+;; Copyright (C) William D Clinger 2008. All Rights Reserved.
9+;;
10+;; Permission is hereby granted, free of charge, to any person obtaining a copy
11+;; of this software and associated documentation files (the "Software"), to deal
12+;; in the Software without restriction, including without limitation the rights
13+;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+;; copies of the Software, and to permit persons to whom the Software is
15+;; furnished to do so, subject to the following conditions:
16+;;
17+;; The above copyright notice and this permission notice shall be included in
18+;; all copies or substantial portions of the Software.
19+;;
20+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO
23+;; SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+(library (srfi :99 records inspection)
28+ (export record? record-rtd rtd-name rtd-parent
29+ rtd-field-names rtd-all-field-names rtd-field-mutable?)
30+ (import
31+ (rnrs base)
32+ (rnrs lists)
33+ (rnrs records inspection)
34+ (srfi :99 records helper))
35+ (define rtd-name record-type-name)
36+ (define rtd-parent record-type-parent)
37+ (define rtd-field-names record-type-field-names)
38+ (define (rtd-all-field-names rtd)
39+ (define (loop rtd othernames)
40+ (let ([parent (rtd-parent rtd)]
41+ [names (append
42+ (vector->list (rtd-field-names rtd))
43+ othernames)])
44+ (if parent (loop parent names) (list->vector names))))
45+ (loop rtd '()))
46+ (define (rtd-field-mutable? rtd0 fieldname)
47+ (define (loop rtd)
48+ (if (rtd? rtd)
49+ (let* ([names (vector->list (rtd-field-names rtd))]
50+ [probe (memq fieldname names)])
51+ (if probe
52+ (record-field-mutable?
53+ rtd
54+ (- (length names) (length probe)))
55+ (loop (rtd-parent rtd))))
56+ (assertion-violation 'rtd-field-mutable?
57+ "illegal argument"
58+ rtd0
59+ fieldname)))
60+ (loop rtd0)))
lib/srfi/:99/records/procedural.larceny.slsnew file+10
@@ -0,0 +1,10 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/procedural.larceny.sls
7+(library (srfi :99 records procedural)
8+ (export make-rtd rtd? rtd-constructor rtd-predicate
9+ rtd-accessor rtd-mutator)
10+ (import (err5rs records procedural)))
lib/srfi/:99/records/procedural.slsnew file+108
@@ -0,0 +1,108 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/procedural.sls
7+#!r6rs
8+;; Copyright (C) William D Clinger 2008. All Rights Reserved.
9+;;
10+;; Permission is hereby granted, free of charge, to any person obtaining a copy
11+;; of this software and associated documentation files (the "Software"), to deal
12+;; in the Software without restriction, including without limitation the rights
13+;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+;; copies of the Software, and to permit persons to whom the Software is
15+;; furnished to do so, subject to the following conditions:
16+;;
17+;; The above copyright notice and this permission notice shall be included in
18+;; all copies or substantial portions of the Software.
19+;;
20+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO
23+;; SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+(library (srfi :99 records procedural)
28+ (export make-rtd rtd? rtd-constructor rtd-predicate
29+ rtd-accessor rtd-mutator)
30+ (import
31+ (rnrs base)
32+ (rnrs lists)
33+ (rnrs records procedural)
34+ (srfi :99 records inspection))
35+ (define (make-rtd name fieldspecs . rest)
36+ (let* ([parent (if (null? rest) #f (car rest))]
37+ [options (if (null? rest) '() (cdr rest))]
38+ [sealed? (and (memq 'sealed options) #t)]
39+ [opaque? (and (memq 'opaque options) #t)]
40+ [uid (let ([probe (memq 'uid options)])
41+ (if (and probe (not (null? (cdr probe))))
42+ (cadr probe)
43+ #f))])
44+ (make-record-type-descriptor name parent uid sealed? opaque?
45+ (vector-map
46+ (lambda (fieldspec)
47+ (if (symbol? fieldspec)
48+ (list 'mutable fieldspec)
49+ fieldspec))
50+ (if (list? fieldspecs)
51+ (list->vector fieldspecs)
52+ fieldspecs)))))
53+ (define rtd? record-type-descriptor?)
54+ (define (rtd-constructor rtd . rest)
55+ (define (make-constructor fieldspecs allnames maker)
56+ (let* ([k (length fieldspecs)]
57+ [n (length allnames)]
58+ [buffer (make-vector n)]
59+ [reverse-all-names (reverse allnames)])
60+ (define (position fieldname)
61+ (let ([names (memq fieldname reverse-all-names)])
62+ (assert names)
63+ (- (length names) 1)))
64+ (let ([indexes (map position fieldspecs)])
65+ (lambda args
66+ (assert (= (length args) k))
67+ (for-each
68+ (lambda (arg posn) (vector-set! buffer posn arg))
69+ args
70+ indexes)
71+ (apply maker (vector->list buffer))))))
72+ (if (null? rest)
73+ (record-constructor
74+ (make-record-constructor-descriptor rtd #f #f))
75+ (begin
76+ (assert (null? (cdr rest)))
77+ (make-constructor
78+ (vector->list (car rest))
79+ (vector->list (rtd-all-field-names rtd))
80+ (record-constructor
81+ (make-record-constructor-descriptor rtd #f #f))))))
82+ (define rtd-predicate record-predicate)
83+ (define (rtd-accessor rtd0 fieldname)
84+ (define (loop rtd)
85+ (if (rtd? rtd)
86+ (let* ([names (vector->list (rtd-field-names rtd))]
87+ [probe (memq fieldname names)])
88+ (if probe
89+ (record-accessor rtd (- (length names) (length probe)))
90+ (loop (rtd-parent rtd))))
91+ (assertion-violation 'rtd-accessor
92+ "illegal argument"
93+ rtd0
94+ fieldname)))
95+ (loop rtd0))
96+ (define (rtd-mutator rtd0 fieldname)
97+ (define (loop rtd)
98+ (if (rtd? rtd)
99+ (let* ([names (vector->list (rtd-field-names rtd))]
100+ [probe (memq fieldname names)])
101+ (if probe
102+ (record-mutator rtd (- (length names) (length probe)))
103+ (loop (rtd-parent rtd))))
104+ (assertion-violation 'rtd-mutator
105+ "illegal argument"
106+ rtd0
107+ fieldname)))
108+ (loop rtd0)))
lib/srfi/:99/records/syntactic.larceny.slsnew file+9
@@ -0,0 +1,9 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/syntactic.larceny.sls
7+(library (srfi :99 records syntactic)
8+ (export define-record-type)
9+ (import (err5rs records syntactic)))
lib/srfi/:99/records/syntactic.slsnew file+208
@@ -0,0 +1,208 @@
1+;; DO NOT EDIT THIS FILE!!
2+;; This inlined chez-srfi library code is autogenerated using command:
3+;; $ ./install.chezscheme.sps ../lib
4+;; Source origin: https://github.com/arcfide/chez-srfi
5+;; Please refer to project site for full credits and original code.
6+;;;;;; File header: %3a99/records/syntactic.sls
7+#!r6rs
8+;; Copyright (C) William D Clinger 2008. All Rights Reserved.
9+;;
10+;; Permission is hereby granted, free of charge, to any person obtaining a copy
11+;; of this software and associated documentation files (the "Software"), to deal
12+;; in the Software without restriction, including without limitation the rights
13+;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+;; copies of the Software, and to permit persons to whom the Software is
15+;; furnished to do so, subject to the following conditions:
16+;;
17+;; The above copyright notice and this permission notice shall be included in
18+;; all copies or substantial portions of the Software.
19+;;
20+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO
23+;; SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25+;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+(library (srfi :99 records syntactic)
28+ (export define-record-type)
29+ (import
30+ (for (rnrs base) run expand)
31+ (for (rnrs lists) run expand)
32+ (for (rnrs syntax-case) run expand)
33+ (srfi :99 records procedural))
34+ (define-syntax define-record-type
35+ (syntax-rules ()
36+ [(_ (type-name parent) constructor-spec predicate-spec .
37+ field-specs)
38+ (define-record-type-helper0 type-name parent
39+ constructor-spec predicate-spec . field-specs)]
40+ [(_ type-name constructor-spec predicate-spec . field-specs)
41+ (define-record-type-helper0 type-name #f constructor-spec
42+ predicate-spec . field-specs)]))
43+ (define-syntax define-record-type-helper0
44+ (lambda (x)
45+ (define (construct-record-type-definitions tname fields
46+ parent cspec pred afields mfields)
47+ (let ()
48+ (define (frob x)
49+ (cond
50+ [(identifier? x) x]
51+ [(pair? x) (cons (frob (car x)) (frob (cdr x)))]
52+ [(vector? x) (vector-map frob x)]
53+ [(symbol? x) (datum->syntax tname x)]
54+ [else x]))
55+ #`(#,(frob #'define-record-type-helper) #,(frob tname) #,(frob fields) #,(frob parent)
56+ #,(frob cspec) #,(frob pred) #,(frob afields)
57+ #,(frob mfields))))
58+ (define (syntax-car x)
59+ (syntax-case x () [(x0 x1 ...) #'x0]))
60+ (define (syntax-cdr x)
61+ (syntax-case x () [(x0 x1 ...) #'(x1 ...)]))
62+ (define (syntax->list x)
63+ (syntax-case x ()
64+ [() '()]
65+ [(x0 . x1) (cons #'x0 (syntax->list #'x1))]))
66+ (define (complain)
67+ (syntax-violation 'define-record-type "illegal syntax" x))
68+ (syntax-case x ()
69+ [(_ tname pname constructor-spec predicate-spec .
70+ field-specs)
71+ (let* ([type-name (syntax->datum #'tname)]
72+ [cspec (syntax->datum #'constructor-spec)]
73+ [pspec (syntax->datum #'predicate-spec)]
74+ [fspecs (syntax->datum #'field-specs)]
75+ [type-name-string (begin
76+ (if (not (symbol? type-name))
77+ (complain))
78+ (symbol->string type-name))]
79+ [constructor-name (cond
80+ [(eq? cspec #f) #'constructor-spec]
81+ [(eq? cspec #t)
82+ (datum->syntax
83+ #'tname
84+ (string->symbol
85+ (string-append
86+ "make-"
87+ type-name-string)))]
88+ [(symbol? cspec) #'constructor-spec]
89+ [(and (pair? cspec)
90+ (symbol? (car cspec)))
91+ (syntax-car #'constructor-spec)]
92+ [else (complain)])]
93+ [constructor-args (cond
94+ [(pair? cspec)
95+ (if (not (for-all symbol? cspec))
96+ (complain)
97+ (list->vector
98+ (syntax->list
99+ (syntax-cdr
100+ #'constructor-spec))))]
101+ [else #f])]
102+ [new-constructor-spec (if constructor-args
103+ (list
104+ constructor-name
105+ constructor-args)
106+ constructor-name)]
107+ [predicate-name (cond
108+ [(eq? pspec #f) #'predicate-spec]
109+ [(eq? pspec #t)
110+ (datum->syntax
111+ #'tname
112+ (string->symbol
113+ (string-append
114+ type-name-string
115+ "?")))]
116+ [(symbol? pspec) #'predicate-spec]
117+ [else (complain)])]
118+ [field-specs (map (lambda (fspec field-spec)
119+ (cond
120+ [(symbol? fspec)
121+ (list
122+ 'immutable
123+ fspec
124+ (string->symbol
125+ (string-append
126+ type-name-string
127+ "-"
128+ (symbol->string fspec))))]
129+ [(not (pair? fspec)) (complain)]
130+ [(not (list? fspec)) (complain)]
131+ [(not (for-all symbol? fspec))
132+ (complain)]
133+ [(null? (cdr fspec))
134+ (list
135+ 'mutable
136+ (car fspec)
137+ (string->symbol
138+ (string-append
139+ type-name-string
140+ "-"
141+ (symbol->string (car fspec))))
142+ (string->symbol
143+ (string-append
144+ type-name-string
145+ "-"
146+ (symbol->string (car fspec))
147+ "-set!")))]
148+ [(null? (cddr fspec))
149+ (list
150+ 'immutable
151+ (car fspec)
152+ (syntax-car
153+ (syntax-cdr field-spec)))]
154+ [(null? (cdddr fspec))
155+ (list
156+ 'mutable
157+ (car fspec)
158+ (syntax-car
159+ (syntax-cdr field-spec))
160+ (syntax-car
161+ (syntax-cdr
162+ (syntax-cdr field-spec))))]
163+ [else (complain)]))
164+ fspecs
165+ (syntax->list #'field-specs))]
166+ [fields (list->vector (map cadr field-specs))]
167+ [accessor-fields (map (lambda (x)
168+ (list (caddr x) (cadr x)))
169+ (filter
170+ (lambda (x) (>= (length x) 3))
171+ field-specs))]
172+ [mutator-fields (map (lambda (x)
173+ (list (cadddr x) (cadr x)))
174+ (filter
175+ (lambda (x) (= (length x) 4))
176+ field-specs))])
177+ (construct-record-type-definitions #'tname fields #'pname new-constructor-spec predicate-name
178+ accessor-fields mutator-fields))])))
179+ (define-syntax define-record-type-helper
180+ (syntax-rules ()
181+ [(_ type-name fields parent #f predicate
182+ ((accessor field) ...) ((mutator mutable-field) ...))
183+ (define-record-type-helper type-name fields parent ignored predicate
184+ ((accessor field) ...) ((mutator mutable-field) ...))]
185+ [(_ type-name fields parent constructor #f
186+ ((accessor field) ...) ((mutator mutable-field) ...))
187+ (define-record-type-helper type-name fields parent constructor ignored
188+ ((accessor field) ...) ((mutator mutable-field) ...))]
189+ [(_ type-name fields parent (constructor args) predicate
190+ ((accessor field) ...) ((mutator mutable-field) ...))
191+ (begin
192+ (define type-name (make-rtd 'type-name 'fields parent))
193+ (define constructor (rtd-constructor type-name 'args))
194+ (define predicate (rtd-predicate type-name))
195+ (define accessor (rtd-accessor type-name 'field))
196+ ...
197+ (define mutator (rtd-mutator type-name 'mutable-field))
198+ ...)]
199+ [(_ type-name fields parent constructor predicate
200+ ((accessor field) ...) ((mutator mutable-field) ...))
201+ (begin
202+ (define type-name (make-rtd 'type-name 'fields parent))
203+ (define constructor (rtd-constructor type-name))
204+ (define predicate (rtd-predicate type-name))
205+ (define accessor (rtd-accessor type-name 'field))
206+ ...
207+ (define mutator (rtd-mutator type-name 'mutable-field))
208+ ...)])))
lib/srfi/private/OS-id-features.slsnew file+22
@@ -0,0 +1,22 @@
1+#!r6rs
2+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
3+;; LICENSE from the original collection this file is distributed with.
4+
5+(library (srfi private OS-id-features)
6+ (export
7+ OS-id-features)
8+ (import
9+ (rnrs))
10+
11+ (define (OS-id-features OS-id features-alist)
12+ (define OS-id-len (string-length OS-id))
13+ (define (OS-id-contains? str)
14+ (define str-len (string-length str))
15+ (let loop ((i 0))
16+ (and (<= (+ i str-len) OS-id-len)
17+ (or (string-ci=? str (substring OS-id i (+ i str-len)))
18+ (loop (+ 1 i))))))
19+ (apply append
20+ (map cdr (filter (lambda (x) (OS-id-contains? (car x)))
21+ features-alist))))
22+)
lib/srfi/private/check-arg.slsnew file+23
@@ -0,0 +1,23 @@
1+#!r6rs
2+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
3+;; LICENSE from the original collection this file is distributed with.
4+
5+;; If your Scheme system doesn't have a stack-tracing debugger, you can change
6+;; this to use the version which actually does check.
7+
8+(library (srfi private check-arg)
9+ (export
10+ check-arg)
11+ (import
12+ (rnrs))
13+
14+#;(define (check-arg pred val who)
15+ (if (pred val)
16+ val
17+ (assertion-violation #F "check-arg failed" who pred val)))
18+
19+ (define-syntax check-arg
20+ (syntax-rules ()
21+ ((_ pred val who)
22+ val)))
23+)
lib/srfi/private/define-values.chezscheme.slsnew file+3
@@ -0,0 +1,3 @@
1+(library (srfi private define-values)
2+ (export define-values)
3+ (import (chezscheme)))
lib/srfi/private/include.chezscheme.slsnew file+3
@@ -0,0 +1,3 @@
1+(library (srfi private include)
2+ (export)
3+ (import (chezscheme)))
lib/srfi/private/platform-features.chezscheme.slsnew file+34
@@ -0,0 +1,34 @@
1+;;; Copyright (c) 2012 Aaron W. Hsu <arcfide@sacrideo.us>
2+;;;
3+;;; Permission to use, copy, modify, and distribute this software for any
4+;;; purpose with or without fee is hereby granted, provided that the above
5+;;; copyright notice and this permission notice appear in all copies.
6+;;;
7+;;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+;;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+;;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10+;;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+;;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12+;;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13+;;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14+
15+(library (srfi private platform-features)
16+ (export expand-time-features run-time-features)
17+ (import (chezscheme) (srfi private OS-id-features))
18+
19+(define (expand-time-features) '(chezscheme syntax-case))
20+
21+(define (run-time-features)
22+ (OS-id-features (symbol->string (machine-type))
23+ '(("t" threads)
24+ ("a6" x86-64)
25+ ("i3" x86)
26+ ("le" linux posix)
27+ ("ob" openbsd posix bsd)
28+ ("fb" freebsd posix bsd)
29+ ("nb" netbsd posix bsd)
30+ ("osx" darwin posix)
31+ ("s2" solaris posix)
32+ ("nt" windows))))
33+
34+)
lib/srfi/private/registry-names.slsnew file+66
@@ -0,0 +1,66 @@
1+#!r6rs
2+;; Automatically generated by registry-names-update.sps
3+(library (srfi private registry-names)
4+ (export SRFIs)
5+ (import (rnrs))
6+ (define SRFIs
7+ '((0 cond-expand)
8+ (1 lists)
9+ (2 and-let*)
10+ (4 numeric-vectors)
11+ (5 let)
12+ (6 basic-string-ports)
13+ (8 receive)
14+ (9 records)
15+ (11 let-values)
16+ (13 strings)
17+ (14 char-sets)
18+ (16 case-lambda)
19+ (17 generalized-set!)
20+ (19 time)
21+ (23 error)
22+ (25 multi-dimensional-arrays)
23+ (26 cut)
24+ (27 random-bits)
25+ (28 basic-format-strings)
26+ (29 localization)
27+ (31 rec)
28+ (34 exception-handling)
29+ (35 conditions)
30+ (37 args-fold)
31+ (38 with-shared-structure)
32+ (39 parameters)
33+ (41 streams)
34+ (42 eager-comprehensions)
35+ (43 vectors)
36+ (45 lazy)
37+ (48 intermediate-format-strings)
38+ (51 rest-values)
39+ (54 cat)
40+ (60 integer-bits)
41+ (61 cond)
42+ (64 testing)
43+ (67 compare-procedures)
44+ (69 basic-hash-tables)
45+ (78 lightweight-testing)
46+ (98 os-environment-variables)
47+ (99 records)
48+ (115 regex)
49+ (117 list-queues)
50+ (125 hashtables)
51+ (126 r6rs-hashtables)
52+ (127 lazy-sequences)
53+ (128 comparators)
54+ (129 titlecase)
55+ (130 string-cursors)
56+ (131 records)
57+ (132 sorting)
58+ (133 vectors)
59+ (141 integer-division)
60+ (143 fixnums)
61+ (145 assumptions)
62+ (151 bitwise-operations)
63+ (152 strings)
64+ (156 predicate-combiners)
65+ (158 generators-and-accumulators)
66+ (175 ascii))))
lib/srfi/private/registry.slsnew file+48
@@ -0,0 +1,48 @@
1+#!r6rs
2+;; Copyright 2010 Derick Eddington. My MIT-style license is in the file named
3+;; LICENSE from the original collection this file is distributed with.
4+
5+(library (srfi private registry)
6+ (export
7+ expand-time-features
8+ run-time-features
9+ available-features)
10+ (import
11+ (rnrs)
12+ (srfi private registry-names)
13+ (for (prefix (srfi private platform-features) platform-)
14+ run expand))
15+
16+ (define-syntax make-expand-time-features
17+ (lambda (_)
18+ (define (SRFI-names x)
19+ (define number car)
20+ (define mnemonic cdr)
21+ (define (make-symbol . args)
22+ (string->symbol (apply string-append
23+ (map (lambda (a)
24+ (if (symbol? a) (symbol->string a) a))
25+ args))))
26+ (let* ((n-str (number->string (number x)))
27+ (colon-n (make-symbol ":" n-str))
28+ (srfi-n (make-symbol "srfi-" n-str))
29+ (srfi-n-m (apply make-symbol srfi-n
30+ (map (lambda (m) (make-symbol "-" m))
31+ (mnemonic x)))))
32+ ;; The first two are recommended by SRFI-97.
33+ ;; The last two are the two types of SRFI-97 library name.
34+ (list srfi-n
35+ srfi-n-m
36+ `(srfi ,colon-n)
37+ `(srfi ,colon-n . ,(mnemonic x)))))
38+ (let ((s (apply append (map SRFI-names SRFIs)))
39+ (h (platform-expand-time-features))
40+ (o '(r6rs)))
41+ #`(quote #,(datum->syntax #'ignored (append s h o))))))
42+
43+ (define expand-time-features (make-expand-time-features))
44+
45+ (define run-time-features (platform-run-time-features))
46+
47+ (define available-features (append run-time-features expand-time-features))
48+)
lib/srfi/private/vanish.slsnew file+35
@@ -0,0 +1,35 @@
1+#!r6rs
2+;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
3+;; LICENSE from the original collection this file is distributed with.
4+
5+(library (srfi private vanish)
6+ (export
7+ vanish-define)
8+ (import
9+ (rnrs)
10+ (for (only (rnrs base) begin) (meta -1)))
11+
12+ (define-syntax vanish-define
13+ (lambda (stx)
14+ (syntax-case stx ()
15+ ((_ def (vanish ...))
16+ (for-all identifier? #'(def vanish ...))
17+ #'(make-vanish-define (syntax def) (syntax vanish) ...)))))
18+
19+ (define (make-vanish-define def . to-vanish)
20+ (lambda (stx)
21+ (define (vanish? id)
22+ (memp (lambda (x) (free-identifier=? id x))
23+ to-vanish))
24+ (syntax-case stx ()
25+ ((_ name . _)
26+ (and (identifier? #'name)
27+ (vanish? #'name))
28+ #'(begin))
29+ ((_ (name . _) . _)
30+ (and (identifier? #'name)
31+ (vanish? #'name))
32+ #'(begin))
33+ ((_ . r)
34+ (cons def #'r)))))
35+)
package-lock.jsonnew file+14
@@ -0,0 +1,14 @@
1+{
2+ "name": "purescm",
3+ "lockfileVersion": 3,
4+ "requires": true,
5+ "packages": {
6+ "": {
7+ "bin": {
8+ "purescm": "index.js"
9+ },
10+ "version": "1.12.0"
11+ }
12+ },
13+ "version": "1.12.0"
14+}
package-sets/1.0.0.jsonnew file+175
@@ -0,0 +1,175 @@
1+{
2+ "compiler": "0.15.10",
3+ "published": "2023-09-30",
4+ "version": "1.0.0",
5+ "packages": {
6+ "arrays": {
7+ "git": "https://github.com/purescm/purescript-core.git",
8+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
9+ "subdir": "arrays"
10+ },
11+ "assert": {
12+ "git": "https://github.com/purescm/purescript-core.git",
13+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
14+ "subdir": "assert"
15+ },
16+ "bifunctors": "6.0.0",
17+ "catenable-lists": "7.0.0",
18+ "console": {
19+ "git": "https://github.com/purescm/purescript-core.git",
20+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
21+ "subdir": "console"
22+ },
23+ "const": "6.0.0",
24+ "contravariant": "6.0.0",
25+ "control": {
26+ "git": "https://github.com/purescm/purescript-core.git",
27+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
28+ "subdir": "control"
29+ },
30+ "datetime": {
31+ "git": "https://github.com/purescm/purescript-core.git",
32+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
33+ "subdir": "datetime"
34+ },
35+ "distributive": "6.0.0",
36+ "effect": {
37+ "git": "https://github.com/purescm/purescript-core.git",
38+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
39+ "subdir": "effect"
40+ },
41+ "either": "6.1.0",
42+ "enums": {
43+ "git": "https://github.com/purescm/purescript-core.git",
44+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
45+ "subdir": "enums"
46+ },
47+ "exceptions": {
48+ "git": "https://github.com/purescm/purescript-core.git",
49+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
50+ "subdir": "exceptions"
51+ },
52+ "exists": "6.0.0",
53+ "filterable": "5.0.0",
54+ "foldable-traversable": {
55+ "git": "https://github.com/purescm/purescript-core.git",
56+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
57+ "subdir": "foldable-traversable"
58+ },
59+ "foreign-object": {
60+ "git": "https://github.com/purescm/purescript-core.git",
61+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
62+ "subdir": "foreign-object"
63+ },
64+ "free": "7.1.0",
65+ "functions": {
66+ "git": "https://github.com/purescm/purescript-core.git",
67+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
68+ "subdir": "functions",
69+ "dependencies": [
70+ "prelude"
71+ ]
72+ },
73+ "functors": "5.0.0",
74+ "gen": "4.0.0",
75+ "identity": "6.0.0",
76+ "integers": {
77+ "git": "https://github.com/purescm/purescript-core.git",
78+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
79+ "subdir": "integers"
80+ },
81+ "invariant": "6.0.0",
82+ "json": {
83+ "git": "https://github.com/purescm/purescript-core.git",
84+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
85+ "subdir": "json"
86+ },
87+ "lazy": {
88+ "git": "https://github.com/purescm/purescript-core.git",
89+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
90+ "subdir": "lazy"
91+ },
92+ "lcg": "4.0.0",
93+ "lists": {
94+ "git": "https://github.com/purescm/purescript-lists.git",
95+ "ref": "71502a132567cf7f32c2242d57b1cba2c77ebc15"
96+ },
97+ "maybe": "6.0.0",
98+ "minibench": {
99+ "git": "https://github.com/purescm/purescript-core.git",
100+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
101+ "subdir": "minibench"
102+ },
103+ "newtype": "5.0.0",
104+ "nonempty": "7.0.0",
105+ "numbers": {
106+ "git": "https://github.com/purescm/purescript-core.git",
107+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
108+ "subdir": "numbers"
109+ },
110+ "ordered-collections": "3.1.1",
111+ "orders": "6.0.0",
112+ "parallel": "7.0.0",
113+ "partial": {
114+ "git": "https://github.com/purescm/purescript-core.git",
115+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
116+ "subdir": "partial",
117+ "dependencies": []
118+ },
119+ "prelude": {
120+ "git": "https://github.com/purescm/purescript-core.git",
121+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
122+ "subdir": "prelude"
123+ },
124+ "profunctor": "6.0.0",
125+ "quickcheck": {
126+ "git": "https://github.com/purescm/purescript-core.git",
127+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
128+ "subdir": "quickcheck"
129+ },
130+ "random": {
131+ "git": "https://github.com/purescm/purescript-core.git",
132+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
133+ "subdir": "random"
134+ },
135+ "record": {
136+ "git": "https://github.com/purescm/purescript-core.git",
137+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
138+ "subdir": "record"
139+ },
140+ "refs": {
141+ "git": "https://github.com/purescm/purescript-core.git",
142+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
143+ "subdir": "refs"
144+ },
145+ "safe-coerce": "2.0.0",
146+ "st": {
147+ "git": "https://github.com/purescm/purescript-core.git",
148+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
149+ "subdir": "st"
150+ },
151+ "strings": {
152+ "git": "https://github.com/purescm/purescript-core.git",
153+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
154+ "subdir": "strings"
155+ },
156+ "semirings": "7.0.0",
157+ "tailrec": "6.1.0",
158+ "transformers": "6.0.0",
159+ "tuples": "7.0.0",
160+ "type-equality": "4.0.1",
161+ "typelevel-prelude": "7.0.0",
162+ "unfoldable": {
163+ "git": "https://github.com/purescm/purescript-core.git",
164+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
165+ "subdir": "unfoldable"
166+ },
167+ "unsafe-coerce": {
168+ "git": "https://github.com/purescm/purescript-core.git",
169+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
170+ "subdir": "unsafe-coerce",
171+ "dependencies": []
172+ },
173+ "validation": "6.0.0"
174+ }
175+}
package.json+15−2
@@ -1,6 +1,19 @@
11{
2− "private": true,
2+ "name": "purescm",
3+ "version": "1.12.0",
4+ "main": "index.js",
5+ "type": "module",
6+ "files": [
7+ "lib/**/*.ss",
8+ "lib/**/*.sls",
9+ "bundle/index.js"
10+ ],
11+ "bin": {
12+ "purescm": "./index.js"
13+ },
314 "scripts": {
4− "test": "spago -x test.dhall test"
15+ "version": "sed -i'' -e \"s|version:.*|version: $npm_package_version|g\" spago.yaml",
16+ "test": "./test-runtime.js && spago test",
17+ "build": "spago build && purs-backend-es bundle-module -m Main --int-tags --platform=node --minify --to=./bundle/index.js"
518 }
619}
publish-release.shnew file+42
@@ -0,0 +1,42 @@
1+#!/usr/bin/env bash
2+# Tag and publish a new release of `purescm`
3+#
4+# Usage:
5+#
6+# ./publish-release.sh <major|minor|patch...>
7+#
8+
9+set -eu
10+
11+# Fail if we are not on trunk
12+BRANCH=$(git branch --show-current)
13+if [ "${BRANCH}" != "master" ]; then
14+ echo "Please checkout master branch"
15+ exit 1;
16+fi
17+
18+if [ $# -eq 0 ]
19+ then
20+ echo "No arguments supplied"
21+ exit 1
22+fi
23+
24+git pull
25+
26+# bump npm version
27+npm version $1 --no-git-tag-version
28+
29+# `npm version` also updates spago.yaml, so we grap the new
30+# tag name from there
31+NEW_TAG=$(grep -Po "(?<=version: )([\d.]+)" spago.yaml)
32+
33+git add package.json package-lock.json spago.yaml
34+git commit -m "$NEW_TAG"
35+git tag "v$NEW_TAG"
36+
37+rm -rf bundle output output-es
38+npm run build
39+
40+npm publish --tag latest
41+
42+git push origin
shell.nix+12−29
@@ -1,29 +1,12 @@
1−let
2− nixpkgs = builtins.fetchTarball {
3− url = "https://github.com/NixOS/nixpkgs/archive/402cc3633cc60dfc50378197305c984518b30773.tar.gz";
4− sha256 = "0yvlprdkqg1kizg83j7nivlc58zk7llrbf82jqvgjimrwhsva1m9";
5− };
6−
7− pkgs = import nixpkgs {};
8−
9− easy-ps = import
10− # On f-f's fork of easy-purescript-nix, as spago-next is not in mainline yet
11− (pkgs.fetchFromGitHub {
12− owner = "f-f";
13− repo = "easy-purescript-nix";
14− rev = "b02cff3db1671fc8fb76a680597a216a9c9b2d03";
15− sha256 = "sha256-vfzrVwBntXao3nMi2hkjYlWGUnuyUOVmYi95mQQ0EEY=";
16− }) {
17− inherit pkgs;
18− };
19−in
20−pkgs.mkShell {
21− buildInputs = [
22− easy-ps.purs-0_15_8
23− easy-ps.purs-tidy
24− easy-ps.psa
25− easy-ps.spago-next
26− pkgs.nodejs-slim-16_x
27− pkgs.chez-racket
28− ];
29−}
1+# A compatibility file that allows non-flakes users to still get a development
2+# shell with `nix-shell`.
3+(import
4+ (
5+ let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
6+ in fetchTarball {
7+ url =
8+ "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
9+ sha256 = lock.nodes.flake-compat.locked.narHash;
10+ }
11+ )
12+ { src = ./.; }).shellNix
spago.locknew file+2001
@@ -0,0 +1,2001 @@
1+{
2+ "workspace": {
3+ "packages": {
4+ "purescm": {
5+ "path": "./",
6+ "core": {
7+ "dependencies": [
8+ "aff",
9+ "argonaut",
10+ "arrays",
11+ "backend-optimizer",
12+ "console",
13+ "control",
14+ "dodo-printer",
15+ "effect",
16+ "foldable-traversable",
17+ "maybe",
18+ "newtype",
19+ "ordered-collections",
20+ "prelude",
21+ "safe-coerce",
22+ "strings",
23+ "transformers",
24+ "tuples"
25+ ],
26+ "build_plan": [
27+ "aff",
28+ "ansi",
29+ "argonaut",
30+ "argonaut-codecs",
31+ "argonaut-core",
32+ "argonaut-traversals",
33+ "argparse-basic",
34+ "arraybuffer-types",
35+ "arrays",
36+ "avar",
37+ "backend-optimizer",
38+ "bifunctors",
39+ "catenable-lists",
40+ "console",
41+ "const",
42+ "contravariant",
43+ "control",
44+ "datetime",
45+ "debug",
46+ "distributive",
47+ "dodo-printer",
48+ "effect",
49+ "either",
50+ "enums",
51+ "exceptions",
52+ "exists",
53+ "filterable",
54+ "foldable-traversable",
55+ "foreign",
56+ "foreign-object",
57+ "free",
58+ "functions",
59+ "functors",
60+ "gen",
61+ "identity",
62+ "integers",
63+ "invariant",
64+ "language-cst-parser",
65+ "lazy",
66+ "lists",
67+ "maybe",
68+ "minibench",
69+ "newtype",
70+ "node-buffer",
71+ "node-event-emitter",
72+ "node-process",
73+ "node-streams",
74+ "nonempty",
75+ "now",
76+ "nullable",
77+ "numbers",
78+ "ordered-collections",
79+ "orders",
80+ "parallel",
81+ "partial",
82+ "posix-types",
83+ "prelude",
84+ "profunctor",
85+ "profunctor-lenses",
86+ "record",
87+ "refs",
88+ "safe-coerce",
89+ "st",
90+ "strings",
91+ "tailrec",
92+ "transformers",
93+ "tuples",
94+ "type-equality",
95+ "typelevel-prelude",
96+ "unfoldable",
97+ "unsafe-coerce"
98+ ]
99+ },
100+ "test": {
101+ "dependencies": [
102+ "ansi",
103+ "argparse-basic",
104+ "bifunctors",
105+ "either",
106+ "filterable",
107+ "language-cst-parser",
108+ "lazy",
109+ "lists",
110+ "node-buffer",
111+ "node-child-process",
112+ "node-execa",
113+ "node-fs",
114+ "node-glob-basic",
115+ "node-path",
116+ "node-process",
117+ "node-streams",
118+ "parallel",
119+ "partial",
120+ "posix-types",
121+ "refs"
122+ ],
123+ "build_plan": [
124+ "aff",
125+ "ansi",
126+ "argparse-basic",
127+ "arraybuffer-types",
128+ "arrays",
129+ "bifunctors",
130+ "catenable-lists",
131+ "console",
132+ "const",
133+ "contravariant",
134+ "control",
135+ "datetime",
136+ "distributive",
137+ "effect",
138+ "either",
139+ "enums",
140+ "exceptions",
141+ "exists",
142+ "filterable",
143+ "foldable-traversable",
144+ "foreign",
145+ "foreign-object",
146+ "free",
147+ "functions",
148+ "functors",
149+ "gen",
150+ "identity",
151+ "integers",
152+ "invariant",
153+ "js-date",
154+ "js-timers",
155+ "language-cst-parser",
156+ "lazy",
157+ "lists",
158+ "maybe",
159+ "newtype",
160+ "node-buffer",
161+ "node-child-process",
162+ "node-event-emitter",
163+ "node-execa",
164+ "node-fs",
165+ "node-glob-basic",
166+ "node-human-signals",
167+ "node-os",
168+ "node-path",
169+ "node-process",
170+ "node-streams",
171+ "nonempty",
172+ "now",
173+ "nullable",
174+ "numbers",
175+ "ordered-collections",
176+ "orders",
177+ "parallel",
178+ "parsing",
179+ "partial",
180+ "posix-types",
181+ "prelude",
182+ "profunctor",
183+ "record",
184+ "refs",
185+ "safe-coerce",
186+ "st",
187+ "strings",
188+ "tailrec",
189+ "transformers",
190+ "tuples",
191+ "type-equality",
192+ "typelevel-prelude",
193+ "unfoldable",
194+ "unicode",
195+ "unsafe-coerce",
196+ "unsafe-reference"
197+ ]
198+ }
199+ }
200+ },
201+ "package_set": {
202+ "address": {
203+ "registry": "41.2.0"
204+ },
205+ "compiler": ">=0.15.10 <0.16.0",
206+ "content": {
207+ "abc-parser": "2.0.1",
208+ "ace": "9.1.0",
209+ "aff": "7.1.0",
210+ "aff-bus": "6.0.0",
211+ "aff-coroutines": "9.0.0",
212+ "aff-promise": "4.0.0",
213+ "aff-retry": "2.0.0",
214+ "affjax": "13.0.0",
215+ "affjax-node": "1.0.0",
216+ "affjax-web": "1.0.0",
217+ "ansi": "7.0.0",
218+ "argonaut": "9.0.0",
219+ "argonaut-aeson-generic": "0.4.1",
220+ "argonaut-codecs": "9.1.0",
221+ "argonaut-core": "7.0.0",
222+ "argonaut-generic": "8.0.0",
223+ "argonaut-traversals": "10.0.0",
224+ "argparse-basic": "2.0.0",
225+ "array-builder": "0.1.2",
226+ "array-search": "0.5.6",
227+ "arraybuffer": "13.2.0",
228+ "arraybuffer-builder": "3.1.0",
229+ "arraybuffer-types": "3.0.2",
230+ "arrays": "7.2.1",
231+ "arrays-extra": "0.3.0",
232+ "arrays-zipper": "2.0.1",
233+ "ask": "1.0.0",
234+ "assert": "6.0.0",
235+ "assert-multiple": "0.3.4",
236+ "avar": "5.0.0",
237+ "b64": "0.0.8",
238+ "barbies": "1.0.1",
239+ "barlow-lens": "0.9.0",
240+ "bifunctors": "6.0.0",
241+ "bigints": "7.0.1",
242+ "bolson": "0.3.9",
243+ "bookhound": "0.1.3",
244+ "bower-json": "3.0.0",
245+ "call-by-name": "4.0.1",
246+ "canvas": "6.0.0",
247+ "canvas-action": "9.0.0",
248+ "cartesian": "1.0.6",
249+ "catenable-lists": "7.0.0",
250+ "chameleon": "1.0.0",
251+ "chameleon-halogen": "1.0.3",
252+ "chameleon-react-basic": "1.1.0",
253+ "chameleon-styled": "2.5.0",
254+ "chameleon-transformers": "1.0.0",
255+ "channel": "1.0.0",
256+ "checked-exceptions": "3.1.1",
257+ "classless": "0.1.1",
258+ "classless-arbitrary": "0.1.1",
259+ "classless-decode-json": "0.1.1",
260+ "classless-encode-json": "0.1.3",
261+ "classnames": "2.0.0",
262+ "codec": "6.0.0",
263+ "codec-argonaut": "10.0.0",
264+ "colors": "7.0.1",
265+ "concur-core": "0.5.0",
266+ "concur-react": "0.5.0",
267+ "concurrent-queues": "3.0.0",
268+ "console": "6.0.0",
269+ "const": "6.0.0",
270+ "contravariant": "6.0.0",
271+ "control": "6.0.0",
272+ "convertable-options": "1.0.0",
273+ "coroutines": "7.0.0",
274+ "css": "6.0.0",
275+ "css-frameworks": "1.0.1",
276+ "data-mvc": "0.0.2",
277+ "datetime": "6.1.0",
278+ "datetime-parsing": "0.2.0",
279+ "debug": "6.0.2",
280+ "decimals": "7.1.0",
281+ "default-values": "1.0.1",
282+ "deku": "0.9.23",
283+ "deno": "0.0.5",
284+ "dissect": "1.0.0",
285+ "distributive": "6.0.0",
286+ "dom-filereader": "7.0.0",
287+ "dom-indexed": "12.0.0",
288+ "dotenv": "4.0.3",
289+ "droplet": "0.6.0",
290+ "dts": "0.2.0",
291+ "dynamic-buffer": "3.0.1",
292+ "echarts-simple": "0.0.1",
293+ "effect": "4.0.0",
294+ "either": "6.1.0",
295+ "elmish": "0.10.0",
296+ "elmish-enzyme": "0.1.1",
297+ "elmish-hooks": "0.9.1",
298+ "elmish-html": "0.8.1",
299+ "elmish-testing-library": "0.3.1",
300+ "email-validate": "7.0.0",
301+ "encoding": "0.0.8",
302+ "enums": "6.0.1",
303+ "env-names": "0.3.4",
304+ "error": "2.0.0",
305+ "exceptions": "6.0.0",
306+ "exists": "6.0.0",
307+ "exitcodes": "4.0.0",
308+ "expect-inferred": "3.0.0",
309+ "fahrtwind": "2.0.0",
310+ "fallback": "0.1.0",
311+ "fast-vect": "1.1.0",
312+ "fetch": "3.0.0",
313+ "fetch-argonaut": "1.0.1",
314+ "fetch-core": "5.1.0",
315+ "fetch-yoga-json": "1.1.0",
316+ "filterable": "5.0.0",
317+ "fix-functor": "0.1.0",
318+ "fixed-points": "7.0.0",
319+ "fixed-precision": "5.0.0",
320+ "flame": "1.3.0",
321+ "float32": "2.0.0",
322+ "fmt": "0.2.0",
323+ "foldable-traversable": "6.0.0",
324+ "foreign": "7.0.0",
325+ "foreign-object": "4.1.0",
326+ "foreign-readwrite": "3.4.0",
327+ "forgetmenot": "0.1.0",
328+ "fork": "6.0.0",
329+ "form-urlencoded": "7.0.0",
330+ "formatters": "7.0.0",
331+ "framer-motion": "1.0.1",
332+ "free": "7.1.0",
333+ "freeap": "7.0.0",
334+ "freer-free": "0.0.1",
335+ "freet": "7.0.0",
336+ "functions": "6.0.0",
337+ "functor1": "3.0.0",
338+ "functors": "5.0.0",
339+ "fuzzy": "0.4.0",
340+ "gen": "4.0.0",
341+ "generate-values": "1.0.1",
342+ "generic-router": "0.0.1",
343+ "geojson": "0.0.5",
344+ "geometry-plane": "1.0.3",
345+ "grain": "3.0.0",
346+ "grain-router": "3.0.0",
347+ "grain-virtualized": "3.0.0",
348+ "graphs": "8.1.0",
349+ "group": "4.1.1",
350+ "halogen": "7.0.0",
351+ "halogen-bootstrap5": "2.2.0",
352+ "halogen-css": "10.0.0",
353+ "halogen-echarts-simple": "0.0.4",
354+ "halogen-formless": "4.0.3",
355+ "halogen-helix": "1.0.0",
356+ "halogen-hooks": "0.6.3",
357+ "halogen-hooks-extra": "0.9.0",
358+ "halogen-store": "0.5.4",
359+ "halogen-storybook": "2.0.0",
360+ "halogen-subscriptions": "2.0.0",
361+ "halogen-svg-elems": "8.0.0",
362+ "halogen-typewriter": "1.0.2",
363+ "halogen-vdom": "8.0.0",
364+ "halogen-vdom-string-renderer": "0.5.0",
365+ "heckin": "2.0.1",
366+ "heterogeneous": "0.6.0",
367+ "homogeneous": "0.4.0",
368+ "http-methods": "6.0.0",
369+ "humdrum": "0.0.1",
370+ "hyrule": "2.3.8",
371+ "identity": "6.0.0",
372+ "identy": "4.0.1",
373+ "indexed-db": "1.0.0",
374+ "indexed-monad": "3.0.0",
375+ "int64": "3.0.0",
376+ "integers": "6.0.0",
377+ "interpolate": "5.0.2",
378+ "invariant": "6.0.0",
379+ "jarilo": "1.0.1",
380+ "jelly": "0.10.0",
381+ "jelly-router": "0.3.0",
382+ "jelly-signal": "0.4.0",
383+ "jest": "1.0.0",
384+ "js-abort-controller": "1.0.0",
385+ "js-bigints": "2.1.0",
386+ "js-date": "8.0.0",
387+ "js-fileio": "3.0.0",
388+ "js-intl": "1.0.2",
389+ "js-iterators": "0.1.1",
390+ "js-maps": "0.1.2",
391+ "js-promise": "1.0.0",
392+ "js-promise-aff": "1.0.0",
393+ "js-timers": "6.1.0",
394+ "js-uri": "3.1.0",
395+ "json-codecs": "4.0.0",
396+ "justifill": "0.5.0",
397+ "jwt": "0.0.9",
398+ "labeled-data": "0.2.0",
399+ "lazy": "6.0.0",
400+ "lazy-joe": "1.0.0",
401+ "lcg": "4.0.0",
402+ "leibniz": "5.0.0",
403+ "liminal": "1.0.1",
404+ "linalg": "6.0.0",
405+ "lists": "7.0.0",
406+ "literals": "1.0.2",
407+ "logging": "3.0.0",
408+ "logging-journald": "0.4.0",
409+ "machines": "7.0.0",
410+ "maps-eager": "0.4.1",
411+ "marionette": "1.0.0",
412+ "marionette-react-basic-hooks": "0.1.1",
413+ "matrices": "5.0.1",
414+ "matryoshka": "1.0.0",
415+ "maybe": "6.0.0",
416+ "media-types": "6.0.0",
417+ "midi": "4.0.0",
418+ "milkis": "9.0.0",
419+ "minibench": "4.0.1",
420+ "mmorph": "7.0.0",
421+ "monad-control": "5.0.0",
422+ "monad-logger": "1.3.1",
423+ "monad-loops": "0.5.0",
424+ "monad-unlift": "1.0.1",
425+ "monoid-extras": "0.0.1",
426+ "monoidal": "0.16.0",
427+ "morello": "0.4.0",
428+ "mote": "3.0.0",
429+ "motsunabe": "2.0.0",
430+ "mvc": "0.0.1",
431+ "mysql": "6.0.1",
432+ "n3": "0.1.0",
433+ "nano-id": "1.1.0",
434+ "nanoid": "0.1.0",
435+ "naturals": "3.0.0",
436+ "nested-functor": "0.2.1",
437+ "newtype": "5.0.0",
438+ "nextjs": "0.1.1",
439+ "nextui": "0.2.0",
440+ "node-buffer": "9.0.0",
441+ "node-child-process": "11.0.0",
442+ "node-event-emitter": "3.0.0",
443+ "node-execa": "4.0.1",
444+ "node-fs": "9.1.0",
445+ "node-http": "9.1.0",
446+ "node-http2": "1.1.1",
447+ "node-human-signals": "1.0.0",
448+ "node-net": "5.1.0",
449+ "node-os": "5.1.0",
450+ "node-path": "5.0.0",
451+ "node-process": "11.2.0",
452+ "node-readline": "8.1.0",
453+ "node-sqlite3": "8.0.0",
454+ "node-streams": "9.0.0",
455+ "node-tls": "0.3.1",
456+ "node-url": "7.0.0",
457+ "node-zlib": "0.4.0",
458+ "nonempty": "7.0.0",
459+ "now": "6.0.0",
460+ "npm-package-json": "2.0.0",
461+ "nullable": "6.0.0",
462+ "numberfield": "0.1.0",
463+ "numbers": "9.0.1",
464+ "oak": "3.1.1",
465+ "oak-debug": "1.2.2",
466+ "object-maps": "0.3.0",
467+ "ocarina": "1.5.4",
468+ "open-folds": "6.3.0",
469+ "open-memoize": "6.1.0",
470+ "open-pairing": "6.1.0",
471+ "options": "7.0.0",
472+ "ordered-collections": "3.1.1",
473+ "ordered-set": "0.4.0",
474+ "orders": "6.0.0",
475+ "pairs": "9.0.1",
476+ "parallel": "7.0.0",
477+ "parsing": "10.2.0",
478+ "parsing-dataview": "3.2.4",
479+ "partial": "4.0.0",
480+ "pathy": "9.0.0",
481+ "pha": "0.11.0",
482+ "phaser": "0.7.0",
483+ "phylio": "1.1.2",
484+ "pipes": "8.0.0",
485+ "pirates-charm": "0.0.1",
486+ "pmock": "0.6.0",
487+ "point-free": "1.0.0",
488+ "pointed-list": "0.5.1",
489+ "polymorphic-vectors": "4.0.0",
490+ "posix-types": "6.0.0",
491+ "precise": "6.0.0",
492+ "precise-datetime": "7.0.0",
493+ "prelude": "6.0.1",
494+ "prettier-printer": "3.0.0",
495+ "profunctor": "6.0.0",
496+ "profunctor-lenses": "8.0.0",
497+ "protobuf": "4.3.0",
498+ "psa-utils": "8.0.0",
499+ "psci-support": "6.0.0",
500+ "qualified-do": "2.2.0",
501+ "quantities": "12.2.0",
502+ "quickcheck": "8.0.1",
503+ "quickcheck-combinators": "0.1.3",
504+ "quickcheck-laws": "7.0.0",
505+ "quickcheck-utf8": "0.0.0",
506+ "random": "6.0.0",
507+ "rationals": "6.0.0",
508+ "rdf": "0.1.0",
509+ "react": "11.0.0",
510+ "react-aria": "0.2.0",
511+ "react-basic": "17.0.0",
512+ "react-basic-classic": "3.0.0",
513+ "react-basic-dnd": "10.1.0",
514+ "react-basic-dom": "6.1.0",
515+ "react-basic-emotion": "7.1.0",
516+ "react-basic-hooks": "8.2.0",
517+ "react-basic-storybook": "2.0.0",
518+ "react-dom": "8.0.0",
519+ "react-halo": "3.0.0",
520+ "react-icons": "1.1.1",
521+ "react-markdown": "0.1.0",
522+ "react-testing-library": "4.0.1",
523+ "react-virtuoso": "1.0.0",
524+ "read": "1.0.1",
525+ "recharts": "1.1.0",
526+ "record": "4.0.0",
527+ "record-extra": "5.0.1",
528+ "record-studio": "1.0.4",
529+ "refs": "6.0.0",
530+ "remotedata": "5.0.0",
531+ "resource": "2.0.1",
532+ "resourcet": "1.0.0",
533+ "result": "1.0.3",
534+ "return": "0.2.0",
535+ "ring-modules": "5.0.1",
536+ "rito": "0.3.4",
537+ "routing": "11.0.0",
538+ "routing-duplex": "0.7.0",
539+ "run": "5.0.0",
540+ "safe-coerce": "2.0.0",
541+ "safely": "4.0.1",
542+ "school-of-music": "1.3.0",
543+ "selection-foldable": "0.2.0",
544+ "semirings": "7.0.0",
545+ "signal": "13.0.0",
546+ "simple-emitter": "3.0.1",
547+ "simple-i18n": "2.0.1",
548+ "simple-json": "9.0.0",
549+ "simple-ulid": "3.0.0",
550+ "sized-matrices": "1.0.0",
551+ "sized-vectors": "5.0.2",
552+ "slug": "3.0.8",
553+ "small-ffi": "4.0.1",
554+ "soundfonts": "4.1.0",
555+ "sparse-matrices": "1.3.0",
556+ "sparse-polynomials": "2.0.5",
557+ "spec": "7.5.5",
558+ "spec-mocha": "5.0.0",
559+ "spec-quickcheck": "5.0.0",
560+ "splitmix": "2.1.0",
561+ "ssrs": "1.0.0",
562+ "st": "6.2.0",
563+ "statistics": "0.3.2",
564+ "strictlypositiveint": "1.0.1",
565+ "string-parsers": "8.0.0",
566+ "strings": "6.0.1",
567+ "strings-extra": "4.0.0",
568+ "stringutils": "0.0.12",
569+ "substitute": "0.2.3",
570+ "supply": "0.2.0",
571+ "svg-parser": "3.0.0",
572+ "systemd-journald": "0.3.0",
573+ "tagged": "4.0.2",
574+ "tailrec": "6.1.0",
575+ "tecton": "0.2.1",
576+ "tecton-halogen": "0.2.0",
577+ "test-unit": "17.0.0",
578+ "thermite": "6.3.1",
579+ "thermite-dom": "0.3.1",
580+ "these": "6.0.0",
581+ "transformation-matrix": "1.0.1",
582+ "transformers": "6.0.0",
583+ "tree-rose": "4.0.2",
584+ "tuples": "7.0.0",
585+ "two-or-more": "1.0.0",
586+ "type-equality": "4.0.1",
587+ "typedenv": "2.0.1",
588+ "typelevel": "6.0.0",
589+ "typelevel-lists": "2.1.0",
590+ "typelevel-peano": "1.0.1",
591+ "typelevel-prelude": "7.0.0",
592+ "typelevel-rows": "0.1.0",
593+ "uint": "7.0.0",
594+ "ulid": "3.0.1",
595+ "uncurried-transformers": "1.1.0",
596+ "undefined": "2.0.0",
597+ "undefined-is-not-a-problem": "1.1.0",
598+ "unfoldable": "6.0.0",
599+ "unicode": "6.0.0",
600+ "unique": "0.6.1",
601+ "unlift": "1.0.1",
602+ "unordered-collections": "3.0.1",
603+ "unsafe-coerce": "6.0.0",
604+ "unsafe-reference": "5.0.0",
605+ "untagged-to-tagged": "0.1.4",
606+ "untagged-union": "1.0.0",
607+ "uri": "9.0.0",
608+ "uuid": "9.0.0",
609+ "uuidv4": "1.0.0",
610+ "validation": "6.0.0",
611+ "variant": "8.0.0",
612+ "variant-encodings": "2.0.0",
613+ "vectorfield": "1.0.1",
614+ "vectors": "2.1.0",
615+ "versions": "7.0.0",
616+ "visx": "0.0.2",
617+ "web-clipboard": "5.0.0",
618+ "web-cssom": "2.0.0",
619+ "web-cssom-view": "0.1.0",
620+ "web-dom": "6.0.0",
621+ "web-dom-parser": "8.0.0",
622+ "web-dom-xpath": "3.0.0",
623+ "web-encoding": "3.0.0",
624+ "web-events": "4.0.0",
625+ "web-fetch": "4.0.1",
626+ "web-file": "4.0.0",
627+ "web-geometry": "0.1.0",
628+ "web-html": "4.1.0",
629+ "web-pointerevents": "1.0.0",
630+ "web-proletarian": "1.0.0",
631+ "web-resize-observer": "2.0.0",
632+ "web-router": "1.0.0",
633+ "web-socket": "4.0.0",
634+ "web-storage": "5.0.0",
635+ "web-streams": "4.0.0",
636+ "web-touchevents": "4.0.0",
637+ "web-uievents": "4.0.0",
638+ "web-url": "2.0.0",
639+ "web-workers": "1.1.0",
640+ "web-xhr": "5.0.1",
641+ "webextension-polyfill": "0.1.0",
642+ "webgpu": "0.0.1",
643+ "which": "2.0.0",
644+ "yoga-fetch": "1.0.1",
645+ "yoga-json": "5.1.0",
646+ "yoga-om": "0.1.0",
647+ "yoga-postgres": "6.0.0",
648+ "yoga-tree": "1.0.0",
649+ "z3": "0.0.2"
650+ }
651+ },
652+ "extra_packages": {
653+ "backend-optimizer": {
654+ "git": "https://github.com/aristanetworks/purescript-backend-optimizer",
655+ "ref": "54b82ac23143dd47bfafaf52dec81dd7ccf2b490",
656+ "dependencies": [
657+ "aff",
658+ "ansi",
659+ "argonaut",
660+ "argparse-basic",
661+ "arrays",
662+ "bifunctors",
663+ "console",
664+ "control",
665+ "datetime",
666+ "debug",
667+ "dodo-printer",
668+ "effect",
669+ "either",
670+ "enums",
671+ "filterable",
672+ "foldable-traversable",
673+ "foreign-object",
674+ "integers",
675+ "language-cst-parser",
676+ "lazy",
677+ "lists",
678+ "maybe",
679+ "newtype",
680+ "now",
681+ "numbers",
682+ "ordered-collections",
683+ "orders",
684+ "parallel",
685+ "partial",
686+ "posix-types",
687+ "prelude",
688+ "refs",
689+ "safe-coerce",
690+ "st",
691+ "strings",
692+ "transformers",
693+ "tuples",
694+ "unsafe-coerce"
695+ ]
696+ },
697+ "dodo-printer": {
698+ "git": "https://github.com/natefaubion/purescript-dodo-printer.git",
699+ "ref": "831c5c963a57ca4bfd62f96335267d7d0785851d",
700+ "dependencies": [
701+ "aff",
702+ "ansi",
703+ "arrays",
704+ "avar",
705+ "console",
706+ "control",
707+ "effect",
708+ "either",
709+ "exceptions",
710+ "foldable-traversable",
711+ "integers",
712+ "lists",
713+ "maybe",
714+ "minibench",
715+ "newtype",
716+ "parallel",
717+ "partial",
718+ "posix-types",
719+ "prelude",
720+ "safe-coerce",
721+ "strings",
722+ "tuples"
723+ ]
724+ },
725+ "language-cst-parser": {
726+ "git": "https://github.com/natefaubion/purescript-language-cst-parser.git",
727+ "ref": "bf5623e08e1f43f923d4ff3c29cafbda25128768",
728+ "dependencies": [
729+ "arrays",
730+ "console",
731+ "const",
732+ "control",
733+ "effect",
734+ "either",
735+ "enums",
736+ "foldable-traversable",
737+ "free",
738+ "functions",
739+ "functors",
740+ "identity",
741+ "integers",
742+ "lazy",
743+ "lists",
744+ "maybe",
745+ "newtype",
746+ "node-process",
747+ "numbers",
748+ "ordered-collections",
749+ "partial",
750+ "prelude",
751+ "st",
752+ "strings",
753+ "transformers",
754+ "tuples",
755+ "typelevel-prelude",
756+ "unfoldable",
757+ "unsafe-coerce"
758+ ]
759+ },
760+ "node-glob-basic": {
761+ "git": "https://github.com/natefaubion/purescript-node-glob-basic.git",
762+ "ref": "v1.2.2",
763+ "dependencies": [
764+ "aff",
765+ "console",
766+ "effect",
767+ "lists",
768+ "maybe",
769+ "node-fs",
770+ "node-path",
771+ "node-process",
772+ "ordered-collections",
773+ "strings"
774+ ]
775+ }
776+ }
777+ },
778+ "packages": {
779+ "aff": {
780+ "type": "registry",
781+ "version": "7.1.0",
782+ "integrity": "sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU=",
783+ "dependencies": [
784+ "arrays",
785+ "bifunctors",
786+ "control",
787+ "datetime",
788+ "effect",
789+ "either",
790+ "exceptions",
791+ "foldable-traversable",
792+ "functions",
793+ "maybe",
794+ "newtype",
795+ "parallel",
796+ "prelude",
797+ "refs",
798+ "tailrec",
799+ "transformers",
800+ "unsafe-coerce"
801+ ]
802+ },
803+ "ansi": {
804+ "type": "registry",
805+ "version": "7.0.0",
806+ "integrity": "sha256-ZMB6HD+q9CXvn9fRCmJ8dvuDrOVHcjombL3oNOerVnE=",
807+ "dependencies": [
808+ "foldable-traversable",
809+ "lists",
810+ "strings"
811+ ]
812+ },
813+ "argonaut": {
814+ "type": "registry",
815+ "version": "9.0.0",
816+ "integrity": "sha256-9sHzkzcFkaMUa9+3FjIybJDYnHtY4Jp4zHOJ84qPTXo=",
817+ "dependencies": [
818+ "argonaut-codecs",
819+ "argonaut-core",
820+ "argonaut-traversals"
821+ ]
822+ },
823+ "argonaut-codecs": {
824+ "type": "registry",
825+ "version": "9.1.0",
826+ "integrity": "sha256-N6efXByUeg848ompEqJfVvZuZPfdRYDGlTDFn0G0Oh8=",
827+ "dependencies": [
828+ "argonaut-core",
829+ "arrays",
830+ "effect",
831+ "foreign-object",
832+ "identity",
833+ "integers",
834+ "maybe",
835+ "nonempty",
836+ "ordered-collections",
837+ "prelude",
838+ "record"
839+ ]
840+ },
841+ "argonaut-core": {
842+ "type": "registry",
843+ "version": "7.0.0",
844+ "integrity": "sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4=",
845+ "dependencies": [
846+ "arrays",
847+ "control",
848+ "either",
849+ "foreign-object",
850+ "functions",
851+ "gen",
852+ "maybe",
853+ "nonempty",
854+ "prelude",
855+ "strings",
856+ "tailrec"
857+ ]
858+ },
859+ "argonaut-traversals": {
860+ "type": "registry",
861+ "version": "10.0.0",
862+ "integrity": "sha256-9nSfqR70rjiNWVVsCoK+jrm9dmyZTx89IKNYO6uNUIk=",
863+ "dependencies": [
864+ "argonaut-codecs",
865+ "argonaut-core",
866+ "profunctor-lenses"
867+ ]
868+ },
869+ "argparse-basic": {
870+ "type": "registry",
871+ "version": "2.0.0",
872+ "integrity": "sha256-3Pp8MDfRL2oeBdfxXIUVJBdhGniaahw2UOG4QmHPm58=",
873+ "dependencies": [
874+ "arrays",
875+ "bifunctors",
876+ "control",
877+ "either",
878+ "foldable-traversable",
879+ "integers",
880+ "lists",
881+ "maybe",
882+ "newtype",
883+ "numbers",
884+ "prelude",
885+ "record",
886+ "strings",
887+ "tuples",
888+ "unfoldable"
889+ ]
890+ },
891+ "arraybuffer-types": {
892+ "type": "registry",
893+ "version": "3.0.2",
894+ "integrity": "sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA=",
895+ "dependencies": []
896+ },
897+ "arrays": {
898+ "type": "registry",
899+ "version": "7.2.1",
900+ "integrity": "sha256-HCUzV3uCSt6YBI9vlt1Ott20/2JfSCUoNsd+D6ORieQ=",
901+ "dependencies": [
902+ "bifunctors",
903+ "control",
904+ "foldable-traversable",
905+ "functions",
906+ "maybe",
907+ "nonempty",
908+ "partial",
909+ "prelude",
910+ "safe-coerce",
911+ "st",
912+ "tailrec",
913+ "tuples",
914+ "unfoldable",
915+ "unsafe-coerce"
916+ ]
917+ },
918+ "avar": {
919+ "type": "registry",
920+ "version": "5.0.0",
921+ "integrity": "sha256-e7hf0x4hEpcygXP0LtvfvAQ49Bbj2aWtZT3gqM///0A=",
922+ "dependencies": [
923+ "aff",
924+ "effect",
925+ "either",
926+ "exceptions",
927+ "functions",
928+ "maybe"
929+ ]
930+ },
931+ "backend-optimizer": {
932+ "type": "git",
933+ "url": "https://github.com/aristanetworks/purescript-backend-optimizer",
934+ "rev": "54b82ac23143dd47bfafaf52dec81dd7ccf2b490",
935+ "dependencies": [
936+ "aff",
937+ "ansi",
938+ "argonaut",
939+ "argparse-basic",
940+ "arrays",
941+ "bifunctors",
942+ "console",
943+ "control",
944+ "datetime",
945+ "debug",
946+ "dodo-printer",
947+ "effect",
948+ "either",
949+ "enums",
950+ "filterable",
951+ "foldable-traversable",
952+ "foreign-object",
953+ "integers",
954+ "language-cst-parser",
955+ "lazy",
956+ "lists",
957+ "maybe",
958+ "newtype",
959+ "now",
960+ "numbers",
961+ "ordered-collections",
962+ "orders",
963+ "parallel",
964+ "partial",
965+ "posix-types",
966+ "prelude",
967+ "refs",
968+ "safe-coerce",
969+ "st",
970+ "strings",
971+ "transformers",
972+ "tuples",
973+ "unsafe-coerce"
974+ ]
975+ },
976+ "bifunctors": {
977+ "type": "registry",
978+ "version": "6.0.0",
979+ "integrity": "sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw=",
980+ "dependencies": [
981+ "const",
982+ "either",
983+ "newtype",
984+ "prelude",
985+ "tuples"
986+ ]
987+ },
988+ "catenable-lists": {
989+ "type": "registry",
990+ "version": "7.0.0",
991+ "integrity": "sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA=",
992+ "dependencies": [
993+ "control",
994+ "foldable-traversable",
995+ "lists",
996+ "maybe",
997+ "prelude",
998+ "tuples",
999+ "unfoldable"
1000+ ]
1001+ },
1002+ "console": {
1003+ "type": "registry",
1004+ "version": "6.0.0",
1005+ "integrity": "sha256-gJpJ53fCDAL8BiCiJXH0HNAJ9K3gJtLo8GDaCK6hA5U=",
1006+ "dependencies": [
1007+ "effect",
1008+ "prelude"
1009+ ]
1010+ },
1011+ "const": {
1012+ "type": "registry",
1013+ "version": "6.0.0",
1014+ "integrity": "sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc=",
1015+ "dependencies": [
1016+ "invariant",
1017+ "newtype",
1018+ "prelude"
1019+ ]
1020+ },
1021+ "contravariant": {
1022+ "type": "registry",
1023+ "version": "6.0.0",
1024+ "integrity": "sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c=",
1025+ "dependencies": [
1026+ "const",
1027+ "either",
1028+ "newtype",
1029+ "prelude",
1030+ "tuples"
1031+ ]
1032+ },
1033+ "control": {
1034+ "type": "registry",
1035+ "version": "6.0.0",
1036+ "integrity": "sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk=",
1037+ "dependencies": [
1038+ "newtype",
1039+ "prelude"
1040+ ]
1041+ },
1042+ "datetime": {
1043+ "type": "registry",
1044+ "version": "6.1.0",
1045+ "integrity": "sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI=",
1046+ "dependencies": [
1047+ "bifunctors",
1048+ "control",
1049+ "either",
1050+ "enums",
1051+ "foldable-traversable",
1052+ "functions",
1053+ "gen",
1054+ "integers",
1055+ "lists",
1056+ "maybe",
1057+ "newtype",
1058+ "numbers",
1059+ "ordered-collections",
1060+ "partial",
1061+ "prelude",
1062+ "tuples"
1063+ ]
1064+ },
1065+ "debug": {
1066+ "type": "registry",
1067+ "version": "6.0.2",
1068+ "integrity": "sha256-vmkYFuXYuELBzeauvgHG6E6Kf/Hp1dAnxwE9ByHfwSg=",
1069+ "dependencies": [
1070+ "functions",
1071+ "prelude"
1072+ ]
1073+ },
1074+ "distributive": {
1075+ "type": "registry",
1076+ "version": "6.0.0",
1077+ "integrity": "sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ=",
1078+ "dependencies": [
1079+ "identity",
1080+ "newtype",
1081+ "prelude",
1082+ "tuples",
1083+ "type-equality"
1084+ ]
1085+ },
1086+ "dodo-printer": {
1087+ "type": "git",
1088+ "url": "https://github.com/natefaubion/purescript-dodo-printer.git",
1089+ "rev": "831c5c963a57ca4bfd62f96335267d7d0785851d",
1090+ "dependencies": [
1091+ "aff",
1092+ "ansi",
1093+ "arrays",
1094+ "avar",
1095+ "console",
1096+ "control",
1097+ "effect",
1098+ "either",
1099+ "exceptions",
1100+ "foldable-traversable",
1101+ "integers",
1102+ "lists",
1103+ "maybe",
1104+ "minibench",
1105+ "newtype",
1106+ "parallel",
1107+ "partial",
1108+ "posix-types",
1109+ "prelude",
1110+ "safe-coerce",
1111+ "strings",
1112+ "tuples"
1113+ ]
1114+ },
1115+ "effect": {
1116+ "type": "registry",
1117+ "version": "4.0.0",
1118+ "integrity": "sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=",
1119+ "dependencies": [
1120+ "prelude"
1121+ ]
1122+ },
1123+ "either": {
1124+ "type": "registry",
1125+ "version": "6.1.0",
1126+ "integrity": "sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY=",
1127+ "dependencies": [
1128+ "control",
1129+ "invariant",
1130+ "maybe",
1131+ "prelude"
1132+ ]
1133+ },
1134+ "enums": {
1135+ "type": "registry",
1136+ "version": "6.0.1",
1137+ "integrity": "sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8=",
1138+ "dependencies": [
1139+ "control",
1140+ "either",
1141+ "gen",
1142+ "maybe",
1143+ "newtype",
1144+ "nonempty",
1145+ "partial",
1146+ "prelude",
1147+ "tuples",
1148+ "unfoldable"
1149+ ]
1150+ },
1151+ "exceptions": {
1152+ "type": "registry",
1153+ "version": "6.0.0",
1154+ "integrity": "sha256-y/xTAEIZIARCE+50/u1di0ncebJ+CIwNOLswyOWzMTw=",
1155+ "dependencies": [
1156+ "effect",
1157+ "either",
1158+ "maybe",
1159+ "prelude"
1160+ ]
1161+ },
1162+ "exists": {
1163+ "type": "registry",
1164+ "version": "6.0.0",
1165+ "integrity": "sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8=",
1166+ "dependencies": [
1167+ "unsafe-coerce"
1168+ ]
1169+ },
1170+ "filterable": {
1171+ "type": "registry",
1172+ "version": "5.0.0",
1173+ "integrity": "sha256-cCojJHRnTmpY1j1kegI4CFwghdQ2Fm/8dzM8IlC+lng=",
1174+ "dependencies": [
1175+ "arrays",
1176+ "either",
1177+ "foldable-traversable",
1178+ "identity",
1179+ "lists",
1180+ "ordered-collections"
1181+ ]
1182+ },
1183+ "foldable-traversable": {
1184+ "type": "registry",
1185+ "version": "6.0.0",
1186+ "integrity": "sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM=",
1187+ "dependencies": [
1188+ "bifunctors",
1189+ "const",
1190+ "control",
1191+ "either",
1192+ "functors",
1193+ "identity",
1194+ "maybe",
1195+ "newtype",
1196+ "orders",
1197+ "prelude",
1198+ "tuples"
1199+ ]
1200+ },
1201+ "foreign": {
1202+ "type": "registry",
1203+ "version": "7.0.0",
1204+ "integrity": "sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA=",
1205+ "dependencies": [
1206+ "either",
1207+ "functions",
1208+ "identity",
1209+ "integers",
1210+ "lists",
1211+ "maybe",
1212+ "prelude",
1213+ "strings",
1214+ "transformers"
1215+ ]
1216+ },
1217+ "foreign-object": {
1218+ "type": "registry",
1219+ "version": "4.1.0",
1220+ "integrity": "sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo=",
1221+ "dependencies": [
1222+ "arrays",
1223+ "foldable-traversable",
1224+ "functions",
1225+ "gen",
1226+ "lists",
1227+ "maybe",
1228+ "prelude",
1229+ "st",
1230+ "tailrec",
1231+ "tuples",
1232+ "typelevel-prelude",
1233+ "unfoldable"
1234+ ]
1235+ },
1236+ "free": {
1237+ "type": "registry",
1238+ "version": "7.1.0",
1239+ "integrity": "sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k=",
1240+ "dependencies": [
1241+ "catenable-lists",
1242+ "control",
1243+ "distributive",
1244+ "either",
1245+ "exists",
1246+ "foldable-traversable",
1247+ "invariant",
1248+ "lazy",
1249+ "maybe",
1250+ "prelude",
1251+ "tailrec",
1252+ "transformers",
1253+ "tuples",
1254+ "unsafe-coerce"
1255+ ]
1256+ },
1257+ "functions": {
1258+ "type": "registry",
1259+ "version": "6.0.0",
1260+ "integrity": "sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI=",
1261+ "dependencies": [
1262+ "prelude"
1263+ ]
1264+ },
1265+ "functors": {
1266+ "type": "registry",
1267+ "version": "5.0.0",
1268+ "integrity": "sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU=",
1269+ "dependencies": [
1270+ "bifunctors",
1271+ "const",
1272+ "contravariant",
1273+ "control",
1274+ "distributive",
1275+ "either",
1276+ "invariant",
1277+ "maybe",
1278+ "newtype",
1279+ "prelude",
1280+ "profunctor",
1281+ "tuples",
1282+ "unsafe-coerce"
1283+ ]
1284+ },
1285+ "gen": {
1286+ "type": "registry",
1287+ "version": "4.0.0",
1288+ "integrity": "sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI=",
1289+ "dependencies": [
1290+ "either",
1291+ "foldable-traversable",
1292+ "identity",
1293+ "maybe",
1294+ "newtype",
1295+ "nonempty",
1296+ "prelude",
1297+ "tailrec",
1298+ "tuples",
1299+ "unfoldable"
1300+ ]
1301+ },
1302+ "identity": {
1303+ "type": "registry",
1304+ "version": "6.0.0",
1305+ "integrity": "sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY=",
1306+ "dependencies": [
1307+ "control",
1308+ "invariant",
1309+ "newtype",
1310+ "prelude"
1311+ ]
1312+ },
1313+ "integers": {
1314+ "type": "registry",
1315+ "version": "6.0.0",
1316+ "integrity": "sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158=",
1317+ "dependencies": [
1318+ "maybe",
1319+ "numbers",
1320+ "prelude"
1321+ ]
1322+ },
1323+ "invariant": {
1324+ "type": "registry",
1325+ "version": "6.0.0",
1326+ "integrity": "sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo=",
1327+ "dependencies": [
1328+ "control",
1329+ "prelude"
1330+ ]
1331+ },
1332+ "js-date": {
1333+ "type": "registry",
1334+ "version": "8.0.0",
1335+ "integrity": "sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo=",
1336+ "dependencies": [
1337+ "datetime",
1338+ "effect",
1339+ "exceptions",
1340+ "foreign",
1341+ "integers",
1342+ "now"
1343+ ]
1344+ },
1345+ "js-timers": {
1346+ "type": "registry",
1347+ "version": "6.1.0",
1348+ "integrity": "sha256-znHWLSSOYw15P5DTcsAdal2lf7nGA2yayLdOZ2t5r7o=",
1349+ "dependencies": [
1350+ "effect"
1351+ ]
1352+ },
1353+ "language-cst-parser": {
1354+ "type": "git",
1355+ "url": "https://github.com/natefaubion/purescript-language-cst-parser.git",
1356+ "rev": "bf5623e08e1f43f923d4ff3c29cafbda25128768",
1357+ "dependencies": [
1358+ "arrays",
1359+ "console",
1360+ "const",
1361+ "control",
1362+ "effect",
1363+ "either",
1364+ "enums",
1365+ "foldable-traversable",
1366+ "free",
1367+ "functions",
1368+ "functors",
1369+ "identity",
1370+ "integers",
1371+ "lazy",
1372+ "lists",
1373+ "maybe",
1374+ "newtype",
1375+ "node-process",
1376+ "numbers",
1377+ "ordered-collections",
1378+ "partial",
1379+ "prelude",
1380+ "st",
1381+ "strings",
1382+ "transformers",
1383+ "tuples",
1384+ "typelevel-prelude",
1385+ "unfoldable",
1386+ "unsafe-coerce"
1387+ ]
1388+ },
1389+ "lazy": {
1390+ "type": "registry",
1391+ "version": "6.0.0",
1392+ "integrity": "sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU=",
1393+ "dependencies": [
1394+ "control",
1395+ "foldable-traversable",
1396+ "invariant",
1397+ "prelude"
1398+ ]
1399+ },
1400+ "lists": {
1401+ "type": "registry",
1402+ "version": "7.0.0",
1403+ "integrity": "sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI=",
1404+ "dependencies": [
1405+ "bifunctors",
1406+ "control",
1407+ "foldable-traversable",
1408+ "lazy",
1409+ "maybe",
1410+ "newtype",
1411+ "nonempty",
1412+ "partial",
1413+ "prelude",
1414+ "tailrec",
1415+ "tuples",
1416+ "unfoldable"
1417+ ]
1418+ },
1419+ "maybe": {
1420+ "type": "registry",
1421+ "version": "6.0.0",
1422+ "integrity": "sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q=",
1423+ "dependencies": [
1424+ "control",
1425+ "invariant",
1426+ "newtype",
1427+ "prelude"
1428+ ]
1429+ },
1430+ "minibench": {
1431+ "type": "registry",
1432+ "version": "4.0.1",
1433+ "integrity": "sha256-7jyxcklZI49q/otYvMV4f9YnJwEqQ3Me5buhDwAOydw=",
1434+ "dependencies": [
1435+ "console",
1436+ "effect",
1437+ "integers",
1438+ "numbers",
1439+ "partial",
1440+ "prelude",
1441+ "refs"
1442+ ]
1443+ },
1444+ "newtype": {
1445+ "type": "registry",
1446+ "version": "5.0.0",
1447+ "integrity": "sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw=",
1448+ "dependencies": [
1449+ "prelude",
1450+ "safe-coerce"
1451+ ]
1452+ },
1453+ "node-buffer": {
1454+ "type": "registry",
1455+ "version": "9.0.0",
1456+ "integrity": "sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4=",
1457+ "dependencies": [
1458+ "arraybuffer-types",
1459+ "effect",
1460+ "maybe",
1461+ "nullable",
1462+ "st",
1463+ "unsafe-coerce"
1464+ ]
1465+ },
1466+ "node-child-process": {
1467+ "type": "registry",
1468+ "version": "11.0.0",
1469+ "integrity": "sha256-1183hFdWspCBzmjIB7m79PpF9g0NB189X5V6WzeiQxo=",
1470+ "dependencies": [
1471+ "exceptions",
1472+ "foreign",
1473+ "foreign-object",
1474+ "functions",
1475+ "node-event-emitter",
1476+ "node-fs",
1477+ "node-os",
1478+ "node-streams",
1479+ "nullable",
1480+ "posix-types",
1481+ "unsafe-coerce"
1482+ ]
1483+ },
1484+ "node-event-emitter": {
1485+ "type": "registry",
1486+ "version": "3.0.0",
1487+ "integrity": "sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w=",
1488+ "dependencies": [
1489+ "effect",
1490+ "either",
1491+ "functions",
1492+ "maybe",
1493+ "nullable",
1494+ "prelude",
1495+ "unsafe-coerce"
1496+ ]
1497+ },
1498+ "node-execa": {
1499+ "type": "registry",
1500+ "version": "4.0.1",
1501+ "integrity": "sha256-f1we41uNEZD7Z2kP/GP2/8tOmtsrAnQWIDwFUiqJDwk=",
1502+ "dependencies": [
1503+ "aff",
1504+ "arrays",
1505+ "control",
1506+ "effect",
1507+ "either",
1508+ "exceptions",
1509+ "foldable-traversable",
1510+ "foreign-object",
1511+ "functions",
1512+ "integers",
1513+ "js-timers",
1514+ "maybe",
1515+ "node-buffer",
1516+ "node-child-process",
1517+ "node-event-emitter",
1518+ "node-fs",
1519+ "node-human-signals",
1520+ "node-os",
1521+ "node-path",
1522+ "node-process",
1523+ "node-streams",
1524+ "nullable",
1525+ "numbers",
1526+ "ordered-collections",
1527+ "parallel",
1528+ "parsing",
1529+ "partial",
1530+ "posix-types",
1531+ "prelude",
1532+ "record",
1533+ "refs",
1534+ "safe-coerce",
1535+ "strings",
1536+ "tailrec",
1537+ "tuples",
1538+ "unsafe-coerce",
1539+ "unsafe-reference"
1540+ ]
1541+ },
1542+ "node-fs": {
1543+ "type": "registry",
1544+ "version": "9.1.0",
1545+ "integrity": "sha256-TzhvGdrwcM0bazDvrWSqh+M/H8GKYf1Na6aGm2Qg4+c=",
1546+ "dependencies": [
1547+ "datetime",
1548+ "effect",
1549+ "either",
1550+ "enums",
1551+ "exceptions",
1552+ "functions",
1553+ "integers",
1554+ "js-date",
1555+ "maybe",
1556+ "node-buffer",
1557+ "node-path",
1558+ "node-streams",
1559+ "nullable",
1560+ "partial",
1561+ "prelude",
1562+ "strings",
1563+ "unsafe-coerce"
1564+ ]
1565+ },
1566+ "node-glob-basic": {
1567+ "type": "git",
1568+ "url": "https://github.com/natefaubion/purescript-node-glob-basic.git",
1569+ "rev": "d20f2866c3bb472c68848be5b153e28933c07a38",
1570+ "dependencies": [
1571+ "aff",
1572+ "console",
1573+ "effect",
1574+ "lists",
1575+ "maybe",
1576+ "node-fs",
1577+ "node-path",
1578+ "node-process",
1579+ "ordered-collections",
1580+ "strings"
1581+ ]
1582+ },
1583+ "node-human-signals": {
1584+ "type": "registry",
1585+ "version": "1.0.0",
1586+ "integrity": "sha256-HOUfMQTAIuL5AOCUlJJcKq78masah+388eQOdloYH1g=",
1587+ "dependencies": [
1588+ "arrays",
1589+ "control",
1590+ "foreign-object",
1591+ "maybe",
1592+ "ordered-collections",
1593+ "prelude"
1594+ ]
1595+ },
1596+ "node-os": {
1597+ "type": "registry",
1598+ "version": "5.1.0",
1599+ "integrity": "sha256-K3gcu9AXanN1+qtk1900+Fi+CuO0s3/H/RMNRNgIzso=",
1600+ "dependencies": [
1601+ "arrays",
1602+ "bifunctors",
1603+ "console",
1604+ "control",
1605+ "datetime",
1606+ "effect",
1607+ "either",
1608+ "exceptions",
1609+ "foldable-traversable",
1610+ "foreign",
1611+ "foreign-object",
1612+ "functions",
1613+ "maybe",
1614+ "node-buffer",
1615+ "nullable",
1616+ "partial",
1617+ "posix-types",
1618+ "prelude",
1619+ "unsafe-coerce"
1620+ ]
1621+ },
1622+ "node-path": {
1623+ "type": "registry",
1624+ "version": "5.0.0",
1625+ "integrity": "sha256-pd82nQ+2l5UThzaxPdKttgDt7xlsgIDLpPG0yxDEdyE=",
1626+ "dependencies": [
1627+ "effect"
1628+ ]
1629+ },
1630+ "node-process": {
1631+ "type": "registry",
1632+ "version": "11.2.0",
1633+ "integrity": "sha256-+2MQDYChjGbVbapCyJtuWYwD41jk+BntF/kcOTKBMVs=",
1634+ "dependencies": [
1635+ "effect",
1636+ "foreign",
1637+ "foreign-object",
1638+ "maybe",
1639+ "node-event-emitter",
1640+ "node-streams",
1641+ "posix-types",
1642+ "prelude",
1643+ "unsafe-coerce"
1644+ ]
1645+ },
1646+ "node-streams": {
1647+ "type": "registry",
1648+ "version": "9.0.0",
1649+ "integrity": "sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ=",
1650+ "dependencies": [
1651+ "aff",
1652+ "effect",
1653+ "either",
1654+ "exceptions",
1655+ "node-buffer",
1656+ "node-event-emitter",
1657+ "nullable",
1658+ "prelude"
1659+ ]
1660+ },
1661+ "nonempty": {
1662+ "type": "registry",
1663+ "version": "7.0.0",
1664+ "integrity": "sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs=",
1665+ "dependencies": [
1666+ "control",
1667+ "foldable-traversable",
1668+ "maybe",
1669+ "prelude",
1670+ "tuples",
1671+ "unfoldable"
1672+ ]
1673+ },
1674+ "now": {
1675+ "type": "registry",
1676+ "version": "6.0.0",
1677+ "integrity": "sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY=",
1678+ "dependencies": [
1679+ "datetime",
1680+ "effect"
1681+ ]
1682+ },
1683+ "nullable": {
1684+ "type": "registry",
1685+ "version": "6.0.0",
1686+ "integrity": "sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o=",
1687+ "dependencies": [
1688+ "effect",
1689+ "functions",
1690+ "maybe"
1691+ ]
1692+ },
1693+ "numbers": {
1694+ "type": "registry",
1695+ "version": "9.0.1",
1696+ "integrity": "sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk=",
1697+ "dependencies": [
1698+ "functions",
1699+ "maybe"
1700+ ]
1701+ },
1702+ "ordered-collections": {
1703+ "type": "registry",
1704+ "version": "3.1.1",
1705+ "integrity": "sha256-boSYHmlz4aSbwsNN4VxiwCStc0t+y1F7BXmBS+1JNtI=",
1706+ "dependencies": [
1707+ "arrays",
1708+ "foldable-traversable",
1709+ "gen",
1710+ "lists",
1711+ "maybe",
1712+ "partial",
1713+ "prelude",
1714+ "st",
1715+ "tailrec",
1716+ "tuples",
1717+ "unfoldable"
1718+ ]
1719+ },
1720+ "orders": {
1721+ "type": "registry",
1722+ "version": "6.0.0",
1723+ "integrity": "sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink=",
1724+ "dependencies": [
1725+ "newtype",
1726+ "prelude"
1727+ ]
1728+ },
1729+ "parallel": {
1730+ "type": "registry",
1731+ "version": "7.0.0",
1732+ "integrity": "sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o=",
1733+ "dependencies": [
1734+ "control",
1735+ "effect",
1736+ "either",
1737+ "foldable-traversable",
1738+ "functors",
1739+ "maybe",
1740+ "newtype",
1741+ "prelude",
1742+ "profunctor",
1743+ "refs",
1744+ "transformers"
1745+ ]
1746+ },
1747+ "parsing": {
1748+ "type": "registry",
1749+ "version": "10.2.0",
1750+ "integrity": "sha256-ZDIdMFAKkst57x6BVa1aUWJnS8smoZnXsZ339Aq1mPA=",
1751+ "dependencies": [
1752+ "arrays",
1753+ "control",
1754+ "effect",
1755+ "either",
1756+ "enums",
1757+ "foldable-traversable",
1758+ "functions",
1759+ "identity",
1760+ "integers",
1761+ "lazy",
1762+ "lists",
1763+ "maybe",
1764+ "newtype",
1765+ "nullable",
1766+ "numbers",
1767+ "partial",
1768+ "prelude",
1769+ "st",
1770+ "strings",
1771+ "tailrec",
1772+ "transformers",
1773+ "tuples",
1774+ "unfoldable",
1775+ "unicode",
1776+ "unsafe-coerce"
1777+ ]
1778+ },
1779+ "partial": {
1780+ "type": "registry",
1781+ "version": "4.0.0",
1782+ "integrity": "sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=",
1783+ "dependencies": []
1784+ },
1785+ "posix-types": {
1786+ "type": "registry",
1787+ "version": "6.0.0",
1788+ "integrity": "sha256-ZfFz8RR1lee/o/Prccyeut3Q+9tYd08mlR72sIh6GzA=",
1789+ "dependencies": [
1790+ "maybe",
1791+ "prelude"
1792+ ]
1793+ },
1794+ "prelude": {
1795+ "type": "registry",
1796+ "version": "6.0.1",
1797+ "integrity": "sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0=",
1798+ "dependencies": []
1799+ },
1800+ "profunctor": {
1801+ "type": "registry",
1802+ "version": "6.0.0",
1803+ "integrity": "sha256-99NzxFgTr4CGlCSRYG1kShL+JhYbihhHtbOk1/0R5zI=",
1804+ "dependencies": [
1805+ "control",
1806+ "distributive",
1807+ "either",
1808+ "exists",
1809+ "invariant",
1810+ "newtype",
1811+ "prelude",
1812+ "tuples"
1813+ ]
1814+ },
1815+ "profunctor-lenses": {
1816+ "type": "registry",
1817+ "version": "8.0.0",
1818+ "integrity": "sha256-K7f29rHRHgVSb2Y/PaSKtfYPriP6n87BJNO7EhsZHas=",
1819+ "dependencies": [
1820+ "arrays",
1821+ "bifunctors",
1822+ "const",
1823+ "control",
1824+ "distributive",
1825+ "either",
1826+ "foldable-traversable",
1827+ "foreign-object",
1828+ "functors",
1829+ "identity",
1830+ "lists",
1831+ "maybe",
1832+ "newtype",
1833+ "ordered-collections",
1834+ "partial",
1835+ "prelude",
1836+ "profunctor",
1837+ "record",
1838+ "transformers",
1839+ "tuples"
1840+ ]
1841+ },
1842+ "record": {
1843+ "type": "registry",
1844+ "version": "4.0.0",
1845+ "integrity": "sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg=",
1846+ "dependencies": [
1847+ "functions",
1848+ "prelude",
1849+ "unsafe-coerce"
1850+ ]
1851+ },
1852+ "refs": {
1853+ "type": "registry",
1854+ "version": "6.0.0",
1855+ "integrity": "sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s=",
1856+ "dependencies": [
1857+ "effect",
1858+ "prelude"
1859+ ]
1860+ },
1861+ "safe-coerce": {
1862+ "type": "registry",
1863+ "version": "2.0.0",
1864+ "integrity": "sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU=",
1865+ "dependencies": [
1866+ "unsafe-coerce"
1867+ ]
1868+ },
1869+ "st": {
1870+ "type": "registry",
1871+ "version": "6.2.0",
1872+ "integrity": "sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY=",
1873+ "dependencies": [
1874+ "partial",
1875+ "prelude",
1876+ "tailrec",
1877+ "unsafe-coerce"
1878+ ]
1879+ },
1880+ "strings": {
1881+ "type": "registry",
1882+ "version": "6.0.1",
1883+ "integrity": "sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k=",
1884+ "dependencies": [
1885+ "arrays",
1886+ "control",
1887+ "either",
1888+ "enums",
1889+ "foldable-traversable",
1890+ "gen",
1891+ "integers",
1892+ "maybe",
1893+ "newtype",
1894+ "nonempty",
1895+ "partial",
1896+ "prelude",
1897+ "tailrec",
1898+ "tuples",
1899+ "unfoldable",
1900+ "unsafe-coerce"
1901+ ]
1902+ },
1903+ "tailrec": {
1904+ "type": "registry",
1905+ "version": "6.1.0",
1906+ "integrity": "sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk=",
1907+ "dependencies": [
1908+ "bifunctors",
1909+ "effect",
1910+ "either",
1911+ "identity",
1912+ "maybe",
1913+ "partial",
1914+ "prelude",
1915+ "refs"
1916+ ]
1917+ },
1918+ "transformers": {
1919+ "type": "registry",
1920+ "version": "6.0.0",
1921+ "integrity": "sha256-Pzw40HjthX77tdPAYzjx43LK3X5Bb7ZspYAp27wksFA=",
1922+ "dependencies": [
1923+ "control",
1924+ "distributive",
1925+ "effect",
1926+ "either",
1927+ "exceptions",
1928+ "foldable-traversable",
1929+ "identity",
1930+ "lazy",
1931+ "maybe",
1932+ "newtype",
1933+ "prelude",
1934+ "tailrec",
1935+ "tuples",
1936+ "unfoldable"
1937+ ]
1938+ },
1939+ "tuples": {
1940+ "type": "registry",
1941+ "version": "7.0.0",
1942+ "integrity": "sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M=",
1943+ "dependencies": [
1944+ "control",
1945+ "invariant",
1946+ "prelude"
1947+ ]
1948+ },
1949+ "type-equality": {
1950+ "type": "registry",
1951+ "version": "4.0.1",
1952+ "integrity": "sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw=",
1953+ "dependencies": []
1954+ },
1955+ "typelevel-prelude": {
1956+ "type": "registry",
1957+ "version": "7.0.0",
1958+ "integrity": "sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM=",
1959+ "dependencies": [
1960+ "prelude",
1961+ "type-equality"
1962+ ]
1963+ },
1964+ "unfoldable": {
1965+ "type": "registry",
1966+ "version": "6.0.0",
1967+ "integrity": "sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg=",
1968+ "dependencies": [
1969+ "foldable-traversable",
1970+ "maybe",
1971+ "partial",
1972+ "prelude",
1973+ "tuples"
1974+ ]
1975+ },
1976+ "unicode": {
1977+ "type": "registry",
1978+ "version": "6.0.0",
1979+ "integrity": "sha256-QJnTVZpmihEAUiMeYrfkusVoziJWp2hJsgi9bMQLue8=",
1980+ "dependencies": [
1981+ "foldable-traversable",
1982+ "maybe",
1983+ "strings"
1984+ ]
1985+ },
1986+ "unsafe-coerce": {
1987+ "type": "registry",
1988+ "version": "6.0.0",
1989+ "integrity": "sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0=",
1990+ "dependencies": []
1991+ },
1992+ "unsafe-reference": {
1993+ "type": "registry",
1994+ "version": "5.0.0",
1995+ "integrity": "sha256-zU7BhfJU14nXQRZG9iADsp0mSiKhz07OcKyjRB2YT+Y=",
1996+ "dependencies": [
1997+ "prelude"
1998+ ]
1999+ }
2000+ }
2001+}
spago.yaml+76−16
@@ -1,5 +1,11 @@
11package:
22 name: purescm
3+ publish:
4+ version: 1.13.0
5+ license: Apache-2.0
6+ location:
7+ githubOwner: purescm
8+ githubRepo: purescm
39 dependencies:
410 - aff
511 - argonaut
@@ -33,7 +39,6 @@ package:
3339 - node-child-process
3440 - node-execa
3541 - node-fs
36− - node-fs-aff
3742 - node-glob-basic
3843 - node-path
3944 - node-process
@@ -43,22 +48,48 @@ package:
4348 - posix-types
4449 - refs
4550workspace:
46− package_set:
47− registry: 20.0.1
48− extra_packages:
51+ packageSet:
52+ registry: 41.2.0
53+ extraPackages:
54+ dodo-printer:
55+ git: https://github.com/natefaubion/purescript-dodo-printer.git
56+ ref: 831c5c963a57ca4bfd62f96335267d7d0785851d
57+ dependencies:
58+ - aff
59+ - ansi
60+ - arrays
61+ - avar
62+ - console
63+ - control
64+ - effect
65+ - either
66+ - exceptions
67+ - foldable-traversable
68+ - integers
69+ - lists
70+ - maybe
71+ - minibench
72+ - newtype
73+ - parallel
74+ - partial
75+ - posix-types
76+ - prelude
77+ - safe-coerce
78+ - strings
79+ - tuples
4980 backend-optimizer:
50− git: https://github.com/JordanMartinez/purescript-backend-optimizer
51− ref: add-ty-con-info
81+ git: https://github.com/aristanetworks/purescript-backend-optimizer
82+ ref: 54b82ac23143dd47bfafaf52dec81dd7ccf2b490
5283 dependencies:
5384 - aff
5485 - ansi
5586 - argonaut
56− - argonaut-codecs
5787 - argparse-basic
5888 - arrays
5989 - bifunctors
6090 - console
6191 - control
92+ - datetime
6293 - debug
6394 - dodo-printer
6495 - effect
@@ -73,25 +104,54 @@ workspace:
73104 - lists
74105 - maybe
75106 - newtype
76− - node-buffer
77− - node-child-process
78− - node-fs
79− - node-fs-aff
80− - node-glob-basic
81− - node-path
82− - node-process
83− - node-streams
107+ - now
108+ - numbers
84109 - ordered-collections
110+ - orders
85111 - parallel
86112 - partial
87113 - posix-types
88114 - prelude
89115 - refs
90116 - safe-coerce
117+ - st
91118 - strings
92119 - transformers
93120 - tuples
94121 - unsafe-coerce
122+ language-cst-parser:
123+ git: https://github.com/natefaubion/purescript-language-cst-parser.git
124+ ref: bf5623e08e1f43f923d4ff3c29cafbda25128768
125+ dependencies:
126+ - arrays
127+ - console
128+ - const
129+ - control
130+ - effect
131+ - either
132+ - enums
133+ - foldable-traversable
134+ - free
135+ - functions
136+ - functors
137+ - identity
138+ - integers
139+ - lazy
140+ - lists
141+ - maybe
142+ - newtype
143+ - node-process
144+ - numbers
145+ - ordered-collections
146+ - partial
147+ - prelude
148+ - st
149+ - strings
150+ - transformers
151+ - tuples
152+ - typelevel-prelude
153+ - unfoldable
154+ - unsafe-coerce
95155 node-glob-basic:
96156 git: https://github.com/natefaubion/purescript-node-glob-basic.git
97157 ref: v1.2.2
@@ -101,7 +161,7 @@ workspace:
101161 - effect
102162 - lists
103163 - maybe
104− - node-fs-aff
164+ - node-fs
105165 - node-path
106166 - node-process
107167 - ordered-collections
src/Main.purs+304−6
@@ -2,12 +2,310 @@ module Main where
22
33import Prelude
44
5+import ArgParse.Basic (ArgParser)
6+import ArgParse.Basic as ArgParser
7+import Data.Array as Array
8+import Data.Either (Either(..), isRight)
9+import Data.Maybe (Maybe(..), fromMaybe)
10+import Data.Monoid (power)
11+import Data.Newtype (unwrap)
12+import Data.Set as Set
13+import Data.String (Pattern(..))
14+import Data.String as String
15+import Data.String.CodeUnits as SCU
16+import Dodo (plainText)
17+import Dodo as Dodo
518import Effect (Effect)
6−import Effect.Aff (launchAff_)
19+import Effect.Aff (Aff, attempt, effectCanceler, error, launchAff_, makeAff, runAff_, throwError)
720import Effect.Class (liftEffect)
8−import Effect.Console (log)
21+import Effect.Class.Console as Console
22+import Effect.Exception (message)
23+import Foreign.Object as Object
24+import Node.Encoding (Encoding(..))
25+import Node.EventEmitter (on_)
26+import Node.FS.Aff as FS
27+import Node.FS.Perms (mkPerms)
28+import Node.FS.Perms as Perms
29+import Node.FS.Stats as Stats
30+import Node.FS.Stream (createReadStream, createWriteStream)
31+import Node.Library.Execa (ExecaResult, execa)
32+import Node.Library.Execa.Which (defaultWhichOptions, which)
33+import Node.Path (FilePath)
34+import Node.Path as Path
35+import Node.Process as Process
36+import Node.Stream as Stream
37+import Partial.Unsafe (unsafeCrashWith)
38+import PureScript.Backend.Chez.Builder (basicBuildMain)
39+import PureScript.Backend.Chez.Constants (moduleForeign, moduleLib, schemeExt)
40+import PureScript.Backend.Chez.Convert (codegenModule)
41+import PureScript.Backend.Chez.Printer as Printer
42+import PureScript.Backend.Optimizer.CoreFn (Module(..), ModuleName(..))
43+import Spago.Generated.BuildInfo as BuildInfo
944
10−main :: Effect Unit
11−main = launchAff_ do
12− liftEffect $ log "Not yet implemented. See tests."
13− pure unit
45+type BuildArgs =
46+ { coreFnDir :: FilePath
47+ , outputDir :: FilePath
48+ , directivesFile :: Maybe FilePath
49+ }
50+
51+type BundleArgs =
52+ { moduleName :: String
53+ , libDir :: FilePath
54+ , outputDir :: FilePath
55+ }
56+
57+type RunArgs =
58+ { moduleName :: String
59+ , libDir :: FilePath
60+ }
61+
62+data Command
63+ = Build BuildArgs
64+ | Bundle BundleArgs
65+ | Run RunArgs
66+
67+cliArgParser :: ArgParser Command
68+cliArgParser =
69+ ArgParser.choose "command"
70+ [ ArgParser.command [ "build" ]
71+ "Builds Chez scheme code from corefn.json files"
72+ do
73+ Build <$> buildCmdArgParser <* ArgParser.flagHelp
74+ , ArgParser.command [ "bundle-app" ]
75+ "Bundles .so files to a single program file."
76+ do Bundle <$> bundleCmdArgParser <* ArgParser.flagHelp
77+ , ArgParser.command [ "run" ]
78+ "Runs a compiled scheme program by invoking\n\
79+ \the main function using the Chez interpreter."
80+ do Run <$> runCmdArgParser <* ArgParser.flagHelp
81+ ]
82+ <* ArgParser.flagHelp
83+ <* ArgParser.flagInfo [ "--version", "-v" ] "Show the current version of purescm."
84+ BuildInfo.packages.purescm
85+
86+buildCmdArgParser :: ArgParser BuildArgs
87+buildCmdArgParser =
88+ ArgParser.fromRecord
89+ { coreFnDir:
90+ ArgParser.argument [ "--corefn-dir" ]
91+ "Path to input directory containing corefn.json files.\n\
92+ \Defaults to './output'."
93+ # ArgParser.default (Path.concat [ ".", "output" ])
94+ , outputDir:
95+ ArgParser.argument [ "--output" ]
96+ "Path to output directory for backend files.\n\
97+ \Defaults to './output'."
98+ # ArgParser.default (Path.concat [ ".", "output" ])
99+ , directivesFile:
100+ ArgParser.argument [ "--directives" ]
101+ "Path to file that defines external inline directives (optional)."
102+ # ArgParser.optional
103+ }
104+
105+bundleCmdArgParser :: ArgParser BundleArgs
106+bundleCmdArgParser =
107+ ArgParser.fromRecord
108+ { moduleName:
109+ ArgParser.argument [ "--main" ]
110+ "Module to be used as the application's entry point.\n\
111+ \Defaults to 'Main'."
112+ # ArgParser.default "Main"
113+ , libDir:
114+ ArgParser.argument [ "--libdir" ]
115+ "Path to scheme source files.\n\
116+ \Defaults to './output'."
117+ # ArgParser.default (Path.concat [ ".", "output" ])
118+ , outputDir:
119+ ArgParser.argument [ "--output" ]
120+ "Path to output directory for backend files.\n\
121+ \Defaults to './output'."
122+ # ArgParser.default (Path.concat [ ".", "output" ])
123+ }
124+
125+runCmdArgParser :: ArgParser RunArgs
126+runCmdArgParser =
127+ ArgParser.fromRecord
128+ { moduleName:
129+ ArgParser.argument [ "--main" ]
130+ "Module to be used as the application's entry point.\n\
131+ \Defaults to 'Main'."
132+ # ArgParser.default "Main"
133+ , libDir:
134+ ArgParser.argument [ "--libdir" ]
135+ "Path to scheme source files.\n\
136+ \Defaults to './output'."
137+ # ArgParser.default (Path.concat [ ".", "output" ])
138+ }
139+
140+main :: FilePath -> Effect Unit
141+main cliRoot = do
142+ cliArgs <- Array.drop 2 <$> Process.argv
143+ case
144+ ArgParser.parseArgs "purescm" "Chez Scheme backend for PureScript" cliArgParser
145+ cliArgs
146+ of
147+ Left err ->
148+ Console.error $ ArgParser.printArgError err
149+ Right (Build args) ->
150+ flip runAff_ (runBuild args) case _ of
151+ Right _ -> pure unit
152+ Left err -> do
153+ Console.error (message err)
154+ Process.exit' 1
155+ Right (Bundle arg) ->
156+ launchAff_ $ runBundle cliRoot arg
157+ Right (Run arg) ->
158+ launchAff_ $ runRun cliRoot arg
159+
160+runBuild :: BuildArgs -> Aff Unit
161+runBuild args = do
162+ basicBuildMain
163+ { coreFnDirectory: args.coreFnDir
164+ , coreFnGlobs: pure "**"
165+ , externalDirectivesFile: args.directivesFile
166+ , onCodegenModule: \_ (Module { name: ModuleName name, path }) backend _ -> do
167+ let
168+ formatted =
169+ Dodo.print plainText Dodo.twoSpaces
170+ $ Printer.printLibrary
171+ $ codegenModule backend
172+ let modPath = Path.concat [ args.outputDir, name ]
173+ mkdirp modPath
174+ let libPath = Path.concat [ modPath, moduleLib <> schemeExt ]
175+ FS.writeTextFile UTF8 libPath formatted
176+ unless (Set.isEmpty backend.foreign) do
177+ let
178+ foreignSiblingPath =
179+ fromMaybe path (String.stripSuffix (Pattern (Path.extname path)) path) <>
180+ schemeExt
181+ let foreignOutputPath = Path.concat [ modPath, moduleForeign <> schemeExt ]
182+ res <- attempt $ copyFile foreignSiblingPath foreignOutputPath
183+ unless (isRight res) do
184+ Console.log $ " Foreign implementation missing."
185+ , onPrepareModule: \build coreFnMod@(Module { name }) -> do
186+ let total = show build.moduleCount
187+ let index = show (build.moduleIndex + 1)
188+ let padding = power " " (SCU.length total - SCU.length index)
189+ Console.log $ Array.fold
190+ [ "[", padding, index, " of ", total, "] purescm: building ", unwrap name ]
191+ pure coreFnMod
192+ }
193+
194+runBundle :: FilePath -> BundleArgs -> Aff Unit
195+runBundle cliRoot args = do
196+ let outPath = Path.concat [ args.outputDir, "main" ]
197+ let mainPath = Path.concat [ args.outputDir, "main.ss" ]
198+ let mainWpoPath = Path.concat [ args.outputDir, "main.wpo" ]
199+ mkdirp args.outputDir
200+ let
201+ mainContent = String.joinWith "\n"
202+ [ "#!chezscheme"
203+ , "(import (chezscheme)"
204+ , " (only (purescm stack-trace) print-stack-trace)"
205+ , " (only (purescm finalizers) run-finalizers)"
206+ , " (only (" <> args.moduleName <> " lib) main))"
207+ , "(base-exception-handler (lambda (e) (print-stack-trace e) (exit -1)))"
208+ , "(collect-request-handler (lambda () (collect) (run-finalizers)))"
209+ , "(main)"
210+ ]
211+ FS.writeTextFile UTF8 mainPath mainContent
212+ let
213+ -- Compile `lib/` to `[output]/`
214+ runtimeLibPath = Path.concat [ cliRoot, "lib" ] <> "::" <> args.outputDir
215+ -- Compile purescm generated scheme code to `[output]/`
216+ purescmLibPath = args.libDir <> "::" <> args.outputDir
217+ libDirs = runtimeLibPath <> ":" <> purescmLibPath <> ":"
218+ arguments = [ "-q", "--libdirs", libDirs ]
219+ res <- evalScheme arguments $ Array.fold
220+ [ "(top-level-program (import (chezscheme))"
221+ -- Catch compilation errors so that we exit with an error code
222+ , " (with-exception-handler (lambda (e) (display-condition e (console-error-port)) (newline (console-error-port)) (exit -1))"
223+ , " (lambda ()"
224+ , " (compile-profile #f)"
225+ , " (optimize-level 3)"
226+ , " (compile-file-message #f)"
227+ , " (compile-imported-libraries #t)"
228+ , " (generate-wpo-files #t)"
229+ , " (compile-program \"" <> mainPath <> "\")"
230+ , " (compile-whole-program \"" <> mainWpoPath <> "\" \"" <> outPath <> "\"))))"
231+ ]
232+ case res.exitCode of
233+ Just 0 -> Console.log $ "Created " <> outPath
234+ _ -> liftEffect $ Process.exit' (fromMaybe 1 res.exitCode)
235+
236+runRun :: FilePath -> RunArgs -> Aff Unit
237+runRun cliRoot args = do
238+ let
239+ runtimeLibPath = Path.concat [ cliRoot, "lib" ]
240+ libDirs = runtimeLibPath <> ":" <> args.libDir <> ":"
241+ arguments = [ "-q", "--libdirs", libDirs ]
242+ res <- evalScheme arguments $ Array.fold
243+ -- Set up an exception handler here so that compilation warnings get caught
244+ [ "(base-exception-handler (lambda (e)"
245+ , " (display-condition e (console-error-port))"
246+ , " (newline (console-error-port))"
247+ , " (exit -1)))"
248+ , "(top-level-program (import (chezscheme)"
249+ , " (only (purescm finalizers) run-finalizers)"
250+ , " (only (purescm stack-trace) print-stack-trace)"
251+ , " (only (" <> args.moduleName <> " lib) main))"
252+ , " (base-exception-handler (lambda (e) (print-stack-trace e) (exit -1)))"
253+ , " (collect-request-handler (lambda () (collect) (run-finalizers)))"
254+ , " (main))"
255+ ]
256+ case res.exitCode of
257+ Just 0 -> pure unit
258+ _ -> liftEffect $ Process.setExitCode (fromMaybe 1 res.exitCode)
259+
260+evalScheme :: Array String -> String -> Aff ExecaResult
261+evalScheme arguments code = do
262+ schemeBin <- getSchemeBinary
263+
264+ -- Apple blocks DYLD environment variables, so loading libraries with DYLD_LIBRARY_PATH
265+ -- will not work across process spawns. We go around this by carrying the library path
266+ -- in CHEZ_DYLD_LIBRARY_PATH and setting DYLD_LIBRARY_PATH when spawning. For more info see:
267+ -- https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html
268+ env <- liftEffect $ Process.getEnv
269+ case Object.lookup "CHEZ_DYLD_LIBRARY_PATH" env of
270+ Just dyldPath -> do
271+ liftEffect $ Process.setEnv "DYLD_LIBRARY_PATH" dyldPath
272+ _ -> pure unit
273+
274+ spawned <- execa schemeBin arguments (_ { extendEnv = Just true })
275+ spawned.stdin.writeUtf8End code
276+ spawned.stdout.pipeToParentStdout
277+ spawned.stderr.pipeToParentStderr
278+ spawned.getResult
279+
280+getSchemeBinary :: Aff String
281+getSchemeBinary = do
282+ useScheme <- isRight <$> which "scheme" defaultWhichOptions
283+ if useScheme then do
284+ pure "scheme"
285+ else do
286+ useChez <- isRight <$> which "chez" defaultWhichOptions
287+ if useChez then
288+ pure "chez"
289+ else do
290+ unsafeCrashWith "Could not find scheme binary"
291+
292+mkdirp :: FilePath -> Aff Unit
293+mkdirp path = FS.mkdir' path { recursive: true, mode: mkPerms Perms.all Perms.all Perms.all }
294+
295+copyFile :: FilePath -> FilePath -> Aff Unit
296+copyFile from to = do
297+ stats <- FS.stat from
298+ unless (Stats.isFile stats) do
299+ throwError $ error $ "Not a file: " <> from
300+ makeAff \k -> do
301+ src <- createReadStream from
302+ dst <- createWriteStream to
303+ src # on_ Stream.errorH \err -> do
304+ Stream.destroy' dst $ error $ "Got error in src stream: " <> message err
305+ k $ Left err
306+ dst # on_ Stream.errorH (k <<< Left)
307+ dst # on_ Stream.finishH (k (Right unit))
308+ Stream.pipe src dst
309+ pure $ effectCanceler do
310+ Stream.destroy dst
311+ Stream.destroy src
src/PureScript/Backend/Chez/Builder.pursnew file+118
@@ -0,0 +1,118 @@
1+module PureScript.Backend.Chez.Builder where
2+
3+import Prelude
4+
5+import Control.Monad.Cont.Trans (lift)
6+import Control.Monad.Except (ExceptT(..), runExceptT)
7+import Control.Parallel (parTraverse)
8+import Data.Argonaut as Json
9+import Data.Array.NonEmpty (NonEmptyArray)
10+import Data.Array.NonEmpty as NonEmptyArray
11+import Data.Bifunctor (lmap)
12+import Data.Compactable (separate)
13+import Data.Either (Either(..))
14+import Data.Foldable (foldl, for_, notElem)
15+import Data.Lazy as Lazy
16+import Data.List (List)
17+import Data.Map as Map
18+import Data.Maybe (Maybe(..), fromMaybe, maybe)
19+import Data.Set as Set
20+import Data.Set.NonEmpty as NonEmptySet
21+import Data.Traversable (traverse)
22+import Data.Tuple (Tuple(..))
23+import Effect.Aff (Aff)
24+import Effect.Class (liftEffect)
25+import Effect.Class.Console as Console
26+import Node.Encoding (Encoding(..))
27+import Node.FS.Aff as FS
28+import Node.Glob.Basic (expandGlobs)
29+import Node.Path (FilePath)
30+import Node.Process as Process
31+import PureScript.Backend.Optimizer.Builder (BuildEnv, buildModules)
32+import PureScript.Backend.Optimizer.Convert (BackendModule, OptimizationSteps)
33+import PureScript.Backend.Optimizer.CoreFn (Ann, Module, ModuleName(..), Qualified(..))
34+import PureScript.Backend.Optimizer.CoreFn.Json (decodeModule)
35+import PureScript.Backend.Optimizer.CoreFn.Sort (emptyPull, pullResult, resumePull, sortModules)
36+import PureScript.Backend.Optimizer.Directives (parseDirectiveFile)
37+import PureScript.Backend.Optimizer.Directives.Defaults (defaultDirectives)
38+import PureScript.Backend.Optimizer.Semantics (InlineDirectiveMap)
39+import PureScript.Backend.Optimizer.Semantics.Foreign (coreForeignSemantics)
40+import PureScript.CST.Errors (printParseError)
41+
42+basicBuildMain
43+ :: { coreFnDirectory :: FilePath
44+ , coreFnGlobs :: NonEmptyArray String
45+ , externalDirectivesFile :: Maybe FilePath
46+ , onCodegenModule :: BuildEnv -> Module Ann -> BackendModule -> OptimizationSteps -> Aff Unit
47+ , onPrepareModule :: BuildEnv -> Module Ann -> Aff (Module Ann)
48+ }
49+ -> Aff Unit
50+basicBuildMain options = do
51+ coreFnModulesFromOutput options.coreFnDirectory options.coreFnGlobs >>= case _ of
52+ Left errors -> do
53+ for_ errors \(Tuple filePath err) -> do
54+ Console.error $ filePath <> " " <> err
55+ liftEffect $ Process.exit' 1
56+ Right coreFnModules -> do
57+ externalDirectives <- map (fromMaybe Map.empty) $ traverse externalDirectivesFromFile
58+ options.externalDirectivesFile
59+ coreFnModules # buildModules
60+ { directives: Map.union externalDirectives (parseDirectiveFile defaultDirectives).directives
61+ , foreignSemantics: coreForeignSemantics # Map.filterKeys \(Qualified mod _) -> mod
62+ `notElem`
63+ -- `Effect.Ref.modify` is implemented as a thread-safe operation
64+ -- in the `refs` package. Note that `Control.Monad.ST.Internal`
65+ -- will still be inlined.
66+ [ Just (ModuleName "Effect.Ref") ]
67+ , onCodegenModule: options.onCodegenModule
68+ , onPrepareModule: options.onPrepareModule
69+ , traceIdents: Set.empty
70+ }
71+
72+coreFnModulesFromOutput
73+ :: String
74+ -> NonEmptyArray String
75+ -> Aff (Either (NonEmptyArray (Tuple FilePath String)) (List (Module Ann)))
76+coreFnModulesFromOutput path globs = runExceptT do
77+ paths <- Set.toUnfoldable <$> lift
78+ (expandGlobs path ((_ <> "/corefn.json") <$> NonEmptyArray.toArray globs))
79+ case NonEmptyArray.toArray globs of
80+ [ "**" ] ->
81+ sortModules <$> modulesFromPaths paths
82+ _ ->
83+ go <<< foldl resumePull emptyPull =<< modulesFromPaths paths
84+ where
85+ modulesFromPaths paths = ExceptT do
86+ { left, right } <- separate <$> parTraverse readCoreFnModule paths
87+ pure $ maybe (Right right) Left $ NonEmptyArray.fromArray left
88+
89+ pathFromModuleName (ModuleName mn) =
90+ path <> "/" <> mn <> "/corefn.json"
91+
92+ go pull = case pullResult pull of
93+ Left needed ->
94+ go <<< foldl resumePull pull =<< modulesFromPaths
95+ (pathFromModuleName <$> NonEmptySet.toUnfoldable needed)
96+ Right modules ->
97+ pure $ Lazy.force modules
98+
99+readCoreFnModule :: String -> Aff (Either (Tuple FilePath String) (Module Ann))
100+readCoreFnModule filePath = do
101+ contents <- FS.readTextFile UTF8 filePath
102+ case lmap Json.printJsonDecodeError <<< decodeModule =<< Json.jsonParser contents of
103+ Left err -> do
104+ pure $ Left $ Tuple filePath err
105+ Right mod ->
106+ pure $ Right mod
107+
108+externalDirectivesFromFile :: FilePath -> Aff InlineDirectiveMap
109+externalDirectivesFromFile filePath = do
110+ fileContent <- FS.readTextFile UTF8 filePath
111+ let { errors, directives } = parseDirectiveFile fileContent
112+ for_ errors \(Tuple directive { position, error }) -> do
113+ Console.warn $ "Invalid directive [" <> show (position.line + 1) <> ":"
114+ <> show (position.column + 1)
115+ <> "]"
116+ Console.warn $ " " <> directive
117+ Console.warn $ " " <> printParseError error
118+ pure directives
src/PureScript/Backend/Chez/Convert.purs+283−117
@@ -6,31 +6,40 @@ import Data.Argonaut as Json
66import Data.Array as Array
77import Data.Array.NonEmpty as NEA
88import Data.Array.NonEmpty as NonEmptyArray
9+import Data.Bifunctor (bimap)
10+import Data.Char (toCharCode)
11+import Data.Foldable (fold, foldMap)
12+import Data.Int as Int
913import Data.Maybe (Maybe(..))
14+import Data.Monoid (power)
1015import Data.Newtype (unwrap, wrap)
16+import Data.Number (isNaN)
17+import Data.Set (Set)
1118import Data.Set as Set
19+import Data.String as String
1220import Data.String.CodeUnits as CodeUnits
13−import Data.Tuple (Tuple(..), uncurry)
21+import Data.Tuple (Tuple(..), fst, uncurry)
1422import Data.Tuple as Tuple
1523import Partial.Unsafe (unsafeCrashWith)
16−import PureScript.Backend.Chez.Constants (libChezSchemePrefix, moduleForeign, moduleLib, runtimePrefix, scmPrefixed)
17−import PureScript.Backend.Chez.Syntax (ChezDefinition(..), ChezExport(..), ChezExpr, ChezImport(..), ChezImportSet(..), ChezLibrary)
24+import PureScript.Backend.Chez.Constants (libChezSchemePrefix, moduleForeign, moduleLib, rtPrefixed, runtimePrefix, scmPrefixed)
25+import PureScript.Backend.Chez.Syntax (ChezDefinition(..), ChezExport(..), ChezExpr, ChezImport(..), ChezImportSet(..), ChezLibrary, recordTypeAccessor, recordTypeCurriedConstructor, recordTypePredicate, recordTypeUncurriedConstructor)
1826import PureScript.Backend.Chez.Syntax as S
1927import PureScript.Backend.Optimizer.Convert (BackendModule, BackendBindingGroup)
20−import PureScript.Backend.Optimizer.CoreFn (Ident(..), Literal(..), ModuleName(..))
28+import PureScript.Backend.Optimizer.CoreFn (Ident(..), Literal(..), ModuleName(..), Qualified(..))
2129import PureScript.Backend.Optimizer.Semantics (NeutralExpr)
22−import PureScript.Backend.Optimizer.Syntax (BackendAccessor(..), BackendOperator(..), BackendOperator1(..), BackendOperator2(..), BackendOperatorNum(..), BackendOperatorOrd(..), BackendSyntax(..), Pair(..))
30+import PureScript.Backend.Optimizer.Syntax (BackendAccessor(..), BackendEffect(..), BackendOperator(..), BackendOperator1(..), BackendOperator2(..), BackendOperatorNum(..), BackendOperatorOrd(..), BackendSyntax(..), Level(..), Pair(..))
2331import Safe.Coerce (coerce)
2432
2533type CodegenEnv =
2634 { currentModule :: ModuleName
35+ , lazyTopLevelRefs :: Set Ident
2736 }
2837
2938codegenModule :: BackendModule -> ChezLibrary
3039codegenModule { name, bindings, imports, foreign: foreign_ } =
3140 let
3241 codegenEnv :: CodegenEnv
33− codegenEnv = { currentModule: name }
42+ codegenEnv = { currentModule: name, lazyTopLevelRefs: Set.empty }
3443
3544 definitions :: Array ChezDefinition
3645 definitions = Array.concat $
@@ -39,7 +48,7 @@ codegenModule { name, bindings, imports, foreign: foreign_ } =
3948 exports' :: Array ChezExport
4049 exports' = map ExportIdentifier
4150 $ Array.sort
42− $ Array.concatMap S.definitionIdentifiers definitions
51+ $ Array.concatMap definitionIdentifiers definitions
4352 <> map coerce (Array.fromFoldable foreign_)
4453
4554 pursImports :: Array ChezImport
@@ -71,7 +80,7 @@ codegenModule { name, bindings, imports, foreign: foreign_ } =
7180 libChezSchemePrefix
7281 , ImportSet $ ImportPrefix
7382 ( ImportLibrary
74− { identifiers: NEA.cons' "_Chez_Runtime" [ moduleLib ], version: Nothing }
83+ { identifiers: NEA.cons' "purescm" [ "runtime" ], version: Nothing }
7584 )
7685 runtimePrefix
7786 ] <> pursImports <> foreignImport
@@ -79,15 +88,78 @@ codegenModule { name, bindings, imports, foreign: foreign_ } =
7988 , body: { definitions, expressions: [] }
8089 }
8190
91+definitionIdentifiers :: ChezDefinition -> Array String
92+definitionIdentifiers = case _ of
93+ Define i _ -> [ i ]
94+ DefineRecordType i [ x ] ->
95+ [ recordTypeCurriedConstructor i
96+ , recordTypePredicate i
97+ , recordTypeAccessor i x
98+ ]
99+ DefineRecordType i fields ->
100+ [ recordTypeUncurriedConstructor i
101+ , recordTypePredicate i
102+ ] <> map (recordTypeAccessor i) fields
103+ DefineLazy _ _ _ -> []
104+
105+flattenQualified :: ModuleName -> Qualified Ident -> String
106+flattenQualified _ (Qualified Nothing (Ident i)) = i
107+flattenQualified currentModule (Qualified (Just m) (Ident i))
108+ | currentModule == m = i
109+ | otherwise = coerce m <> "." <> i
110+
111+toChezIdent :: Maybe Ident -> Level -> String
112+toChezIdent i (Level l) = case i of
113+ Just (Ident i') -> case i' of
114+ "$__unused" -> "_"
115+ _ -> i' <> show l
116+ Nothing -> "_" <> show l
117+
82118codegenTopLevelBindingGroup
83119 :: CodegenEnv
84120 -> BackendBindingGroup Ident NeutralExpr
85121 -> Array ChezDefinition
86−codegenTopLevelBindingGroup codegenEnv { recursive, bindings }
87− | recursive, Just bindings' <- NonEmptyArray.fromArray bindings =
88− [ DefineValue "rtlbg" $ S.Identifier "recursive-top-level-binding-group" ]
89− | otherwise =
90− Array.concatMap (codegenTopLevelBinding codegenEnv) bindings
122+codegenTopLevelBindingGroup codegenEnv { bindings, recursive }
123+ | recursive, Just bindings' <- NonEmptyArray.fromArray bindings = do
124+ -- Turn non-lazy bindings into lazy bindings so that they can refer to each
125+ -- other during initialization. Some definitions are initialized lazily,
126+ -- like lambda exressions, so we don't have to touch those.
127+ let lazyBindings = NonEmptyArray.partition isLazyBinding bindings'
128+ let
129+ codegenEnv' = codegenEnv
130+ { lazyTopLevelRefs = foldMap (Set.singleton <<< fst) lazyBindings.no }
131+ fold
132+ [ Array.concatMap (codegenTopLevelBinding codegenEnv') lazyBindings.yes
133+ , map (codegenLazyTopLevelBinding codegenEnv') lazyBindings.no
134+ , map (\(Tuple (Ident ident) _) -> Define ident $ S.forceLazyRef ident) lazyBindings.no
135+ ]
136+ | otherwise = Array.concatMap (codegenTopLevelBinding codegenEnv) bindings
137+
138+isLazyBinding :: Tuple Ident NeutralExpr -> Boolean
139+isLazyBinding (Tuple _ expr) = case unwrap expr of
140+ Abs _ _ ->
141+ true
142+ UncurriedAbs _ _ ->
143+ true
144+ UncurriedEffectAbs _ _ ->
145+ true
146+ CtorDef _ _ _ _ ->
147+ true
148+ EffectBind _ _ _ _ ->
149+ true
150+ EffectPure _ ->
151+ true
152+ EffectDefer _ ->
153+ true
154+ _ ->
155+ false
156+
157+codegenLazyTopLevelBinding
158+ :: CodegenEnv
159+ -> Tuple Ident NeutralExpr
160+ -> ChezDefinition
161+codegenLazyTopLevelBinding codegenEnv (Tuple (Ident i) n) =
162+ DefineLazy i codegenEnv.currentModule $ codegenExpr codegenEnv n
91163
92164codegenTopLevelBinding
93165 :: CodegenEnv
@@ -95,25 +167,12 @@ codegenTopLevelBinding
95167 -> Array ChezDefinition
96168codegenTopLevelBinding codegenEnv (Tuple (Ident i) n) =
97169 case unwrap n of
98− Abs a e ->
99− [ DefineCurriedFunction
100− i
101− (uncurry S.toChezIdent <$> a)
102− (codegenExpr codegenEnv e)
103− ]
104− UncurriedAbs a e ->
105− [ DefineUncurriedFunction
106− i
107− (uncurry S.toChezIdent <$> a)
108− (codegenExpr codegenEnv e)
109− ]
110170 CtorDef _ _ _ ss ->
111171 case NonEmptyArray.fromArray ss of
112172 Nothing ->
113− [ DefineValue i (S.quote $ S.Identifier i)
114− , DefineUncurriedFunction
115− (S.recordTypePredicate i)
116− [ "v" ]
173+ [ Define i (S.quote $ S.Identifier i)
174+ , Define (S.recordTypePredicate i)
175+ $ S.mkUncurriedFn [ "v" ]
117176 $ S.eqQ (S.quote $ S.Identifier i) (S.Identifier "v")
118177 ]
119178 Just xs
@@ -121,69 +180,91 @@ codegenTopLevelBinding codegenEnv (Tuple (Ident i) n) =
121180 [ DefineRecordType i ss ]
122181 | otherwise ->
123182 [ DefineRecordType i ss
124− , DefineCurriedFunction i xs
125− $ S.chezUncurriedApplication
183+ , Define i $ S.mkCurriedFn xs
184+ $ S.runUncurriedFn
126185 (S.Identifier $ S.recordTypeUncurriedConstructor i)
127186 (map S.Identifier ss)
128187 ]
129188 _ ->
130− [ DefineValue i $ codegenExpr codegenEnv n ]
189+ [ Define i $ codegenExpr codegenEnv n ]
131190
132191codegenExpr :: CodegenEnv -> NeutralExpr -> ChezExpr
133−codegenExpr codegenEnv@{ currentModule } s = case unwrap s of
192+codegenExpr codegenEnv@{ currentModule, lazyTopLevelRefs } s = case unwrap s of
193+ Var (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Cons")) ->
194+ S.Identifier (rtPrefixed "list-cons")
195+ Var qi@(Qualified (Just moduleName) ident)
196+ | moduleName == currentModule && Set.member ident lazyTopLevelRefs ->
197+ S.forceLazyRef $ flattenQualified currentModule qi
134198 Var qi ->
135− S.Identifier $ S.resolve currentModule qi
199+ S.Identifier $ flattenQualified currentModule qi
136200 Local i l ->
137− S.Identifier $ coerce $ S.toChezIdent i l
201+ S.Identifier $ coerce $ toChezIdent i l
138202 Lit l ->
139203 codegenLiteral codegenEnv l
140204 App f p ->
141− S.chezCurriedApplication (codegenExpr codegenEnv f) (codegenExpr codegenEnv <$> p)
205+ S.runCurriedFn (codegenExpr codegenEnv f) (codegenExpr codegenEnv <$> p)
142206 Abs a e -> do
143− S.chezCurriedFunction (uncurry S.toChezIdent <$> a) (codegenExpr codegenEnv e)
207+ S.mkCurriedFn (uncurry toChezIdent <$> a) (codegenExpr codegenEnv e)
208+ UncurriedApp f p ->
209+ S.runUncurriedFn (codegenExpr codegenEnv f) (codegenExpr codegenEnv <$> p)
210+ UncurriedAbs a e ->
211+ S.mkUncurriedFn (uncurry toChezIdent <$> a) (codegenExpr codegenEnv e)
212+ UncurriedEffectApp f p ->
213+ S.thunk $ S.runUncurriedFn (codegenExpr codegenEnv f)
214+ (codegenExpr codegenEnv <$> p)
215+ UncurriedEffectAbs a e ->
216+ S.mkUncurriedFn (uncurry toChezIdent <$> a)
217+ (codegenChain effectChainMode codegenEnv e)
144218
145− UncurriedApp fn args ->
146− S.List $ Array.cons (codegenExpr codegenEnv fn) $
147− (codegenExpr codegenEnv <$> args)
148− UncurriedAbs args body ->
149− S.List
150− [ S.Identifier $ scmPrefixed "lambda"
151− , S.List $ (S.Identifier <<< uncurry S.toChezIdent) <$> args
152− , S.List [ codegenExpr codegenEnv body ]
219+ Accessor e (GetProp i) ->
220+ S.runUncurriedFn
221+ (S.Identifier $ rtPrefixed "record-ref")
222+ [ codegenExpr codegenEnv e
223+ , S.recordLabel i
153224 ]
154−
155− UncurriedEffectApp _ _ ->
156− S.Identifier "uncurried-effect-app"
157− UncurriedEffectAbs _ _ ->
158− S.Identifier "uncurried-effect-ab"
159−
160− Accessor _ (GetProp _) ->
161− S.Identifier $ "accessor-get-prop"
162225 Accessor e (GetIndex i) ->
163− S.chezUncurriedApplication
164− (S.Identifier $ scmPrefixed "vector-ref")
226+ S.runUncurriedFn
227+ (S.Identifier $ rtPrefixed "array-ref")
165228 [ codegenExpr codegenEnv e, S.Integer $ wrap $ show i ]
229+ Accessor e
230+ (GetCtorField (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Cons")) _ _ _ _ 0) ->
231+ S.List [ S.Identifier (scmPrefixed "car"), (codegenExpr codegenEnv e) ]
232+ Accessor e
233+ (GetCtorField (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Cons")) _ _ _ _ 1) ->
234+ S.List [ S.Identifier (scmPrefixed "cdr"), (codegenExpr codegenEnv e) ]
166235 Accessor e (GetCtorField qi _ _ _ field _) ->
167− S.recordAccessor (codegenExpr codegenEnv e) (S.resolve currentModule qi) field
168− Update _ _ ->
169− S.Identifier "object-update"
236+ S.recordAccessor (codegenExpr codegenEnv e) (flattenQualified currentModule qi) field
237+ Update e f ->
238+ S.recordUpdate (codegenExpr codegenEnv e) (map (codegenExpr codegenEnv) <$> f)
170239
240+ CtorSaturated (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Nil")) _ _ _ _ ->
241+ S.List [ S.Identifier $ scmPrefixed "quote", S.List [] ]
242+ CtorSaturated (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Cons")) _ _ _ xs ->
243+ S.runUncurriedFn
244+ (S.Identifier $ scmPrefixed "cons")
245+ (map (codegenExpr codegenEnv <<< Tuple.snd) xs)
246+ CtorSaturated qi _ _ _ [] ->
247+ S.Identifier $ flattenQualified currentModule qi
248+ CtorSaturated qi _ _ _ [ Tuple _ x ] ->
249+ S.app
250+ (S.Identifier $ S.recordTypeCurriedConstructor $ flattenQualified currentModule qi)
251+ (codegenExpr codegenEnv x)
171252 CtorSaturated qi _ _ _ xs ->
172− S.chezUncurriedApplication
173− (S.Identifier $ S.recordTypeUncurriedConstructor $ S.resolve currentModule qi)
253+ S.runUncurriedFn
254+ (S.Identifier $ S.recordTypeUncurriedConstructor $ flattenQualified currentModule qi)
174255 (map (codegenExpr codegenEnv <<< Tuple.snd) xs)
175256 CtorDef _ _ _ _ ->
176257 unsafeCrashWith "codegenExpr:CtorDef - handled by codegenTopLevelBinding!"
177−
178− LetRec _ _ _ ->
179− S.Identifier "let-rec"
258+ LetRec lvl bindings expr ->
259+ S.Let true (map (bimap (flip toChezIdent lvl <<< Just) (codegenExpr codegenEnv)) bindings) $
260+ codegenExpr codegenEnv expr
180261 Let _ _ _ _ ->
181262 codegenPureChain codegenEnv s
182263 Branch b o -> do
183264 let
184− goPair :: Pair NeutralExpr -> { c :: _, e :: _ }
185− goPair (Pair c e) = { c: codegenExpr codegenEnv c, e: codegenExpr codegenEnv e }
186− S.chezCond (goPair <$> b) (codegenExpr codegenEnv <$> o)
265+ goPair :: Pair NeutralExpr -> Tuple ChezExpr ChezExpr
266+ goPair (Pair c e) = Tuple (codegenExpr codegenEnv c) (codegenExpr codegenEnv e)
267+ S.Cond (goPair <$> b) (codegenExpr codegenEnv o)
187268
188269 EffectBind _ _ _ _ ->
189270 codegenEffectChain codegenEnv s
@@ -191,76 +272,126 @@ codegenExpr codegenEnv@{ currentModule } s = case unwrap s of
191272 codegenEffectChain codegenEnv s
192273 EffectDefer _ ->
193274 codegenEffectChain codegenEnv s
275+ PrimEffect _ ->
276+ codegenEffectChain codegenEnv s
194277
195278 PrimOp o ->
196279 codegenPrimOp codegenEnv o
197− PrimEffect _ ->
198− S.Identifier "prim-effect"
199− PrimUndefined ->
200− S.Identifier "prim-undefined"
280+ PrimUndefined -> S.quote $ S.Identifier "undefined"
201281
202− Fail i ->
282+ Fail "Failed pattern match" ->
203283 -- Note: This can be improved by using `error`, but it requires
204284 -- that we track where exactly this `Fail` is defined. We can
205285 -- make use of the `codegenEnv` for this.
206− S.List
207− [ S.Identifier $ scmPrefixed "raise"
208− , S.List
209− [ S.Identifier $ scmPrefixed "condition"
210− , S.List [ S.Identifier $ scmPrefixed "make-error" ]
211− , S.List
212− [ S.Identifier $ scmPrefixed "make-message-condition"
213− , S.String $ Json.stringify $ Json.fromString i
214− ]
215− ]
216− ]
286+ S.List [ S.Identifier $ rtPrefixed "fail" ]
287+ Fail _ ->
288+ unsafeCrashWith "Unsupported fail."
217289
218290codegenLiteral :: CodegenEnv -> Literal NeutralExpr -> ChezExpr
219291codegenLiteral codegenEnv = case _ of
220292 LitInt i -> S.Integer $ wrap $ show i
221− LitNumber n -> S.Float $ wrap $ show n
222− LitString s -> S.String $ S.jsonToChezString $ Json.stringify $ Json.fromString s
223− LitChar c -> S.Identifier $ "#\\" <> CodeUnits.singleton c
293+ LitNumber n -> S.Float $ wrap $ codegenFloat n
294+ LitString s -> S.List
295+ [ S.Identifier $ rtPrefixed "string->pstring"
296+ , S.StringExpr s
297+ ]
298+ LitChar c -> codegenChar c
224299 LitBoolean b -> S.Identifier $ if b then "#t" else "#f"
225300 LitArray a -> S.vector $ codegenExpr codegenEnv <$> a
226301 LitRecord r -> S.record $ (map $ codegenExpr codegenEnv) <$> r
227302
228−type BlockMode = { effect :: Boolean }
303+-- PureScript doesn't have syntax for literal number infinity or NaN
304+-- but the backend-optimizer might evaluate an expression to such a value
305+-- so we need to deal with those separately.
306+codegenFloat :: Number -> String
307+codegenFloat x = case x of
308+ _
309+ | top == x -> "+inf.0"
310+ | bottom == x -> "-inf.0"
311+ | isNaN x -> "+nan.0"
312+ | otherwise -> show x
229313
230−pureBlockMode :: BlockMode
231−pureBlockMode = { effect: false }
314+-- > In addition to the standard named characters
315+-- > #\alarm, #\backspace, #\delete, #\esc, #\linefeed, #\newline, #\page, #\return, #\space, and #\tab,
316+-- > Chez Scheme recognizes #\bel, #\ls, #\nel, #\nul, #\rubout, and #\vt (or #\vtab).
317+--
318+-- Source: https://cisco.github.io/ChezScheme/csug9.5/intro.html#./intro:h1, 6th paragraph
319+codegenChar :: Char -> ChezExpr
320+codegenChar c = S.Char $ append """#\""" $ escapeChar $ toCharCode c
321+ where
322+ escapeChar code
323+ | code == toCharCode '\x0000' = "nul"
324+ | code == toCharCode '\x0007' = "alarm" -- bel
325+ | code == toCharCode '\x0008' = "backspace"
326+ | code == toCharCode '\t' = "tab"
327+ | code == toCharCode '\n' = "linefeed" -- nel/newline; per R6Rs, newline is deprecated
328+ | code == toCharCode '\x000B' = "vtab"
329+ | code == toCharCode '\x000C' = "page"
330+ | code == toCharCode '\r' = "return"
331+ | code == toCharCode '\x001B' = "esc"
332+ | code == toCharCode ' ' = "space"
333+ | code == toCharCode '\x007F' = "delete" -- rubout
334+ | code == toCharCode '\x2028' = "ls"
335+ | code < 20 || code > 127 = "x" <> (padLeft "0" 4 $ Int.toStringAs Int.hexadecimal code)
336+ | otherwise = CodeUnits.singleton c
337+
338+ padLeft char i s = power char (i - String.length s) <> s
339+
340+type ChainMode = { effect :: Boolean }
232341
233−effectBlockMode :: BlockMode
234−effectBlockMode = { effect: true }
342+pureChainMode :: ChainMode
343+pureChainMode = { effect: false }
344+
345+effectChainMode :: ChainMode
346+effectChainMode = { effect: true }
235347
236348codegenPureChain :: CodegenEnv -> NeutralExpr -> ChezExpr
237−codegenPureChain codegenEnv = codegenChain pureBlockMode codegenEnv
349+codegenPureChain codegenEnv = codegenChain pureChainMode codegenEnv
238350
239351codegenEffectChain :: CodegenEnv -> NeutralExpr -> ChezExpr
240−codegenEffectChain codegenEnv = S.chezThunk <<< codegenChain effectBlockMode codegenEnv
352+codegenEffectChain codegenEnv = S.thunk <<< codegenChain effectChainMode codegenEnv
241353
242−codegenChain :: BlockMode -> CodegenEnv -> NeutralExpr -> ChezExpr
243−codegenChain blockMode codegenEnv = go []
354+codegenChain :: ChainMode -> CodegenEnv -> NeutralExpr -> ChezExpr
355+codegenChain chainMode codegenEnv = collect []
244356 where
245− go :: Array _ -> NeutralExpr -> ChezExpr
246− go bindings expression = case unwrap expression of
357+ recursive :: Boolean
358+ recursive = false
359+
360+ -- `expression` has type `Effect ..`, so we can confidently unthunk here
361+ codegenEffectBind :: NeutralExpr -> ChezExpr
362+ codegenEffectBind expression = case unwrap expression of
363+ PrimEffect e' ->
364+ codegenPrimEffect codegenEnv e'
365+ UncurriedEffectApp f p ->
366+ S.runUncurriedFn (codegenExpr codegenEnv f) (codegenExpr codegenEnv <$> p)
367+ _ ->
368+ S.unthunk $ codegenExpr codegenEnv expression
369+
370+ finish :: Boolean -> Array _ -> ChezExpr -> ChezExpr
371+ finish shouldUnthunk bindings expression = do
372+ let
373+ maybeUnthunk :: ChezExpr -> ChezExpr
374+ maybeUnthunk = if shouldUnthunk then S.unthunk else identity
375+ case NEA.fromArray bindings of
376+ Nothing -> maybeUnthunk expression
377+ Just bindings' -> S.Let recursive bindings' $ maybeUnthunk expression
378+
379+ collect :: Array _ -> NeutralExpr -> ChezExpr
380+ collect bindings expression = case unwrap expression of
247381 Let i l v e' ->
248− go (Array.cons { i, l, v: codegenExpr codegenEnv v } bindings) e'
249− EffectBind i l v e' | blockMode.effect ->
250− go (Array.cons { i, l, v: S.chezUnthunk $ codegenExpr codegenEnv v } bindings) e'
251− EffectPure e' | blockMode.effect ->
252− go bindings e'
253− EffectDefer e' | blockMode.effect ->
254− go bindings e'
255− _ | Array.null bindings ->
256− codegenExpr codegenEnv expression
382+ collect (Array.snoc bindings $ Tuple (toChezIdent i l) (codegenExpr codegenEnv v)) e'
383+ EffectPure e' | chainMode.effect ->
384+ finish false bindings (codegenExpr codegenEnv e')
385+ PrimEffect e' | chainMode.effect ->
386+ finish false bindings (codegenPrimEffect codegenEnv e')
387+ EffectBind i l v e' | chainMode.effect ->
388+ collect
389+ (Array.snoc bindings $ Tuple (toChezIdent i l) (codegenEffectBind v))
390+ e'
391+ EffectDefer e' | chainMode.effect ->
392+ collect bindings e'
257393 _ ->
258− S.List $
259− [ S.Identifier $ scmPrefixed "let*"
260− , S.List $ Array.reverse bindings <#> \binding ->
261− S.List [ S.Identifier $ S.toChezIdent binding.i binding.l, binding.v ]
262− , codegenExpr codegenEnv expression
263− ]
394+ finish chainMode.effect bindings (codegenExpr codegenEnv expression)
264395
265396codegenPrimOp :: CodegenEnv -> BackendOperator NeutralExpr -> ChezExpr
266397codegenPrimOp codegenEnv@{ currentModule } = case _ of
@@ -277,10 +408,14 @@ codegenPrimOp codegenEnv@{ currentModule } = case _ of
277408 OpNumberNegate ->
278409 S.List [ S.Identifier $ scmPrefixed "fl-", x' ]
279410 OpArrayLength ->
280− S.List [ S.Identifier $ scmPrefixed "vector-length", x' ]
411+ S.List [ S.Identifier $ rtPrefixed "array-length", x' ]
412+ OpIsTag (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Cons")) ->
413+ S.List [ S.Identifier (scmPrefixed "pair?"), x' ]
414+ OpIsTag (Qualified (Just (ModuleName "Data.List.Types")) (Ident "Nil")) ->
415+ S.List [ S.Identifier (scmPrefixed "null?"), x' ]
281416 OpIsTag qi ->
282417 S.app
283− (S.Identifier $ S.recordTypePredicate $ S.resolve currentModule qi)
418+ (S.Identifier $ S.recordTypePredicate $ flattenQualified currentModule qi)
284419 x'
285420 Op2 o x y ->
286421 let
@@ -315,7 +450,7 @@ codegenPrimOp codegenEnv@{ currentModule } = case _ of
315450 in
316451 case o of
317452 OpArrayIndex ->
318− S.List [ S.Identifier $ scmPrefixed "vector-ref", x', y' ]
453+ S.List [ S.Identifier $ rtPrefixed "array-ref", x', y' ]
319454 OpBooleanAnd ->
320455 S.List [ S.Identifier $ scmPrefixed "and", x', y' ]
321456 OpBooleanOr ->
@@ -366,6 +501,37 @@ codegenPrimOp codegenEnv@{ currentModule } = case _ of
366501 OpNumberOrd o' ->
367502 makeComparison "fl" o'
368503 OpStringAppend ->
369− S.List [ S.Identifier $ scmPrefixed "string-append", x', y' ]
370− OpStringOrd o' ->
371− makeComparison "string" o'
504+ S.List [ S.Identifier $ rtPrefixed "pstring-concat", x', y' ]
505+ OpStringOrd o' -> do
506+ let
507+ makeStringComparison :: BackendOperatorOrd -> ChezExpr
508+ makeStringComparison = do
509+ let
510+ comparisonExpression :: String -> ChezExpr
511+ comparisonExpression opName =
512+ S.List [ S.Identifier $ Array.fold [ rtPrefixed "pstring", opName ], x', y' ]
513+ case _ of
514+ OpEq -> comparisonExpression "=?"
515+ OpNotEq -> S.List [ S.Identifier $ scmPrefixed "not", comparisonExpression "=?" ]
516+ OpGt -> comparisonExpression ">?"
517+ OpGte -> comparisonExpression ">=?"
518+ OpLt -> comparisonExpression "<?"
519+ OpLte -> comparisonExpression "<=?"
520+ makeStringComparison o'
521+
522+codegenPrimEffect :: CodegenEnv -> BackendEffect NeutralExpr -> ChezExpr
523+codegenPrimEffect codegenEnv = case _ of
524+ EffectRefNew v ->
525+ S.app (S.Identifier $ scmPrefixed "box") (codegenExpr codegenEnv v)
526+ EffectRefRead r ->
527+ S.app (S.Identifier $ scmPrefixed "unbox") (codegenExpr codegenEnv r)
528+ EffectRefWrite r v ->
529+ S.List
530+ [ S.Identifier $ scmPrefixed "begin"
531+ , S.List
532+ [ S.Identifier $ scmPrefixed "set-box!"
533+ , codegenExpr codegenEnv r
534+ , codegenExpr codegenEnv v
535+ ]
536+ , S.List [ S.Identifier $ scmPrefixed "unbox", codegenExpr codegenEnv r ]
537+ ]
src/PureScript/Backend/Chez/Printer.pursnew file+371
@@ -0,0 +1,371 @@
1+module PureScript.Backend.Chez.Printer
2+ ( printLibrary
3+ ) where
4+
5+import Prelude
6+
7+import Control.Alternative as Alternative
8+import Data.Argonaut as Json
9+import Data.Array as Array
10+import Data.Array.NonEmpty (NonEmptyArray)
11+import Data.Array.NonEmpty as NEA
12+import Data.Array.NonEmpty as NonEmptyArray
13+import Data.Bifunctor (bimap)
14+import Data.Maybe (Maybe(..), maybe)
15+import Data.Newtype (un)
16+import Data.String (Pattern(..), Replacement(..))
17+import Data.String as String
18+import Data.String.Regex as R
19+import Data.String.Regex.Flags as R.Flags
20+import Data.String.Regex.Unsafe as R.Unsafe
21+import Data.Tuple (Tuple(..))
22+import Partial.Unsafe (unsafeCrashWith)
23+import Dodo (Doc)
24+import Dodo as D
25+import PureScript.Backend.Chez.Constants (rtPrefixed, scmPrefixed)
26+import PureScript.Backend.Chez.Syntax (ChezDefinition(..), ChezExport(..), ChezExpr(..), ChezImport(..), ChezImportLevel(..), ChezImportSet(..), ChezLibrary, LibraryBody, LibraryName, LibraryReference, LibraryVersion(..), LiteralDigit(..), SubVersionReference(..), VersionReference(..), lazyRefName, recordTypeAccessor, recordTypeCurriedConstructor, recordTypeName, recordTypePredicate, recordTypeUncurriedConstructor)
27+import PureScript.Backend.Optimizer.CoreFn (ModuleName(..))
28+
29+printWrap :: Doc Void -> Doc Void -> Doc Void -> Doc Void
30+printWrap l r x = l <> x <> r
31+
32+printList :: Doc Void -> Doc Void
33+printList = printWrap (D.text "(") (D.text ")")
34+
35+printBrackets :: Doc Void -> Doc Void
36+printBrackets = printWrap (D.text "[") (D.text "]")
37+
38+printNamedList :: Prim.String -> Doc Void -> Doc Void
39+printNamedList name body
40+ | D.isEmpty body =
41+ printList $ D.text name
42+ | otherwise =
43+ printList $ D.words [ D.text name, body ]
44+
45+printIndentedList :: Doc Void -> Doc Void -> Doc Void
46+printIndentedList ident body
47+ | D.isEmpty body =
48+ printList ident
49+ | otherwise =
50+ D.lines
51+ [ D.text "(" <> ident
52+ , D.indent body <> D.text ")"
53+ ]
54+
55+linesSeparated :: Prim.Array (Doc Void) -> Doc Void
56+linesSeparated = Array.intercalate twoLineBreaks
57+ where
58+ twoLineBreaks = D.break <> D.break
59+
60+escapeIdentifiers :: ChezLibrary -> ChezLibrary
61+escapeIdentifiers lib = lib
62+ { name = lib.name { identifiers = map escapeIdent lib.name.identifiers }
63+ , exports = map escapeExport lib.exports
64+ , imports = map escapeImport lib.imports
65+ , body =
66+ { definitions: escapeDefinition <$> lib.body.definitions
67+ , expressions: escapeExpr <$> lib.body.expressions
68+ }
69+ }
70+ where
71+ escapeIdent = String.replaceAll (Pattern "'") (Replacement "$p")
72+ escapeExport = case _ of
73+ ExportIdentifier x -> ExportIdentifier $ escapeIdent x
74+ ExportRename arr -> ExportRename $ arr <#> \r ->
75+ { original: escapeIdent r.original, rename: escapeIdent r.rename }
76+
77+ escapeImport = case _ of
78+ ImportSet set -> ImportSet $ escapeImportSet set
79+ ImportFor set lvls -> ImportFor (escapeImportSet set) lvls
80+
81+ escapeImportSet = case _ of
82+ ImportLibrary libRef ->
83+ ImportLibrary $ escapeLibRef libRef
84+ ImportOnly set idents ->
85+ ImportOnly (escapeImportSet set) $ map escapeIdent idents
86+ ImportExcept set idents ->
87+ ImportExcept (escapeImportSet set) $ map escapeIdent idents
88+ ImportPrefix set ident ->
89+ ImportPrefix (escapeImportSet set) $ escapeIdent ident
90+ ImportRename set renames ->
91+ ImportRename (escapeImportSet set) $ renames <#> \r ->
92+ { original: escapeIdent r.original, rename: escapeIdent r.rename }
93+
94+ escapeLibRef libRef = libRef { identifiers = map escapeIdent libRef.identifiers }
95+
96+ escapeDefinition = case _ of
97+ Define i expr -> Define (escapeIdent i) $ escapeExpr expr
98+ DefineLazy i moduleName expr -> DefineLazy (escapeIdent i) moduleName $ escapeExpr expr
99+ DefineRecordType i fields -> DefineRecordType (escapeIdent i) $ map escapeIdent fields
100+
101+ escapeExpr = case _ of
102+ Identifier i -> Identifier $ escapeIdent i
103+ List exprs -> List $ map escapeExpr exprs
104+ Cond b o -> Cond (map (bimap escapeExpr escapeExpr) b) (escapeExpr o)
105+ Let recursive bindings expr ->
106+ Let recursive (map (bimap escapeIdent escapeExpr) bindings) $ escapeExpr expr
107+ Lambda args expr -> Lambda (map escapeIdent args) $ escapeExpr expr
108+ x@(Integer _) -> x
109+ x@(Float _) -> x
110+ x@(StringExpr _) -> x
111+ x@(Char _) -> x
112+ x@(Bool _) -> x
113+
114+printLibrary :: ChezLibrary -> Doc Void
115+printLibrary = escapeIdentifiers >>> printLibrary'
116+
117+printLibrary' :: ChezLibrary -> Doc Void
118+printLibrary' lib =
119+ flip append D.break
120+ $ D.lines
121+ $ Array.catMaybes
122+ [ D.text "#!r6rs" <$ Alternative.guard lib."#!r6rs"
123+ , D.text "#!chezscheme" <$ Alternative.guard lib."#!chezscheme"
124+ , Just $ printNamedIndentedList (D.text "library") $ D.lines
125+ [ printLibraryName lib.name
126+ , printIndentedList (D.text "export") $ D.lines $ map printExport lib.exports
127+ , (printIndentedList (D.text "import") $ D.lines $ map printImport lib.imports)
128+ <> D.break
129+ , printBody lib.body
130+ ]
131+ ]
132+
133+printLibraryName :: LibraryName -> Doc Void
134+printLibraryName { identifiers, version } =
135+ printList $ D.words
136+ [ D.words $ map D.text identifiers
137+ , case version of
138+ [] -> mempty
139+ _ -> printList $ D.words $ map printLibraryVersion version
140+ ]
141+
142+printLibraryVersion :: LibraryVersion -> Doc Void
143+printLibraryVersion = D.text <<< show <<< un LibraryVersion
144+
145+printExport :: ChezExport -> Doc Void
146+printExport = case _ of
147+ ExportIdentifier s -> D.text s
148+ ExportRename arr ->
149+ printNamedList "rename"
150+ $ D.words
151+ $ map (\r -> printList $ D.words [ D.text r.original, D.text r.rename ]) arr
152+
153+printImport :: ChezImport -> Doc Void
154+printImport = case _ of
155+ ImportSet is -> printImportSet is
156+ ImportFor is lvls ->
157+ printNamedList "for" $ D.words
158+ [ printImportSet is
159+ , D.words $ map printImportLevel lvls
160+ ]
161+
162+printImportLevel :: ChezImportLevel -> Doc Void
163+printImportLevel = case _ of
164+ ImportLevelRun -> D.text "run"
165+ ImportLevelExpand -> D.text "expand"
166+ ImportLevelMeta level -> printNamedList "meta" $ D.text $ show level
167+
168+printImportSet :: ChezImportSet -> Doc Void
169+printImportSet = case _ of
170+ ImportLibrary libRef ->
171+ printLibraryReference libRef
172+ ImportOnly impSet identifiers ->
173+ printNamedList "only" $ D.words
174+ [ printImportSet impSet, D.words $ map D.text identifiers ]
175+ ImportExcept impSet identifiers ->
176+ printNamedList "except" $ D.words
177+ [ printImportSet impSet, D.words $ map D.text identifiers ]
178+ ImportPrefix impSet rename ->
179+ printNamedList "prefix" $ D.words [ printImportSet impSet, D.text rename ]
180+ ImportRename impSet identifiers ->
181+ printNamedList "rename" $ D.words
182+ [ printImportSet impSet
183+ , D.words $ map (\r -> printList $ D.words $ map D.text [ r.original, r.rename ])
184+ identifiers
185+ ]
186+
187+printLibraryReference :: LibraryReference -> Doc Void
188+printLibraryReference lib = do
189+ let
190+ printListFn
191+ | Array.elem (NEA.head lib.identifiers)
192+ [ "for", "library", "only", "except", "prefix", "rename" ] =
193+ printNamedList "library"
194+ | otherwise =
195+ printList
196+ printListFn $ D.words
197+ [ D.words $ map D.text lib.identifiers
198+ , maybe mempty printVersionReference lib.version
199+ ]
200+
201+printVersionReference :: VersionReference -> Doc Void
202+printVersionReference = case _ of
203+ VersionRef ref ->
204+ printList $ D.words $ map printSubVersionReference ref
205+ VersionAnd ref ->
206+ printNamedList "and" $ D.words $ map printVersionReference ref
207+ VersionOr ref ->
208+ printNamedList "or" $ D.words $ map printVersionReference ref
209+ VersionNot ref ->
210+ printNamedList "not" $ printVersionReference ref
211+
212+printSubVersionReference :: SubVersionReference -> Doc Void
213+printSubVersionReference = case _ of
214+ SubVersionRef ref -> printList $ printLibraryVersion ref
215+ SubVersionGTE ref -> printNamedList ">=" $ printLibraryVersion ref
216+ SubVersionLTE ref -> printNamedList "<=" $ printLibraryVersion ref
217+ SubVersionAnd ref -> printNamedList "and" $ D.words
218+ $ map printSubVersionReference ref
219+ SubVersionOr ref -> printNamedList "or" $ D.words
220+ $ map printSubVersionReference ref
221+ SubVersionNot ref -> printNamedList "not" $ printSubVersionReference ref
222+
223+printBody :: LibraryBody -> Doc Void
224+printBody lib = do
225+ let
226+ defs = map printDefinition lib.definitions
227+ exprs = map printChezExpr lib.expressions
228+ linesSeparated $ defs <> exprs
229+
230+printNamedIndentedList :: Doc Void -> Doc Void -> Doc Void
231+printNamedIndentedList firstLine body
232+ | D.isEmpty body =
233+ printList firstLine
234+ | otherwise =
235+ D.lines
236+ [ D.text "(" <> firstLine
237+ , D.indent $ body <> D.text ")"
238+ ]
239+
240+printDefinition :: ChezDefinition -> Doc Void
241+printDefinition = case _ of
242+ Define ident expr ->
243+ printNamedIndentedList (D.words [ D.text $ scmPrefixed "define", D.text ident ])
244+ $ printChezExpr expr
245+ DefineLazy ident (ModuleName m) expr -> do
246+ let origIdentName = Json.stringify $ Json.fromString ident
247+ let moduleName = Json.stringify $ Json.fromString m
248+ printNamedIndentedList
249+ ( D.words
250+ [ D.text $ rtPrefixed "define-lazy"
251+ , D.text (lazyRefName ident)
252+ , D.text origIdentName
253+ , D.text moduleName
254+ ]
255+ )
256+ $ printChezExpr expr
257+ DefineRecordType ident [ field ] ->
258+ printRecordDefinition
259+ ident
260+ (recordTypeName ident)
261+ (recordTypeCurriedConstructor ident)
262+ (recordTypePredicate ident)
263+ [ field ]
264+ DefineRecordType ident fields ->
265+ printRecordDefinition
266+ ident
267+ (recordTypeName ident)
268+ (recordTypeUncurriedConstructor ident)
269+ (recordTypePredicate ident)
270+ fields
271+
272+printChezExpr :: ChezExpr -> Doc Void
273+printChezExpr e = case e of
274+ Integer (LiteralDigit x) -> D.text x
275+ Float (LiteralDigit x) -> D.text x
276+ Char x -> D.text x
277+ StringExpr x -> D.text $ jsonToChezString $ Json.stringify $ Json.fromString x
278+ Bool x -> D.text $ if x then "#t" else "#f"
279+ Identifier x -> D.text x
280+ List xs -> printList $ D.words (printChezExpr <$> xs)
281+ Cond branches fallback -> printCond branches fallback
282+ Let recursive bindings' expr -> printLet recursive bindings' expr
283+ Lambda args expr -> printLambda args expr
284+
285+jsonToChezString :: String -> String
286+jsonToChezString str = unicodeReplace str
287+ where
288+ unicodeRegex :: R.Regex
289+ unicodeRegex = R.Unsafe.unsafeRegex """\\u([A-F\d]{4})""" R.Flags.global
290+
291+ unicodeReplace :: String -> String
292+ unicodeReplace s = R.replace' unicodeRegex unicodeReplaceMatch s
293+
294+ unicodeReplaceMatch
295+ :: String
296+ -> Array (Maybe String)
297+ -> String
298+ unicodeReplaceMatch _ = case _ of
299+ [ (Just x) ] -> "\\x" <> x <> ";"
300+ _ -> unsafeCrashWith "Error matching at unicodeReplaceMatch in jsonToChezString"
301+
302+printRecordDefinition
303+ :: Prim.String
304+ -> Prim.String
305+ -> Prim.String
306+ -> Prim.String
307+ -> Prim.Array Prim.String
308+ -> Doc Void
309+printRecordDefinition ident name constructor predicate fields =
310+ printNamedIndentedList defineForm fieldsForm
311+ where
312+ defineForm :: Doc Void
313+ defineForm = D.words
314+ [ D.text $ scmPrefixed "define-record-type"
315+ , printList $ D.words $ map D.text [ name, constructor, predicate ]
316+ ]
317+
318+ fieldForm :: Prim.String -> Doc Void
319+ fieldForm field = printList $ D.words
320+ $ map D.text [ scmPrefixed "immutable", field, recordTypeAccessor ident field ]
321+
322+ fieldsForm :: Doc Void
323+ fieldsForm = printList $ D.words $ Array.cons (D.text $ scmPrefixed "fields")
324+ $ map fieldForm fields
325+
326+printLet :: Boolean -> NonEmptyArray (Tuple String ChezExpr) -> ChezExpr -> Doc Void
327+printLet recursive bindings' expr = do
328+ let
329+ multiLetKeyword
330+ | recursive = D.text $ scmPrefixed "letrec*"
331+ | otherwise = D.text $ scmPrefixed "let*"
332+ singleLetKeyword
333+ | recursive = D.text $ scmPrefixed "letrec"
334+ | otherwise = D.text $ scmPrefixed "let"
335+ printBinding (Tuple b e) = printBrackets $ D.words [ D.text b, printChezExpr e ]
336+
337+ case NEA.uncons bindings' of
338+ { head, tail: [] } ->
339+ D.lines
340+ [ D.text "(" <> D.words [ singleLetKeyword, printList $ printBinding head ]
341+ , D.indent $ printChezExpr expr <> D.text ")"
342+ ]
343+ { head, tail } ->
344+ D.lines
345+ [ D.text "(" <> multiLetKeyword
346+ , D.indent $ D.lines
347+ [ D.text "(" <> printBinding head
348+ , (D.lines $ map (append D.space <<< printBinding) tail) <> D.text ")"
349+ , D.indent $ printChezExpr expr <> D.text ")"
350+ ]
351+ ]
352+
353+printLambda :: Array String -> ChezExpr -> Doc Void
354+printLambda args expr =
355+ printNamedIndentedList
356+ (D.words [ D.text $ scmPrefixed "lambda", printList $ D.words $ map D.text args ])
357+ $ printChezExpr expr
358+
359+printCond :: NonEmptyArray (Tuple ChezExpr ChezExpr) -> ChezExpr -> Doc Void
360+printCond branches fallback = do
361+ let
362+ b' :: Array (Doc Void)
363+ b' = NonEmptyArray.toArray branches <#> \(Tuple cond expr) ->
364+ printBrackets $ D.words [ printChezExpr cond, printChezExpr expr ]
365+
366+ o' :: Doc Void
367+ o' = printBrackets $ D.words [ D.text $ scmPrefixed "else", printChezExpr fallback ]
368+
369+ printNamedIndentedList (D.text $ scmPrefixed "cond")
370+ $ D.lines
371+ $ Array.snoc b' o'
src/PureScript/Backend/Chez/Runtime.pursdeleted−69
@@ -1,69 +0,0 @@
1−module PureScript.Backend.Chez.Runtime (runtimeModule) where
2−
3−import Prelude
4−
5−import Control.Monad.State (runState)
6−import Control.Monad.State.Class (class MonadState, modify_)
7−import Data.Array as Array
8−import Data.Array.NonEmpty as NEA
9−import Data.Maybe (Maybe(..))
10−import Data.Traversable (sequence)
11−import Data.Tuple (Tuple(..))
12−import PureScript.Backend.Chez.Constants (libChezSchemePrefix, scmPrefixed)
13−import PureScript.Backend.Chez.Syntax (ChezDefinition(..), ChezExport(..), ChezExpr, ChezImport(..), ChezImportSet(..), ChezLibrary)
14−import PureScript.Backend.Chez.Syntax as S
15−
16−makeExportedFunction
17− :: forall m
18− . Monad m
19− => MonadState (Array ChezExport) m
20− => String
21− -> Array String
22− -> ChezExpr
23− -> m ChezDefinition
24−makeExportedFunction name args expr = do
25− modify_ $ Array.cons $ ExportIdentifier name
26− pure $ DefineUncurriedFunction name args expr
27−
28−makeBooleanComparison
29− :: forall m. Monad m => MonadState (Array ChezExport) m => String -> m ChezDefinition
30−makeBooleanComparison suffix =
31− makeExportedFunction ("boolean" <> suffix) [ "x", "y" ] $
32− S.List
33− [ S.Identifier $ scmPrefixed "fx" <> suffix
34− , S.List [ S.Identifier "boolean->integer", S.Identifier "x" ]
35− , S.List [ S.Identifier "boolean->integer", S.Identifier "y" ]
36− ]
37−
38−runtimeModule :: ChezLibrary
39−runtimeModule = do
40− let
41− Tuple definitions exports = flip runState [] $ sequence
42− [ pure $ DefineUncurriedFunction "boolean->integer" [ "x" ] $ S.List
43− [ S.Identifier $ scmPrefixed "if"
44− , S.Identifier "x"
45− , S.Integer $ S.LiteralDigit "1"
46− , S.Integer $ S.LiteralDigit "0"
47− ]
48− , makeBooleanComparison ">?"
49− , makeBooleanComparison ">=?"
50− , makeBooleanComparison "<=?"
51− , makeBooleanComparison "<?"
52− ]
53− { "#!chezscheme": true
54− , "#!r6rs": true
55− , name:
56− { identifiers: NEA.cons' "_Chez_Runtime" [ "lib" ]
57− , version: []
58− }
59− , exports
60− , imports:
61− [ ImportSet $ ImportPrefix
62− (ImportLibrary { identifiers: NEA.singleton "chezscheme", version: Nothing })
63− libChezSchemePrefix
64− ]
65− , body:
66− { definitions
67− , expressions: []
68− }
69− }
src/PureScript/Backend/Chez/Syntax.purs+92−386
@@ -2,38 +2,29 @@ module PureScript.Backend.Chez.Syntax where
22
33import Prelude
44
5−import Control.Alternative as Alternative
65import Data.Argonaut as Json
6+import Data.Array (foldr)
77import Data.Array as Array
88import Data.Array.NonEmpty (NonEmptyArray)
9−import Data.Array.NonEmpty as NEA
109import Data.Array.NonEmpty as NonEmptyArray
11−import Data.Maybe (Maybe(..), maybe)
12−import Data.Newtype (class Newtype, un)
13−import Data.String.Regex as R
14−import Data.String.Regex.Unsafe as R.Unsafe
15−import Data.String.Regex.Flags as R.Flags
16−import Dodo (Doc)
17−import Dodo as D
18−import Partial.Unsafe (unsafeCrashWith)
19−import Prim as Prim
20−import PureScript.Backend.Chez.Constants (libChezSchemePrefix, scmPrefixed)
21−import PureScript.Backend.Optimizer.CoreFn (Ident(..), ModuleName(..), Prop(..), Qualified(..))
22−import PureScript.Backend.Optimizer.Syntax (Level(..))
23−import Safe.Coerce (coerce)
10+import Data.Maybe (Maybe)
11+import Data.Newtype (class Newtype)
12+import Data.Tuple (Tuple)
13+import PureScript.Backend.Chez.Constants (rtPrefixed, scmPrefixed)
14+import PureScript.Backend.Optimizer.CoreFn (ModuleName, Prop(..))
2415
2516type ChezLibrary =
26− { "#!r6rs" :: Prim.Boolean
27− , "#!chezscheme" :: Prim.Boolean
17+ { "#!r6rs" :: Boolean
18+ , "#!chezscheme" :: Boolean
2819 , name :: LibraryName
29− , exports :: Prim.Array ChezExport
30− , imports :: Prim.Array ChezImport
20+ , exports :: Array ChezExport
21+ , imports :: Array ChezImport
3122 , body :: LibraryBody
3223 }
3324
3425type LibraryName =
35− { identifiers :: NonEmptyArray Prim.String
36− , version :: Prim.Array LibraryVersion
26+ { identifiers :: NonEmptyArray String
27+ , version :: Array LibraryVersion
3728 }
3829
3930newtype LibraryVersion = LibraryVersion Prim.Int
@@ -41,31 +32,31 @@ newtype LibraryVersion = LibraryVersion Prim.Int
4132derive instance Newtype LibraryVersion _
4233
4334data ChezExport
44− = ExportIdentifier Prim.String
45− | ExportRename (Prim.Array { original :: Prim.String, rename :: Prim.String })
35+ = ExportIdentifier String
36+ | ExportRename (Array { original :: String, rename :: String })
4637
4738type LibraryReference =
48− { identifiers :: NonEmptyArray Prim.String
39+ { identifiers :: NonEmptyArray String
4940 , version :: Maybe VersionReference
5041 }
5142
5243data VersionReference
5344 = VersionRef (NonEmptyArray SubVersionReference)
54− | VersionAnd (Prim.Array VersionReference)
55− | VersionOr (Prim.Array VersionReference)
45+ | VersionAnd (Array VersionReference)
46+ | VersionOr (Array VersionReference)
5647 | VersionNot VersionReference
5748
5849data SubVersionReference
5950 = SubVersionRef LibraryVersion
6051 | SubVersionGTE LibraryVersion
6152 | SubVersionLTE LibraryVersion
62− | SubVersionAnd (Prim.Array SubVersionReference)
63− | SubVersionOr (Prim.Array SubVersionReference)
53+ | SubVersionAnd (Array SubVersionReference)
54+ | SubVersionOr (Array SubVersionReference)
6455 | SubVersionNot SubVersionReference
6556
6657data ChezImport
6758 = ImportSet ChezImportSet
68− | ImportFor ChezImportSet (Prim.Array ChezImportLevel)
59+ | ImportFor ChezImportSet (Array ChezImportLevel)
6960
7061data ChezImportLevel
7162 = ImportLevelRun
@@ -74,23 +65,22 @@ data ChezImportLevel
7465
7566data ChezImportSet
7667 = ImportLibrary LibraryReference
77− | ImportOnly ChezImportSet (Prim.Array Prim.String)
78− | ImportExcept ChezImportSet (Prim.Array Prim.String)
79− | ImportPrefix ChezImportSet Prim.String
80− | ImportRename ChezImportSet (Prim.Array { original :: Prim.String, rename :: Prim.String })
68+ | ImportOnly ChezImportSet (Array String)
69+ | ImportExcept ChezImportSet (Array String)
70+ | ImportPrefix ChezImportSet String
71+ | ImportRename ChezImportSet (Array { original :: String, rename :: String })
8172
8273type LibraryBody =
83− { definitions :: Prim.Array ChezDefinition
84− , expressions :: Prim.Array ChezExpr
74+ { definitions :: Array ChezDefinition
75+ , expressions :: Array ChezExpr
8576 }
8677
8778data ChezDefinition
88− = DefineValue Prim.String ChezExpr
89− | DefineCurriedFunction Prim.String (NonEmptyArray Prim.String) ChezExpr
90− | DefineUncurriedFunction Prim.String (Prim.Array Prim.String) ChezExpr
91− | DefineRecordType Prim.String (Prim.Array Prim.String)
79+ = Define String ChezExpr
80+ | DefineRecordType String (Array String)
81+ | DefineLazy String ModuleName ChezExpr
9282
93−newtype LiteralDigit = LiteralDigit Prim.String
83+newtype LiteralDigit = LiteralDigit String
9484
9585derive instance Newtype LiteralDigit _
9686derive newtype instance Eq LiteralDigit
@@ -99,384 +89,100 @@ derive newtype instance Ord LiteralDigit
9989data ChezExpr
10090 = Integer LiteralDigit
10191 | Float LiteralDigit
102− | String Prim.String
103− | Boolean Prim.Boolean
104− | Identifier Prim.String
105− | List (Prim.Array ChezExpr)
106−
107−definitionIdentifiers :: ChezDefinition -> Prim.Array Prim.String
108−definitionIdentifiers (DefineValue i _) = [ i ]
109−definitionIdentifiers (DefineCurriedFunction i _ _) = [ i ]
110−definitionIdentifiers (DefineUncurriedFunction i _ _) = [ i ]
111−definitionIdentifiers (DefineRecordType i [ x ]) =
112− [ recordTypeCurriedConstructor i
113− , recordTypePredicate i
114− , recordTypeAccessor i x
115− ]
116−definitionIdentifiers (DefineRecordType i fields) =
117− [ recordTypeUncurriedConstructor i
118− , recordTypePredicate i
119− ] <> map (recordTypeAccessor i) fields
120−
121−resolve :: ModuleName -> Qualified Ident -> Prim.String
122−resolve _ (Qualified Nothing (Ident i)) = i
123−resolve currentModule (Qualified (Just m) (Ident i))
124− | currentModule == m = i
125− | otherwise = coerce m <> "." <> i
126−
127−printWrap :: Doc Void -> Doc Void -> Doc Void -> Doc Void
128−printWrap l r x = l <> x <> r
129−
130−printList :: Doc Void -> Doc Void
131−printList = printWrap (D.text "(") (D.text ")")
132−
133−printNamedList :: Prim.String -> Doc Void -> Doc Void
134−printNamedList name body
135− | D.isEmpty body =
136− printList $ D.text name
137− | otherwise =
138− printList $ D.words [ D.text name, body ]
139−
140−printIndentedList :: Doc Void -> Doc Void -> Doc Void
141−printIndentedList ident body
142− | D.isEmpty body =
143− printList ident
144− | otherwise =
145− D.lines
146− [ D.text "(" <> ident
147− , D.indent body <> D.text ")"
148− ]
149−
150−linesSeparated :: Prim.Array (Doc Void) -> Doc Void
151−linesSeparated = Array.intercalate twoLineBreaks
152− where
153− twoLineBreaks = D.break <> D.break
154−
155−printLibrary :: ChezLibrary -> Doc Void
156−printLibrary lib =
157− flip append D.break
158− $ D.lines
159− $ Array.catMaybes
160− [ D.text "#!r6rs" <$ Alternative.guard lib."#!r6rs"
161− , D.text "#!chezscheme" <$ Alternative.guard lib."#!chezscheme"
162− , Just $ printNamedIndentedList (D.text "library") $ D.lines
163− [ printLibraryName lib.name
164− , printIndentedList (D.text "export") $ D.lines $ map printExport lib.exports
165− , (printIndentedList (D.text "import") $ D.lines $ map printImport lib.imports)
166− <> D.break
167− , printBody lib.body
168− ]
169− ]
170−
171−printLibraryName :: LibraryName -> Doc Void
172−printLibraryName { identifiers, version } =
173− printList $ D.words
174− [ D.words $ map D.text identifiers
175− , case version of
176− [] -> mempty
177− _ -> printList $ D.words $ map printLibraryVersion version
178− ]
179−
180−printLibraryVersion :: LibraryVersion -> Doc Void
181−printLibraryVersion = D.text <<< show <<< un LibraryVersion
182−
183−printExport :: ChezExport -> Doc Void
184−printExport = case _ of
185− ExportIdentifier s -> D.text s
186− ExportRename arr ->
187− printNamedList "rename"
188− $ D.words
189− $ map (\r -> printList $ D.words [ D.text r.original, D.text r.rename ]) arr
190−
191−printImport :: ChezImport -> Doc Void
192−printImport = case _ of
193− ImportSet is -> printImportSet is
194− ImportFor is lvls ->
195− printNamedList "for" $ D.words
196− [ printImportSet is
197− , D.words $ map printImportLevel lvls
198− ]
199−
200−printImportLevel :: ChezImportLevel -> Doc Void
201−printImportLevel = case _ of
202− ImportLevelRun -> D.text "run"
203− ImportLevelExpand -> D.text "expand"
204− ImportLevelMeta level -> printNamedList "meta" $ D.text $ show level
205−
206−printImportSet :: ChezImportSet -> Doc Void
207−printImportSet = case _ of
208− ImportLibrary libRef ->
209− printLibraryReference libRef
210− ImportOnly impSet identifiers ->
211− printNamedList "only" $ D.words
212− [ printImportSet impSet, D.words $ map D.text identifiers ]
213− ImportExcept impSet identifiers ->
214− printNamedList "except" $ D.words
215− [ printImportSet impSet, D.words $ map D.text identifiers ]
216− ImportPrefix impSet rename ->
217− printNamedList "prefix" $ D.words [ printImportSet impSet, D.text rename ]
218− ImportRename impSet identifiers ->
219− printNamedList "rename" $ D.words
220− [ printImportSet impSet
221− , D.words $ map (\r -> printList $ D.words $ map D.text [ r.original, r.rename ])
222− identifiers
223− ]
224−
225−printLibraryReference :: LibraryReference -> Doc Void
226−printLibraryReference lib = do
227− let
228− printListFn
229− | Array.elem (NEA.head lib.identifiers)
230− [ "for", "library", "only", "except", "prefix", "rename" ] =
231− printNamedList "library"
232− | otherwise =
233− printList
234− printListFn $ D.words
235− [ D.words $ map D.text lib.identifiers
236− , maybe mempty printVersionReference lib.version
237− ]
238−
239−printVersionReference :: VersionReference -> Doc Void
240−printVersionReference = case _ of
241− VersionRef ref ->
242− printList $ D.words $ map printSubVersionReference ref
243− VersionAnd ref ->
244− printNamedList "and" $ D.words $ map printVersionReference ref
245− VersionOr ref ->
246− printNamedList "or" $ D.words $ map printVersionReference ref
247− VersionNot ref ->
248− printNamedList "not" $ printVersionReference ref
249−
250−printSubVersionReference :: SubVersionReference -> Doc Void
251−printSubVersionReference = case _ of
252− SubVersionRef ref -> printList $ printLibraryVersion ref
253− SubVersionGTE ref -> printNamedList ">=" $ printLibraryVersion ref
254− SubVersionLTE ref -> printNamedList "<=" $ printLibraryVersion ref
255− SubVersionAnd ref -> printNamedList "and" $ D.words
256− $ map printSubVersionReference ref
257− SubVersionOr ref -> printNamedList "or" $ D.words
258− $ map printSubVersionReference ref
259− SubVersionNot ref -> printNamedList "not" $ printSubVersionReference ref
260−
261−printBody :: LibraryBody -> Doc Void
262−printBody lib = do
263− let
264− defs = map printDefinition lib.definitions
265− exprs = map printChezExpr lib.expressions
266− linesSeparated $ defs <> exprs
267−
268−printNamedIndentedList :: Doc Void -> Doc Void -> Doc Void
269−printNamedIndentedList firstLine body
270− | D.isEmpty body =
271− printList firstLine
272− | otherwise =
273− D.lines
274− [ D.text "(" <> firstLine
275− , D.indent $ body <> D.text ")"
276− ]
277−
278−printDefinition :: ChezDefinition -> Doc Void
279−printDefinition = case _ of
280− DefineValue ident expr ->
281− printNamedIndentedList (D.words [ D.text $ scmPrefixed "define", D.text ident ])
282− $ printChezExpr expr
283− DefineCurriedFunction ident args expr ->
284− printNamedIndentedList (D.text (scmPrefixed "define ") <> D.text ident)
285− $ printCurriedAbs (NEA.toArray args) expr
286− DefineUncurriedFunction ident args expr ->
287− printNamedIndentedList (D.text (scmPrefixed "define ") <> D.text ident)
288− $ printNamedIndentedList
289− (D.text (scmPrefixed "lambda ") <> printList (D.words $ map D.text args))
290− (printChezExpr expr)
291− DefineRecordType ident [ field ] ->
292− printRecordDefinition
293− ident
294− (recordTypeName ident)
295− (recordTypeCurriedConstructor ident)
296− (recordTypePredicate ident)
297− [ field ]
298− DefineRecordType ident fields ->
299− printRecordDefinition
300− ident
301− (recordTypeName ident)
302− (recordTypeUncurriedConstructor ident)
303− (recordTypePredicate ident)
304− fields
305−
306−printCurriedAbs :: Prim.Array Prim.String -> ChezExpr -> Doc Void
307−printCurriedAbs args body = Array.foldr foldFn (printChezExpr body) args
308− where
309− foldFn next bodyOrRest =
310− printNamedIndentedList
311− (D.words [ D.text $ scmPrefixed "lambda", printList (D.text next) ])
312− bodyOrRest
313−
314−printChezExpr :: forall a. ChezExpr -> Doc a
315−printChezExpr e = case e of
316− Integer (LiteralDigit x) -> D.text x
317− Float (LiteralDigit x) -> D.text x
318− String x -> D.text x
319− Boolean x -> D.text $ if x then "#t" else "#f"
320− Identifier x -> D.text x
321− List xs -> D.text "(" <> D.words (printChezExpr <$> xs) <> D.text ")"
322−
323−printRecordDefinition
324− :: Prim.String
325− -> Prim.String
326− -> Prim.String
327− -> Prim.String
328− -> Prim.Array Prim.String
329− -> Doc Void
330−printRecordDefinition ident name constructor predicate fields =
331− printNamedIndentedList defineForm fieldsForm
332− where
333− defineForm :: Doc Void
334− defineForm = D.words
335− [ D.text $ scmPrefixed "define-record-type"
336− , printList $ D.words $ map D.text [ name, constructor, predicate ]
337− ]
338−
339− fieldForm :: Prim.String -> Doc Void
340− fieldForm field = printList $ D.words
341− $ map D.text [ scmPrefixed "immutable", field, recordTypeAccessor ident field ]
342−
343− fieldsForm :: Doc Void
344− fieldsForm = printList $ D.words $ Array.cons (D.text $ scmPrefixed "fields")
345− $ map fieldForm fields
346−
347−toChezIdent :: Maybe Ident -> Level -> Prim.String
348−toChezIdent i (Level l) = case i of
349− Just (Ident i') -> case i' of
350− "$__unused" -> "_"
351− _ -> i' <> show l
352− Nothing -> "_" <> show l
353−
354−jsonToChezString :: Prim.String -> Prim.String
355−jsonToChezString str = unicodeReplace str
356− where
357− unicodeRegex :: R.Regex
358− unicodeRegex = R.Unsafe.unsafeRegex """\\u([A-F\d]{4})""" R.Flags.global
359−
360− unicodeReplace :: Prim.String -> Prim.String
361− unicodeReplace s = R.replace' unicodeRegex unicodeReplaceMatch s
362−
363− unicodeReplaceMatch
364− :: Prim.String
365− -> Prim.Array (Maybe Prim.String)
366− -> Prim.String
367− unicodeReplaceMatch _ = case _ of
368− [ (Just x) ] -> "\\x" <> x <> ";"
369− _ -> unsafeCrashWith "Error matching at unicodeReplaceMatch in jsonToChezString"
92+ | Char String
93+ | StringExpr String
94+ | Bool Boolean
95+ | Identifier String
96+ | List (Array ChezExpr)
97+ | Cond (NonEmptyArray (Tuple ChezExpr ChezExpr)) ChezExpr
98+ | Let Boolean (NonEmptyArray (Tuple String ChezExpr)) ChezExpr
99+ | Lambda (Array String) ChezExpr
370100
371101--
372102
373−chezCond :: NonEmptyArray { c :: ChezExpr, e :: ChezExpr } -> Maybe ChezExpr -> ChezExpr
374−chezCond b o =
375− let
376− b' :: Prim.Array ChezExpr
377− b' = NonEmptyArray.toArray b <#> \{ c, e } -> List [ c, e ]
378−
379− o' :: Prim.Array ChezExpr
380− o' = Array.fromFoldable o <#> \x -> List [ Identifier $ scmPrefixed "else", x ]
381− in
382− List $ [ Identifier $ scmPrefixed "cond" ] <> b' <> o'
103+runUncurriedFn :: ChezExpr -> Array ChezExpr -> ChezExpr
104+runUncurriedFn f s = List $ Array.cons f s
383105
384−chezUncurriedApplication :: ChezExpr -> Prim.Array ChezExpr -> ChezExpr
385−chezUncurriedApplication f args = List $ Array.cons f args
106+mkUncurriedFn :: Array String -> ChezExpr -> ChezExpr
107+mkUncurriedFn a e = Lambda a e
386108
387−chezCurriedApplication :: ChezExpr -> NonEmptyArray ChezExpr -> ChezExpr
388−chezCurriedApplication f s = NonEmptyArray.foldl1 app $ NonEmptyArray.cons f s
109+runCurriedFn :: ChezExpr -> NonEmptyArray ChezExpr -> ChezExpr
110+runCurriedFn f s = NonEmptyArray.foldl1 app $ NonEmptyArray.cons f s
389111
390−chezCurriedFunction :: NonEmptyArray Prim.String -> ChezExpr -> ChezExpr
391−chezCurriedFunction a e = Array.foldr lambda e $ NonEmptyArray.toArray a
112+mkCurriedFn :: NonEmptyArray String -> ChezExpr -> ChezExpr
113+mkCurriedFn a e = Array.foldr (Lambda <<< Array.singleton) e $ NonEmptyArray.toArray a
392114
393−chezThunk :: ChezExpr -> ChezExpr
394−chezThunk e = List [ Identifier $ scmPrefixed "lambda", List [], e ]
115+thunk :: ChezExpr -> ChezExpr
116+thunk e = Lambda [] e
395117
396−chezUnthunk :: ChezExpr -> ChezExpr
397−chezUnthunk e = List [ e ]
118+unthunk :: ChezExpr -> ChezExpr
119+unthunk e = List [ e ]
398120
399121--
400122
401123app :: ChezExpr -> ChezExpr -> ChezExpr
402124app f x = List [ f, x ]
403125
404−define :: Ident -> ChezExpr -> ChezExpr
405−define i e = List [ Identifier $ scmPrefixed "define", Identifier $ coerce i, e ]
406−
407−library :: ModuleName -> Prim.Array Ident -> Prim.Array ChezExpr -> ChezExpr
408−library moduleName exports bindings =
409− List $
410− [ Identifier "library"
411− , Identifier $ "(" <> coerce moduleName <> " lib" <> ")"
412− , List $
413− [ Identifier "export"
414− ] <> (Identifier <$> coerce exports)
415− , List
416− [ Identifier "import"
417− , List
418− [ Identifier "prefix"
419− , List
420− [ Identifier "chezscheme"
421− ]
422− , Identifier libChezSchemePrefix
423− ]
424− ]
425− ] <> bindings
126+recordLabel :: String -> ChezExpr
127+recordLabel key = List
128+ [ Identifier $ scmPrefixed "string->symbol"
129+ , StringExpr key
130+ ]
426131
427−record :: Prim.Array (Prop ChezExpr) -> ChezExpr
428−record r =
132+record :: Array (Prop ChezExpr) -> ChezExpr
133+record r = do
429134 let
430135 field :: Prop ChezExpr -> ChezExpr
431− field (Prop k v) =
432− List
433− [ Identifier $ scmPrefixed "hashtable-set!"
434− , Identifier "$record"
435− , String $ Json.stringify $ Json.fromString k
436− , v
437− ]
438− in
439− List $
440− [ Identifier $ scmPrefixed "letrec*"
441− , List
442− [ List
443− [ Identifier "$record"
444− , List
445− [ Identifier $ scmPrefixed "make-hashtable"
446− , Identifier $ scmPrefixed "string-hash"
447− , Identifier $ scmPrefixed "string=?"
448− ]
449− ]
450− ]
451− ] <> (field <$> r) <> [ Identifier "$record" ]
136+ field (Prop k v) = List
137+ [ Identifier $ scmPrefixed "cons"
138+ , recordLabel k
139+ , v
140+ ]
141+ List $ [ Identifier $ scmPrefixed "list" ] <> (field <$> r)
452142
453143quote :: ChezExpr -> ChezExpr
454144quote e = app (Identifier $ scmPrefixed "quote") e
455145
456146eqQ :: ChezExpr -> ChezExpr -> ChezExpr
457−eqQ x y = chezUncurriedApplication (Identifier $ scmPrefixed "eq?") [ x, y ]
458−
459−lambda :: Prim.String -> ChezExpr -> ChezExpr
460−lambda a e = List [ Identifier $ scmPrefixed "lambda", List [ Identifier a ], e ]
147+eqQ x y = runUncurriedFn (Identifier $ scmPrefixed "eq?") [ x, y ]
461148
462−vector :: Prim.Array ChezExpr -> ChezExpr
463−vector = List <<< Array.cons (Identifier $ scmPrefixed "vector")
149+vector :: Array ChezExpr -> ChezExpr
150+vector = List <<< Array.cons (Identifier $ rtPrefixed "make-array")
464151
465−recordTypeName :: Prim.String -> Prim.String
152+recordTypeName :: String -> String
466153recordTypeName i = i <> "$"
467154
468−recordTypeCurriedConstructor :: Prim.String -> Prim.String
155+recordTypeCurriedConstructor :: String -> String
469156recordTypeCurriedConstructor i = i
470157
471−recordTypeUncurriedConstructor :: Prim.String -> Prim.String
158+recordTypeUncurriedConstructor :: String -> String
472159recordTypeUncurriedConstructor i = i <> "*"
473160
474−recordTypePredicate :: Prim.String -> Prim.String
161+recordTypePredicate :: String -> String
475162recordTypePredicate i = i <> "?"
476163
477−recordTypeAccessor :: Prim.String -> Prim.String -> Prim.String
164+recordTypeAccessor :: String -> String -> String
478165recordTypeAccessor i field = i <> "-" <> field
479166
480−recordAccessor :: ChezExpr -> Prim.String -> Prim.String -> ChezExpr
167+recordAccessor :: ChezExpr -> String -> String -> ChezExpr
481168recordAccessor expr name field =
482− chezUncurriedApplication (Identifier $ recordTypeAccessor name field) [ expr ]
169+ runUncurriedFn (Identifier $ recordTypeAccessor name field) [ expr ]
170+
171+recordUpdate :: ChezExpr -> Array (Prop ChezExpr) -> ChezExpr
172+recordUpdate h f = do
173+ let
174+ field :: Prop ChezExpr -> ChezExpr -> ChezExpr
175+ field (Prop k v) rest =
176+ List
177+ [ Identifier $ scmPrefixed "cons"
178+ , List [ Identifier $ scmPrefixed "cons", recordLabel k, v ]
179+ , rest
180+ ]
181+ foldr field h f
182+
183+forceLazyRef :: String -> ChezExpr
184+forceLazyRef i = List [ Identifier $ lazyRefName i ]
185+
186+lazyRefName :: String -> String
187+lazyRefName i = "$lazy-" <> i
188+
test-runtime.jsnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env node
2+
3+import { spawnSync } from 'child_process';
4+let env = process.env;
5+env['DYLD_LIBRARY_PATH'] = env['CHEZ_DYLD_LIBRARY_PATH'];
6+spawnSync('scheme', ["--libdirs", "lib:", "--program", "test-runtime.ss"], { env, stdio: 'inherit' });
test-runtime.ssnew file+12
@@ -0,0 +1,12 @@
1+(import (chezscheme)
2+ (only (purescm finalizers) run-finalizers)
3+ (only (purescm stack-trace) print-stack-trace)
4+ (only (purescm test pstring-test) main)
5+ (rename (purescm test bytevector-test) (main bytevector-main)))
6+(collect-request-handler (lambda () (collect) (run-finalizers)))
7+(base-exception-handler (lambda (e) (print-stack-trace e) (exit -1)))
8+(display "Testing pstring\n")
9+(main)
10+(display "\nTesting bytevector\n")
11+(bytevector-main)
12+(display "All good!\n")
test-snapshots/.gitignorenew file+1
@@ -0,0 +1 @@
1+.spago
test-snapshots/spago.locknew file+922
@@ -0,0 +1,922 @@
1+{
2+ "workspace": {
3+ "packages": {
4+ "purescm-snapshots": {
5+ "path": "./",
6+ "core": {
7+ "dependencies": [
8+ "arrays",
9+ "assert",
10+ "bifunctors",
11+ "catenable-lists",
12+ "console",
13+ "const",
14+ "contravariant",
15+ "control",
16+ "distributive",
17+ "effect",
18+ "either",
19+ "enums",
20+ "exceptions",
21+ "exists",
22+ "filterable",
23+ "foldable-traversable",
24+ "free",
25+ "functions",
26+ "functors",
27+ "gen",
28+ "identity",
29+ "integers",
30+ "invariant",
31+ "lazy",
32+ "lists",
33+ "maybe",
34+ "minibench",
35+ "newtype",
36+ "nonempty",
37+ "numbers",
38+ "ordered-collections",
39+ "orders",
40+ "parallel",
41+ "partial",
42+ "prelude",
43+ "profunctor",
44+ "record",
45+ "refs",
46+ "safe-coerce",
47+ "semirings",
48+ "st",
49+ "strings",
50+ "tailrec",
51+ "transformers",
52+ "tuples",
53+ "type-equality",
54+ "unfoldable",
55+ "unsafe-coerce",
56+ "validation"
57+ ],
58+ "build_plan": [
59+ "arrays",
60+ "assert",
61+ "bifunctors",
62+ "catenable-lists",
63+ "console",
64+ "const",
65+ "contravariant",
66+ "control",
67+ "distributive",
68+ "effect",
69+ "either",
70+ "enums",
71+ "exceptions",
72+ "exists",
73+ "filterable",
74+ "foldable-traversable",
75+ "free",
76+ "functions",
77+ "functors",
78+ "gen",
79+ "identity",
80+ "integers",
81+ "invariant",
82+ "lazy",
83+ "lists",
84+ "maybe",
85+ "minibench",
86+ "newtype",
87+ "nonempty",
88+ "numbers",
89+ "ordered-collections",
90+ "orders",
91+ "parallel",
92+ "partial",
93+ "prelude",
94+ "profunctor",
95+ "record",
96+ "refs",
97+ "safe-coerce",
98+ "semirings",
99+ "st",
100+ "strings",
101+ "tailrec",
102+ "transformers",
103+ "tuples",
104+ "type-equality",
105+ "unfoldable",
106+ "unsafe-coerce",
107+ "validation"
108+ ]
109+ },
110+ "test": {
111+ "dependencies": [],
112+ "build_plan": []
113+ }
114+ }
115+ },
116+ "package_set": {
117+ "address": {
118+ "path": "../package-sets/1.0.0.json"
119+ },
120+ "compiler": ">=0.15.10 <0.16.0",
121+ "content": {
122+ "arrays": {
123+ "git": "https://github.com/purescm/purescript-core.git",
124+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
125+ "subdir": "arrays"
126+ },
127+ "assert": {
128+ "git": "https://github.com/purescm/purescript-core.git",
129+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
130+ "subdir": "assert"
131+ },
132+ "bifunctors": "6.0.0",
133+ "catenable-lists": "7.0.0",
134+ "console": {
135+ "git": "https://github.com/purescm/purescript-core.git",
136+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
137+ "subdir": "console"
138+ },
139+ "const": "6.0.0",
140+ "contravariant": "6.0.0",
141+ "control": {
142+ "git": "https://github.com/purescm/purescript-core.git",
143+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
144+ "subdir": "control"
145+ },
146+ "datetime": {
147+ "git": "https://github.com/purescm/purescript-core.git",
148+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
149+ "subdir": "datetime"
150+ },
151+ "distributive": "6.0.0",
152+ "effect": {
153+ "git": "https://github.com/purescm/purescript-core.git",
154+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
155+ "subdir": "effect"
156+ },
157+ "either": "6.1.0",
158+ "enums": {
159+ "git": "https://github.com/purescm/purescript-core.git",
160+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
161+ "subdir": "enums"
162+ },
163+ "exceptions": {
164+ "git": "https://github.com/purescm/purescript-core.git",
165+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
166+ "subdir": "exceptions"
167+ },
168+ "exists": "6.0.0",
169+ "filterable": "5.0.0",
170+ "foldable-traversable": {
171+ "git": "https://github.com/purescm/purescript-core.git",
172+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
173+ "subdir": "foldable-traversable"
174+ },
175+ "foreign-object": {
176+ "git": "https://github.com/purescm/purescript-core.git",
177+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
178+ "subdir": "foreign-object"
179+ },
180+ "free": "7.1.0",
181+ "functions": {
182+ "git": "https://github.com/purescm/purescript-core.git",
183+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
184+ "subdir": "functions",
185+ "dependencies": [
186+ "prelude"
187+ ]
188+ },
189+ "functors": "5.0.0",
190+ "gen": "4.0.0",
191+ "identity": "6.0.0",
192+ "integers": {
193+ "git": "https://github.com/purescm/purescript-core.git",
194+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
195+ "subdir": "integers"
196+ },
197+ "invariant": "6.0.0",
198+ "json": {
199+ "git": "https://github.com/purescm/purescript-core.git",
200+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
201+ "subdir": "json"
202+ },
203+ "lazy": {
204+ "git": "https://github.com/purescm/purescript-core.git",
205+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
206+ "subdir": "lazy"
207+ },
208+ "lcg": "4.0.0",
209+ "lists": {
210+ "git": "https://github.com/purescm/purescript-lists.git",
211+ "ref": "71502a132567cf7f32c2242d57b1cba2c77ebc15"
212+ },
213+ "maybe": "6.0.0",
214+ "minibench": {
215+ "git": "https://github.com/purescm/purescript-core.git",
216+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
217+ "subdir": "minibench"
218+ },
219+ "newtype": "5.0.0",
220+ "nonempty": "7.0.0",
221+ "numbers": {
222+ "git": "https://github.com/purescm/purescript-core.git",
223+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
224+ "subdir": "numbers"
225+ },
226+ "ordered-collections": "3.1.1",
227+ "orders": "6.0.0",
228+ "parallel": "7.0.0",
229+ "partial": {
230+ "git": "https://github.com/purescm/purescript-core.git",
231+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
232+ "subdir": "partial",
233+ "dependencies": []
234+ },
235+ "prelude": {
236+ "git": "https://github.com/purescm/purescript-core.git",
237+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
238+ "subdir": "prelude"
239+ },
240+ "profunctor": "6.0.0",
241+ "quickcheck": {
242+ "git": "https://github.com/purescm/purescript-core.git",
243+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
244+ "subdir": "quickcheck"
245+ },
246+ "random": {
247+ "git": "https://github.com/purescm/purescript-core.git",
248+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
249+ "subdir": "random"
250+ },
251+ "record": {
252+ "git": "https://github.com/purescm/purescript-core.git",
253+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
254+ "subdir": "record"
255+ },
256+ "refs": {
257+ "git": "https://github.com/purescm/purescript-core.git",
258+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
259+ "subdir": "refs"
260+ },
261+ "safe-coerce": "2.0.0",
262+ "semirings": "7.0.0",
263+ "st": {
264+ "git": "https://github.com/purescm/purescript-core.git",
265+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
266+ "subdir": "st"
267+ },
268+ "strings": {
269+ "git": "https://github.com/purescm/purescript-core.git",
270+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
271+ "subdir": "strings"
272+ },
273+ "tailrec": "6.1.0",
274+ "transformers": "6.0.0",
275+ "tuples": "7.0.0",
276+ "type-equality": "4.0.1",
277+ "typelevel-prelude": "7.0.0",
278+ "unfoldable": {
279+ "git": "https://github.com/purescm/purescript-core.git",
280+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
281+ "subdir": "unfoldable"
282+ },
283+ "unsafe-coerce": {
284+ "git": "https://github.com/purescm/purescript-core.git",
285+ "ref": "b5474536977275bda9b1771e06e5f697e0a846d9",
286+ "subdir": "unsafe-coerce",
287+ "dependencies": []
288+ },
289+ "validation": "6.0.0"
290+ }
291+ },
292+ "extra_packages": {}
293+ },
294+ "packages": {
295+ "arrays": {
296+ "type": "git",
297+ "url": "https://github.com/purescm/purescript-core.git",
298+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
299+ "subdir": "arrays",
300+ "dependencies": [
301+ "bifunctors",
302+ "control",
303+ "foldable-traversable",
304+ "functions",
305+ "maybe",
306+ "nonempty",
307+ "partial",
308+ "prelude",
309+ "safe-coerce",
310+ "st",
311+ "tailrec",
312+ "tuples",
313+ "unfoldable",
314+ "unsafe-coerce"
315+ ]
316+ },
317+ "assert": {
318+ "type": "git",
319+ "url": "https://github.com/purescm/purescript-core.git",
320+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
321+ "subdir": "assert",
322+ "dependencies": [
323+ "console",
324+ "effect",
325+ "prelude"
326+ ]
327+ },
328+ "bifunctors": {
329+ "type": "registry",
330+ "version": "6.0.0",
331+ "integrity": "sha256-tXhmlMiyVy6mbUreVZQt/2EGEsPr0T1PjJi+YCG5J7E=",
332+ "dependencies": [
333+ "const",
334+ "either",
335+ "newtype",
336+ "prelude",
337+ "tuples"
338+ ]
339+ },
340+ "catenable-lists": {
341+ "type": "registry",
342+ "version": "7.0.0",
343+ "integrity": "sha256-7+i/MHBLIRh604iCNT4ENWRWE/wuHIotER4kpdX9Ve0=",
344+ "dependencies": [
345+ "control",
346+ "foldable-traversable",
347+ "lists",
348+ "maybe",
349+ "prelude",
350+ "tuples",
351+ "unfoldable"
352+ ]
353+ },
354+ "console": {
355+ "type": "git",
356+ "url": "https://github.com/purescm/purescript-core.git",
357+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
358+ "subdir": "console",
359+ "dependencies": [
360+ "effect",
361+ "prelude"
362+ ]
363+ },
364+ "const": {
365+ "type": "registry",
366+ "version": "6.0.0",
367+ "integrity": "sha256-S+m0lQsxnji0z1XRUmkn+3RFuWJ5CXWuIr1u3i8Bfoc=",
368+ "dependencies": [
369+ "invariant",
370+ "newtype",
371+ "prelude"
372+ ]
373+ },
374+ "contravariant": {
375+ "type": "registry",
376+ "version": "6.0.0",
377+ "integrity": "sha256-nuckEWqL80NaPmR/l9AUyrfycNh18XcvlZV9PAamwqc=",
378+ "dependencies": [
379+ "const",
380+ "either",
381+ "newtype",
382+ "prelude",
383+ "tuples"
384+ ]
385+ },
386+ "control": {
387+ "type": "git",
388+ "url": "https://github.com/purescm/purescript-core.git",
389+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
390+ "subdir": "control",
391+ "dependencies": [
392+ "newtype",
393+ "prelude"
394+ ]
395+ },
396+ "distributive": {
397+ "type": "registry",
398+ "version": "6.0.0",
399+ "integrity": "sha256-netyJK4B32PDYHD0tF2AenKgo3urzbI770ycM0pArAo=",
400+ "dependencies": [
401+ "identity",
402+ "newtype",
403+ "prelude",
404+ "tuples",
405+ "type-equality"
406+ ]
407+ },
408+ "effect": {
409+ "type": "git",
410+ "url": "https://github.com/purescm/purescript-core.git",
411+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
412+ "subdir": "effect",
413+ "dependencies": [
414+ "prelude"
415+ ]
416+ },
417+ "either": {
418+ "type": "registry",
419+ "version": "6.1.0",
420+ "integrity": "sha256-tBHx3PgtH4GZOApZCDkcM7szRTYJinrUrVGWazQCUUg=",
421+ "dependencies": [
422+ "control",
423+ "invariant",
424+ "maybe",
425+ "prelude"
426+ ]
427+ },
428+ "enums": {
429+ "type": "git",
430+ "url": "https://github.com/purescm/purescript-core.git",
431+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
432+ "subdir": "enums",
433+ "dependencies": [
434+ "control",
435+ "either",
436+ "gen",
437+ "maybe",
438+ "newtype",
439+ "nonempty",
440+ "partial",
441+ "prelude",
442+ "tuples",
443+ "unfoldable"
444+ ]
445+ },
446+ "exceptions": {
447+ "type": "git",
448+ "url": "https://github.com/purescm/purescript-core.git",
449+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
450+ "subdir": "exceptions",
451+ "dependencies": [
452+ "effect",
453+ "either",
454+ "maybe",
455+ "prelude"
456+ ]
457+ },
458+ "exists": {
459+ "type": "registry",
460+ "version": "6.0.0",
461+ "integrity": "sha256-vtLbrWNaI+pzx/2fw2AQnCovoLtcosClIhjO26QKkh8=",
462+ "dependencies": [
463+ "unsafe-coerce"
464+ ]
465+ },
466+ "filterable": {
467+ "type": "registry",
468+ "version": "5.0.0",
469+ "integrity": "sha256-be7ci1Bzwud2waqoCtNGsTBZbt7fi+gCLvGddQQRJ3A=",
470+ "dependencies": [
471+ "arrays",
472+ "either",
473+ "foldable-traversable",
474+ "identity",
475+ "lists",
476+ "ordered-collections"
477+ ]
478+ },
479+ "foldable-traversable": {
480+ "type": "git",
481+ "url": "https://github.com/purescm/purescript-core.git",
482+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
483+ "subdir": "foldable-traversable",
484+ "dependencies": [
485+ "bifunctors",
486+ "const",
487+ "control",
488+ "either",
489+ "functors",
490+ "identity",
491+ "maybe",
492+ "newtype",
493+ "orders",
494+ "prelude",
495+ "tuples"
496+ ]
497+ },
498+ "free": {
499+ "type": "registry",
500+ "version": "7.1.0",
501+ "integrity": "sha256-tUBInfUpRQEw4u94GWcYW7EYdmSdDHSRn88a+C0eltU=",
502+ "dependencies": [
503+ "catenable-lists",
504+ "control",
505+ "distributive",
506+ "either",
507+ "exists",
508+ "foldable-traversable",
509+ "invariant",
510+ "lazy",
511+ "maybe",
512+ "prelude",
513+ "tailrec",
514+ "transformers",
515+ "tuples",
516+ "unsafe-coerce"
517+ ]
518+ },
519+ "functions": {
520+ "type": "git",
521+ "url": "https://github.com/purescm/purescript-core.git",
522+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
523+ "subdir": "functions",
524+ "dependencies": [
525+ "prelude"
526+ ]
527+ },
528+ "functors": {
529+ "type": "registry",
530+ "version": "5.0.0",
531+ "integrity": "sha256-W1o/4wcp6S3chodYL8uixlXK2mfr1L+SzM1R+whqUco=",
532+ "dependencies": [
533+ "bifunctors",
534+ "const",
535+ "contravariant",
536+ "control",
537+ "distributive",
538+ "either",
539+ "invariant",
540+ "maybe",
541+ "newtype",
542+ "prelude",
543+ "profunctor",
544+ "tuples",
545+ "unsafe-coerce"
546+ ]
547+ },
548+ "gen": {
549+ "type": "registry",
550+ "version": "4.0.0",
551+ "integrity": "sha256-kyOateeOtQa07vfTMYeSuCKdelgKE1R65fwKkZ10wsY=",
552+ "dependencies": [
553+ "either",
554+ "foldable-traversable",
555+ "identity",
556+ "maybe",
557+ "newtype",
558+ "nonempty",
559+ "prelude",
560+ "tailrec",
561+ "tuples",
562+ "unfoldable"
563+ ]
564+ },
565+ "identity": {
566+ "type": "registry",
567+ "version": "6.0.0",
568+ "integrity": "sha256-RY/iXPpxpqvKHYfJeFVNI1J06kohB9rbtWYuha8t0LE=",
569+ "dependencies": [
570+ "control",
571+ "invariant",
572+ "newtype",
573+ "prelude"
574+ ]
575+ },
576+ "integers": {
577+ "type": "git",
578+ "url": "https://github.com/purescm/purescript-core.git",
579+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
580+ "subdir": "integers",
581+ "dependencies": [
582+ "maybe",
583+ "numbers",
584+ "prelude"
585+ ]
586+ },
587+ "invariant": {
588+ "type": "registry",
589+ "version": "6.0.0",
590+ "integrity": "sha256-HyoT1I5qIHRq8RSZji6zZDvqnpVjLw748utrKwZtqsw=",
591+ "dependencies": [
592+ "control",
593+ "prelude"
594+ ]
595+ },
596+ "lazy": {
597+ "type": "git",
598+ "url": "https://github.com/purescm/purescript-core.git",
599+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
600+ "subdir": "lazy",
601+ "dependencies": [
602+ "control",
603+ "foldable-traversable",
604+ "invariant",
605+ "prelude"
606+ ]
607+ },
608+ "lists": {
609+ "type": "git",
610+ "url": "https://github.com/purescm/purescript-lists.git",
611+ "rev": "71502a132567cf7f32c2242d57b1cba2c77ebc15",
612+ "dependencies": [
613+ "bifunctors",
614+ "control",
615+ "foldable-traversable",
616+ "lazy",
617+ "maybe",
618+ "newtype",
619+ "nonempty",
620+ "partial",
621+ "prelude",
622+ "tailrec",
623+ "tuples",
624+ "unfoldable"
625+ ]
626+ },
627+ "maybe": {
628+ "type": "registry",
629+ "version": "6.0.0",
630+ "integrity": "sha256-8X6XEgtZ5lqfkEuc1hWOofnL6mwhk8gSJTxwvbR/SbY=",
631+ "dependencies": [
632+ "control",
633+ "invariant",
634+ "newtype",
635+ "prelude"
636+ ]
637+ },
638+ "minibench": {
639+ "type": "git",
640+ "url": "https://github.com/purescm/purescript-core.git",
641+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
642+ "subdir": "minibench",
643+ "dependencies": [
644+ "console",
645+ "effect",
646+ "integers",
647+ "numbers",
648+ "prelude",
649+ "refs"
650+ ]
651+ },
652+ "newtype": {
653+ "type": "registry",
654+ "version": "5.0.0",
655+ "integrity": "sha256-dt6w0cty4OS+Pjt9fsh3iU6ottqSU83mdAZkaEEvo6c=",
656+ "dependencies": [
657+ "prelude",
658+ "safe-coerce"
659+ ]
660+ },
661+ "nonempty": {
662+ "type": "registry",
663+ "version": "7.0.0",
664+ "integrity": "sha256-Ctkq8/+KiGqCE53Y/LvibA/coy7ev9HtRZU+GYS7yfQ=",
665+ "dependencies": [
666+ "control",
667+ "foldable-traversable",
668+ "maybe",
669+ "prelude",
670+ "tuples",
671+ "unfoldable"
672+ ]
673+ },
674+ "numbers": {
675+ "type": "git",
676+ "url": "https://github.com/purescm/purescript-core.git",
677+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
678+ "subdir": "numbers",
679+ "dependencies": [
680+ "functions",
681+ "maybe",
682+ "prelude"
683+ ]
684+ },
685+ "ordered-collections": {
686+ "type": "registry",
687+ "version": "3.1.1",
688+ "integrity": "sha256-gr9Eqg4/XcJylARhTyxb0w9yqzS3tgloqyg57Q6SHug=",
689+ "dependencies": [
690+ "arrays",
691+ "foldable-traversable",
692+ "gen",
693+ "lists",
694+ "maybe",
695+ "partial",
696+ "prelude",
697+ "st",
698+ "tailrec",
699+ "tuples",
700+ "unfoldable"
701+ ]
702+ },
703+ "orders": {
704+ "type": "registry",
705+ "version": "6.0.0",
706+ "integrity": "sha256-nSMxZK7wxyDULkjZqvMyB71mVo6b0AyLLHosDVbv1XM=",
707+ "dependencies": [
708+ "newtype",
709+ "prelude"
710+ ]
711+ },
712+ "parallel": {
713+ "type": "registry",
714+ "version": "7.0.0",
715+ "integrity": "sha256-bAGpVhrFz2IyHkA4MR7+tE/19FZ7dzYBdYPgK5svkqw=",
716+ "dependencies": [
717+ "control",
718+ "effect",
719+ "either",
720+ "foldable-traversable",
721+ "functors",
722+ "maybe",
723+ "newtype",
724+ "prelude",
725+ "profunctor",
726+ "refs",
727+ "transformers"
728+ ]
729+ },
730+ "partial": {
731+ "type": "git",
732+ "url": "https://github.com/purescm/purescript-core.git",
733+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
734+ "subdir": "partial",
735+ "dependencies": []
736+ },
737+ "prelude": {
738+ "type": "git",
739+ "url": "https://github.com/purescm/purescript-core.git",
740+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
741+ "subdir": "prelude",
742+ "dependencies": []
743+ },
744+ "profunctor": {
745+ "type": "registry",
746+ "version": "6.0.0",
747+ "integrity": "sha256-f1L0opNYQcjRpbmjgkSA2AlbaiSEfsu60mW3j/hcs2U=",
748+ "dependencies": [
749+ "control",
750+ "distributive",
751+ "either",
752+ "exists",
753+ "invariant",
754+ "newtype",
755+ "prelude",
756+ "tuples"
757+ ]
758+ },
759+ "record": {
760+ "type": "git",
761+ "url": "https://github.com/purescm/purescript-core.git",
762+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
763+ "subdir": "record",
764+ "dependencies": [
765+ "functions",
766+ "prelude",
767+ "unsafe-coerce"
768+ ]
769+ },
770+ "refs": {
771+ "type": "git",
772+ "url": "https://github.com/purescm/purescript-core.git",
773+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
774+ "subdir": "refs",
775+ "dependencies": [
776+ "effect",
777+ "prelude"
778+ ]
779+ },
780+ "safe-coerce": {
781+ "type": "registry",
782+ "version": "2.0.0",
783+ "integrity": "sha256-EJrxtKt5xC7TYjBZrSBO/J7Aw3DmtilYjt4olpAXWVc=",
784+ "dependencies": [
785+ "unsafe-coerce"
786+ ]
787+ },
788+ "semirings": {
789+ "type": "registry",
790+ "version": "7.0.0",
791+ "integrity": "sha256-wjcUvWi+KK4pktI1PAJKjPFTBPeSeIZniTi30VlYtSs=",
792+ "dependencies": [
793+ "foldable-traversable",
794+ "lists",
795+ "newtype",
796+ "prelude"
797+ ]
798+ },
799+ "st": {
800+ "type": "git",
801+ "url": "https://github.com/purescm/purescript-core.git",
802+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
803+ "subdir": "st",
804+ "dependencies": [
805+ "effect",
806+ "partial",
807+ "prelude",
808+ "tailrec",
809+ "unsafe-coerce"
810+ ]
811+ },
812+ "strings": {
813+ "type": "git",
814+ "url": "https://github.com/purescm/purescript-core.git",
815+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
816+ "subdir": "strings",
817+ "dependencies": [
818+ "arrays",
819+ "control",
820+ "either",
821+ "enums",
822+ "foldable-traversable",
823+ "gen",
824+ "integers",
825+ "maybe",
826+ "newtype",
827+ "nonempty",
828+ "partial",
829+ "prelude",
830+ "tailrec",
831+ "tuples",
832+ "unfoldable",
833+ "unsafe-coerce"
834+ ]
835+ },
836+ "tailrec": {
837+ "type": "registry",
838+ "version": "6.1.0",
839+ "integrity": "sha256-xrorCfP0xV1wubs27idQCHQqdvSUuqmmL/am7Ji1wVU=",
840+ "dependencies": [
841+ "bifunctors",
842+ "effect",
843+ "either",
844+ "identity",
845+ "maybe",
846+ "partial",
847+ "prelude",
848+ "refs"
849+ ]
850+ },
851+ "transformers": {
852+ "type": "registry",
853+ "version": "6.0.0",
854+ "integrity": "sha256-Nl3yXAIeeTzP6MyrkazkK7pbgeVqUm+ynLv7U5cpJYQ=",
855+ "dependencies": [
856+ "control",
857+ "distributive",
858+ "effect",
859+ "either",
860+ "exceptions",
861+ "foldable-traversable",
862+ "identity",
863+ "lazy",
864+ "maybe",
865+ "newtype",
866+ "prelude",
867+ "tailrec",
868+ "tuples",
869+ "unfoldable"
870+ ]
871+ },
872+ "tuples": {
873+ "type": "registry",
874+ "version": "7.0.0",
875+ "integrity": "sha256-BKy7EfK8S1KeTCwyWqyW1wwcpSAQuh3IsczSVgS6fzY=",
876+ "dependencies": [
877+ "control",
878+ "invariant",
879+ "prelude"
880+ ]
881+ },
882+ "type-equality": {
883+ "type": "registry",
884+ "version": "4.0.1",
885+ "integrity": "sha256-BBqYOSnAKmayRvR5mtZoCf4SlYs2ipatD/+5nQx73aw=",
886+ "dependencies": []
887+ },
888+ "unfoldable": {
889+ "type": "git",
890+ "url": "https://github.com/purescm/purescript-core.git",
891+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
892+ "subdir": "unfoldable",
893+ "dependencies": [
894+ "foldable-traversable",
895+ "maybe",
896+ "partial",
897+ "prelude",
898+ "tuples"
899+ ]
900+ },
901+ "unsafe-coerce": {
902+ "type": "git",
903+ "url": "https://github.com/purescm/purescript-core.git",
904+ "rev": "b5474536977275bda9b1771e06e5f697e0a846d9",
905+ "subdir": "unsafe-coerce",
906+ "dependencies": []
907+ },
908+ "validation": {
909+ "type": "registry",
910+ "version": "6.0.0",
911+ "integrity": "sha256-wavSVs3zeQmO3iXJJlhyQuDOh6w3ngO3gwWqcwekG/U=",
912+ "dependencies": [
913+ "bifunctors",
914+ "control",
915+ "either",
916+ "foldable-traversable",
917+ "newtype",
918+ "prelude"
919+ ]
920+ }
921+ }
922+}
test-snapshots/spago.yaml+51−21
@@ -1,29 +1,59 @@
11package:
22 name: purescm-snapshots
33 dependencies:
4+ - arrays
5+ - assert
6+ - bifunctors
7+ - catenable-lists
8+ - console
9+ - const
10+ - contravariant
11+ - control
12+ - distributive
413 - effect
14+ - either
15+ - enums
16+ - exceptions
17+ - exists
18+ - filterable
19+ - foldable-traversable
20+ - free
521 - functions
22+ - functors
23+ - gen
24+ - identity
25+ - integers
26+ - invariant
27+ - lazy
28+ - lists
29+ - maybe
30+ - minibench
31+ - newtype
32+ - nonempty
33+ - numbers
34+ - ordered-collections
35+ - orders
36+ - parallel
637 - partial
738 - prelude
39+ - profunctor
40+ - record
41+ - refs
42+ - safe-coerce
43+ - semirings
44+ - st
45+ - strings
46+ - tailrec
47+ - transformers
48+ - tuples
49+ - type-equality
50+ - unfoldable
51+ - unsafe-coerce
52+ - validation
853workspace:
9− package_set:
10− registry: 19.1.0
11− extra_packages:
12− prelude:
13− git: https://github.com/purescm/purescript-prelude.git
14− ref: 63ff5a24beba191c8fda919a58489f36bde2d506
15− dependencies: []
16− partial:
17− git: https://github.com/purescm/purescript-partial.git
18− ref: d8b6daf068e4aab0ad85a42d0f890ed37f416923
19− dependencies: []
20− functions:
21− git: https://github.com/purescm/purescript-functions.git
22− ref: a43d127384ab568575fb9ee9e4a7a1844b21d39b
23− dependencies:
24− - prelude
25− effect:
26− git: https://github.com/purescm/purescript-effect.git
27− ref: 8aee2c2fbf5425bf8fa4537a5ad2070170622acf
28− dependencies:
29− - prelude
54+ backend:
55+ cmd: ../index.dev.js
56+ args:
57+ - build
58+ packageSet:
59+ path: ../package-sets/1.0.0.json
test-snapshots/src/snapshots-input/Snapshot.Constructor.purs+9
@@ -5,3 +5,12 @@ data Maybe a = Just a | Nothing
55data Tree a
66 = Nil
77 | Node (Tree a) a (Tree a)
8+
9+-- recursive constructors
10+data Mutual1
11+ = Stop1
12+ | Continue1 Mutual2
13+
14+data Mutual2
15+ = Stop2
16+ | Continue2 Mutual1
test-snapshots/src/snapshots-input/Snapshot.ConstructorAccessor.purs+16−7
@@ -21,14 +21,23 @@ test1 :: NoArgs -> Boolean
2121test1 = case _ of
2222 NoArgs -> true
2323
24−data HasArgs = HasArgs Int Int Int
24+data OneArg = OneArg Int
25+
26+one :: OneArg
27+one = OneArg 1
2528
26−test2 :: HasArgs -> Int
29+test2 :: OneArg -> Int
2730test2 = case _ of
28− HasArgs i1 _ _ -> i1
31+ OneArg i -> i
32+
33+data HasArgs = HasArgs Int Int Int
2934
3035test3 :: HasArgs -> Int
3136test3 = case _ of
37+ HasArgs i1 _ _ -> i1
38+
39+test4 :: HasArgs -> Int
40+test4 = case _ of
3241 HasArgs i1 i2 i3
3342 | i1 < i3 -> i1
3443 | otherwise -> i2
@@ -37,11 +46,11 @@ data SumWithArgs
3746 = First Int
3847 | Last Int
3948
40−test4 :: SumWithArgs -> Int
41−test4 = case _ of
49+test5 :: SumWithArgs -> Int
50+test5 = case _ of
4251 First i -> i
4352 Last i -> i
4453
45−test5 :: Partial => SumWithArgs -> Int
46−test5 = case _ of
54+test6 :: Partial => SumWithArgs -> Int
55+test6 = case _ of
4756 First i -> i
test-snapshots/src/snapshots-input/Snapshot.Effect.purs+13−5
@@ -8,11 +8,19 @@ import Effect (Effect)
88dontInlineMe :: forall a. a -> Effect Unit
99dontInlineMe _ = pure unit
1010
11−main :: Effect Unit
12−main = do
11+lastComponentIsRun :: Effect Unit
12+lastComponentIsRun = do
1313 dontInlineMe "a"
1414 dontInlineMe "b"
15− value <- dontInlineMe "c"
16− dontInlineMe "d"
17− dontInlineMe "e"
15+ dontInlineMe "c"
16+
17+lastPureIsUnwrapped :: Effect Unit
18+lastPureIsUnwrapped = do
19+ value <- dontInlineMe "a"
20+ dontInlineMe "b"
1821 pure value
22+
23+main :: Effect Unit
24+main = do
25+ lastComponentIsRun
26+ lastPureIsUnwrapped
test-snapshots/src/snapshots-input/Snapshot.EffectRef.pursnew file+53
@@ -0,0 +1,53 @@
1+-- @inline Snapshot.EffectRef.onLet never
2+module Snapshot.EffectRef where
3+
4+import Prelude
5+
6+import Effect (Effect)
7+import Effect.Ref (Ref, modify, modify_, new, read)
8+import Effect.Class.Console (log)
9+import Test.Assert (assert)
10+
11+positionZero :: Effect (Ref Int)
12+positionZero = new 0
13+
14+onLet :: Int -> Effect (Ref Int)
15+onLet x =
16+ let
17+ a = x + x
18+ b = a + x
19+ in
20+ new $ a + b
21+
22+basicTest :: Effect Unit
23+basicTest = do
24+ n <- new 0
25+ modify_ (_ + 1) n
26+ v <- read n
27+ assert $ v == 1
28+
29+onLetTest :: Effect Unit
30+onLetTest = do
31+ n <- onLet 1
32+ v <- read n
33+ assert $ v == 5
34+
35+primEffectAtTheEnd :: Effect Int
36+primEffectAtTheEnd = do
37+ n <- new 1
38+ read n
39+
40+newCase :: Effect Unit
41+newCase = do
42+ counter <- new 0
43+ newCounter <- modify (_ + 1) counter
44+ log $ "New counter is " <> show newCounter
45+ assert $ newCounter == 1
46+
47+main :: Effect Unit
48+main = do
49+ basicTest
50+ onLetTest
51+ newCase
52+ _ <- primEffectAtTheEnd
53+ pure unit
test-snapshots/src/snapshots-input/Snapshot.Failing.RecursiveBindingGroupLet.pursnew file+23
@@ -0,0 +1,23 @@
1+module Snapshot.Failing.RecursiveBindingGroupLet where
2+
3+import Prelude
4+import Effect (Effect)
5+
6+test :: Int
7+test = test1.bar
8+ where
9+ test1 =
10+ { foo: (\_ -> test2.baz) unit
11+ , bar: (\_ -> test3 42) unit
12+ }
13+
14+ test2 =
15+ { baz: (\_ -> test1.bar) unit
16+ }
17+
18+ test3 n
19+ | n < 100 = n
20+ | otherwise = test1.bar
21+
22+main :: Effect Unit
23+main = pure unit
test-snapshots/src/snapshots-input/Snapshot.Failing.RecursiveBindingGroupTopLevel.pursnew file+23
@@ -0,0 +1,23 @@
1+module Snapshot.Failing.RecursiveBindingGroupTopLevel where
2+
3+import Prelude
4+import Effect (Effect)
5+
6+test1 :: { bar :: Int, foo :: Int }
7+test1 =
8+ { foo: (\_ -> test2.baz) unit
9+ , bar: (\_ -> test3 42) unit
10+ }
11+
12+test2 :: { baz :: Int }
13+test2 =
14+ { baz: (\_ -> test1.bar) unit
15+ }
16+
17+test3 :: Int -> Int
18+test3 n
19+ | n < 100 = n
20+ | otherwise = test1.bar
21+
22+main :: Effect Unit
23+main = pure unit
test-snapshots/src/snapshots-input/Snapshot.Import.Constructor.pursnew file+3
@@ -0,0 +1,3 @@
1+module Snapshot.Import.Constructor where
2+
3+data Foo = Foo
test-snapshots/src/snapshots-input/Snapshot.Import.Impl.purs+2
@@ -4,3 +4,5 @@ foreign import addImpl :: Int -> Int -> Int
44
55fortyTwo :: Int
66fortyTwo = addImpl 21 21
7+
8+data Product = Product Int Int
test-snapshots/src/snapshots-input/Snapshot.Import.Product.pursnew file+3
@@ -0,0 +1,3 @@
1+module Snapshot.Import.Product where
2+
3+data Product = Product Int Int
test-snapshots/src/snapshots-input/Snapshot.Import.purs+8
@@ -1,6 +1,14 @@
11module Snapshot.Import where
22
33import Snapshot.Import.Impl as I
4+import Snapshot.Import.Product
5+import Snapshot.Import.Constructor
46
57fortyThree :: Int
68fortyThree = I.addImpl 21 22
9+
10+fst :: Product -> Int
11+fst (Product x _) = x
12+
13+foo :: Foo
14+foo = Foo
test-snapshots/src/snapshots-input/Snapshot.Let.purs+16
@@ -11,3 +11,19 @@ letChain x =
1111 d = c * c
1212 in
1313 a + b + c + d
14+
15+letRecursive :: Int -> Int
16+letRecursive x = go x
17+ where
18+ go 0 = 0
19+ go x' = go (x' - 1)
20+
21+isEven :: Int -> Boolean
22+isEven x
23+ | x == 0 = true
24+ | otherwise = isOdd (x - 1)
25+
26+isOdd :: Int -> Boolean
27+isOdd x
28+ | x == 1 = false
29+ | otherwise = isEven (x - 1)
test-snapshots/src/snapshots-input/Snapshot.List.pursnew file+34
@@ -0,0 +1,34 @@
1+module Snapshot.List where
2+
3+import Prelude
4+
5+import Data.List (List(..), (:))
6+import Data.Maybe (Maybe(..))
7+import Effect (Effect)
8+import Test.Assert (assert)
9+
10+xs :: List Int
11+xs = Cons 1 Nil
12+
13+curried :: Int -> List Int -> List Int
14+curried = Cons
15+
16+cons2 :: List Int -> List Int
17+cons2 = Cons 2
18+
19+car :: List Int -> Maybe Int
20+car Nil = Nothing
21+car (Cons x _) = Just x
22+
23+cdr :: List Int -> Maybe (List Int)
24+cdr Nil = Nothing
25+cdr (Cons _ xs') = Just xs'
26+
27+main :: Effect Unit
28+main = do
29+ let l = 1 : 2 : Nil
30+ assert $ car l == Just 1
31+ assert $ cdr l == Just (2 : Nil)
32+ assert $ curried 1 Nil == 1 : Nil
33+ assert $ cons2 (3 : Nil) == 2 : 3 : Nil
34+ assert $ show l == "(1 : 2 : Nil)"
test-snapshots/src/snapshots-input/Snapshot.Literals.Char.pursnew file+33
@@ -0,0 +1,33 @@
1+module Snapshot.Literals.Char where
2+
3+null = '\x0000' :: Char
4+alarm = '\x0007' :: Char
5+backspace = '\x0008' :: Char
6+tab = '\x0009' :: Char
7+newline = '\x000A' :: Char
8+vtab = '\x000B' :: Char
9+page = '\x000C' :: Char
10+return = '\x00D' :: Char
11+escape = '\x001B' :: Char
12+space = ' ' :: Char
13+delete = '\x007F' :: Char
14+ls = '\x2028' :: Char
15+
16+firstPrintableChar = '!' :: Char
17+
18+singleQuote = '\'' :: Char
19+doubleQuote = '\"' :: Char
20+
21+lastPrintableChar = '~' :: Char -- \x007E
22+
23+latin1Supplement = '±' :: Char -- \x00B1
24+
25+latinExtendedA = 'ā' :: Char -- \x0101
26+
27+latinExtendedB = 'ƀ' :: Char -- \x0180
28+
29+forallChar = '∀' :: Char -- \x2200
30+
31+closeToTop = '︙' :: Char -- \xFE19'
32+
33+biggestChar = '\xFFFF' :: Char
test-snapshots/src/snapshots-input/Snapshot.Literals.Number.pursnew file+12
@@ -0,0 +1,12 @@
1+module Snapshot.Literals.Number where
2+
3+import Prelude
4+
5+nan :: Number
6+nan = 0.0 / 0.0
7+
8+plusInfinity :: Number
9+plusInfinity = 1.0 / 0.0
10+
11+minusInfinity :: Number
12+minusInfinity = -1.0 / 0.0
test-snapshots/src/snapshots-input/Snapshot.Literals.Record.pursnew file+41
@@ -0,0 +1,41 @@
1+-- @inline Snapshot.Literals.Record.recordAccess never
2+-- @inline Snapshot.Literals.Record.recordUpdate never
3+-- @inline Snapshot.Literals.Record.recordAddField never
4+module Snapshot.Literals.Record where
5+
6+import Prelude
7+
8+import Effect (Effect)
9+import Prim.Row (class Lacks)
10+import Record as Record
11+import Test.Assert (assert, assertThrows)
12+import Type.Proxy (Proxy(..))
13+
14+recordAccess :: forall a r. { fooBarBaz :: a | r } -> a
15+recordAccess = _.fooBarBaz
16+
17+recordUpdate :: forall r. { fooBarBaz :: Int | r } -> { fooBarBaz :: Int | r }
18+recordUpdate = _ { fooBarBaz = 10 }
19+
20+recordAddField :: forall r. Lacks "anotherField" r => { fooBarBaz :: Int | r } -> { fooBarBaz :: Int, anotherField :: Int | r }
21+recordAddField = Record.insert (Proxy :: _ "anotherField") 42
22+
23+foreign import minusTwo :: Int
24+
25+foreign import data Foreign :: Type
26+
27+foreign import unsafeGetNotFound :: forall r. Record r -> Foreign
28+
29+main :: Effect Unit
30+main = do
31+ let r = { fooBarBaz: 5 }
32+ let s = recordUpdate r
33+ let t = recordAddField s
34+ let u = { fooBarBaz: minusTwo }
35+
36+ assert $ recordAccess t == 10
37+ assert $ t.anotherField == 42
38+ assert $ recordAccess s == 10
39+ assert $ recordAccess r == 5
40+ assert $ recordAccess u == minusTwo
41+ assertThrows $ \_ -> unsafeGetNotFound u
test-snapshots/src/snapshots-input/Snapshot.Literals.Record.ssnew file+13
@@ -0,0 +1,13 @@
1+(library (Snapshot.Literals.Record foreign)
2+ (export minusTwo unsafeGetNotFound)
3+ (import (chezscheme)
4+ (prefix (purescm runtime) rt:))
5+
6+ (define minusTwo -2)
7+
8+ (define unsafeGetNotFound
9+ (lambda (r)
10+ (rt:record-ref r 'not-found)))
11+
12+
13+ )
test-snapshots/src/snapshots-input/Snapshot.PrimUndefined.pursnew file+15
@@ -0,0 +1,15 @@
1+-- @inline Snapshot.PrimUndefined.testCase never
2+module Snapshot.PrimUndefined where
3+
4+import Prelude
5+
6+import Effect (Effect)
7+import Test.Assert (assert)
8+
9+-- One place where PrimUndefined appears is to get the instance dictionary
10+-- for a superclass, which is hidden behind a `(lambda (_) ..)` abstraction
11+testCase :: forall a. Ring a => a -> a -> a
12+testCase x y = x + y
13+
14+main :: Effect Unit
15+main = assert $ testCase 1 1 == 2
test-snapshots/src/snapshots-input/Snapshot.Prime.pursnew file+76
@@ -0,0 +1,76 @@
1+module Snapshot.Prime where
2+
3+import Data.Semigroup ((<>))
4+
5+foo :: String
6+foo = "foo"
7+
8+-- declarations ending in prime shouldn't cause issues
9+foo' :: String
10+foo' = "foo'"
11+
12+-- declarations ending in prime shouldn't cause issues
13+foo'' :: String
14+foo'' = "foo'"
15+
16+foo'oo :: String
17+foo'oo = "foo'oo"
18+
19+data DataType' = DCtor
20+
21+data DataCtor = Ctor' String Int
22+
23+newtype NewtypeType' = NCtor Int
24+
25+newtype NewtypeCtor = NewtypeCtor' Int
26+
27+class ClassName' a where
28+ ignore :: a -> String
29+
30+class ClassMember a where
31+ classMember' :: a -> String
32+
33+data Foo
34+ = F1
35+ | F2
36+
37+class Normal a where
38+ normal :: a -> String
39+
40+instance instanceName' :: Normal Foo where
41+ normal = case _ of
42+ F1 -> "F1"
43+ F2 -> "F2"
44+
45+useFooPrime1 :: String
46+useFooPrime1 = foo'
47+
48+useFooPrime2 :: String
49+useFooPrime2 = foo''
50+
51+useFooPrime3 :: String
52+useFooPrime3 = foo'oo
53+
54+useDataType :: String -> DataType'
55+useDataType _ = DCtor
56+
57+useDataCtor :: String -> DataCtor
58+useDataCtor s = Ctor' s 4
59+
60+useNewtypeType :: Int -> NewtypeType'
61+useNewtypeType i = NCtor i
62+
63+useNewtypeCtor :: Int -> NewtypeCtor
64+useNewtypeCtor i = NewtypeCtor' i
65+
66+useClass :: forall a. ClassName' a => a -> String
67+useClass x = ignore x
68+
69+useMember :: forall a. ClassMember a => a -> String
70+useMember x = classMember' x
71+
72+useNormal :: forall a b. Normal a => Normal b => a -> b -> String
73+useNormal a b = normal a <> normal b
74+
75+useInstance :: String
76+useInstance = useNormal F1 F2
test-snapshots/src/snapshots-input/Snapshot.RecursiveDefinition.pursnew file+26
@@ -0,0 +1,26 @@
1+-- This example is from <https://github.com/purescript/purescript/blob/0527e71725257bf16a3c7bd5fce608e856a77dae/tests/purs/optimize/4179.purs>
2+module Snapshot.RecursiveDefinition where
3+
4+import Prelude
5+import Effect (Effect)
6+
7+alpha :: Int -> Int -> Number
8+alpha = case _ of
9+ 0 -> bravo
10+ 1 -> charlie
11+ 2 -> \y -> if y > 0 then bravo y else charlie y
12+ x -> \y -> delta y x
13+
14+bravo :: Int -> Number
15+bravo = (\_ -> alpha) {} 3
16+
17+charlie :: Int -> Number
18+charlie = (\_ -> alpha) {} 4
19+
20+delta :: Int -> Int -> Number
21+delta =
22+ let b = (\_ -> bravo) {}
23+ in \x y -> if x == y then b 0 else 1.0
24+
25+main :: Effect Unit
26+main = pure unit
test-snapshots/src/snapshots-input/Snapshot.UncurriedFunction.purs+36−2
@@ -1,15 +1,49 @@
1+-- @inline Snapshot.UncurriedFunction.pure' never
12module Snapshot.UncurriedFunction where
23
3−import Data.Function.Uncurried (mkFn0, mkFn2, runFn0, runFn2)
4+import Prelude
45
6+import Data.Function.Uncurried (Fn0, Fn2, mkFn0, mkFn2, runFn0, runFn2)
7+import Data.Unit (Unit)
8+import Effect (Effect)
9+import Effect.Console (log)
10+import Effect.Uncurried (EffectFn1, mkEffectFn1, runEffectFn1)
11+import Test.Assert (assert)
12+
13+test1a :: Fn0 Int
514test1a = mkFn0 \_ -> 1
615
7−test1b = runFn0
16+test1b :: Int
17+test1b = runFn0 test1a
818
19+test2a :: forall a b. Fn2 a b a
920test2a = mkFn2 \a _ -> a
1021
22+test2b :: Int
1123test2b = runFn2 test2a 1 2
1224
25+test3a :: forall a b. Fn2 a b b
1326test3a = mkFn2 \_ b -> b
1427
28+test3b :: Int
1529test3b = runFn2 test3a 1 2
30+
31+test4a :: EffectFn1 String String
32+test4a = mkEffectFn1 $ \a -> do
33+ log a
34+ pure a
35+
36+test4b :: Effect String
37+test4b = runEffectFn1 test4a "test4b"
38+
39+main :: Effect Unit
40+main = do
41+ assert $ test1b == 1
42+ assert $ test2b == 1
43+ assert $ test3b == 2
44+
45+ v <- test4b
46+ assert $ v == "test4b"
47+
48+ w <- runEffectFn1 test4a "test4b"
49+ assert $ w == "test4b"
test-snapshots/src/snapshots-output/Snapshot.ArrayIndex.ss+4−2
@@ -6,8 +6,10 @@
66 testAccessorGetIndex)
77 (import
88 (prefix (chezscheme) scm:)
9− (prefix (_Chez_Runtime lib) rt:))
9+ (prefix (purescm runtime) rt:))
1010
1111 (scm:define testAccessorGetIndex
1212 (scm:lambda (v0)
13− (scm:cond ((scm:fx=? (scm:vector-length v0) 1) (scm:vector-ref v0 0)) (scm:else 0)))))
13+ (scm:cond
14+ [(scm:fx=? (rt:array-length v0) 1) (rt:array-ref v0 0)]
15+ [scm:else 0]))))
test-snapshots/src/snapshots-output/Snapshot.Branch.ss+21−5
@@ -9,23 +9,39 @@
99 i)
1010 (import
1111 (prefix (chezscheme) scm:)
12− (prefix (_Chez_Runtime lib) rt:))
12+ (prefix (purescm runtime) rt:))
1313
1414 (scm:define i
1515 (scm:lambda (v0)
1616 (scm:lambda (v11)
17− (scm:cond (v0 (scm:not v11)) ((scm:not v11) #t) (v11 #f) (scm:else (scm:raise (scm:condition (scm:make-error) (scm:make-message-condition "Failed pattern match"))))))))
17+ (scm:cond
18+ [v0 (scm:not v11)]
19+ [(scm:not v11) #t]
20+ [v11 #f]
21+ [scm:else (rt:fail)]))))
1822
1923 (scm:define h
2024 (scm:lambda (v0)
21− (scm:cond ((scm:fl=? v0 3.14) 3.14159) (scm:else (scm:raise (scm:condition (scm:make-error) (scm:make-message-condition "Failed pattern match")))))))
25+ (scm:cond
26+ [(scm:fl=? v0 3.14) 3.14159]
27+ [scm:else (rt:fail)])))
2228
2329 (scm:define g
2430 (scm:lambda (v0)
25− (scm:cond ((scm:fx=? v0 0) 1) ((scm:fx=? v0 1) 2) ((scm:fx=? v0 2) 3) (scm:else 0))))
31+ (scm:cond
32+ [(scm:fx=? v0 0) 1]
33+ [(scm:fx=? v0 1) 2]
34+ [(scm:fx=? v0 2) 3]
35+ [scm:else 0])))
2636
2737 (scm:define f
2838 (scm:lambda (x0)
2939 (scm:lambda (y1)
3040 (scm:lambda (z2)
31− (scm:cond (x0 (scm:cond (y1 (scm:cond (z2 0) (scm:else 1))) (scm:else 2))) (scm:else 3)))))))
41+ (scm:cond
42+ [x0 (scm:cond
43+ [y1 (scm:cond
44+ [z2 0]
45+ [scm:else 1])]
46+ [scm:else 2])]
47+ [scm:else 3]))))))
test-snapshots/src/snapshots-output/Snapshot.Comparison.ss+6−6
@@ -10,29 +10,29 @@
1010 stringComparison)
1111 (import
1212 (prefix (chezscheme) scm:)
13− (prefix (_Chez_Runtime lib) rt:))
13+ (prefix (purescm runtime) rt:))
1414
1515 (scm:define stringComparison
1616 (scm:lambda (x0)
1717 (scm:lambda (y1)
18− (scm:vector (scm:string=? x0 y1) (scm:not (scm:string=? x0 y1)) (scm:string<? x0 y1) (scm:string<=? x0 y1) (scm:string>=? x0 y1) (scm:string>? x0 y1)))))
18+ (rt:make-array (rt:pstring=? x0 y1) (scm:not (rt:pstring=? x0 y1)) (rt:pstring<? x0 y1) (rt:pstring<=? x0 y1) (rt:pstring>=? x0 y1) (rt:pstring>? x0 y1)))))
1919
2020 (scm:define numberComparison
2121 (scm:lambda (x0)
2222 (scm:lambda (y1)
23− (scm:vector (scm:fl=? x0 y1) (scm:not (scm:fl=? x0 y1)) (scm:fl<? x0 y1) (scm:fl<=? x0 y1) (scm:fl>=? x0 y1) (scm:fl>? x0 y1)))))
23+ (rt:make-array (scm:fl=? x0 y1) (scm:not (scm:fl=? x0 y1)) (scm:fl<? x0 y1) (scm:fl<=? x0 y1) (scm:fl>=? x0 y1) (scm:fl>? x0 y1)))))
2424
2525 (scm:define integerComparison
2626 (scm:lambda (x0)
2727 (scm:lambda (y1)
28− (scm:vector (scm:fx=? x0 y1) (scm:not (scm:fx=? x0 y1)) (scm:fx<? x0 y1) (scm:fx<=? x0 y1) (scm:fx>=? x0 y1) (scm:fx>? x0 y1)))))
28+ (rt:make-array (scm:fx=? x0 y1) (scm:not (scm:fx=? x0 y1)) (scm:fx<? x0 y1) (scm:fx<=? x0 y1) (scm:fx>=? x0 y1) (scm:fx>? x0 y1)))))
2929
3030 (scm:define charComparison
3131 (scm:lambda (x0)
3232 (scm:lambda (y1)
33− (scm:vector (scm:char=? x0 y1) (scm:not (scm:char=? x0 y1)) (scm:char<? x0 y1) (scm:char<=? x0 y1) (scm:char>=? x0 y1) (scm:char>? x0 y1)))))
33+ (rt:make-array (scm:char=? x0 y1) (scm:not (scm:char=? x0 y1)) (scm:char<? x0 y1) (scm:char<=? x0 y1) (scm:char>=? x0 y1) (scm:char>? x0 y1)))))
3434
3535 (scm:define booleanComparison
3636 (scm:lambda (x0)
3737 (scm:lambda (y1)
38− (scm:vector (scm:boolean=? x0 y1) (scm:not (scm:boolean=? x0 y1)) (rt:boolean<? x0 y1) (rt:boolean<=? x0 y1) (rt:boolean>=? x0 y1) (rt:boolean>? x0 y1))))))
38+ (rt:make-array (scm:boolean=? x0 y1) (scm:not (scm:boolean=? x0 y1)) (rt:boolean<? x0 y1) (rt:boolean<=? x0 y1) (rt:boolean>=? x0 y1) (rt:boolean>? x0 y1))))))
test-snapshots/src/snapshots-output/Snapshot.Constructor.ss+32−2
@@ -3,6 +3,12 @@
33(library
44 (Snapshot.Constructor lib)
55 (export
6+ Continue1
7+ Continue1-value0
8+ Continue1?
9+ Continue2
10+ Continue2-value0
11+ Continue2?
612 Just
713 Just-value0
814 Just?
@@ -15,10 +21,14 @@
1521 Node-value2
1622 Node?
1723 Nothing
18− Nothing?)
24+ Nothing?
25+ Stop1
26+ Stop1?
27+ Stop2
28+ Stop2?)
1929 (import
2030 (prefix (chezscheme) scm:)
21− (prefix (_Chez_Runtime lib) rt:))
31+ (prefix (purescm runtime) rt:))
2232
2333 (scm:define Nil
2434 (scm:quote Nil))
@@ -36,6 +46,26 @@
3646 (scm:lambda (value2)
3747 (Node* value0 value1 value2)))))
3848
49+ (scm:define Stop1
50+ (scm:quote Stop1))
51+
52+ (scm:define Stop1?
53+ (scm:lambda (v)
54+ (scm:eq? (scm:quote Stop1) v)))
55+
56+ (scm:define-record-type (Continue1$ Continue1 Continue1?)
57+ (scm:fields (scm:immutable value0 Continue1-value0)))
58+
59+ (scm:define Stop2
60+ (scm:quote Stop2))
61+
62+ (scm:define Stop2?
63+ (scm:lambda (v)
64+ (scm:eq? (scm:quote Stop2) v)))
65+
66+ (scm:define-record-type (Continue2$ Continue2 Continue2?)
67+ (scm:fields (scm:immutable value0 Continue2-value0)))
68+
3969 (scm:define-record-type (Just$ Just Just?)
4070 (scm:fields (scm:immutable value0 Just-value0)))
4171
test-snapshots/src/snapshots-output/Snapshot.ConstructorAccessor.ss+29−7
@@ -23,17 +23,22 @@
2323 Last?
2424 NoArgs
2525 NoArgs?
26+ OneArg
27+ OneArg-value0
28+ OneArg?
29+ one
2630 test1
2731 test2
2832 test3
2933 test4
3034 test5
35+ test6
3136 x
3237 y
3338 z)
3439 (import
3540 (prefix (chezscheme) scm:)
36− (prefix (_Chez_Runtime lib) rt:))
41+ (prefix (purescm runtime) rt:))
3742
3843 (scm:define-record-type (First$ First First?)
3944 (scm:fields (scm:immutable value0 First-value0)))
@@ -41,6 +46,9 @@
4146 (scm:define-record-type (Last$ Last Last?)
4247 (scm:fields (scm:immutable value0 Last-value0)))
4348
49+ (scm:define-record-type (OneArg$ OneArg OneArg?)
50+ (scm:fields (scm:immutable value0 OneArg-value0)))
51+
4452 (scm:define NoArgs
4553 (scm:quote NoArgs))
4654
@@ -75,23 +83,37 @@
7583 (scm:define x
7684 (Foo 1))
7785
78− (scm:define test5
86+ (scm:define test6
7987 (scm:lambda (_)
8088 (scm:lambda (v1)
81− (scm:cond ((First? v1) (First-value0 v1)) (scm:else (scm:raise (scm:condition (scm:make-error) (scm:make-message-condition "Failed pattern match"))))))))
89+ (scm:cond
90+ [(First? v1) (First-value0 v1)]
91+ [scm:else (rt:fail)]))))
92+
93+ (scm:define test5
94+ (scm:lambda (v0)
95+ (scm:cond
96+ [(First? v0) (First-value0 v0)]
97+ [(Last? v0) (Last-value0 v0)]
98+ [scm:else (rt:fail)])))
8299
83100 (scm:define test4
84101 (scm:lambda (v0)
85− (scm:cond ((First? v0) (First-value0 v0)) ((Last? v0) (Last-value0 v0)) (scm:else (scm:raise (scm:condition (scm:make-error) (scm:make-message-condition "Failed pattern match")))))))
102+ (scm:cond
103+ [(scm:fx<? (HasArgs-value0 v0) (HasArgs-value2 v0)) (HasArgs-value0 v0)]
104+ [scm:else (HasArgs-value1 v0)])))
86105
87106 (scm:define test3
88107 (scm:lambda (v0)
89− (scm:cond ((scm:fx<? (HasArgs-value0 v0) (HasArgs-value2 v0)) (HasArgs-value0 v0)) (scm:else (HasArgs-value1 v0)))))
108+ (HasArgs-value0 v0)))
90109
91110 (scm:define test2
92111 (scm:lambda (v0)
93− (HasArgs-value0 v0)))
112+ (OneArg-value0 v0)))
94113
95114 (scm:define test1
96115 (scm:lambda (v0)
97− #t)))
116+ #t))
117+
118+ (scm:define one
119+ (OneArg 1)))
test-snapshots/src/snapshots-output/Snapshot.Effect.ss+24−3
@@ -4,15 +4,36 @@
44 (Snapshot.Effect lib)
55 (export
66 dontInlineMe
7+ lastComponentIsRun
8+ lastPureIsUnwrapped
79 main)
810 (import
911 (prefix (chezscheme) scm:)
10− (prefix (_Chez_Runtime lib) rt:)
12+ (prefix (purescm runtime) rt:)
1113 (prefix (Data.Unit lib) Data.Unit.))
1214
1315 (scm:define dontInlineMe
1416 (scm:lambda (v0)
15− (scm:lambda () Data.Unit.unit)))
17+ (scm:lambda ()
18+ Data.Unit.unit)))
19+
20+ (scm:define lastComponentIsRun
21+ (scm:let ([_0 (dontInlineMe (rt:string->pstring "a"))])
22+ (scm:lambda ()
23+ (scm:let*
24+ ([_ (_0)]
25+ [_ ((dontInlineMe (rt:string->pstring "b")))])
26+ ((dontInlineMe (rt:string->pstring "c")))))))
27+
28+ (scm:define lastPureIsUnwrapped
29+ (scm:let ([_0 (dontInlineMe (rt:string->pstring "a"))])
30+ (scm:lambda ()
31+ (scm:let*
32+ ([value1 (_0)]
33+ [_ ((dontInlineMe (rt:string->pstring "b")))])
34+ value1))))
1635
1736 (scm:define main
18− (scm:let* ((_0 (dontInlineMe "a"))) (scm:lambda () (scm:let* ((_ (_0)) (_ ((dontInlineMe "b"))) (value3 ((dontInlineMe "c"))) (_ ((dontInlineMe "d"))) (_ ((dontInlineMe "e")))) value3)))))
37+ (scm:lambda ()
38+ (scm:let ([_ (lastComponentIsRun)])
39+ (lastPureIsUnwrapped)))))
test-snapshots/src/snapshots-output/Snapshot.EffectRef.ssnew file+72
@@ -0,0 +1,72 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.EffectRef lib)
5+ (export
6+ basicTest
7+ main
8+ newCase
9+ onLet
10+ onLetTest
11+ positionZero
12+ primEffectAtTheEnd)
13+ (import
14+ (prefix (chezscheme) scm:)
15+ (prefix (purescm runtime) rt:)
16+ (prefix (Data.Show lib) Data.Show.)
17+ (prefix (Data.Unit lib) Data.Unit.)
18+ (prefix (Effect.Console lib) Effect.Console.)
19+ (prefix (Effect.Ref lib) Effect.Ref.)
20+ (prefix (Test.Assert lib) Test.Assert.))
21+
22+ (scm:define primEffectAtTheEnd
23+ (scm:let ([_0 (Effect.Ref._new 1)])
24+ (scm:lambda ()
25+ (scm:let ([n1 (_0)])
26+ ((Effect.Ref.read n1))))))
27+
28+ (scm:define positionZero
29+ (Effect.Ref._new 0))
30+
31+ (scm:define onLet
32+ (scm:lambda (x0)
33+ (scm:let ([a1 (scm:fx+ x0 x0)])
34+ (Effect.Ref._new (scm:fx+ (scm:fx+ a1 a1) x0)))))
35+
36+ (scm:define onLetTest
37+ (scm:let ([_0 (onLet 1)])
38+ (scm:lambda ()
39+ (scm:let*
40+ ([n1 (_0)]
41+ [v2 ((Effect.Ref.read n1))])
42+ ((Test.Assert.assert (scm:fx=? v2 5)))))))
43+
44+ (scm:define newCase
45+ (scm:let ([_0 (Effect.Ref._new 0)])
46+ (scm:lambda ()
47+ (scm:let*
48+ ([counter1 (_0)]
49+ [newCounter2 (((Effect.Ref.modifyImpl (scm:lambda (s2)
50+ (scm:let ([s$p3 (scm:fx+ s2 1)])
51+ (scm:list (scm:cons (scm:string->symbol "state") s$p3) (scm:cons (scm:string->symbol "value") s$p3))))) counter1))]
52+ [_ ((Effect.Console.log (rt:pstring-concat (rt:string->pstring "New counter is ") (Data.Show.showIntImpl newCounter2))))])
53+ ((Test.Assert.assert (scm:fx=? newCounter2 1)))))))
54+
55+ (scm:define basicTest
56+ (scm:let ([_0 (Effect.Ref._new 0)])
57+ (scm:lambda ()
58+ (scm:let*
59+ ([n1 (_0)]
60+ [_ (((Effect.Ref.modify_ (scm:lambda (v2)
61+ (scm:fx+ v2 1))) n1))]
62+ [v3 ((Effect.Ref.read n1))])
63+ ((Test.Assert.assert (scm:fx=? v3 1)))))))
64+
65+ (scm:define main
66+ (scm:lambda ()
67+ (scm:let*
68+ ([_ (basicTest)]
69+ [_ (onLetTest)]
70+ [_ (newCase)]
71+ [_ (primEffectAtTheEnd)])
72+ Data.Unit.unit))))
test-snapshots/src/snapshots-output/Snapshot.Failing.RecursiveBindingGroupLet.ssnew file+25
@@ -0,0 +1,25 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Failing.RecursiveBindingGroupLet lib)
5+ (export
6+ main
7+ test)
8+ (import
9+ (prefix (chezscheme) scm:)
10+ (prefix (purescm runtime) rt:)
11+ (prefix (Data.Unit lib) Data.Unit.))
12+
13+ (scm:define test
14+ (scm:letrec*
15+ ([test30 (scm:lambda (n1)
16+ (scm:cond
17+ [(scm:fx<? n1 100) n1]
18+ [scm:else (rt:record-ref test10 (scm:string->symbol "bar"))]))]
19+ [test20 (scm:list (scm:cons (scm:string->symbol "baz") (rt:record-ref test10 (scm:string->symbol "bar"))))]
20+ [test10 (scm:list (scm:cons (scm:string->symbol "foo") (rt:record-ref test20 (scm:string->symbol "baz"))) (scm:cons (scm:string->symbol "bar") (test30 42)))])
21+ (rt:record-ref test10 (scm:string->symbol "bar"))))
22+
23+ (scm:define main
24+ (scm:lambda ()
25+ Data.Unit.unit)))
test-snapshots/src/snapshots-output/Snapshot.Failing.RecursiveBindingGroupTopLevel.ssnew file+35
@@ -0,0 +1,35 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Failing.RecursiveBindingGroupTopLevel lib)
5+ (export
6+ main
7+ test1
8+ test2
9+ test3)
10+ (import
11+ (prefix (chezscheme) scm:)
12+ (prefix (purescm runtime) rt:)
13+ (prefix (Data.Unit lib) Data.Unit.))
14+
15+ (scm:define test3
16+ (scm:lambda (n0)
17+ (scm:cond
18+ [(scm:fx<? n0 100) n0]
19+ [scm:else (rt:record-ref ($lazy-test1) (scm:string->symbol "bar"))])))
20+
21+ (rt:define-lazy $lazy-test2 "test2" "Snapshot.Failing.RecursiveBindingGroupTopLevel"
22+ (scm:list (scm:cons (scm:string->symbol "baz") (rt:record-ref ($lazy-test1) (scm:string->symbol "bar")))))
23+
24+ (rt:define-lazy $lazy-test1 "test1" "Snapshot.Failing.RecursiveBindingGroupTopLevel"
25+ (scm:list (scm:cons (scm:string->symbol "foo") (rt:record-ref ($lazy-test1) (scm:string->symbol "bar"))) (scm:cons (scm:string->symbol "bar") 42)))
26+
27+ (scm:define test2
28+ ($lazy-test2))
29+
30+ (scm:define test1
31+ ($lazy-test1))
32+
33+ (scm:define main
34+ (scm:lambda ()
35+ Data.Unit.unit)))
test-snapshots/src/snapshots-output/Snapshot.Function.ss+2−2
@@ -7,12 +7,12 @@
77 g)
88 (import
99 (prefix (chezscheme) scm:)
10− (prefix (_Chez_Runtime lib) rt:))
10+ (prefix (purescm runtime) rt:))
1111
1212 (scm:define f
1313 (scm:lambda (x0)
1414 (scm:lambda (y1)
15− (scm:vector x0 y1 x0 y1 x0))))
15+ (rt:make-array x0 y1 x0 y1 x0))))
1616
1717 (scm:define g
1818 (scm:lambda (x0)
test-snapshots/src/snapshots-output/Snapshot.Import.Constructor.ssnew file+17
@@ -0,0 +1,17 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Import.Constructor lib)
5+ (export
6+ Foo
7+ Foo?)
8+ (import
9+ (prefix (chezscheme) scm:)
10+ (prefix (purescm runtime) rt:))
11+
12+ (scm:define Foo
13+ (scm:quote Foo))
14+
15+ (scm:define Foo?
16+ (scm:lambda (v)
17+ (scm:eq? (scm:quote Foo) v))))
test-snapshots/src/snapshots-output/Snapshot.Import.Impl.ss+14−1
@@ -3,12 +3,25 @@
33(library
44 (Snapshot.Import.Impl lib)
55 (export
6+ Product
7+ Product*
8+ Product-value0
9+ Product-value1
10+ Product?
611 addImpl
712 fortyTwo)
813 (import
914 (prefix (chezscheme) scm:)
10− (prefix (_Chez_Runtime lib) rt:)
15+ (prefix (purescm runtime) rt:)
1116 (Snapshot.Import.Impl foreign))
1217
18+ (scm:define-record-type (Product$ Product* Product?)
19+ (scm:fields (scm:immutable value0 Product-value0) (scm:immutable value1 Product-value1)))
20+
21+ (scm:define Product
22+ (scm:lambda (value0)
23+ (scm:lambda (value1)
24+ (Product* value0 value1))))
25+
1326 (scm:define fortyTwo
1427 ((addImpl 21) 21)))
test-snapshots/src/snapshots-output/Snapshot.Import.Product.ssnew file+21
@@ -0,0 +1,21 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Import.Product lib)
5+ (export
6+ Product
7+ Product*
8+ Product-value0
9+ Product-value1
10+ Product?)
11+ (import
12+ (prefix (chezscheme) scm:)
13+ (prefix (purescm runtime) rt:))
14+
15+ (scm:define-record-type (Product$ Product* Product?)
16+ (scm:fields (scm:immutable value0 Product-value0) (scm:immutable value1 Product-value1)))
17+
18+ (scm:define Product
19+ (scm:lambda (value0)
20+ (scm:lambda (value1)
21+ (Product* value0 value1)))))
test-snapshots/src/snapshots-output/Snapshot.Import.ss+15−4
@@ -3,11 +3,22 @@
33(library
44 (Snapshot.Import lib)
55 (export
6− fortyThree)
6+ foo
7+ fortyThree
8+ fst)
79 (import
810 (prefix (chezscheme) scm:)
9− (prefix (_Chez_Runtime lib) rt:)
10− (prefix (Snapshot.Import.Impl lib) Snapshot.Import.Impl.))
11+ (prefix (purescm runtime) rt:)
12+ (prefix (Snapshot.Import.Constructor lib) Snapshot.Import.Constructor.)
13+ (prefix (Snapshot.Import.Impl lib) Snapshot.Import.Impl.)
14+ (prefix (Snapshot.Import.Product lib) Snapshot.Import.Product.))
15+
16+ (scm:define fst
17+ (scm:lambda (v0)
18+ (Snapshot.Import.Product.Product-value0 v0)))
1119
1220 (scm:define fortyThree
13− ((Snapshot.Import.Impl.addImpl 21) 22)))
21+ ((Snapshot.Import.Impl.addImpl 21) 22))
22+
23+ (scm:define foo
24+ Snapshot.Import.Constructor.Foo))
test-snapshots/src/snapshots-output/Snapshot.Let.ss+33−3
@@ -3,11 +3,41 @@
33(library
44 (Snapshot.Let lib)
55 (export
6− letChain)
6+ isEven
7+ isOdd
8+ letChain
9+ letRecursive)
710 (import
811 (prefix (chezscheme) scm:)
9− (prefix (_Chez_Runtime lib) rt:))
12+ (prefix (purescm runtime) rt:))
13+
14+ (scm:define letRecursive
15+ (scm:lambda (x0)
16+ (scm:letrec ([go1 (scm:lambda (v2)
17+ (scm:cond
18+ [(scm:fx=? v2 0) 0]
19+ [scm:else (go1 (scm:fx- v2 1))]))])
20+ (go1 x0))))
1021
1122 (scm:define letChain
1223 (scm:lambda (x0)
13− (scm:let* ((a1 (scm:fx+ x0 x0)) (b2 (scm:fx+ a1 a1)) (c3 (scm:fx+ b2 b2))) (scm:fx+ (scm:fx+ (scm:fx+ a1 b2) c3) (scm:fx* c3 c3))))))
24+ (scm:let*
25+ ([a1 (scm:fx+ x0 x0)]
26+ [b2 (scm:fx+ a1 a1)]
27+ [c3 (scm:fx+ b2 b2)])
28+ (scm:fx+ (scm:fx+ (scm:fx+ a1 b2) c3) (scm:fx* c3 c3)))))
29+
30+ (scm:define isOdd
31+ (scm:lambda (x0)
32+ (scm:cond
33+ [(scm:fx=? x0 1) #f]
34+ [scm:else (isEven (scm:fx- x0 1))])))
35+
36+ (scm:define isEven
37+ (scm:lambda (x0)
38+ (scm:cond
39+ [(scm:fx=? x0 0) #t]
40+ [scm:else (scm:let ([_1 (scm:fx- x0 1)])
41+ (scm:cond
42+ [(scm:fx=? _1 1) #f]
43+ [scm:else (isEven (scm:fx- _1 1))]))]))))
test-snapshots/src/snapshots-output/Snapshot.List.ssnew file+76
@@ -0,0 +1,76 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.List lib)
5+ (export
6+ car
7+ cdr
8+ cons2
9+ curried
10+ main
11+ show
12+ xs)
13+ (import
14+ (prefix (chezscheme) scm:)
15+ (prefix (purescm runtime) rt:)
16+ (prefix (Data.List.Types lib) Data.List.Types.)
17+ (prefix (Data.Maybe lib) Data.Maybe.)
18+ (prefix (Data.Show lib) Data.Show.)
19+ (prefix (Test.Assert lib) Test.Assert.))
20+
21+ (scm:define show
22+ (rt:record-ref (Data.List.Types.showList Data.Show.showInt) (scm:string->symbol "show")))
23+
24+ (scm:define xs
25+ (scm:cons 1 (scm:quote ())))
26+
27+ (scm:define curried
28+ rt:list-cons)
29+
30+ (scm:define cons2
31+ (rt:list-cons 2))
32+
33+ (scm:define cdr
34+ (scm:lambda (v0)
35+ (scm:cond
36+ [(scm:null? v0) Data.Maybe.Nothing]
37+ [(scm:pair? v0) (Data.Maybe.Just (scm:cdr v0))]
38+ [scm:else (rt:fail)])))
39+
40+ (scm:define car
41+ (scm:lambda (v0)
42+ (scm:cond
43+ [(scm:null? v0) Data.Maybe.Nothing]
44+ [(scm:pair? v0) (Data.Maybe.Just (scm:car v0))]
45+ [scm:else (rt:fail)])))
46+
47+ (scm:define main
48+ (scm:let ([_0 (Test.Assert.assert #t)])
49+ (scm:lambda ()
50+ (scm:let*
51+ ([_ (_0)]
52+ [_ ((Test.Assert.assert (scm:letrec ([go2 (scm:lambda (v3)
53+ (scm:lambda (v14)
54+ (scm:lambda (v25)
55+ (scm:cond
56+ [(scm:not v25) #f]
57+ [(scm:null? v3) (scm:and (scm:null? v14) v25)]
58+ [scm:else (scm:and (scm:pair? v3) (scm:and (scm:pair? v14) (((go2 (scm:cdr v3)) (scm:cdr v14)) (scm:and v25 (scm:fx=? (scm:car v14) (scm:car v3))))))]))))])
59+ (((go2 (scm:cons 2 (scm:quote ()))) (scm:cons 2 (scm:quote ()))) #t))))]
60+ [_ ((Test.Assert.assert (scm:letrec ([go3 (scm:lambda (v4)
61+ (scm:lambda (v15)
62+ (scm:lambda (v26)
63+ (scm:cond
64+ [(scm:not v26) #f]
65+ [(scm:null? v4) (scm:and (scm:null? v15) v26)]
66+ [scm:else (scm:and (scm:pair? v4) (scm:and (scm:pair? v15) (((go3 (scm:cdr v4)) (scm:cdr v15)) (scm:and v26 (scm:fx=? (scm:car v15) (scm:car v4))))))]))))])
67+ (((go3 (scm:cons 1 (scm:quote ()))) (scm:cons 1 (scm:quote ()))) #t))))]
68+ [_ ((Test.Assert.assert (scm:letrec ([go4 (scm:lambda (v5)
69+ (scm:lambda (v16)
70+ (scm:lambda (v27)
71+ (scm:cond
72+ [(scm:not v27) #f]
73+ [(scm:null? v5) (scm:and (scm:null? v16) v27)]
74+ [scm:else (scm:and (scm:pair? v5) (scm:and (scm:pair? v16) (((go4 (scm:cdr v5)) (scm:cdr v16)) (scm:and v27 (scm:fx=? (scm:car v16) (scm:car v5))))))]))))])
75+ (((go4 (cons2 (scm:cons 3 (scm:quote ())))) (scm:cons 2 (scm:cons 3 (scm:quote ())))) #t))))])
76+ ((Test.Assert.assert (rt:pstring=? (show (scm:cons 1 (scm:cons 2 (scm:quote ())))) (rt:string->pstring "(1 : 2 : Nil)")))))))))
test-snapshots/src/snapshots-output/Snapshot.Literals.Char.ssnew file+96
@@ -0,0 +1,96 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Literals.Char lib)
5+ (export
6+ alarm
7+ backspace
8+ biggestChar
9+ closeToTop
10+ delete
11+ doubleQuote
12+ escape
13+ firstPrintableChar
14+ forallChar
15+ lastPrintableChar
16+ latin1Supplement
17+ latinExtendedA
18+ latinExtendedB
19+ ls
20+ newline
21+ null
22+ page
23+ return
24+ singleQuote
25+ space
26+ tab
27+ vtab)
28+ (import
29+ (prefix (chezscheme) scm:)
30+ (prefix (purescm runtime) rt:))
31+
32+ (scm:define vtab
33+ #\vtab)
34+
35+ (scm:define tab
36+ #\tab)
37+
38+ (scm:define space
39+ #\space)
40+
41+ (scm:define singleQuote
42+ #\')
43+
44+ (scm:define return
45+ #\return)
46+
47+ (scm:define page
48+ #\page)
49+
50+ (scm:define null
51+ #\nul)
52+
53+ (scm:define newline
54+ #\linefeed)
55+
56+ (scm:define ls
57+ #\ls)
58+
59+ (scm:define latinExtendedB
60+ #\x0180)
61+
62+ (scm:define latinExtendedA
63+ #\x0101)
64+
65+ (scm:define latin1Supplement
66+ #\x00b1)
67+
68+ (scm:define lastPrintableChar
69+ #\~)
70+
71+ (scm:define forallChar
72+ #\x2200)
73+
74+ (scm:define firstPrintableChar
75+ #\!)
76+
77+ (scm:define escape
78+ #\esc)
79+
80+ (scm:define doubleQuote
81+ #\")
82+
83+ (scm:define delete
84+ #\delete)
85+
86+ (scm:define closeToTop
87+ #\xfe19)
88+
89+ (scm:define biggestChar
90+ #\xffff)
91+
92+ (scm:define backspace
93+ #\backspace)
94+
95+ (scm:define alarm
96+ #\alarm))
test-snapshots/src/snapshots-output/Snapshot.Literals.Number.ssnew file+20
@@ -0,0 +1,20 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Literals.Number lib)
5+ (export
6+ minusInfinity
7+ nan
8+ plusInfinity)
9+ (import
10+ (prefix (chezscheme) scm:)
11+ (prefix (purescm runtime) rt:))
12+
13+ (scm:define plusInfinity
14+ +inf.0)
15+
16+ (scm:define nan
17+ +nan.0)
18+
19+ (scm:define minusInfinity
20+ -inf.0))
test-snapshots/src/snapshots-output/Snapshot.Literals.Record.ssnew file+52
@@ -0,0 +1,52 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Literals.Record lib)
5+ (export
6+ insert
7+ main
8+ minusTwo
9+ recordAccess
10+ recordAddField
11+ recordUpdate
12+ unsafeGetNotFound)
13+ (import
14+ (prefix (chezscheme) scm:)
15+ (prefix (purescm runtime) rt:)
16+ (prefix (Record lib) Record.)
17+ (prefix (Test.Assert lib) Test.Assert.)
18+ (prefix (Type.Proxy lib) Type.Proxy.)
19+ (Snapshot.Literals.Record foreign))
20+
21+ (scm:define insert
22+ (((Record.insert (scm:list (scm:cons (scm:string->symbol "reflectSymbol") (scm:lambda (_)
23+ (rt:string->pstring "anotherField"))))) (scm:quote undefined)) (scm:quote undefined)))
24+
25+ (scm:define recordUpdate
26+ (scm:lambda (v0)
27+ (scm:cons (scm:cons (scm:string->symbol "fooBarBaz") 10) v0)))
28+
29+ (scm:define recordAddField
30+ (scm:lambda (_)
31+ ((insert Type.Proxy.Proxy) 42)))
32+
33+ (scm:define recordAccess
34+ (scm:lambda (v0)
35+ (rt:record-ref v0 (scm:string->symbol "fooBarBaz"))))
36+
37+ (scm:define main
38+ (scm:let*
39+ ([r0 (scm:list (scm:cons (scm:string->symbol "fooBarBaz") 5))]
40+ [s1 (recordUpdate r0)]
41+ [t2 ((recordAddField (scm:quote undefined)) s1)]
42+ [u3 (scm:list (scm:cons (scm:string->symbol "fooBarBaz") minusTwo))]
43+ [_4 (Test.Assert.assert (scm:fx=? (recordAccess t2) 10))])
44+ (scm:lambda ()
45+ (scm:let*
46+ ([_ (_4)]
47+ [_ ((Test.Assert.assert (scm:fx=? (rt:record-ref t2 (scm:string->symbol "anotherField")) 42)))]
48+ [_ ((Test.Assert.assert (scm:fx=? (recordAccess s1) 10)))]
49+ [_ ((Test.Assert.assert (scm:fx=? (recordAccess r0) 5)))]
50+ [_ ((Test.Assert.assert (scm:fx=? (recordAccess u3) minusTwo)))])
51+ (((Test.Assert.assertThrows$p (rt:string->pstring "Assertion failed: An error should have been thrown")) (scm:lambda (v10)
52+ (unsafeGetNotFound u3)))))))))
test-snapshots/src/snapshots-output/Snapshot.Literals.String.ss+21−21
@@ -25,64 +25,64 @@
2525 unicode7)
2626 (import
2727 (prefix (chezscheme) scm:)
28− (prefix (_Chez_Runtime lib) rt:))
28+ (prefix (purescm runtime) rt:))
2929
3030 (scm:define unicode7
31− "Foo \b\b\b\b Bar")
31+ (rt:string->pstring "Foo \b\b\b\b Bar"))
3232
3333 (scm:define unicode6
34− "2342✓")
34+ (rt:string->pstring "2342✓"))
3535
3636 (scm:define unicode5
37− "Foo ✓ Bar ✓ \n Baz ✓")
37+ (rt:string->pstring "Foo ✓ Bar ✓ \n Baz ✓"))
3838
3939 (scm:define unicode4
40− "✓")
40+ (rt:string->pstring "✓"))
4141
4242 (scm:define unicode3
43− "✓")
43+ (rt:string->pstring "✓"))
4444
4545 (scm:define unicode2
46− "􏿿")
46+ (rt:string->pstring "􏿿"))
4747
4848 (scm:define unicode1
49− "\x0000;")
49+ (rt:string->pstring "\x0000;"))
5050
5151 (scm:define escape8
52− "'")
52+ (rt:string->pstring "'"))
5353
5454 (scm:define escape7
55− "\"")
55+ (rt:string->pstring "\""))
5656
5757 (scm:define escape6
58− "\\")
58+ (rt:string->pstring "\\"))
5959
6060 (scm:define escape5
61− "\r\n")
61+ (rt:string->pstring "\r\n"))
6262
6363 (scm:define escape4
64− "\r")
64+ (rt:string->pstring "\r"))
6565
6666 (scm:define escape3
67− "\r")
67+ (rt:string->pstring "\r"))
6868
6969 (scm:define escape2
70− "\n")
70+ (rt:string->pstring "\n"))
7171
7272 (scm:define escape1
73− "\t")
73+ (rt:string->pstring "\t"))
7474
7575 (scm:define block5
76− "foo\nbar\nbaz\n")
76+ (rt:string->pstring "foo\nbar\nbaz\n"))
7777
7878 (scm:define block4
79− "foo\nbar\nbaz")
79+ (rt:string->pstring "foo\nbar\nbaz"))
8080
8181 (scm:define block3
82− "foo\nbar")
82+ (rt:string->pstring "foo\nbar"))
8383
8484 (scm:define block2
85− "\nfoo\nbar\n")
85+ (rt:string->pstring "\nfoo\nbar\n"))
8686
8787 (scm:define block1
88− "block"))
88+ (rt:string->pstring "block")))
test-snapshots/src/snapshots-output/Snapshot.Literals.ss+6−6
@@ -15,16 +15,16 @@
1515 string)
1616 (import
1717 (prefix (chezscheme) scm:)
18− (prefix (_Chez_Runtime lib) rt:))
18+ (prefix (purescm runtime) rt:))
1919
2020 (scm:define string
21− "string")
21+ (rt:string->pstring "string"))
2222
2323 (scm:define record2
24− (scm:letrec* (($record (scm:make-hashtable scm:string-hash scm:string=?))) (scm:hashtable-set! $record "foo" "bar") $record))
24+ (scm:list (scm:cons (scm:string->symbol "foo") (rt:string->pstring "bar"))))
2525
2626 (scm:define record
27− (scm:letrec* (($record (scm:make-hashtable scm:string-hash scm:string=?))) $record))
27+ (scm:list))
2828
2929 (scm:define number
3030 2.0)
@@ -42,7 +42,7 @@
4242 #t)
4343
4444 (scm:define array2
45− (scm:vector 1 2 3))
45+ (rt:make-array 1 2 3))
4646
4747 (scm:define array
48− (scm:vector)))
48+ (rt:make-array)))
test-snapshots/src/snapshots-output/Snapshot.PrimUndefined.ssnew file+19
@@ -0,0 +1,19 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.PrimUndefined lib)
5+ (export
6+ main
7+ testCase)
8+ (import
9+ (prefix (chezscheme) scm:)
10+ (prefix (purescm runtime) rt:)
11+ (prefix (Data.Ring lib) Data.Ring.)
12+ (prefix (Test.Assert lib) Test.Assert.))
13+
14+ (scm:define testCase
15+ (scm:lambda (dictRing0)
16+ (rt:record-ref ((rt:record-ref dictRing0 (scm:string->symbol "Semiring0")) (scm:quote undefined)) (scm:string->symbol "add"))))
17+
18+ (scm:define main
19+ (Test.Assert.assert (scm:fx=? (((testCase Data.Ring.ringInt) 1) 1) 2))))
test-snapshots/src/snapshots-output/Snapshot.Prime.ssnew file+151
@@ -0,0 +1,151 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.Prime lib)
5+ (export
6+ Ctor$p
7+ Ctor$p*
8+ Ctor$p-value0
9+ Ctor$p-value1
10+ Ctor$p?
11+ DCtor
12+ DCtor?
13+ F1
14+ F1?
15+ F2
16+ F2?
17+ NCtor
18+ NewtypeCtor$p
19+ classMember$p
20+ foo
21+ foo$p
22+ foo$p$p
23+ foo$poo
24+ ignore
25+ instanceName$p
26+ normal
27+ useClass
28+ useDataCtor
29+ useDataType
30+ useFooPrime1
31+ useFooPrime2
32+ useFooPrime3
33+ useInstance
34+ useMember
35+ useNewtypeCtor
36+ useNewtypeType
37+ useNormal)
38+ (import
39+ (prefix (chezscheme) scm:)
40+ (prefix (purescm runtime) rt:))
41+
42+ (scm:define NCtor
43+ (scm:lambda (x0)
44+ x0))
45+
46+ (scm:define NewtypeCtor$p
47+ (scm:lambda (x0)
48+ x0))
49+
50+ (scm:define F1
51+ (scm:quote F1))
52+
53+ (scm:define F1?
54+ (scm:lambda (v)
55+ (scm:eq? (scm:quote F1) v)))
56+
57+ (scm:define F2
58+ (scm:quote F2))
59+
60+ (scm:define F2?
61+ (scm:lambda (v)
62+ (scm:eq? (scm:quote F2) v)))
63+
64+ (scm:define DCtor
65+ (scm:quote DCtor))
66+
67+ (scm:define DCtor?
68+ (scm:lambda (v)
69+ (scm:eq? (scm:quote DCtor) v)))
70+
71+ (scm:define-record-type (Ctor$p$ Ctor$p* Ctor$p?)
72+ (scm:fields (scm:immutable value0 Ctor$p-value0) (scm:immutable value1 Ctor$p-value1)))
73+
74+ (scm:define Ctor$p
75+ (scm:lambda (value0)
76+ (scm:lambda (value1)
77+ (Ctor$p* value0 value1))))
78+
79+ (scm:define useNewtypeType
80+ (scm:lambda (i0)
81+ i0))
82+
83+ (scm:define useNewtypeCtor
84+ (scm:lambda (i0)
85+ i0))
86+
87+ (scm:define useDataType
88+ (scm:lambda (v0)
89+ DCtor))
90+
91+ (scm:define useDataCtor
92+ (scm:lambda (s0)
93+ (Ctor$p* s0 4)))
94+
95+ (scm:define normal
96+ (scm:lambda (dict0)
97+ (rt:record-ref dict0 (scm:string->symbol "normal"))))
98+
99+ (scm:define useNormal
100+ (scm:lambda (dictNormal0)
101+ (scm:lambda (dictNormal11)
102+ (scm:lambda (a2)
103+ (scm:lambda (b3)
104+ (rt:pstring-concat ((rt:record-ref dictNormal0 (scm:string->symbol "normal")) a2) ((rt:record-ref dictNormal11 (scm:string->symbol "normal")) b3)))))))
105+
106+ (scm:define instanceName$p
107+ (scm:list (scm:cons (scm:string->symbol "normal") (scm:lambda (v0)
108+ (scm:cond
109+ [(F1? v0) (rt:string->pstring "F1")]
110+ [(F2? v0) (rt:string->pstring "F2")]
111+ [scm:else (rt:fail)])))))
112+
113+ (scm:define useInstance
114+ (rt:string->pstring "F1F2"))
115+
116+ (scm:define ignore
117+ (scm:lambda (dict0)
118+ (rt:record-ref dict0 (scm:string->symbol "ignore"))))
119+
120+ (scm:define useClass
121+ (scm:lambda (dictClassName$p0)
122+ (rt:record-ref dictClassName$p0 (scm:string->symbol "ignore"))))
123+
124+ (scm:define foo$poo
125+ (rt:string->pstring "foo'oo"))
126+
127+ (scm:define useFooPrime3
128+ (rt:string->pstring "foo'oo"))
129+
130+ (scm:define foo$p$p
131+ (rt:string->pstring "foo'"))
132+
133+ (scm:define useFooPrime2
134+ (rt:string->pstring "foo'"))
135+
136+ (scm:define foo$p
137+ (rt:string->pstring "foo'"))
138+
139+ (scm:define useFooPrime1
140+ (rt:string->pstring "foo'"))
141+
142+ (scm:define foo
143+ (rt:string->pstring "foo"))
144+
145+ (scm:define classMember$p
146+ (scm:lambda (dict0)
147+ (rt:record-ref dict0 (scm:string->symbol "classMember'"))))
148+
149+ (scm:define useMember
150+ (scm:lambda (dictClassMember0)
151+ (rt:record-ref dictClassMember0 (scm:string->symbol "classMember'")))))
test-snapshots/src/snapshots-output/Snapshot.RecursiveDefinition.ssnew file+51
@@ -0,0 +1,51 @@
1+#!r6rs
2+#!chezscheme
3+(library
4+ (Snapshot.RecursiveDefinition lib)
5+ (export
6+ alpha
7+ bravo
8+ charlie
9+ delta
10+ main)
11+ (import
12+ (prefix (chezscheme) scm:)
13+ (prefix (purescm runtime) rt:)
14+ (prefix (Data.Unit lib) Data.Unit.))
15+
16+ (scm:define main
17+ (scm:lambda ()
18+ Data.Unit.unit))
19+
20+ (scm:define delta
21+ (scm:lambda (x0)
22+ (scm:lambda (y1)
23+ (scm:cond
24+ [(scm:fx=? x0 y1) (($lazy-bravo) 0)]
25+ [scm:else 1.0]))))
26+
27+ (scm:define alpha
28+ (scm:lambda (v0)
29+ (scm:cond
30+ [(scm:fx=? v0 0) ($lazy-bravo)]
31+ [(scm:fx=? v0 1) ($lazy-charlie)]
32+ [(scm:fx=? v0 2) (scm:lambda (y1)
33+ (scm:cond
34+ [(scm:fx>? y1 0) (($lazy-bravo) y1)]
35+ [scm:else (($lazy-charlie) y1)]))]
36+ [scm:else (scm:lambda (y1)
37+ (scm:cond
38+ [(scm:fx=? y1 v0) (($lazy-bravo) 0)]
39+ [scm:else 1.0]))])))
40+
41+ (rt:define-lazy $lazy-charlie "charlie" "Snapshot.RecursiveDefinition"
42+ (alpha 4))
43+
44+ (rt:define-lazy $lazy-bravo "bravo" "Snapshot.RecursiveDefinition"
45+ (alpha 3))
46+
47+ (scm:define charlie
48+ ($lazy-charlie))
49+
50+ (scm:define bravo
51+ ($lazy-bravo)))
test-snapshots/src/snapshots-output/Snapshot.UncurriedFunction.ss+35−6
@@ -3,16 +3,32 @@
33(library
44 (Snapshot.UncurriedFunction lib)
55 (export
6+ main
67 test1a
78 test1b
89 test2a
910 test2b
1011 test3a
11− test3b)
12+ test3b
13+ test4a
14+ test4b)
1215 (import
1316 (prefix (chezscheme) scm:)
14− (prefix (_Chez_Runtime lib) rt:)
15− (prefix (Data.Function.Uncurried lib) Data.Function.Uncurried.))
17+ (prefix (purescm runtime) rt:)
18+ (prefix (Data.Function.Uncurried lib) Data.Function.Uncurried.)
19+ (prefix (Effect.Console lib) Effect.Console.)
20+ (prefix (Test.Assert lib) Test.Assert.))
21+
22+ (scm:define test4a
23+ (scm:lambda (a0)
24+ (scm:let*
25+ ([_1 (Effect.Console.log a0)]
26+ [_ (_1)])
27+ a0)))
28+
29+ (scm:define test4b
30+ (scm:lambda ()
31+ (test4a (rt:string->pstring "test4b"))))
1632
1733 (scm:define test3a
1834 (scm:lambda (v0 b1)
@@ -28,8 +44,21 @@
2844 (scm:define test2b
2945 (test2a 1 2))
3046
47+ (scm:define test1a
48+ (Data.Function.Uncurried.mkFn0 (scm:lambda (v0)
49+ 1)))
50+
3151 (scm:define test1b
32− Data.Function.Uncurried.runFn0)
52+ (Data.Function.Uncurried.runFn0 test1a))
3353
34− (scm:define test1a
35− (Data.Function.Uncurried.mkFn0 (scm:lambda (v0) 1))))
54+ (scm:define main
55+ (scm:let ([_0 (Test.Assert.assert (scm:fx=? test1b 1))])
56+ (scm:lambda ()
57+ (scm:let*
58+ ([_ (_0)]
59+ [_ ((Test.Assert.assert (scm:fx=? test2b 1)))]
60+ [_ ((Test.Assert.assert (scm:fx=? test3b 2)))]
61+ [v4 (test4b)]
62+ [_ ((Test.Assert.assert (rt:pstring=? v4 (rt:string->pstring "test4b"))))]
63+ [w6 (test4a (rt:string->pstring "test4b"))])
64+ ((Test.Assert.assert (rt:pstring=? w6 (rt:string->pstring "test4b")))))))))
test/Main.purs+90−137
@@ -11,29 +11,22 @@ import Ansi.Codes (Color(..))
1111import Ansi.Output (foreground, withGraphics)
1212import ArgParse.Basic (ArgParser)
1313import ArgParse.Basic as ArgParser
14−import Data.Array (findMap)
1514import Data.Array as Array
1615import Data.Array.NonEmpty (NonEmptyArray)
16+import Data.Array.NonEmpty as NonEmptyArray
1717import Data.Either (Either(..), either, isRight)
18−import Data.Foldable (for_)
1918import Data.Foldable as Foldable
20−import Data.Map as Map
21−import Data.Maybe (Maybe(..), fromMaybe, isJust)
19+import Data.Maybe (Maybe(..))
2220import Data.Monoid (power)
23−import Data.Newtype (unwrap)
2421import Data.Set as Set
25−import Data.String (Pattern(..))
22+import Data.String (Pattern(..), Replacement(..))
2623import Data.String as String
2724import Data.String.CodeUnits as SCU
2825import Data.TraversableWithIndex (forWithIndex)
29−import Data.Tuple (Tuple(..))
30−import Dodo (plainText)
31−import Dodo as Dodo
3226import Effect (Effect)
3327import Effect.Aff (Aff, attempt, launchAff_)
3428import Effect.Class (liftEffect)
3529import Effect.Class.Console as Console
36−import Effect.Ref as Ref
3730import Node.Encoding (Encoding(..))
3831import Node.FS.Aff as FS
3932import Node.Glob.Basic (expandGlobs)
@@ -41,17 +34,8 @@ import Node.Library.Execa.Which (defaultWhichOptions, which)
4134import Node.Path as Path
4235import Node.Process as Process
4336import Partial.Unsafe (unsafeCrashWith)
44−import PureScript.Backend.Chez.Constants (moduleForeign, moduleLib, schemeExt)
45−import PureScript.Backend.Chez.Convert (codegenModule)
46−import PureScript.Backend.Chez.Runtime (runtimeModule)
47−import PureScript.Backend.Chez.Syntax as S
48−import PureScript.Backend.Optimizer.Builder (buildModules)
49−import PureScript.Backend.Optimizer.Convert (BackendModule)
50−import PureScript.Backend.Optimizer.CoreFn (Comment(..), Module(..), ModuleName(..))
51−import PureScript.Backend.Optimizer.Directives (parseDirectiveFile)
52−import PureScript.Backend.Optimizer.Directives.Defaults (defaultDirectives)
53−import PureScript.Backend.Optimizer.Semantics.Foreign (coreForeignSemantics)
54−import Test.Utils (bufferToUTF8, canRunMain, copyFile, coreFnModulesFromOutput, execWithStdin, loadModuleMain, mkdirp, spawnFromParent)
37+import PureScript.Backend.Chez.Constants (moduleLib, schemeExt)
38+import Test.Utils (canRunMain, execWithStdin, loadModuleMain, mkdirp, spawnFromParent)
5539
5640type TestArgs =
5741 { accept :: Boolean
@@ -84,128 +68,97 @@ main = do
8468
8569runSnapshotTests :: TestArgs -> Aff Unit
8670runSnapshotTests { accept, filter } = do
71+ currentDirectory <- liftEffect Process.cwd
72+ let runtimeLibPath = Path.concat [ currentDirectory, "lib" ]
73+
74+ -- Get into the snapshot project and build it
8775 liftEffect $ Process.chdir $ Path.concat [ "test-snapshots" ]
88− spawnFromParent "spago" [ "build", "--purs-args", "-g corefn" ]
76+ spawnFromParent "spago" [ "build" ]
8977 snapshotDir <- liftEffect Process.cwd
90− snapshotPaths <- expandGlobs (Path.concat [ snapshotDir, "src", "snapshots-input" ])
91− [ "Snapshot.*.purs" ]
92− schemeBin <- getSchemeBinary
93− outputRef <- liftEffect $ Ref.new Map.empty
78+ let snapshotInput = Path.concat [ snapshotDir, "src", "snapshots-input" ]
9479 let snapshotsOut = Path.concat [ snapshotDir, "src", "snapshots-output" ]
95− let testOut = Path.concat [ snapshotDir, "test-out" ]
80+ snapshotPaths <- expandGlobs snapshotInput (map (_ <> ".purs") $ NonEmptyArray.toArray filter)
9681 mkdirp snapshotsOut
97− mkdirp testOut
98− -- RUNTIME
99− let runtimePath = Path.concat [ testOut, "_Chez_Runtime" ]
100− mkdirp runtimePath
101− let runtimeFilePath = Path.concat [ runtimePath, moduleLib <> schemeExt ]
102− let runtimeContents = Dodo.print plainText Dodo.twoSpaces $ S.printLibrary $ runtimeModule
103− FS.writeTextFile UTF8 runtimeFilePath runtimeContents
104− coreFnModulesFromOutput "output" filter >>= case _ of
105− Left errors -> do
106− for_ errors \(Tuple filePath err) -> do
107− Console.error $ filePath <> " " <> err
108− liftEffect $ Process.exit 1
109− Right coreFnModules -> do
110− let { directives } = parseDirectiveFile defaultDirectives
111− -- No runtime .ss files needed yet
112− -- copyFile (Path.concat [ "..", "..", "runtime.js" ]) (Path.concat [ testOut, "runtime.js" ])
113− coreFnModules # buildModules
114− { directives
115− , foreignSemantics: coreForeignSemantics -- no chez scheme specific foreign semantics yet
116− , onCodegenModule: \_ (Module { name: ModuleName name, path }) backend -> do
117− let
118− formatted =
119− Dodo.print plainText Dodo.twoSpaces
120− $ S.printLibrary
121− $ codegenModule backend
122− let testFileDir = Path.concat [ testOut, name ]
123− let testFilePath = Path.concat [ testFileDir, moduleLib <> schemeExt ]
124− mkdirp testFileDir
125− FS.writeTextFile UTF8 testFilePath formatted
126− unless (Set.isEmpty backend.foreign) do
127− let
128− foreignSiblingPath =
129− fromMaybe path (String.stripSuffix (Pattern (Path.extname path)) path) <>
130− schemeExt
131− let foreignOutputPath = Path.concat [ testFileDir, moduleForeign <> schemeExt ]
132− copyFile foreignSiblingPath foreignOutputPath
133− let snapshotDirFile = Path.concat [ snapshotDir, path ]
134− when (Set.member snapshotDirFile snapshotPaths) do
135− originalFileSourceCode <- FS.readTextFile UTF8 snapshotDirFile
136− hasMain <- either unsafeCrashWith pure $
137− canRunMain originalFileSourceCode
138− void $ liftEffect $ Ref.modify
139− (Map.insert name ({ formatted, failsWith: hasFails backend, hasMain }))
140− outputRef
141− , onPrepareModule: \build coreFnMod@(Module { name }) -> do
142− let total = show build.moduleCount
143− let index = show (build.moduleIndex + 1)
144− let padding = power " " (SCU.length total - SCU.length index)
145− Console.log $ "[" <> padding <> index <> " of " <> total <> "] Building " <> unwrap name
146− pure coreFnMod
147− }
148− outputModules <- liftEffect $ Ref.read outputRef
149− results <- forWithIndex outputModules \name ({ formatted, failsWith, hasMain }) -> do
150− let
151− snapshotFilePath = Path.concat [ snapshotsOut, name <> schemeExt ]
152− runAcceptedTest = do
153− schemeFile <- liftEffect $ Path.resolve [ testOut, name ] $ moduleLib <> schemeExt
154− result <- loadModuleMain
155− { libdir: testOut
156− , scheme: schemeBin
157− , hasMain
158− , modulePath: schemeFile
159− , moduleName: name
160− }
161− case result of
162− Left err | matchesFail err.message failsWith -> do
163− Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <> " failed."
164− Console.log err.message
165− pure false
166− Right _ | isJust failsWith -> do
167− Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <>
168− " succeeded when it should have failed."
169− pure false
170− _ ->
171− pure true
172− attempt (FS.readTextFile UTF8 snapshotFilePath) >>= case _ of
173− Left _ -> do
174− Console.log $ withGraphics (foreground Yellow) "✓" <> " " <> name <> " saved."
175− FS.writeTextFile UTF8 snapshotFilePath formatted
176− pure true
177− Right prevOutput
178− | formatted == prevOutput ->
179− runAcceptedTest
180− | accept -> do
181− Console.log $ withGraphics (foreground Yellow) "✓" <> " " <> name <> " accepted."
182− FS.writeTextFile UTF8 snapshotFilePath formatted
183− runAcceptedTest
184− | otherwise -> do
185− Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <> " failed."
186− diff <- bufferToUTF8 <<< _.stdout =<< execWithStdin
187− ("diff " <> snapshotFilePath <> " -")
188− formatted
189− Console.log diff
190− pure false
191− unless (Foldable.and results) do
192− liftEffect $ Process.exit 1
82+ schemeBin <- getSchemeBinary
83+
84+ -- Tests return true or false depending on whether they pass
85+ results <- forWithIndex (Set.toUnfoldable snapshotPaths :: Array _) \i snapshotInputPath -> do
86+ let
87+ -- The idea here is that we get files from the `output` directory, and check if
88+ -- they look like the ones we have in `snapshots-output`
89+ expectedSnapshotOutputPath =
90+ String.replace (Pattern snapshotInput) (Replacement snapshotsOut)
91+ $ String.replace (Pattern ".purs") (Replacement schemeExt)
92+ $ snapshotInputPath
93+ actualSnapshotOutputPath =
94+ String.replace (Pattern snapshotInput) (Replacement (Path.concat [ snapshotDir, "output" ]))
95+ $ String.replace (Pattern ".purs") (Replacement $ "/" <> moduleLib <> schemeExt)
96+ $ snapshotInputPath
97+ name = String.replace (Pattern $ snapshotInput <> "/") (Replacement "")
98+ $ String.replace (Pattern ".purs") (Replacement "")
99+ $ snapshotInputPath
100+
101+ let
102+ total = show $ Set.size snapshotPaths
103+ index = show i
104+ padding = power " " (SCU.length total - SCU.length index)
105+ Console.log $ "[" <> padding <> index <> " of " <> total <> "] Running test " <> name
106+
107+ -- Read the file generated by purescm
108+ actualSnapshotOutput <- FS.readTextFile UTF8 actualSnapshotOutputPath
109+ purescriptFile <- FS.readTextFile UTF8 snapshotInputPath
110+ hasMain <- either unsafeCrashWith pure $ canRunMain purescriptFile
111+
112+ let
113+ runAcceptedTest = do
114+ result <- loadModuleMain
115+ { libdir: runtimeLibPath <> ":output"
116+ , scheme: schemeBin
117+ , hasMain
118+ , modulePath: actualSnapshotOutputPath
119+ , moduleName: name
120+ }
121+ let shouldFail = isFailingTestFile purescriptFile
122+ case result.exitCode of
123+ Just 0 -> pure true
124+ Just 0 | shouldFail -> do
125+ Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <> " should have failed."
126+ Console.log result.message
127+ pure false
128+ _ | shouldFail -> pure true
129+ _ -> do
130+ Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <> " failed."
131+ Console.log result.message
132+ pure false
133+
134+ attempt (FS.readTextFile UTF8 expectedSnapshotOutputPath) >>= case _ of
135+ -- If we don't have this fixture yet, save it
136+ Left _ -> do
137+ Console.log $ withGraphics (foreground Yellow) "✓" <> " " <> name <> " saved."
138+ FS.writeTextFile UTF8 expectedSnapshotOutputPath actualSnapshotOutput
139+ pure true
140+ Right prevOutput
141+ -- We have and it looks the same -> run it
142+ | actualSnapshotOutput == prevOutput ->
143+ runAcceptedTest
144+ -- We have it but we are accepting the new output -> save it, and run it afterwards
145+ | accept -> do
146+ Console.log $ withGraphics (foreground Yellow) "✓" <> " " <> name <> " accepted."
147+ FS.writeTextFile UTF8 expectedSnapshotOutputPath actualSnapshotOutput
148+ runAcceptedTest
149+ -- We have it and it's broken
150+ | otherwise -> do
151+ Console.log $ withGraphics (foreground Red) "✗" <> " " <> name <> " failed."
152+ diff <- _.stdout <$> execWithStdin "diff" [ expectedSnapshotOutputPath, "-" ]
153+ actualSnapshotOutput
154+ Console.log diff
155+ pure false
193156
194−hasFails :: BackendModule -> Maybe String
195−hasFails = findMap go <<< _.comments
196− where
197− go = case _ of
198− LineComment comm ->
199− String.stripPrefix (Pattern "@fails ") (String.trim comm)
200− _ ->
201− Nothing
157+ unless (Foldable.and results) do
158+ liftEffect $ Process.exit' 1
202159
203−matchesFail :: String -> Maybe String -> Boolean
204−matchesFail errMsg = case _ of
205− Just msg ->
206− not $ String.contains (Pattern msg) errMsg
207− Nothing ->
208− true
160+isFailingTestFile :: String -> Boolean
161+isFailingTestFile = String.contains (Pattern "Failing")
209162
210163getSchemeBinary :: Aff String
211164getSchemeBinary = do
test/Utils.purs+47−91
@@ -9,71 +9,44 @@ module Test.Utils where
99
1010import Prelude
1111
12−import Control.Monad.Except (ExceptT(..), lift, runExceptT)
13−import Control.Parallel (parTraverse)
14−import Data.Argonaut as Json
1512import Data.Array as Array
1613import Data.Array.NonEmpty as NonEmptyArray
1714import Data.Array.NonEmpty.Internal (NonEmptyArray(..))
18−import Data.Bifunctor (lmap)
19−import Data.Compactable (separate)
2015import Data.Either (Either(..))
21−import Data.Foldable (foldl)
22−import Data.Lazy as Lazy
23−import Data.List (List)
24−import Data.Maybe (maybe)
25−import Data.Posix.Signal (Signal(..))
26−import Data.Set as Set
27−import Data.Set.NonEmpty as NonEmptySet
28−import Data.Tuple (Tuple(..))
29−import Effect.Aff (Aff, effectCanceler, error, makeAff, throwError)
16+import Data.Maybe (Maybe(..))
17+import Effect.Aff (Aff, effectCanceler, error, makeAff, message, throwError)
3018import Effect.Class (liftEffect)
31−import Node.Buffer (Buffer, freeze)
32−import Node.Buffer.Immutable as ImmutableBuffer
33−import Node.ChildProcess (ExecResult, Exit(..), defaultExecOptions, defaultSpawnOptions, inherit)
34−import Node.ChildProcess as ChildProcess
35−import Node.Encoding (Encoding(..))
19+import Foreign.Object as Object
20+import Node.EventEmitter (on_)
3621import Node.FS.Aff as FS
37−import Node.FS.Perms (mkPerms)
3822import Node.FS.Perms as Perms
3923import Node.FS.Stats as Stats
4024import Node.FS.Stream (createReadStream, createWriteStream)
41−import Node.Glob.Basic (expandGlobs)
42−import Node.Library.Execa (ExecaError, ExecaSuccess, execa)
25+import Node.Library.Execa (ExecaResult, execa)
4326import Node.Path (FilePath)
4427import Node.Process as Process
4528import Node.Stream as Stream
46−import PureScript.Backend.Optimizer.CoreFn (Ann, Module, ModuleName(..))
47−import PureScript.Backend.Optimizer.CoreFn.Json (decodeModule)
48−import PureScript.Backend.Optimizer.CoreFn.Sort (emptyPull, pullResult, resumePull, sortModules)
4929import PureScript.CST (RecoveredParserResult(..), parseModule)
5030import PureScript.CST.Errors (printParseError)
5131import PureScript.CST.Types as CSTT
5232
5333spawnFromParent :: String -> Array String -> Aff Unit
54−spawnFromParent command args = makeAff \k -> do
55− childProc <- ChildProcess.spawn command args defaultSpawnOptions { stdio = inherit }
56− ChildProcess.onExit childProc case _ of
57− Normally code
58− | code > 0 -> Process.exit code
59− | otherwise -> k (Right unit)
60− BySignal _ ->
61− Process.exit 1
62− pure $ effectCanceler do
63− ChildProcess.kill SIGABRT childProc
34+spawnFromParent command args = do
35+ spawned <- execa command args identity
36+ spawned.stdout.pipeToParentStdout
37+ spawned.stderr.pipeToParentStderr
38+ result <- spawned.getResult
39+ unless (result.exitCode == Just 0) do
40+ liftEffect $ Process.exit' 1
6441
65−execWithStdin :: String -> String -> Aff ExecResult
66−execWithStdin command input = makeAff \k -> do
67− childProc <- ChildProcess.exec command defaultExecOptions (k <<< pure)
68− _ <- Stream.writeString (ChildProcess.stdin childProc) UTF8 input mempty
69− Stream.end (ChildProcess.stdin childProc) mempty
70− pure $ effectCanceler $ ChildProcess.kill SIGABRT childProc
71−
72−bufferToUTF8 :: Buffer -> Aff String
73−bufferToUTF8 = liftEffect <<< map (ImmutableBuffer.toString UTF8) <<< freeze
42+execWithStdin :: String -> Array String -> String -> Aff ExecaResult
43+execWithStdin command args input = do
44+ spawned <- execa command args identity
45+ spawned.stdin.writeUtf8End input
46+ spawned.getResult
7447
7548mkdirp :: FilePath -> Aff Unit
76−mkdirp path = FS.mkdir' path { recursive: true, mode: mkPerms Perms.all Perms.all Perms.all }
49+mkdirp path = FS.mkdir' path { recursive: true, mode: Perms.permsAll }
7750
7851loadModuleMain
7952 :: { libdir :: FilePath
@@ -82,7 +55,7 @@ loadModuleMain
8255 , moduleName :: String
8356 , modulePath :: String
8457 }
85− -> Aff (Either ExecaError ExecaSuccess)
58+ -> Aff ExecaResult
8659loadModuleMain options = do
8760 let
8861 arguments :: Array String
@@ -91,11 +64,30 @@ loadModuleMain options = do
9164 [ "--script", options.modulePath ]
9265 else
9366 []
94− spawned <- execa options.scheme arguments identity
67+
68+ -- Apple blocks DYLD environment variables, so loading libraries with DYLD_LIBRARY_PATH
69+ -- will not work across process spawns. We go around this by carrying the library path
70+ -- in CHEZ_DYLD_LIBRARY_PATH and setting DYLD_LIBRARY_PATH when spawning. For more info see:
71+ -- https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html
72+ env <- liftEffect $ Process.getEnv
73+ case Object.lookup "CHEZ_DYLD_LIBRARY_PATH" env of
74+ Just dyldPath -> do
75+ liftEffect $ Process.setEnv "DYLD_LIBRARY_PATH" dyldPath
76+ _ -> pure unit
77+
78+ spawned <- execa options.scheme arguments (_ { extendEnv = Just true })
9579 when options.hasMain do
9680 spawned.stdin.writeUtf8End $ Array.fold
97− [ "(import (", options.moduleName, " lib)) (main)" ]
98− spawned.result
81+ [ "(base-exception-handler (lambda (e) (display-condition e (console-error-port)) (newline (console-error-port)) (exit -1)))"
82+ , "(top-level-program (import (only (chezscheme) base-exception-handler exit lambda)"
83+ , " (" <> options.moduleName <> " lib)"
84+ , " (only (purescm stack-trace) print-stack-trace))"
85+ , " (base-exception-handler (lambda (e) (print-stack-trace e) (exit -1)))"
86+ , " (main))"
87+ ]
88+ spawned.stdout.pipeToParentStdout
89+ spawned.stderr.pipeToParentStderr
90+ spawned.getResult
9991
10092copyFile :: FilePath -> FilePath -> Aff Unit
10193copyFile from to = do
@@ -105,52 +97,16 @@ copyFile from to = do
10597 makeAff \k -> do
10698 src <- createReadStream from
10799 dst <- createWriteStream to
108− res <- Stream.pipe src dst
109− Stream.onError src (k <<< Left)
110− Stream.onError dst (k <<< Left)
111− Stream.onError res (k <<< Left)
112− Stream.onFinish res (k (Right unit))
100+ src # on_ Stream.errorH \err -> do
101+ Stream.destroy' dst $ error $ "Got error in src stream: " <> message err
102+ k $ Left err
103+ dst # on_ Stream.errorH (k <<< Left)
104+ dst # on_ Stream.finishH (k (Right unit))
105+ Stream.pipe src dst
113106 pure $ effectCanceler do
114− Stream.destroy res
115107 Stream.destroy dst
116108 Stream.destroy src
117109
118−coreFnModulesFromOutput
119− :: String
120− -> NonEmptyArray String
121− -> Aff (Either (NonEmptyArray (Tuple FilePath String)) (List (Module Ann)))
122−coreFnModulesFromOutput path globs = runExceptT do
123− paths <- Set.toUnfoldable <$> lift
124− (expandGlobs path ((_ <> "/corefn.json") <$> NonEmptyArray.toArray globs))
125− case NonEmptyArray.toArray globs of
126− [ "**" ] ->
127− sortModules <$> modulesFromPaths paths
128− _ ->
129− go <<< foldl resumePull emptyPull =<< modulesFromPaths paths
130− where
131− modulesFromPaths paths = ExceptT do
132− { left, right } <- separate <$> parTraverse readCoreFnModule paths
133− pure $ maybe (Right right) Left $ NonEmptyArray.fromArray left
134−
135− pathFromModuleName (ModuleName mn) =
136− path <> "/" <> mn <> "/corefn.json"
137−
138− go pull = case pullResult pull of
139− Left needed ->
140− go <<< foldl resumePull pull =<< modulesFromPaths
141− (pathFromModuleName <$> NonEmptySet.toUnfoldable needed)
142− Right modules ->
143− pure $ Lazy.force modules
144−
145−readCoreFnModule :: String -> Aff (Either (Tuple FilePath String) (Module Ann))
146−readCoreFnModule filePath = do
147− contents <- FS.readTextFile UTF8 filePath
148− case lmap Json.printJsonDecodeError <<< decodeModule =<< Json.jsonParser contents of
149− Left err -> do
150− pure $ Left $ Tuple filePath err
151− Right mod ->
152− pure $ Right mod
153−
154110-- | Returns `Right true` if the source code has this type signature
155111-- | somewhere in it:
156112-- | ```