diff --git a/.gitignore b/.gitignore
index a6d408d..8593ffc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,5 @@
.DS_Store
*.tgz
-/.cargo/
/packages/core/README.md
-/packages/wasm/wbg/
-/target/
-bindings/
dist/
node_modules/
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 5557bca..78dc8eb 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,8 +1 @@
-{
- "recommendations": [
- "esbenp.prettier-vscode",
- "rust-lang.rust-analyzer",
- "tamasfe.even-better-toml",
- "timonwong.shellcheck"
- ]
-}
+{ "recommendations": ["esbenp.prettier-vscode", "timonwong.shellcheck"] }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 205f93a..8553edb 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,15 +5,11 @@
// Prettier-supported languages here: https://prettier.io/docs/en/index.html
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
- "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
- "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
- "editor.formatOnSave": true,
- "evenBetterToml.formatter.alignComments": false,
- "rust-analyzer.check.command": "clippy"
+ "editor.formatOnSave": true
}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b3cb5e7..a90a799 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -7,7 +7,6 @@ Make sure to have these tools installed:
- [Git][]
- [Make][]
- [Node][]
-- [Rust][]
## Setup
@@ -61,9 +60,8 @@ Sometimes old build artifacts can hide errors. To clean your build:
make clean
```
-This doesn't clean everything; it keeps around downloaded files and Rust's
-`target` directory. You should be able to run `make all` right after it without
-an Internet connection.
+This doesn't clean everything; it keeps around downloaded files. You should be
+able to run `make all` right after it without an Internet connection.
## Site
@@ -82,4 +80,3 @@ make site-deps && npm run --workspace=@rose-lang/site dev -- --host
[git]: https://git-scm.com/downloads
[make]: https://en.wikipedia.org/wiki/Make_(software)
[node]: https://nodejs.org/en/download
-[rust]: https://www.rust-lang.org/tools/install
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index f9bc8c5..0000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,464 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "Inflector"
-version = "0.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
-
-[[package]]
-name = "bumpalo"
-version = "3.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
-
-[[package]]
-name = "by_address"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf8dba2868114ed769a1f2590fc9ae5eb331175b44313b6c9b922f8f7ca813d0"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "console_error_panic_hook"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
-dependencies = [
- "cfg-if",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "console_log"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f"
-dependencies = [
- "log",
- "web-sys",
-]
-
-[[package]]
-name = "darling"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
-dependencies = [
- "darling_core",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "enumset"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753"
-dependencies = [
- "enumset_derive",
-]
-
-[[package]]
-name = "enumset_derive"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "hashbrown"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
-name = "indexmap"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
-dependencies = [
- "equivalent",
- "hashbrown",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "leb128"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
-
-[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.17.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.56"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rose"
-version = "0.4.5"
-dependencies = [
- "enumset",
-]
-
-[[package]]
-name = "rose-autodiff"
-version = "0.4.5"
-dependencies = [
- "rose",
-]
-
-[[package]]
-name = "rose-interp"
-version = "0.4.5"
-dependencies = [
- "enumset",
- "indexmap",
- "rose",
- "serde",
- "thiserror",
- "ts-rs",
-]
-
-[[package]]
-name = "rose-transpose"
-version = "0.4.5"
-dependencies = [
- "enumset",
- "indexmap",
- "rose",
-]
-
-[[package]]
-name = "rose-wasm"
-version = "0.4.5"
-dependencies = [
- "by_address",
- "indexmap",
- "rose",
- "wasm-encoder",
-]
-
-[[package]]
-name = "rose-web"
-version = "0.4.5"
-dependencies = [
- "by_address",
- "console_error_panic_hook",
- "console_log",
- "enumset",
- "indexmap",
- "js-sys",
- "rose",
- "rose-autodiff",
- "rose-interp",
- "rose-transpose",
- "rose-wasm",
- "serde",
- "serde-wasm-bindgen",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.163"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde-wasm-bindgen"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
-dependencies = [
- "js-sys",
- "serde",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.163"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.14",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.14",
-]
-
-[[package]]
-name = "ts-rs"
-version = "6.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4added4070a4fdf9df03457206cd2e4b12417c8560a2954d91ffcbe60177a56a"
-dependencies = [
- "thiserror",
- "ts-rs-macros",
-]
-
-[[package]]
-name = "ts-rs-macros"
-version = "6.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f807fdb3151fee75df7485b901a89624358cd07a67a8fb1a5831bf5a07681ff"
-dependencies = [
- "Inflector",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "termcolor",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn 2.0.14",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.14",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.33.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39de0723a53d3c8f54bed106cfbc0d06b3e4d945c5c5022115a61e3b29183ae"
-dependencies = [
- "leb128",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
deleted file mode 100644
index d428e36..0000000
--- a/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[workspace]
-members = ["crates/*"]
-resolver = "2"
-
-[profile.release]
-codegen-units = 1
-lto = true
-
-# https://github.com/johnthagen/min-sized-rust
-[profile.web]
-inherits = "release"
-opt-level = "z"
-strip = true
diff --git a/Makefile b/Makefile
index 9abc29f..57d60e7 100644
--- a/Makefile
+++ b/Makefile
@@ -2,43 +2,18 @@
build: packages
# run all tests
-test: test-rust test-js
+test: test-js
# run other checks
check: prettier
- cargo fmt --check
- cargo clippy
# delete build artifacts, but not dependencies or downloaded files
clean:
- git clean -Xdf crates packages -e '!node_modules'
+ git clean -Xdf packages -e '!node_modules'
# do everything
all: build test check
-### Rust
-
-# install additional Rust stuff that we need
-rust:
- cargo install --root=.cargo --version=0.2.87 wasm-bindgen-cli
-
-# export TypeScript bindings from Rust types
-bindings:
- cargo test export_bindings_
-
-# compile Rust to WebAssembly
-wbg: rust
- cargo build --package=rose-web --target=wasm32-unknown-unknown --release
- cargo build --package=rose-web --no-default-features -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target wasm32-unknown-unknown --profile web
- .cargo/bin/wasm-bindgen --target=web --out-dir=packages/wasm/wbg target/wasm32-unknown-unknown/release/rose_web.wasm
- .cargo/bin/wasm-bindgen --target=web --out-dir=packages/wasm/dist/wbg target/wasm32-unknown-unknown/web/rose_web.wasm
-
-# run Rust tests
-test-rust:
- cargo test --quiet
-
-### JavaScript
-
# fetch JavaScript dependencies
npm:
npm i
@@ -48,7 +23,7 @@ prettier: npm
npx prettier --check .
# build `packages/`
-packages: core site wasm
+packages: core site
# run JavaScript tests
test-js: test-core test-site
@@ -56,12 +31,12 @@ test-js: test-core test-site
## `packages/core`
# build
-core: npm wasm
+core: npm
cp README.md packages/core
npm run --workspace=rose build
# test
-test-core: npm wasm
+test-core: npm
npm run --workspace=rose test -- run --no-threads
## `packages/site`
@@ -75,10 +50,3 @@ site: site-deps
# test
test-site: site-deps
npm run --workspace=@rose-lang/site test -- run --no-threads
-
-## `packages/wasm`
-
-# build
-wasm: npm bindings wbg
- npm run --workspace=@rose-lang/wasm build
- node bindings.js
diff --git a/README.md b/README.md
index 57aca98..eef9731 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
icon by Aaron Weiss / CC BY 4.0
-Rose is an automatic differentiation engine for the web, inspired by [JAX][].
+Rose is a differentiable programming for the web, inspired by [Dex][].
## Installation
@@ -33,59 +33,7 @@ bun add rose
## Usage
-This example defines custom derivatives for the builtin JavaScript logarithm and
-power functions, then computes the output, gradient, and Hessian for the power
-function applied with base 2 and exponent 3:
-
-```js
-import { Dual, Real, Vec, add, compile, div, fn, mul, opaque, vjp } from "rose";
-
-const log = opaque([Real], Real, Math.log);
-log.jvp = fn([Dual], Dual, ({ re: x, du: dx }) => {
- return { re: log(x), du: div(dx, x) };
-});
-
-const pow = opaque([Real, Real], Real, Math.pow);
-pow.jvp = fn([Dual, Dual], Dual, ({ re: x, du: dx }, { re: y, du: dy }) => {
- const z = pow(x, y);
- return { re: z, du: mul(add(mul(dx, div(y, x)), mul(dy, log(x))), z) };
-});
-
-const Vec2 = Vec(2, Real);
-const Mat2 = Vec(2, Vec2);
-
-const f = fn([Vec2], Real, ([x, y]) => pow(x, y));
-const g = fn([Vec2], Vec2, (v) => vjp(f)(v).grad(1));
-const h = fn([Vec2], Mat2, (v) => {
- const { grad } = vjp(g)(v);
- return [grad([1, 0]), grad([0, 1])];
-});
-
-const funcs = await Promise.all([compile(f), compile(g), compile(h)]);
-console.log(funcs.map((func) => func([2, 3])));
-```
-
-### With Vite
-
-If you are using [Vite][] then you will need to also install the
-[vite-plugin-top-level-await][] package, because Rose internally uses [top-level
-`await`][], which Vite does not directly support. You must also include the
-following in your Vite config:
-
-```js
-import { defineConfig } from "vite";
-import topLevelAwait from "vite-plugin-top-level-await";
-
-export default defineConfig({
- // the plugin described above
- plugins: [topLevelAwait()],
-
- // Vite bundles external dependencies by default in development mode, but that
- // process does not include assets; this option disables that particular kind
- // of bundling for Rose so that it can use its internal WebAssembly module
- optimizeDeps: { exclude: ["rose"] },
-});
-```
+TODO
## Contributing
@@ -95,13 +43,10 @@ See [`CONTRIBUTING.md`][].
Rose is licensed under the [MIT License][].
+[Dex]: https://github.com/google-research/dex-lang
[`CONTRIBUTING.md`]: https://github.com/rose-lang/rose/blob/main/CONTRIBUTING.md
[Bun]: https://bun.sh/
-[JAX]: http://jax.readthedocs.io/
[MIT License]: https://github.com/rose-lang/rose/blob/main/LICENSE
[npm]: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
[pnpm]: https://pnpm.io/installation
-[top-level `await`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await
-[vite-plugin-top-level-await]: https://www.npmjs.com/package/vite-plugin-top-level-await
-[Vite]: https://vitejs.dev/
[Yarn]: https://classic.yarnpkg.com/lang/en/docs/install/
diff --git a/bindings.js b/bindings.js
deleted file mode 100644
index 550cf35..0000000
--- a/bindings.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import fs from "fs/promises";
-import path from "path";
-import prettier from "prettier";
-
-const start_dir = "crates";
-const dest_dir = "packages/wasm/dist/bindings";
-
-const crates = await fs.readdir(start_dir, { withFileTypes: true });
-for (const crate of crates) {
- if (!crate.isDirectory()) continue;
- const bindings_dir = path.join(start_dir, crate.name, "bindings");
-
- const stat = await fs.stat(bindings_dir).catch(() => null);
- if (!stat || !stat.isDirectory()) {
- continue; // bindings directory does not exist for this crate, so skip it
- }
-
- // Create the destination directory
- const dest_folder = path.join(dest_dir, crate.name);
- await fs.mkdir(dest_folder, { recursive: true });
-
- // Read all .ts files in the bindings directory
- const files = (await fs.readdir(bindings_dir)).filter((f) =>
- f.endsWith(".ts"),
- );
- for (const file of files) {
- const tsfile = path.join(bindings_dir, file);
-
- // Get the base filename, without the .ts extension
- const base_name = path.basename(tsfile, ".ts");
-
- // Read the content of the .ts file
- const ts_content = await fs.readFile(tsfile, "utf-8");
-
- // Add .js to import lines
- const updated_content = ts_content.replace(/^(import .*)";$/gm, '$1.js";');
-
- // Write the updated content to the new location with .d.ts extension
- await fs.writeFile(
- path.join(dest_folder, `${base_name}.d.ts`),
- await prettier.format(updated_content, { parser: "typescript" }),
- );
- }
-}
diff --git a/crates/autodiff/Cargo.toml b/crates/autodiff/Cargo.toml
deleted file mode 100644
index 84478ea..0000000
--- a/crates/autodiff/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "rose-autodiff"
-version = "0.4.5"
-publish = false
-edition = "2021"
-
-[dependencies]
-rose = { path = "../core" }
diff --git a/crates/autodiff/src/lib.rs b/crates/autodiff/src/lib.rs
deleted file mode 100644
index 1d2a9eb..0000000
--- a/crates/autodiff/src/lib.rs
+++ /dev/null
@@ -1,410 +0,0 @@
-use rose::{id, Binop, Expr, Func, Instr, Ty, Unop};
-
-// see docstring of `pub fn jvp` below
-
-const REAL: id::Ty = id::ty(0);
-const DUAL: id::Ty = id::ty(1);
-
-// JS frontend requires field names to be alphabetized, and `"du"` comes before `"re"`
-const DU: id::Member = id::member(0);
-const RE: id::Member = id::member(1);
-
-fn map(t: id::Ty) -> id::Ty {
- id::ty(t.ty() + 2)
-}
-
-struct Autodiff<'a> {
- old_types: &'a [Ty],
- old_vars: &'a [id::Ty],
- new_vars: &'a mut Vec,
- unpacked: &'a mut [Option<(id::Var, id::Var)>],
- dual_zero: id::Var,
- code: Vec,
-}
-
-impl Autodiff<'_> {
- fn set(&mut self, t: id::Ty, expr: Expr) -> id::Var {
- let var = id::var(self.new_vars.len());
- self.new_vars.push(t);
- self.code.push(Instr { var, expr });
- var
- }
-
- fn real(&mut self, expr: Expr) -> id::Var {
- self.set(REAL, expr)
- }
-
- fn dual(&mut self, expr: Expr) -> id::Var {
- self.set(DUAL, expr)
- }
-
- fn unpack(&mut self, var: id::Var) {
- let i = var.var();
- if self.unpacked[i].is_none() {
- if let Ty::F64 = self.old_types[self.old_vars[i].ty()] {
- let x = self.real(Expr::Member {
- tuple: var,
- member: RE,
- });
- let dx = self.dual(Expr::Member {
- tuple: var,
- member: DU,
- });
- self.unpacked[i] = Some((x, dx))
- }
- }
- }
-
- fn get(&self, var: id::Var) -> (id::Var, id::Var) {
- self.unpacked[var.var()].unwrap()
- }
-
- fn pack(&mut self, var: id::Var, x: id::Var, dx: id::Var) {
- self.unpacked[var.var()] = Some((x, dx));
- self.code.push(Instr {
- var,
- expr: Expr::Tuple {
- members: [dx, x].into(), // alphabetical order
- },
- })
- }
-
- fn child(&mut self, orig: &[Instr]) -> Box<[Instr]> {
- Autodiff {
- old_types: self.old_types,
- old_vars: self.old_vars,
- new_vars: self.new_vars,
- unpacked: self.unpacked,
- dual_zero: self.dual_zero,
- code: vec![],
- }
- .block(orig)
- }
-
- fn block(mut self, orig: &[Instr]) -> Box<[Instr]> {
- for Instr { var, expr } in orig {
- self.instr(*var, expr);
- self.unpack(*var);
- }
- self.code.into()
- }
-
- fn instr(&mut self, var: id::Var, expr: &Expr) {
- match expr {
- // boring cases
- Expr::Unit => self.code.push(Instr {
- var,
- expr: Expr::Unit,
- }),
- &Expr::Bool { val } => self.code.push(Instr {
- var,
- expr: Expr::Bool { val },
- }),
- &Expr::Fin { val } => self.code.push(Instr {
- var,
- expr: Expr::Fin { val },
- }),
- Expr::Array { elems } => self.code.push(Instr {
- var,
- expr: Expr::Array {
- elems: elems.clone(),
- },
- }),
- Expr::Tuple { members } => self.code.push(Instr {
- var,
- expr: Expr::Tuple {
- members: members.clone(),
- },
- }),
- &Expr::Index { array, index } => self.code.push(Instr {
- var,
- expr: Expr::Index { array, index },
- }),
- &Expr::Member { tuple, member } => self.code.push(Instr {
- var,
- expr: Expr::Member { tuple, member },
- }),
- &Expr::Slice { array, index } => self.code.push(Instr {
- var,
- expr: Expr::Slice { array, index },
- }),
- &Expr::Field { tuple, member } => self.code.push(Instr {
- var,
- expr: Expr::Field { tuple, member },
- }),
- &Expr::Select { cond, then, els } => self.code.push(Instr {
- var,
- expr: Expr::Select { cond, then, els },
- }),
- &Expr::Accum { shape } => self.code.push(Instr {
- var,
- expr: Expr::Accum { shape },
- }),
- &Expr::Add { accum, addend } => self.code.push(Instr {
- var,
- expr: Expr::Add { accum, addend },
- }),
- &Expr::Resolve { var: container } => self.code.push(Instr {
- var,
- expr: Expr::Resolve { var: container },
- }),
-
- // less boring cases
- Expr::Call { id, generics, args } => self.code.push(Instr {
- var,
- expr: Expr::Call {
- id: *id,
- generics: generics.iter().copied().map(map).collect(),
- args: args.clone(),
- },
- }),
- Expr::For { arg, body, ret } => {
- let body = self.child(body);
- self.code.push(Instr {
- var,
- expr: Expr::For {
- arg: *arg,
- body,
- ret: *ret,
- },
- })
- }
-
- // interesting cases
- &Expr::F64 { val } => {
- let x = self.real(Expr::F64 { val });
- let dx = self.dual_zero;
- self.pack(var, x, dx)
- }
- &Expr::Unary { op, arg } => match op {
- // boring case
- Unop::Not => self.code.push(Instr {
- var,
- expr: Expr::Unary { op: Unop::Not, arg },
- }),
-
- // interesting cases
- Unop::Neg => {
- let (x, dx) = self.get(arg);
- let y = self.real(Expr::Unary {
- op: Unop::Neg,
- arg: x,
- });
- let dy = self.dual(Expr::Unary {
- op: Unop::Neg,
- arg: dx,
- });
- self.pack(var, y, dy)
- }
- Unop::Abs => {
- let (x, dx) = self.get(arg);
- let y = self.real(Expr::Unary {
- op: Unop::Abs,
- arg: x,
- });
- let sign = self.real(Expr::Unary {
- op: Unop::Sign,
- arg: x,
- });
- let dy = self.dual(Expr::Binary {
- op: Binop::Mul,
- left: dx,
- right: sign,
- });
- self.pack(var, y, dy)
- }
- Unop::Sign | Unop::Ceil | Unop::Floor | Unop::Trunc => {
- let (x, _) = self.get(arg);
- let y = self.real(Expr::Unary { op, arg: x });
- let dy = self.dual_zero;
- self.pack(var, y, dy)
- }
- Unop::Sqrt => {
- let (x, dx) = self.get(arg);
- let y = self.real(Expr::Unary {
- op: Unop::Sqrt,
- arg: x,
- });
- let z = self.real(Expr::Binary {
- op: Binop::Add,
- left: y,
- right: y,
- });
- let dy = self.dual(Expr::Binary {
- op: Binop::Div,
- left: dx,
- right: z,
- });
- self.pack(var, y, dy)
- }
- },
- &Expr::Binary { op, left, right } => match op {
- // boring cases
- Binop::And | Binop::Or | Binop::Iff | Binop::Xor => self.code.push(Instr {
- var,
- expr: Expr::Binary { op, left, right },
- }),
-
- // less boring cases
- Binop::Neq | Binop::Lt | Binop::Leq | Binop::Eq | Binop::Gt | Binop::Geq => {
- let (x, _) = self.get(left);
- let (y, _) = self.get(right);
- self.code.push(Instr {
- var,
- expr: Expr::Binary {
- op,
- left: x,
- right: y,
- },
- })
- }
-
- // interesting cases
- Binop::Add => {
- let (x, dx) = self.get(left);
- let (y, dy) = self.get(right);
- let z = self.real(Expr::Binary {
- op: Binop::Add,
- left: x,
- right: y,
- });
- let dz = self.dual(Expr::Binary {
- op: Binop::Add,
- left: dx,
- right: dy,
- });
- self.pack(var, z, dz)
- }
- Binop::Sub => {
- let (x, dx) = self.get(left);
- let (y, dy) = self.get(right);
- let z = self.real(Expr::Binary {
- op: Binop::Sub,
- left: x,
- right: y,
- });
- let dz = self.dual(Expr::Binary {
- op: Binop::Sub,
- left: dx,
- right: dy,
- });
- self.pack(var, z, dz)
- }
- Binop::Mul => {
- let (x, dx) = self.get(left);
- let (y, dy) = self.get(right);
- let z = self.real(Expr::Binary {
- op: Binop::Mul,
- left: x,
- right: y,
- });
- let a = self.dual(Expr::Binary {
- op: Binop::Mul,
- left: dx,
- right: y,
- });
- let b = self.dual(Expr::Binary {
- op: Binop::Mul,
- left: dy,
- right: x,
- });
- let dz = self.dual(Expr::Binary {
- op: Binop::Add,
- left: a,
- right: b,
- });
- self.pack(var, z, dz)
- }
- Binop::Div => {
- let (x, dx) = self.get(left);
- let (y, dy) = self.get(right);
- let z = self.real(Expr::Binary {
- op: Binop::Div,
- left: x,
- right: y,
- });
- let a = self.real(Expr::Binary {
- op: Binop::Div,
- left: z,
- right: y,
- });
- let b = self.dual(Expr::Binary {
- op: Binop::Div,
- left: dx,
- right: y,
- });
- let c = self.dual(Expr::Binary {
- op: Binop::Mul,
- left: dy,
- right: a,
- });
- let dz = self.dual(Expr::Binary {
- op: Binop::Sub,
- left: b,
- right: c,
- });
- self.pack(var, z, dz)
- }
- },
- }
- }
-}
-
-/// Return a function that computes the Jacobian-vector product of this function.
-///
-/// The first two types in the new function are the nonlinear and linear `F64` types, respectively.
-/// Every type from the original function is then mapped over directly in a one-to-one fashion, with
-/// indices shifted by two as necessary. Instances of the `F64` type from the original function are
-/// replaced with a `Tuple` type whose members are the linear and nonlinear `F64` types,
-/// respectively (note that this member order does not match the order of the types themselves).
-pub fn jvp(f: &Func) -> Func {
- let mut types = vec![Ty::F64, Ty::F64];
- types.extend(f.types.iter().map(|ty| match ty {
- // boring cases
- Ty::Unit => Ty::Unit,
- Ty::Bool => Ty::Bool,
- &Ty::Fin { size } => Ty::Fin { size },
- &Ty::Generic { id } => Ty::Generic { id },
-
- // less boring cases
- &Ty::Ref { inner } => Ty::Ref { inner: map(inner) },
- &Ty::Array { index, elem } => Ty::Array {
- index: map(index),
- elem: map(elem),
- },
- Ty::Tuple { members } => Ty::Tuple {
- members: members.iter().copied().map(map).collect(),
- },
-
- // interesting case
- Ty::F64 => Ty::Tuple {
- members: [DUAL, REAL].into(), // alphabetical order
- },
- }));
- let mut vars: Vec<_> = f.vars.iter().copied().map(map).collect();
- let dual_zero = id::var(vars.len());
- vars.push(DUAL);
- let mut ad = Autodiff {
- old_types: &f.types,
- old_vars: &f.vars,
- new_vars: &mut vars,
- unpacked: &mut vec![None; f.vars.len()],
- dual_zero,
- code: vec![Instr {
- var: dual_zero,
- expr: Expr::F64 { val: 0. },
- }],
- };
- for ¶m in f.params.iter() {
- ad.unpack(param);
- }
- let body = ad.block(&f.body);
- Func {
- generics: f.generics.clone(),
- types: types.into(),
- vars: vars.into(),
- params: f.params.clone(),
- ret: f.ret,
- body,
- }
-}
diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml
deleted file mode 100644
index 34cba31..0000000
--- a/crates/core/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "rose"
-version = "0.4.5"
-publish = false
-edition = "2021"
-
-[dependencies]
-enumset = "1"
diff --git a/crates/core/src/id.rs b/crates/core/src/id.rs
deleted file mode 100644
index e8cbcd0..0000000
--- a/crates/core/src/id.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-/// Index of a member in a tuple.
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct Member(usize);
-
-pub const fn member(id: usize) -> Member {
- Member(id)
-}
-
-impl Member {
- pub const fn member(self) -> usize {
- self.0
- }
-}
-
-/// Index of an uninstantiated function reference in a definition context.
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct Func(usize);
-
-pub const fn func(id: usize) -> Func {
- Func(id)
-}
-
-impl Func {
- pub const fn func(self) -> usize {
- self.0
- }
-}
-
-/// Index of a generic type parameter in a definition context.
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct Generic(usize);
-
-pub const fn generic(id: usize) -> Generic {
- Generic(id)
-}
-
-impl Generic {
- pub const fn generic(self) -> usize {
- self.0
- }
-}
-
-/// Index of a type in a definition context.
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct Ty(usize);
-
-pub const fn ty(id: usize) -> Ty {
- Ty(id)
-}
-
-impl Ty {
- pub const fn ty(self) -> usize {
- self.0
- }
-}
-
-/// Index of a local variable in a function definition context.
-#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct Var(usize);
-
-pub const fn var(id: usize) -> Var {
- Var(id)
-}
-
-impl Var {
- pub const fn var(self) -> usize {
- self.0
- }
-}
diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs
deleted file mode 100644
index 478123e..0000000
--- a/crates/core/src/lib.rs
+++ /dev/null
@@ -1,226 +0,0 @@
-pub mod id;
-
-use enumset::{EnumSet, EnumSetType};
-
-/// A type constraint.
-#[allow(clippy::derived_hash_with_manual_eq)] // `PartialEq` impl comes from enumset; should be fine
-#[derive(Debug, EnumSetType, Hash)]
-pub enum Constraint {
- /// Not a `Ref`.
- Value,
- /// Can be the `index` type of an `Array`.
- Index,
-}
-
-/// A type.
-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-pub enum Ty {
- Unit,
- Bool,
- F64,
- /// A nonnegative integer less than `size`. Satisfies `Constraint::Index`.
- Fin {
- size: usize,
- },
- Generic {
- id: id::Generic,
- },
- Ref {
- inner: id::Ty,
- },
- Array {
- /// Must satisfy `Constraint::Index`.
- index: id::Ty,
- elem: id::Ty,
- },
- Tuple {
- members: Box<[id::Ty]>,
- },
-}
-
-/// A function definition.
-#[derive(Debug)]
-pub struct Func {
- /// Generic type parameters.
- pub generics: Box<[EnumSet]>,
- /// Types used in this function definition.
- pub types: Box<[Ty]>,
- /// Local variable types.
- pub vars: Box<[id::Ty]>,
- /// Parameter variables.
- pub params: Box<[id::Var]>,
- /// Return variable.
- pub ret: id::Var,
- /// Function body.
- pub body: Box<[Instr]>,
-}
-
-/// Resolves `id::Func`s.
-pub trait Refs<'a> {
- /// See `Node`.
- type Opaque;
-
- /// Resolve `id` to a function node.
- fn get(&self, id: id::Func) -> Option>
- where
- Self: Sized;
-}
-
-/// A node in a graph of functions.
-#[derive(Clone, Debug, Copy)]
-pub enum Node<'a, O, T: Refs<'a, Opaque = O>> {
- /// A function with an explicit body.
- Transparent {
- /// To traverse the graph by resolving functions called by this one.
- refs: T,
- /// The signature and definition of this function.
- def: &'a Func,
- },
- /// A function with an opaque body.
- Opaque {
- /// Generic type parameters.
- generics: &'a [EnumSet],
- /// Types used in this function's signature.
- types: &'a [Ty],
- /// Parameter types.
- params: &'a [id::Ty],
- /// Return type.
- ret: id::Ty,
- /// Definition of this function; semantics may vary.
- def: O,
- },
-}
-
-#[derive(Debug)]
-pub struct Instr {
- pub var: id::Var,
- pub expr: Expr,
-}
-
-#[derive(Debug)]
-pub enum Expr {
- Unit,
- Bool {
- val: bool,
- },
- F64 {
- val: f64,
- },
- Fin {
- val: usize,
- },
-
- Array {
- elems: Box<[id::Var]>,
- },
- Tuple {
- members: Box<[id::Var]>,
- },
-
- Index {
- array: id::Var,
- index: id::Var,
- },
- Member {
- tuple: id::Var,
- member: id::Member,
- },
-
- Slice {
- /// Must actually be a `Ref` of an array, not just an array.
- array: id::Var,
- index: id::Var,
- },
- Field {
- /// Must actually be a `Ref` of a tuple, not just a tuple.
- tuple: id::Var,
- member: id::Member,
- },
-
- Unary {
- op: Unop,
- arg: id::Var,
- },
- Binary {
- op: Binop,
- left: id::Var,
- right: id::Var,
- },
- Select {
- /// Must be of type `Bool`.
- cond: id::Var,
- then: id::Var,
- els: id::Var,
- },
-
- Call {
- id: id::Func,
- generics: Box<[id::Ty]>,
- args: Box<[id::Var]>,
- },
- For {
- /// Type must satisfy `Constraint::Index`.
- arg: id::Var,
- body: Box<[Instr]>,
- /// Variable from `body` holding an array element.
- ret: id::Var,
- },
-
- /// Start a scope for an accumulator `Ref`.
- Accum {
- /// Topology of the `Ref`.
- shape: id::Var,
- },
-
- /// Accumulate into an accumulator `Ref`. Returns `Unit`.
- Add {
- /// The `Ref`, which must be in scope.
- accum: id::Var,
- /// Must be of the `Ref`'s inner type.
- addend: id::Var,
- },
-
- /// Consume a `Ref` to get its contained value.
- Resolve {
- /// The `Ref`, which must be in scope.
- var: id::Var,
- },
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum Unop {
- // `Bool` -> `Bool`
- Not,
-
- // `F64` -> `F64`
- Neg,
- Abs,
- Sign,
- Ceil,
- Floor,
- Trunc,
- Sqrt,
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum Binop {
- // `Bool` -> `Bool` -> `Bool`
- And,
- Or,
- Iff,
- Xor,
-
- // `F64` -> `F64` -> `Bool`
- Neq,
- Lt,
- Leq,
- Eq,
- Gt,
- Geq,
-
- // `F64` -> `F64` -> `F64`
- Add,
- Sub,
- Mul,
- Div,
-}
diff --git a/crates/interp/Cargo.toml b/crates/interp/Cargo.toml
deleted file mode 100644
index efbdaf5..0000000
--- a/crates/interp/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "rose-interp"
-version = "0.4.5"
-publish = false
-edition = "2021"
-
-[dependencies]
-enumset = "1"
-indexmap = "2"
-rose = { path = "../core" }
-serde = { version = "1", features = ["derive", "rc"], optional = true }
-thiserror = "1"
-
-[dev-dependencies]
-ts-rs = "6"
-
-[features]
-default = ["serde"]
-serde = ["dep:serde"]
diff --git a/crates/interp/src/lib.rs b/crates/interp/src/lib.rs
deleted file mode 100644
index 185c629..0000000
--- a/crates/interp/src/lib.rs
+++ /dev/null
@@ -1,509 +0,0 @@
-use indexmap::IndexSet;
-use rose::{id, Binop, Expr, Func, Node, Refs, Ty, Unop};
-use std::{cell::Cell, convert::Infallible, rc::Rc};
-
-#[cfg(feature = "serde")]
-use serde::{Deserialize, Serialize};
-
-#[cfg(test)]
-use ts_rs::TS;
-
-#[cfg_attr(test, derive(TS), ts(export))]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Clone, Debug, PartialEq)]
-pub enum Val {
- Unit,
- Bool(bool),
- F64(Cell),
- Fin(usize),
- Ref(Rc, Option),
- Array(Vals), // assume all indices are `Fin`
- Tuple(Vals),
-}
-
-pub type Vals = Rc>; // TODO: change to `Rc<[Val]>` https://github.com/rose-lang/rose/issues/63
-
-pub fn vals(v: [Val; N]) -> Vals {
- Rc::new(v.to_vec())
-}
-
-pub fn collect_vals(it: impl Iterator- ) -> Vals {
- Rc::new(it.collect())
-}
-
-pub fn val_f64(x: f64) -> Val {
- Val::F64(Cell::new(x))
-}
-
-impl Val {
- fn bool(&self) -> bool {
- match self {
- &Val::Bool(x) => x,
- _ => unreachable!(),
- }
- }
-
- fn f64(&self) -> f64 {
- match self {
- Val::F64(x) => x.get(),
- _ => unreachable!(),
- }
- }
-
- fn fin(&self) -> usize {
- match self {
- &Val::Fin(i) => i,
- _ => unreachable!(),
- }
- }
-
- fn get(&self, i: usize) -> &Self {
- match self {
- Val::Array(x) => &x[i],
- Val::Tuple(x) => &x[i],
- _ => unreachable!(),
- }
- }
-
- fn slice(&self, i: usize) -> Self {
- match self {
- Val::Ref(x, None) => Val::Ref(Rc::clone(x), Some(i)),
- Val::Ref(x, Some(j)) => Val::Ref(Rc::new(x.get(*j).clone()), Some(i)),
- _ => unreachable!(),
- }
- }
-
- fn inner(&self) -> &Self {
- match self {
- Val::Ref(x, i) => match i {
- None => x.as_ref(),
- &Some(j) => x.get(j),
- },
- _ => unreachable!(),
- }
- }
-
- /// Return a zero value with this value's topology.
- fn zero(&self) -> Self {
- match self {
- Self::Unit => Self::Unit,
- &Self::Bool(x) => Self::Bool(x),
- Self::F64(_) => Self::F64(Cell::new(0.)),
- &Self::Fin(x) => Self::Fin(x),
- Self::Ref(..) => unreachable!(),
- Self::Array(x) => Self::Array(collect_vals(x.iter().map(|x| x.zero()))),
- Self::Tuple(x) => Self::Tuple(collect_vals(x.iter().map(|x| x.zero()))),
- }
- }
-
- /// Add `x` to this value, which must represent a mutable `Ref` type.
- fn add(&self, x: &Self) {
- match (self, x) {
- (Self::Unit, Self::Unit)
- | (Self::Bool(_), Self::Bool(_))
- | (Self::Fin(_), Self::Fin(_)) => {}
- (Self::F64(a), Self::F64(b)) => a.set(a.get() + b.get()),
- (Self::Array(a), Self::Array(b)) => {
- for (a, b) in a.iter().zip(b.iter()) {
- a.add(b);
- }
- }
- (Self::Tuple(a), Self::Tuple(b)) => {
- for (a, b) in a.iter().zip(b.iter()) {
- a.add(b);
- }
- }
- _ => unreachable!(),
- }
- }
-}
-
-/// Resolve `ty` via `generics` and `types`, then return its ID in `typemap`, inserting if need be.
-///
-/// This is meant to be used to pull all the types from a callee into a broader context. The
-/// `generics` are the IDs of all the types provided as generic type parameters for the callee. The
-/// `types are the IDs of all the types that have been pulled in so far.
-fn resolve(typemap: &mut IndexSet, generics: &[id::Ty], types: &[id::Ty], ty: &Ty) -> id::Ty {
- let resolved = match ty {
- Ty::Generic { id } => return generics[id.generic()],
-
- Ty::Unit => Ty::Unit,
- Ty::Bool => Ty::Bool,
- Ty::F64 => Ty::F64,
- &Ty::Fin { size } => Ty::Fin { size },
-
- Ty::Ref { inner } => Ty::Ref {
- inner: types[inner.ty()],
- },
- Ty::Array { index, elem } => Ty::Array {
- index: types[index.ty()],
- elem: types[elem.ty()],
- },
- Ty::Tuple { members } => Ty::Tuple {
- members: members.iter().map(|&x| types[x.ty()]).collect(),
- },
- };
- let (i, _) = typemap.insert_full(resolved);
- id::ty(i)
-}
-
-/// An opaque function that can be called by the interpreter.
-pub trait Opaque {
- fn call(&self, types: &IndexSet, generics: &[id::Ty], args: &[Val]) -> Val;
-}
-
-impl Opaque for Infallible {
- fn call(&self, _: &IndexSet, _: &[id::Ty], _: &[Val]) -> Val {
- match *self {}
- }
-}
-
-/// basically, the `'a` lifetime is for the graph of functions, and the `'b` lifetime is just for
-/// this particular instance of interpretation
-struct Interpreter<'a, 'b, O, T: Refs<'a, Opaque = O>> {
- typemap: &'b mut IndexSet,
- refs: T,
- def: &'a Func,
- types: Vec,
- vars: Vec